summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-10-12 18:29:45 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2007-10-12 18:29:45 (GMT)
commit58b1c821c143af73888a254ee9aaa70d66e0fd3d (patch)
tree11e0190acce9301549a5cac5862c05f805ed6135
parent91db595ad44708d38ccf839ac8ca7248f8645733 (diff)
downloadpbn-58b1c821c143af73888a254ee9aaa70d66e0fd3d.zip
pbn-58b1c821c143af73888a254ee9aaa70d66e0fd3d.tar.gz
pbn-58b1c821c143af73888a254ee9aaa70d66e0fd3d.tar.bz2
pbn-58b1c821c143af73888a254ee9aaa70d66e0fd3d.tar.xz
Fix right shift, and add test for shifts
Right shift was broken; correct. Add simple test for shifts.
-rw-r--r--pbn_shift.c34
-rw-r--r--test.c21
2 files changed, 42 insertions, 13 deletions
diff --git a/pbn_shift.c b/pbn_shift.c
index e80cb24..21d65cf 100644
--- a/pbn_shift.c
+++ b/pbn_shift.c
@@ -35,6 +35,7 @@ struct pbn *pbn_shl(struct pbn *src, int shift)
len = (bits+PBN_ATOM_BITS-1)/PBN_ATOM_BITS;
dst = pbn_cow(src, len);
+ dst->bits = bits; /* This is guaranteed accurate */
sw = shift / PBN_ATOM_BITS;
sb = shift % PBN_ATOM_BITS;
@@ -76,21 +77,28 @@ struct pbn *pbn_shr(struct pbn *src, int shift)
len = src->len;
dst = pbn_cow(src, len); /* Leave at its old size */
- sw = shift / PBN_ATOM_BITS;
- sb = shift % PBN_ATOM_BITS;
-
- if (sb == 0) {
- /* Particularly simple case... */
- memmove(&dst->num[0], &dst->num[sw], len-sw);
+ if (shift > dst->bits) {
+ dst->bits = dst->minus = 0; /* Zero result */
+ sw = len; /* Zero it all */
} else {
- c = dst->num[sw];
- for (i = sw; i < len-1; i++) {
- /* c == dst->num[i] */
- b = dst->num[i+1];
- dst->num[i-sw] = (c >> sb) | (b << (PBN_ATOM_BITS-sb));
- c = b;
+ dst->bits -= shift;
+
+ sw = shift / PBN_ATOM_BITS;
+ sb = shift % PBN_ATOM_BITS;
+
+ if (sb == 0) {
+ /* Particularly simple case... */
+ memmove(&dst->num[0], &dst->num[sw], len-sw);
+ } else {
+ c = dst->num[sw];
+ for (i = sw; i < len-1; i++) {
+ /* c == dst->num[i] */
+ b = dst->num[i+1];
+ dst->num[i-sw] = (c >> sb) | (b << (PBN_ATOM_BITS-sb));
+ c = b;
+ }
+ dst->num[len-sw-1] = c >> sb;
}
- dst->num[len-sw] = c >> sb;
}
if (sw)
diff --git a/test.c b/test.c
index 00a5ddf..b899741 100644
--- a/test.c
+++ b/test.c
@@ -51,6 +51,27 @@ int main(int argc, char *argv[])
m = pbn_sub(m, pbn_ref(mj));
mj = pbn_add(mj, pbn_ref(mj));
}
+
+ printf("[ 0] ");
+ pbn_dump(stdout, pbn_ref(m));
+ printf(" (%d)", m->bits);
+ putchar('\n');
+
+ for (n = 1; n <= 8; n++) {
+ m = pbn_shl(m, n);
+ printf("[%2d] ", n);
+ pbn_dump(stdout, pbn_ref(m));
+ printf(" (%d)", m->bits);
+ putchar('\n');
+ }
+
+ for (n = 1; n <= 16; n++) {
+ m = pbn_shr(m, n);
+ printf("[%2d] ", n);
+ pbn_dump(stdout, pbn_ref(m));
+ printf(" (%d)", m->bits);
+ putchar('\n');
+ }
return 0;
}