16 typedef unsigned short Data;
21 : count(0), sign(1), data(nullptr)
28 : count(0), sign(1), data(nullptr)
37 assert(i <
sizeof(l));
46 this->
data[i] = buf[i];
52 : count(0), sign(1), data(nullptr)
61 assert(i <
sizeof(l));
70 this->
data[i] = buf[i];
76 : count(0), sign(1), data(nullptr)
81 assert(i <
sizeof(l));
90 this->
data[i] = buf[i];
96 : count(0), sign(1), data(nullptr)
101 assert(i <
sizeof(l));
110 this->
data[i] = buf[i];
116 : count(0), sign(1), data(nullptr)
133 std::vector<Data> buf;
135 buf.push_back(
Data(std::fmod(d,0x10000L)) );
139 this->
data = buf.size()>0 ?
new Data[buf.size()] :
nullptr;
140 this->
count = (
unsigned short)(buf.size());
141 std::copy( buf.begin(), buf.end(),
data );
148 : count(0), sign(1), data(nullptr)
164 std::vector<Data> buf;
166 buf.push_back(
Data(std::fmod(d,0x10000L)) );
170 this->
data = buf.size()>0 ?
new Data[buf.size()] :
nullptr;
171 this->
count = (
unsigned short)(buf.size());
172 std::copy( buf.begin(), buf.end(),
data );
179 : count(0), sign(1), data(nullptr)
195 std::vector<Data> buf;
197 buf.push_back(
Data(std::fmod(d,0x10000L)) );
201 this->
count = (
unsigned short)(buf.size());
202 if (this->
count > 0) {
204 std::copy( buf.begin(), buf.end(),
data );
207 this->
data =
nullptr;
212 static char rt[4096];
213 static int rt_pos = 0;
215 static char next(
const char*& s, std::istream** is)
217 if (!is || *s) {
char c = *s;
if (c) ++rt_pos, ++s;
return c; }
218 if (rt_pos == 4096)
return '\0';
219 (*is)->get(rt[rt_pos]);
221 rt[++rt_pos] =
'\0';
return rt[rt_pos-1];
224 static bool is_decimal(
const char* s, std::istream** is =
nullptr)
228 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
229 if (c ==
'+' || c ==
'-') c = next(s,is);
230 if (c < '1' || c >
'9')
return false;
231 while (c >=
'0' && c <=
'9') c = next(s,is);
232 if (c ==
'l' || c ==
'L') c = next(s,is);
233 if (rt_pos > 0) rt[++rt_pos] =
'\0';
234 return is ? true : c ==
'\0';
237 static bool is_exponential(
const char* s, std::istream** is =
nullptr)
241 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
242 if (c ==
'+' || c ==
'-') c = next(s,is);
243 if (c < '1' || c >
'9')
return false;
244 while (c >=
'0' && c <=
'9') c = next(s,is);
245 if (c !=
'e' && c !=
'E')
return false;
247 if (c ==
'+') c = next(s,is);
248 if (c < '0' || c >
'9')
return false;
249 while (c >=
'0' && c <=
'9') c = next(s,is);
250 if (rt_pos > 0) rt[++rt_pos] =
'\0';
251 return is ? true : c ==
'\0';
254 static bool is_hexadecimal(
const char* s, std::istream** is =
nullptr)
258 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
259 if (c ==
'+' || c ==
'-') c = next(s,is);
260 if (c !=
'0')
return false;
262 if (c !=
'x' && c !=
'X')
return false;
264 if ((c < '0' || c >
'9') &&
265 (c < 'a' || c >
'f') &&
266 (c < 'A' || c >
'F'))
return false;
267 while ((c >=
'0' && c <=
'9') ||
268 (c >=
'a' && c <=
'f') ||
269 (c >=
'A' && c <=
'F')) c = next(s,is);
270 if (c ==
'l' || c ==
'L') c = next(s,is);
271 if (rt_pos > 0) rt[++rt_pos] =
'\0';
272 return is ? true : c ==
'\0';
275 static bool is_octal(
const char* s, std::istream** is =
nullptr)
279 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
280 if (c ==
'+' || c ==
'-') c = next(s,is);
281 if (c !=
'0')
return false;
282 while (c >=
'0' && c <=
'7') c = next(s,is);
283 if (c ==
'l' || c ==
'L') c = next(s,is);
284 if (rt_pos > 0) rt[++rt_pos] =
'\0';
285 return is ? true : c ==
'\0';
288 static bool is_plus_inf(
const char* s, std::istream** is =
nullptr)
292 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
293 if (c ==
'+') c = next(s,is);
294 if (c !=
'I')
return false; c = next(s,is);
295 if (c !=
'n')
return false; c = next(s,is);
296 if (c !=
'f')
return false; c = next(s,is);
297 if (c ==
'i') c = next(s,is);
298 if (c ==
'n') c = next(s,is);
299 if (c ==
'i') c = next(s,is);
300 if (c ==
't') c = next(s,is);
301 if (c ==
'y') c = next(s,is);
302 if (rt_pos > 0) rt[++rt_pos] =
'\0';
303 return is ? true : c ==
'\0';
306 static bool is_minus_inf(
const char* s, std::istream** is =
nullptr)
310 while (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') c = next(s,is);
311 if (c !=
'-')
return false; c = next(s,is);
312 if (c !=
'I')
return false; c = next(s,is);
313 if (c !=
'n')
return false; c = next(s,is);
314 if (c !=
'f')
return false; c = next(s,is);
315 if (c ==
'i') c = next(s,is);
316 if (c ==
'n') c = next(s,is);
317 if (c ==
'i') c = next(s,is);
318 if (c ==
't') c = next(s,is);
319 if (c ==
'y') c = next(s,is);
320 if (rt_pos > 0) rt[++rt_pos] =
'\0';
321 return is ? true : c ==
'\0';
327 : count(0), sign(1), data(nullptr)
337 else if (is_minus_inf(s))
339 else if (is_decimal(s))
341 else if (is_exponential(s))
343 else if (is_hexadecimal(s))
345 else if (is_octal(s))
348 std::cerr <<
"Cannot convert string " << s <<
" to vnl_bignum\n";
360 std::istream* isp = &is;
364 if (is_plus_inf(rt,&isp))
366 else if (is_minus_inf(rt,&isp))
368 else if (is_exponential(rt,&isp))
370 else if (is_decimal(rt,&isp))
372 else if (is_hexadecimal(rt,&isp))
374 else if (is_octal(rt,&isp))
377 std::cerr <<
"Cannot convert string " << rt <<
" to vnl_bignum\n";
385 : count(b.count), sign(b.sign)
393 this->
data =
nullptr;
417 this->
data =
nullptr;
509 if (this->
is_infinity())
return (*
this) = (b.
sign<0 ? -(*this) : *
this);
511 if (b.
count == 0 || this->count == 0)
529 if (this->
is_infinity())
return (*
this) = (b.
sign<0 ? -(*this) : *
this);
530 assert (b.
count!=0 || this->count != 0);
536 return (*
this) = quot;
547 assert (b.
count!=0 || this->count != 0);
548 if (b.
count == 0)
return (*
this) = 0L;
552 return (*
this) = remain;
562 if (l == 0 || *
this == 0L)
577 if (l == 0 || *
this == 0L)
590 if (this->
sign != rhs.
sign)
return false;
594 if ( ( ! this->
data ) || ( ! rhs.
data ) || (this->data[i] != rhs.
data[i]))
607 if (this->
sign < rhs.
sign)
return true;
608 if (this->
sign > rhs.
sign)
return false;
626 char *cbuf =
new char[5 * (b.
count+1)];
630 cbuf[i++] = char(
long(r) +
'0');
646 std::string::size_type insert_point = 0;
650 s.insert(insert_point,
"-");
658 s.insert(insert_point, 1,
char(
'0'+
long(r)));
672 if (is_plus_inf(s.c_str()))
674 else if (is_minus_inf(s.c_str()))
683 vnl_bignum::operator short()
const 685 int j = this->
operator int();
691 vnl_bignum::operator int()
const 694 for (
Counter i = this->count; i > 0; )
695 j =
int(j*0x10000 + this->data[--i]);
696 return (this->sign < 0) ? -j : j;
701 vnl_bignum::operator long()
const 704 for (
Counter i = this->count; i > 0; )
705 l = l*0x10000L + this->data[--i];
706 return (this->sign < 0) ? -l : l;
711 vnl_bignum::operator float()
const 714 for (
Counter i = this->count; i > 0; )
715 f = f*0x10000 + this->data[--i];
716 if (this->is_infinity()) f = std::numeric_limits<float>::infinity();
717 return (this->sign < 0) ? -f : f;
722 vnl_bignum::operator double()
const 725 for (
Counter i = this->count; i > 0; )
726 d = d*0x10000 + this->data[--i];
727 if (this->is_infinity()) d = std::numeric_limits<double>::infinity();
728 return (this->sign < 0) ? -d : d;
733 vnl_bignum::operator
long double()
const 736 for (
Counter i = this->count; i > 0; )
737 d = d*0x10000 + this->data[--i];
738 if (this->is_infinity()) d = std::numeric_limits<long double>::infinity();
739 return (this->sign < 0) ? -d : d;
746 os <<
"{count=" << this->
count 747 <<
", sign=" << this->
sign 748 <<
", data=" << this->
data 749 <<
", value=" << *
this 755 if (this->
count > 0) {
756 os << std::hex << (this->data[this->
count-1]);
759 if (this->data[i-1] < 0x10) os <<
'0';
760 if (this->data[i-1] < 0x100) os <<
'0';
761 if (this->data[i-1] < 0x1000) os <<
'0';
762 os << this->data[i-1];
776 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n' || *s ==
'\r') ++s;
777 if (*s ==
'-' || *s ==
'+') ++len;
778 while (s[len]>=
'0' && s[len]<=
'9') {
783 if (*s ==
'-') this->
sign = -1;
791 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n' || *s ==
'\r') ++s;
793 long pow = std::atol(s + pos);
795 *
this = (*this) * 10L;
804 if (
'0' <= c && c <=
'9')
806 if (
'a' <= c && c <=
'f')
816 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n' || *s ==
'\r') ++s;
817 auto size =
Counter(std::strlen(s));
820 (*this) = ((*this) * 16L) +
830 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n' || *s ==
'\r') ++s;
831 auto size =
Counter(std::strlen(s));
834 (*this) = ((*this) * 8L) +
843 assert(new_count >= 0);
844 if (new_count == this->
count)
return;
845 Data *new_data = (new_count > 0 ?
new Data[new_count] :
nullptr);
847 if (this->
count <= new_count) {
849 if( this->
data && new_data )
851 for (; i < this->
count; i++)
852 new_data[i] = this->
data[i];
854 for (; i < new_count; i++)
858 for (
short i = 0; i < new_count; i++)
859 new_data[i] = this->
data[i];
862 delete [] this->
data;
863 this->
data = new_data;
864 this->
count = new_count;
873 if (this->
data[i - 1] != 0)
break;
874 if (i < this->
count) {
876 Data *new_data = (i > 0 ?
new Data[i] :
nullptr);
878 new_data[i - 1] = this->
data[i - 1];
879 delete [] this->
data;
880 this->
data = new_data;
899 unsigned long temp, carry = 0;
903 while (i < bmin->count) {
905 temp = (
unsigned long)b1.
data[i] + (
unsigned long)b2.
data[i] + carry;
906 carry = temp/0x10000L;
913 while (i < bmax->count ) {
914 temp = bmax->
data[i] + carry;
915 carry = temp/0x10000L;
931 unsigned long carry = 1;
932 while (i < bnum.
count && carry) {
933 unsigned long temp = (
unsigned long)bnum.
data[i] + carry;
934 carry = temp/0x10000L;
953 for (; i < bmin.
count; i++) {
954 temp = (
unsigned long)bmax.
data[i] + 0x10000L - borrow;
955 temp -= (
unsigned long)bmin.
data[i];
956 borrow = (temp/0x10000L == 0);
959 for (; i < bmax.
count; i++) {
960 temp = (
unsigned long)bmax.
data[i] + 0x10000L - borrow;
961 borrow = (temp/0x10000L == 0);
972 unsigned long borrow = 1;
973 while (i < bnum.
count && borrow) {
974 unsigned long temp = (
unsigned long)bnum.
data[i] + 0x10000L - borrow;
975 borrow = (temp/0x10000L == 0);
996 if (b1.
data[i - 1] > b2.
data[i - 1])
998 else if (b1.
data[i - 1] < b2.
data[i - 1])
1018 while (j < prod.
count)
1026 for (; j < b.
count; j++) {
1028 temp = (
unsigned long)b.
data[j] * (
unsigned long)d
1029 + (
unsigned long)prod.
data[i + j] + carry;
1030 prod.
data[i + j] =
Data(temp % 0x10000L);
1031 carry =
Data(temp/0x10000L);
1033 if (i+j < prod.
count)
1034 prod.
data[i + j] = carry;
1067 temp = (
unsigned long)r*0x10000L + (
unsigned long)b1.
data[j - 1];
1068 if (j < 1 + q.
count)
1085 v1 =
v.data[
v.count - 1],
1086 v2 =
v.data[
v.count - 2],
1092 q_hat = (u0 == v1 ?
Data(0xffff) :
Data(((
unsigned long)u0 * 0x10000L + (
unsigned long)u1) / (
unsigned long)v1));
1102 unsigned long lhs, rhs;
1103 for (
Counter i = 0; i < 2; i++) {
1104 lhs = (
unsigned long)v2 * (
unsigned long)q_hat;
1105 rhs = (
unsigned long)u0 * 0x10000L +(
unsigned long)u1;
1106 rhs -= ((
unsigned long)q_hat * (
unsigned long)v1);
1108 if ( rhs >= 0x10000L )
1112 if (rhs > rhs + (
unsigned long)u2)
1135 if (q_hat == 0)
return q_hat;
1141 unsigned long prod, diff;
1142 Data carry = 0, borrow = 0;
1144 for (; i <
v.count; ++i) {
1146 prod = (
unsigned long)
v.data[i] * (
unsigned long)q_hat + carry;
1147 diff = (
unsigned long)u.
data[u.
count -
v.count - 1 - j + i] + (0x10000L - (
unsigned long)borrow);
1148 diff -= (
unsigned long)
Data(prod);
1150 borrow = (diff/0x10000L == 0) ? 1 : 0;
1151 carry =
Data(prod/0x10000L);
1154 diff = (
unsigned long)u.
data[tmpcnt]
1155 + (0x10000L - (
unsigned long)borrow);
1156 diff -= (
unsigned long)carry;
1158 borrow = (diff/0x10000L == 0) ? 1 : 0;
1167 for (i = 0; i <
v.count; ++i) {
1168 sum = (
unsigned long)rslt.
data[i] + (
unsigned long)
v.data[i] + carry;
1169 carry =
Data(sum/0x10000L);
1175 for (i = 0; i < rslt.
count; ++i)
1190 assert(&b1 != &q && &b2 != &q && &b1 != &r && &b2 != &r);
1202 if (b2.
count == 1) {
1208 std::cerr <<
"\nvnl_bignum::divide: b1 ="; b1.
dump(std::cerr);
1209 std::cerr <<
"vnl_bignum::divide: b2 ="; b2.
dump(std::cerr);
1213 std::cerr <<
"vnl_bignum::divide: d = " << d << std::hex <<
" (0x" << d <<
")\n" << std::dec;
1214 std::cerr <<
"vnl_bignum::divide: u = "; u.
dump(std::cerr);
1215 std::cerr <<
"vnl_bignum::divide: v = ";
v.dump(std::cerr);
1224 std::cerr <<
"vnl_bignum::divide: q_hat = " << q_hat << std::hex <<
" (0x" << q_hat <<
")\n" << std::dec;
1225 std::cerr <<
"vnl_bignum::divide: u = "; u.
dump(std::cerr);
1232 std::cerr <<
"vnl_bignum::divide: q = "; q.
dump(std::cerr);
1233 std::cerr <<
"vnl_bignum::divide: r = "; r.
dump(std::cerr);
1254 auto growth =
Counter(l / 16);
1259 rslt.
resize(b1.
count + growth + (carry ? 1u : 0u));
1263 rslt.
data[i++] = b1.
data[0] << shift;
1264 while (i < rslt.
count - 1) {
1265 rslt.
data[i] = (b1.
data[i - growth] << shift) +
1266 (b1.
data[i - 1 - growth] >> rshift);
1269 if (i < rslt.
count) {
1271 rslt.
data[i] = carry;
1273 rslt.
data[i] = (b1.
data[i - growth] << shift)
1274 + (b1.
data[i - 1 - growth] >> rshift);
1287 auto shrinkage =
Counter(l / 16);
1290 if (shrinkage + (dregs == 0) < b1.
count) {
1292 rslt.
resize(b1.
count - shrinkage - (dregs == 0 ? 1 : 0));
1295 while (i < rslt.
count - 1) {
1296 rslt.
data[i] = (b1.
data[i + shrinkage] >> shift) +
1297 (b1.
data[i + shrinkage + 1u] << lshift);
1301 rslt.
data[i] = dregs;
1303 rslt.
data[i] = (b1.
data[i + shrinkage] >> shift) +
1304 (b1.
data[i + shrinkage + 1u] << lshift);
bool operator<(vnl_bignum const &) const
Compares two vnl_bignums.
Data multiply_subtract(vnl_bignum &u, const vnl_bignum &v, Data q_hat, Counter j)
calculate u - v*q_hat.
vnl_bignum left_shift(const vnl_bignum &b1, int l)
left shift (arithmetic) non-infinite vnl_bignum by positive number.
vnl_bignum & operator%=(vnl_bignum const &r)
Divides this by a vnl_bignum and replaces this by remainder.
vnl_bignum & operator--()
decrement.
void resize(short)
change the data allotment for a vnl_bignum.
vnl_bignum()
Creates a zero vnl_bignum.
void decrement(vnl_bignum &bnum)
Subtract 1 from bnum (unsigned, non-infinite, non-zero).
friend vnl_bignum left_shift(const vnl_bignum &b1, int l)
left shift (arithmetic) non-infinite vnl_bignum by positive number.
vnl_bignum & operator/=(vnl_bignum const &r)
Divides this by a vnl_bignum.
friend vnl_bignum right_shift(const vnl_bignum &b1, int l)
right shift (arithmetic) non-infinite vnl_bignum by positive number.
vnl_bignum operator>>(int l) const
Shifts bignum to the right l digits.
vnl_bignum right_shift(const vnl_bignum &b1, int l)
right shift (arithmetic) non-infinite vnl_bignum by positive number.
Data estimate_q_hat(const vnl_bignum &u, const vnl_bignum &v, Counter j)
estimate next dividend.
Namespace with standard math functions.
void add(const vnl_bignum &b1, const vnl_bignum &b2, vnl_bignum &sum)
add two non-infinite vnl_bignum values and save their sum.
int dtoBigNum(const char *s)
Converts decimal string to a vnl_bignum.
int magnitude_cmp(const vnl_bignum &b1, const vnl_bignum &b2)
compare absolute values of two vnl_bignums.
void otoBigNum(const char *s)
convert octal string to vnl_bignum.
friend void add(const vnl_bignum &, const vnl_bignum &, vnl_bignum &)
add two non-infinite vnl_bignum values and save their sum.
friend void multiply_aux(const vnl_bignum &, unsigned short, vnl_bignum &, unsigned short)
multiply a non-infinite vnl_bignum by a "single digit".
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Infinite precision integers.
bool is_plus_infinity() const
vnl_bignum operator+() const
void subtract(const vnl_bignum &bmax, const vnl_bignum &bmin, vnl_bignum &diff)
subtract bmin from bmax (unsigned, non-infinite), result in diff.
void exptoBigNum(const char *s)
convert exponential string to a vnl_bignum.
vnl_bignum operator-() const
Returns the negation of a vnl_bignum.
vnl_bignum & operator++()
prefix increment (++b).
Data normalize(const vnl_bignum &b1, const vnl_bignum &b2, vnl_bignum &u, vnl_bignum &v)
normalize two vnl_bignums.
void dump(std::ostream &=std::cout) const
dump the contents of a vnl_bignum to a stream, default cout.
bool isfinite(vnl_bignum const &x)
void increment(vnl_bignum &bnum)
Add 1 to bnum (unsigned, non-infinite).
std::string & vnl_bignum_to_string(std::string &s, const vnl_bignum &b)
Convert the number to a decimal representation in a string.
vnl_decnum pow(vnl_decnum const &x, unsigned long p)
Infinite precision integers.
vnl_bignum & vnl_bignum_from_string(vnl_bignum &b, const std::string &s)
Convert the number from a decimal representation in a string.
friend void decrement(vnl_bignum &bnum)
Subtract 1 from bnum (unsigned, non-infinite, non-zero).
vnl_bignum & operator=(const vnl_bignum &)
Copies rhs vnl_bignum to lhs vnl_bignum.
friend void increment(vnl_bignum &bnum)
Add 1 to bnum (unsigned, non-infinite).
vnl_bignum & operator *=(vnl_bignum const &r)
Multiplies this with a vnl_bignum.
VNL_EXPORT std::istream & operator>>(std::istream &s, vnl_decnum &r)
decimal input.
void xtoBigNum(const char *s)
convert hex string to vnl_bignum.
void divide(const vnl_bignum &b1, const vnl_bignum &b2, vnl_bignum &q, vnl_bignum &r)
divide b2 into b1, getting quotient q and remainder r.
friend void divide(const vnl_bignum &, const vnl_bignum &, vnl_bignum &, vnl_bignum &)
divide b2 into b1, getting quotient q and remainder r.
vnl_bignum operator<<(int l) const
Shifts bignum to the left l digits.
bool operator==(vnl_bignum const &) const
Two vnl_bignums are equal if and only if they have the same integer representation.
void multiply_aux(const vnl_bignum &b, Data d, vnl_bignum &prod, Counter i)
multiply a non-infinite vnl_bignum by a "single digit".
unsigned int ctox(int c)
convert hex character to integer hex value (ASCII or EBCDIC).
void divide_aux(const vnl_bignum &b1, Data d, vnl_bignum &q, Data &r)
divide a vnl_bignum by a "single digit".
friend int magnitude_cmp(const vnl_bignum &, const vnl_bignum &)
compare absolute values of two vnl_bignums.
~vnl_bignum()
Frees space for vnl_bignum.
bool is_minus_infinity() const
friend void subtract(const vnl_bignum &, const vnl_bignum &, vnl_bignum &)
subtract bmin from bmax (unsigned, non-infinite), result in diff.
vnl_bignum & trim()
trim non-infinite vnl_bignum of excess data allotment.