ref: 9661b205b1d932f96693376bc920cfa6060fbed4
parent: 5d9e71b6e4724f04b04fdb70452a2459f545ec98
author: Ori Bernstein <[email protected]>
date: Tue Jan 21 18:47:54 EST 2014
Implement bigint shifts.
--- a/libstd/bigint.myr
+++ b/libstd/bigint.myr
@@ -33,6 +33,8 @@
const bigmul : (a : bigint#, b : bigint# -> bigint#)
const bigdiv : (a : bigint#, b : bigint# -> bigint#)
const bigshl : (a : bigint#, b : bigint# -> bigint#)
+ const bigsrl : (a : bigint#, b : bigint# -> bigint#)
+ const bigsra : (a : bigint#, b : bigint# -> bigint#)
/* bigint*int -> bigint ops */
const bigaddi : (a : bigint#, b : int64 -> bigint#)
@@ -39,9 +41,9 @@
const bigsubi : (a : bigint#, b : int64 -> bigint#)
const bigmuli : (a : bigint#, b : int64 -> bigint#)
const bigdivi : (a : bigint#, b : int64 -> bigint#)
- const bigshli : (a : bigint#, b : uint64 -> bigint#)
- const bigshri : (a : bigint#, b : uint64 -> bigint#)
- const bigsari : (a : bigint#, b : uint64 -> bigint#)
+ const bigslli : (a : bigint#, b : uint64 -> bigint#)
+ const bigsrli : (a : bigint#, b : uint64 -> bigint#)
+ const bigsrai : (a : bigint#, b : uint64 -> bigint#)
;;
const mkbigint = {v
@@ -307,13 +309,23 @@
;;
}
-/*
-const bigsll = {a, b
+/* a >>= b, unsigned */
+const bigsrl = {a, b
+ match b.dig.len
+ | 0: -> a
+ | 1: -> bigsrli(a, b.dig[0] castto(uint64))
+ | n: die("shift by way too much\n")
+ ;;
}
-const bigshr = {a, b
+/* a >>= b, sign extending */
+const bigsra = {a, b
+ match b.dig.len
+ | 0: -> a
+ | 1: -> bigsrai(a, b.dig[0] castto(uint64))
+ | n: die("shift by way too much\n")
+ ;;
}
-*/
const trim = {a
var i
@@ -351,6 +363,42 @@
t = (a.dig[i] castto(uint64)) << shift
a.dig[i] = (t | carry) castto(uint32)
carry = t >> 32
+ ;;
+ -> trim(a)
+}
+
+const bigshri = {a, s
+ -> bigshrfill(a, s, 0)
+}
+
+const bigsari = {a, s
+ if a.sign == -1
+ bigshrfill(a, s, ~0)
+ else
+ bigshrfill(a, s, 0)
+ ;;
+}
+
+const bigshrfill = {a, s, fill
+ var off, shift
+ var t, carry
+ var i
+
+ off = s/32
+ shift = s % 32
+
+ /* blit over the base values */
+ for i = 0; i < a.dig.len - off; i++
+ a.dig[i] = a.dig[i + off]
+ ;;
+ for i = a.dig.len; i < a.dig.len + off; i++
+ a.dig[i] = fill
+ ;;
+ /* and shift over by the remainder */
+ for i = a.dig.len; i > 0; i--
+ t = (a.dig[i] castto(uint64))
+ a.dig[i] = (carry | (t >> shift)) castto(uint32)
+ carry = t << (32 - shift)
;;
-> trim(a)
}