Click
Loading...
Searching...
No Matches
bigint.hh
Go to the documentation of this file.
1#ifndef CLICK_BIGINT_HH
2#define CLICK_BIGINT_HH 1
3/*
4 * bigint.hh -- multiple-precision arithmetic
5 * Eddie Kohler and the authors of GMP
6 *
7 * Copyright (c) 2008 Meraki, Inc.
8 * Derived from the GNU Multiple Precision Arithmetic Library, which is
9 * Copyright (c) 2001-2008 Free Software Foundation, Inc.
10 *
11 * This source code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, version 3.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * Using the interfaces provided by this file does not create a derived work.
21 */
22#include <click/integers.hh>
23#include <click/type_traits.hh>
24#include <click/string.hh>
25CLICK_DECLS
26
59template <typename L, typename Lhalf = L>
60class Bigint { public:
61
63 typedef L limb_type;
64
66 typedef Lhalf half_limb_type;
67
68 enum {
69 limb_bits = sizeof(limb_type) * 8,
70 half_limb_bits = sizeof(limb_type) * 4
71 };
72 enum {
73 limb_high_bit = limb_type(1) << (limb_bits - 1),
74 limb_half = limb_type(1) << half_limb_bits,
75 limb_low_mask = limb_half - 1,
76 limb_zero = limb_type(0)
77 };
78
82 static inline half_limb_type low(limb_type x) {
83 return x & limb_low_mask;
84 }
85
87 static inline half_limb_type high(limb_type x) {
88 return x >> half_limb_bits;
89 }
90
101 static void add(limb_type &x1, limb_type &x0,
102 limb_type a1, limb_type a0, limb_type b1, limb_type b0) {
103 x0 = a0 + b0;
104 x1 = a1 + b1 + (x0 < a0);
105 }
106
113 static void multiply(limb_type &x1, limb_type &x0,
114 limb_type a, limb_type b) {
115 int_multiply(a, b, x0, x1);
116 }
117
124 static void multiply_half(limb_type &x1, limb_type &x0,
126 if (has_fast_int_multiply<limb_type>::value)
127 multiply(x1, x0, a, b);
128 else {
129 half_limb_type al = low(a), ah = high(a);
130
131 limb_type r0 = (limb_type) al * b;
132
133 limb_type r1 = (limb_type) ah * b;
134 limb_type r2 = high(r0) + r1;
135
136 x1 = (r2 < r1 ? limb_half : limb_zero) + high(r2);
137 x0 = (r2 << half_limb_bits) + low(r0);
138 }
139 }
140
147 limb_type y1 = ~x, y0 = ~limb_zero;
148
149 // now calculate [y1y0] / x
150 limb_type x1 = high(x), x0 = low(x);
151 limb_type q1 = y1 / x1;
152 limb_type r1 = y1 - q1 * x1;
153 limb_type m = q1 * x0;
154 r1 = r1 * limb_half | high(y0);
155 if (r1 < m) {
156 --q1, r1 += x;
157 if (r1 >= x && r1 < m)
158 --q1, r1 += x;
159 }
160 r1 -= m;
161
162 limb_type q0 = r1 / x1;
163 limb_type r0 = r1 - q0 * x1;
164 m = q0 * x0;
165 r0 = r0 * limb_half | low(y0);
166 if (r0 < m) {
167 --q0, r0 += x;
168 if (r0 >= x && r0 < m)
169 --q0, r0 += x;
170 }
171
172 return q1 * limb_half | q0;
173 }
174
180 static click_uintmax_t set(limb_type *a, int n, click_uintmax_t b) {
181 while (n > 0) {
182 *a++ = b;
183 n--;
184 b >>= limb_bits;
185 }
186 return b;
187 }
188
200 static limb_type multiply_add(limb_type *x, const limb_type *a, int n,
201 limb_type b) {
202 limb_type carry = 0;
203 do {
204 limb_type x0, x1;
205 multiply(x1, x0, *a++, b);
206 x0 += carry;
207 carry = (x0 < carry) + x1;
208 x0 += *x;
209 carry += (x0 < *x);
210 *x++ = x0;
211 } while (--n != 0);
212 return carry;
213 }
214
227 static limb_type multiply(limb_type *x, const limb_type *a, int n,
228 limb_type b, limb_type carry = 0) {
229 do {
230 limb_type x0, x1;
231 multiply(x1, x0, *a++, b);
232 x0 += carry;
233 carry = (x0 < carry) + x1;
234 *x++ = x0;
235 } while (--n != 0);
236 return carry;
237 }
238
251 static limb_type multiply_half(limb_type *x, const limb_type *a, int n,
252 half_limb_type b, limb_type carry = 0) {
253 do {
254 limb_type x0, x1;
255 multiply_half(x1, x0, *a++, b);
256 x0 += carry;
257 carry = (x0 < carry) + x1;
258 *x++ = x0;
259 } while (--n != 0);
260 return carry;
261 }
262
274 static limb_type divide(limb_type *x, const limb_type *a, int n,
275 limb_type b) {
276 x += n - 1; /* Make x point at most significant quotient limb */
277 a += n - 1; /* Make a point at most significant dividend limb */
278 limb_type r = 0;
279
280 if (b & limb_high_bit) {
281 /* High quotient limb is 0 or 1, skip a divide step. */
282 r = *a;
283 *x = (r >= b);
284 r -= (b & -*x);
285 --x, --a, --n;
286
287 /* Multiply-by-inverse, divisor already normalized. */
288 limb_type b_inverse = inverse(b);
289 while (n > 0) {
290 preinverted_divide(*x, r, r, *a, b, b_inverse);
291 --x, --a, --n;
292 }
293
294 } else {
295 /* Most significant bit of divisor == 0. */
296 /* Skip a division if high < divisor (high quotient 0). Testing
297 here before normalizing will still skip as often as
298 possible. */
299 if (*a < b) {
300 r = *a;
301 *x = 0;
302 --x, --a, --n;
303 }
304
305 if (n != 0) {
306 int norm = ffs_msb(b) - 1; // number of most significant 0 bits
307 b <<= norm;
308 r <<= norm;
309 limb_type b_inverse = inverse(b);
310
311 limb_type a1 = *a;
312 r |= (a1 >> (limb_bits - norm));
313 --a, --n;
314 while (n > 0) {
315 limb_type a0 = *a;
316 preinverted_divide(*x, r, r, ((a1 << norm) | (a0 >> (limb_bits - norm))), b, b_inverse);
317 --x, --a, --n;
318 a1 = a0;
319 }
320 preinverted_divide(*x, r, r, a1 << norm, b, b_inverse);
321 r >>= norm;
322 }
323 }
324
325 return r;
326 }
327
334 static String unparse_clear(limb_type *x, int n, int base = 10, bool uppercase = false) {
335 // need d chars, min d s.t. 10^d >= 2^(sizeof(limb_type) * 8 * n)
336 // == min d s.t. d >= sizeof(limb_type) * 8 * n / lg 10
337 int div = (base >= 16 ? 4 : (base >= 8 ? 3 : 1));
338 String s = String::make_uninitialized((n * limb_bits) / div + 1);
339 char *q = const_cast<char *>(s.end());
340 assert(base >= 2 && base <= 36);
341 while (1) {
342 while (n > 0 && x[n - 1] == 0)
343 --n;
344 if (n == 0)
345 break;
346 int r = divide(x, x, n, base);
347 if (r <= 9)
348 *--q = '0' + r;
349 else if (uppercase)
350 *--q = 'A' + r - 10;
351 else
352 *--q = 'a' + r - 10;
353 }
354 assert(q >= s.begin());
355 if (q == s.end())
356 *--q = '0';
357 return s.substring(q, s.end());
358 }
359
360 private:
361
362 /* Divide the two-limb number in (a1,a0) by b, with b_inverse being the
363 largest limb not larger than (2**(2*limb_bits))/b - (2**limb_bits). If
364 this would yield overflow, b_inverse should be the largest possible
365 number (i.e., only ones). For correct operation, the most significant
366 bit of b has to be set. Put the quotient in q and the remainder in
367 r. */
368 /* Like udiv_qrnnd_preinv, but branch-free. */
369 static void preinverted_divide(limb_type &q, limb_type &r,
370 limb_type a1, limb_type a0, limb_type b,
371 limb_type b_inverse) {
372 limb_type a0_mask = (a0 & limb_high_bit ? ~limb_zero : limb_zero);
373 limb_type a0_adjusted = a0 + (b & a0_mask);
374 limb_type x1, x0;
375 multiply(x1, x0, b_inverse, a1 - a0_mask);
376 add(x1, x0, x1, x0, a1, a0_adjusted);
377 limb_type q1 = ~x1;
378 multiply(x1, x0, q1, b);
379 add(x1, x0, x1, x0, a1, a0);
380 x1 -= b;
381 r = x0 + (b & x1);
382 q = x1 - q1;
383 }
384
385};
386
389
390CLICK_ENDDECLS
391#endif
Bigint< uint64_t > bigint
Typical Bigint usage with uint64_t limb_type.
Definition bigint.hh:388
Template for multiple-precision integer arithmetic.
Definition bigint.hh:60
static limb_type multiply_half(limb_type *x, const limb_type *a, int n, half_limb_type b, limb_type carry=0)
Multiply n-limb integer a by 1/2-limb integer b, add 1-limb integer carry, and store the result in n-...
Definition bigint.hh:251
Lhalf half_limb_type
Type of an arithmetic unit no smaller than one-half limb_type.
Definition bigint.hh:66
static void add(limb_type &x1, limb_type &x0, limb_type a1, limb_type a0, limb_type b1, limb_type b0)
Add two-limb integers [a1,a0] and [b1,b0], storing the result in [x1,x0].
Definition bigint.hh:101
static void multiply(limb_type &x1, limb_type &x0, limb_type a, limb_type b)
Multiply one-limb integers a and b, storing the result in [x1,x0].
Definition bigint.hh:113
static half_limb_type high(limb_type x)
Return the more significant half of x.
Definition bigint.hh:87
static void multiply_half(limb_type &x1, limb_type &x0, limb_type a, half_limb_type b)
Multiply one-limb integer a by half-limb integer b, storing the result in [x1,x0].
Definition bigint.hh:124
static limb_type inverse(limb_type x)
Return the inverse of limb x.
Definition bigint.hh:146
static limb_type multiply_add(limb_type *x, const limb_type *a, int n, limb_type b)
Multiply n-limb integer a by 1-limb integer b and add the result to n-limb integer x.
Definition bigint.hh:200
static limb_type divide(limb_type *x, const limb_type *a, int n, limb_type b)
Divide n-limb integer a by 1-limb integer b and store the result in n-limb integer x.
Definition bigint.hh:274
static half_limb_type low(limb_type x)
Return the less significant half of x.
Definition bigint.hh:82
L limb_type
Type of a limb, the unit of single arithmetic.
Definition bigint.hh:63
static limb_type multiply(limb_type *x, const limb_type *a, int n, limb_type b, limb_type carry=0)
Multiply n-limb integer a by 1-limb integer b, add 1-limb integer carry, and store the result in n-li...
Definition bigint.hh:227
static String unparse_clear(limb_type *x, int n, int base=10, bool uppercase=false)
Return a string representation of n-limb integer x and set x to 0.
Definition bigint.hh:334
static click_uintmax_t set(limb_type *a, int n, click_uintmax_t b)
Set n-limb integer a to the value b.
Definition bigint.hh:180
A string of characters.
Definition string.hh:22
String substring(const char *begin, const char *end) const
Return a substring of the current string starting at first and ending before last.
Definition string.hh:550
const_iterator end() const
Return an iterator for the end of the string.
Definition string.hh:584
static String make_uninitialized(int len)
Return a String containing len unknown characters.
Definition string.hh:444
const_iterator begin() const
Return an iterator for the first character in the string.
Definition string.hh:576
Functions for manipulating integers.
void int_multiply(T a, T b, T &xlow, T &xhigh)
Multiply a * b, placing the low-order bits of the result in xlow and the high-order bits in xhigh.
Definition integers.hh:395
int ffs_msb(unsigned x)
Return the index of the most significant bit set in x.
Definition integers.hh:210
Click's String class.
Type traits structures.