summaryrefslogtreecommitdiff
path: root/src/libbiguint/bu_div_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libbiguint/bu_div_internal.c')
-rw-r--r--src/libbiguint/bu_div_internal.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/libbiguint/bu_div_internal.c b/src/libbiguint/bu_div_internal.c
new file mode 100644
index 0000000..d1be789
--- /dev/null
+++ b/src/libbiguint/bu_div_internal.c
@@ -0,0 +1,46 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/biguint.h>
+
+/*
+ q = a/b, a = a mod b. Assumes b != 0 and qn >= alen - blen + 1.
+*/
+
+void bu_div_internal (uint32 *a, unsigned int an, uint32 const *b, unsigned int bn, uint32 *q, unsigned int qn)
+{
+ unsigned int alen = bu_len(a, an) ;
+ unsigned int blen = bu_len(b, bn) ;
+ bu_zero(q, qn) ;
+ if (alen < blen) return ;
+ {
+ uint32 bb[alen + 1] ;
+ unsigned int i = 1 + ((alen - blen) << 5) ;
+ bu_zero(bb, alen - blen) ;
+ bu_copy_internal(bb + alen - blen, b, blen) ;
+ bb[alen] = 0 ;
+
+ while (bu_cmp(a, alen, bb, alen+1) >= 0)
+ {
+ bu_slb(bb + alen - blen, blen + 1) ;
+ i++ ;
+ }
+ while (i && (bu_cmp(a, alen, bb, alen+1) < 0))
+ {
+ bu_srb(bb, alen + 1) ;
+ i-- ;
+ }
+
+ while (i--)
+ {
+ bu_slb(q, alen - blen + 1) ;
+ if (bu_cmp(a, alen, bb, alen) >= 0)
+ {
+ bu_sub(a, alen, a, alen, bb, alen) ;
+ q[0] |= 1 ;
+ }
+ bu_srb(bb, alen) ;
+ }
+ }
+}