vnl_bignum.cxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_bignum.cxx
2 #include <cstdlib>
3 #include <cstring>
4 #include <cmath>
5 #include <cassert>
6 #include <algorithm>
7 #include <vector>
8 #include <iostream>
9 #include "vnl_bignum.h"
10 //:
11 // \file
12 
13 #include <vnl/vnl_math.h> // for vnl_math::isfinite(double)
14 
15 typedef unsigned short Counter;
16 typedef unsigned short Data;
17 
18 //: Creates a zero vnl_bignum.
19 
21 : count(0), sign(1), data(nullptr)
22 {
23 }
24 
25 //: Creates a vnl_bignum from a long integer.
26 
28 : count(0), sign(1), data(nullptr)
29 {
30  if (l < 0) { // Get correct sign
31  l = -l; // Get absolute value of l
32  this->sign = -1;
33  }
34  Data buf[sizeof(l)]; // Temp buffer to store l in
35  Counter i = 0; // buffer index
36  while (l) { // While more bits in l
37  assert(i < sizeof(l)); // no more buffer space
38  buf[i] = Data(l); // Peel off lower order bits
39  l >>= 16; // Shift next bits into place
40  ++i;
41  }
42  if (i > 0)
43  this->data = new Data[this->count=i]; // Allocate permanent data
44 
45  while (i--) // Save buffer into perm. data
46  this->data[i] = buf[i];
47 }
48 
49 //: Creates a vnl_bignum from an integer.
50 
52 : count(0), sign(1), data(nullptr)
53 {
54  if (l < 0) { // Get correct sign
55  l = -l; // Get absolute value of l
56  this->sign = -1;
57  }
58  Data buf[sizeof(l)]; // Temp buffer to store l in
59  Counter i = 0; // buffer index
60  while (l) { // While more bits in l
61  assert(i < sizeof(l)); // no more buffer space
62  buf[i] = Data(l); // Peel off lower order bits
63  l >>= 16; // Shift next bits into place
64  i++;
65  }
66  if (i > 0)
67  this->data = new Data[this->count=i]; // Allocate permanent data
68 
69  while (i--) // Save buffer into perm. data
70  this->data[i] = buf[i];
71 }
72 
73 //: Creates a vnl_bignum from an unsigned long integer.
74 
75 vnl_bignum::vnl_bignum(unsigned long l)
76 : count(0), sign(1), data(nullptr)
77 {
78  Data buf[sizeof(l)]; // Temp buffer to store l in
79  Counter i = 0; // buffer index
80  while (l) { // While more bits in l
81  assert(i < sizeof(l)); // no more buffer space
82  buf[i] = Data(l); // Peel off lower order bits
83  l >>= 16; // Shift next bits into place
84  i++;
85  }
86  if (i > 0)
87  this->data = new Data[this->count=i]; // Allocate permanent data
88 
89  while (i--) // Save buffer into perm. data
90  this->data[i] = buf[i];
91 }
92 
93 //: Creates a vnl_bignum from an unsigned integer.
94 
95 vnl_bignum::vnl_bignum(unsigned int l)
96 : count(0), sign(1), data(nullptr)
97 {
98  Data buf[sizeof(l)]; // Temp buffer to store l in
99  Counter i = 0; // buffer index
100  while (l) { // While more bits in l
101  assert(i < sizeof(l)); // no more buffer space
102  buf[i] = Data(l); // Peel off lower order bits
103  l >>= 16; // Shift next bits into place
104  i++;
105  }
106  if (i > 0)
107  this->data = new Data[this->count=i]; // Allocate permanent data
108 
109  while (i--) // Save buffer into perm. data
110  this->data[i] = buf[i];
111 }
112 
113 //: Creates a vnl_bignum from a single-precision floating point number.
114 
116 : count(0), sign(1), data(nullptr)
117 {
118  double d = f;
119  if (d < 0.0) { // Get sign of d
120  d = -d; // Get absolute value of d
121  this->sign = -1;
122  }
123 
124  if (!vnl_math::isfinite(d)) {
125  // Infinity is represented as: count=1, data[0]=0.
126  // This is an otherwise unused representation, since 0 is represented as count=0.
127  this->count = 1;
128  this->data = new Data[1];
129  this->data[0] = 0;
130  }
131  else if (d >= 1.0) {
132  // Note: 0x10000L == 1 >> 16: the (assumed) size of unsigned short is 16 bits.
133  std::vector<Data> buf;
134  while (d >= 1.0) {
135  buf.push_back( Data(std::fmod(d,0x10000L)) ); // Get next data "digit" from d
136  d /= 0x10000L; // Shift d right 1 data "digit"
137  }
138  // Allocate and copy into permanent buffer
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 );
142  }
143 }
144 
145 //: Creates a vnl_bignum from a double floating point number.
146 
148 : count(0), sign(1), data(nullptr)
149 {
150  if (d < 0.0) { // Get sign of d
151  d = -d; // Get absolute value of d
152  this->sign = -1;
153  }
154 
155  if (!vnl_math::isfinite(d)) {
156  // Infinity is represented as: count=1, data[0]=0.
157  // This is an otherwise unused representation, since 0 is represented as count=0.
158  this->count = 1;
159  this->data = new Data[1];
160  this->data[0] = 0;
161  }
162  else if (d >= 1.0) {
163  // Note: 0x10000L == 1 >> 16: the (assumed) size of unsigned short is 16 bits.
164  std::vector<Data> buf;
165  while (d >= 1.0) {
166  buf.push_back( Data(std::fmod(d,0x10000L)) ); // Get next data "digit" from d
167  d /= 0x10000L; // Shift d right 1 data "digit"
168  }
169  // Allocate and copy into permanent buffer
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 );
173  }
174 }
175 
176 //: Creates a vnl_bignum from a "long double" floating point number.
177 
179 : count(0), sign(1), data(nullptr)
180 {
181  if (d < 0.0) { // Get sign of d
182  d = -d; // Get absolute value of d
183  this->sign = -1;
184  }
185 
186  if (!vnl_math::isfinite(d)) {
187  // Infinity is represented as: count=1, data[0]=0.
188  // This is an otherwise unused representation, since 0 is represented as count=0.
189  this->count = 1;
190  this->data = new Data[1];
191  this->data[0] = 0;
192  }
193  else if (d >= 1.0) {
194  // Note: 0x10000L == 1 >> 16: the (assumed) size of unsigned short is 16 bits.
195  std::vector<Data> buf;
196  while (d >= 1.0) {
197  buf.push_back( Data(std::fmod(d,0x10000L)) ); // Get next data "digit" from d
198  d /= 0x10000L; // Shift d right 1 data "digit"
199  }
200  // Allocate and copy into permanent buffer
201  this->count = (unsigned short)(buf.size());
202  if (this->count > 0) {
203  this->data = new Data[this->count];
204  std::copy( buf.begin(), buf.end(), data );
205  }
206  else {
207  this->data = nullptr;
208  }
209  }
210 }
211 
212 static char rt[4096];
213 static int rt_pos = 0;
214 
215 static char next(const char*& s, std::istream** is)
216 {
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]); // read a single byte from istream
220  if (*s) ++s; // in case s == rt+rt_pos
221  rt[++rt_pos] = '\0'; return rt[rt_pos-1];
222 }
223 
224 static bool is_decimal(const char* s, std::istream** is = nullptr)
225 {
226  rt_pos = 0;
227  char c = next(s,is);
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';
235 }
236 
237 static bool is_exponential(const char* s, std::istream** is = nullptr)
238 {
239  rt_pos = 0;
240  char c = next(s,is);
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;
246  c = next(s,is);
247  if (c == '+') c = next(s,is); // no negative exponent!
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';
252 }
253 
254 static bool is_hexadecimal(const char* s, std::istream** is = nullptr)
255 {
256  rt_pos = 0;
257  char c = next(s,is);
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;
261  c = next(s,is);
262  if (c != 'x' && c != 'X') return false;
263  c = next(s,is);
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';
273 }
274 
275 static bool is_octal(const char* s, std::istream** is = nullptr)
276 {
277  rt_pos = 0;
278  char c = next(s,is);
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';
286 }
287 
288 static bool is_plus_inf(const char* s, std::istream** is = nullptr)
289 {
290  rt_pos = 0;
291  char c = next(s,is);
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';
304 }
305 
306 static bool is_minus_inf(const char* s, std::istream** is = nullptr)
307 {
308  rt_pos = 0;
309  char c = next(s,is);
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';
322 }
323 
324 //: Creates a vnl_bignum from the character string representation.
325 
327 : count(0), sign(1), data(nullptr)
328 {
329  // decimal: "^ *[-+]?[1-9][0-9]*$"
330  // exponential: "^ *[-+]?[1-9][0-9]*[eE][+]?[0-9]+$"
331  // hexadecimal: "^ *[-+]?0[xX][0-9a-fA-F]+$"
332  // octal: "^ *[-+]?0[0-7]*$"
333  // infinity: "^ *[-+]?Inf(inity)?$"
334 
335  if (is_plus_inf(s))
336  count=1,data=new Data[1],data[0]=0;
337  else if (is_minus_inf(s))
338  sign=-1,count=1,data=new Data[1],data[0]=0;
339  else if (is_decimal(s)) // If string is decimal
340  this->dtoBigNum(s); // convert decimal to vnl_bignum
341  else if (is_exponential(s)) // If string is exponential
342  this->exptoBigNum(s); // convert exp. to vnl_bignum
343  else if (is_hexadecimal(s)) // If string is hex,
344  this->xtoBigNum(s); // convert hex to vnl_bignum
345  else if (is_octal(s)) // If string is octal
346  this->otoBigNum(s); // convert octal to vnl_bignum
347  else { // Otherwise
348  std::cerr << "Cannot convert string " << s << " to vnl_bignum\n";
349  }
350 }
351 
352 //: Reads a vnl_bignum from a stream
353 
354 std::istream& operator>>(std::istream& is, vnl_bignum& x)
355 {
356  // decimal: "^ *[-+]?[1-9][0-9]*$"
357  // exponential: "^ *[-+]?[1-9][0-9]*[eE][+]?[0-9]+$"
358  // hexadecimal: "^ *[-+]?0[xX][0-9a-fA-F]+$"
359  // octal: "^ *[-+]?0[0-7]*$"
360  std::istream* isp = &is;
361  rt[0] = '\0';
362 
363  x = 0L;
364  if (is_plus_inf(rt,&isp))
365  x.sign=1,x.count=1,x.data=new Data[1],x.data[0]=0;
366  else if (is_minus_inf(rt,&isp))
367  x.sign=-1,x.count=1,x.data=new Data[1],x.data[0]=0;
368  else if (is_exponential(rt,&isp)) // If input stream string is exponential
369  x.exptoBigNum(rt); // convert exp. to vnl_bignum
370  else if (is_decimal(rt,&isp)) // If string is decimal
371  x.dtoBigNum(rt); // convert decimal to vnl_bignum
372  else if (is_hexadecimal(rt,&isp)) // If string is hex,
373  x.xtoBigNum(rt); // convert hex to vnl_bignum
374  else if (is_octal(rt,&isp)) // If string is octal
375  x.otoBigNum(rt); // convert octal to vnl_bignum
376  else { // Otherwise
377  std::cerr << "Cannot convert string " << rt << " to vnl_bignum\n";
378  }
379  return is; // FIXME - should probably push back read characters to istream
380 }
381 
382 //: Copies the contents of vnl_bignum b.
383 
385 : count(b.count), sign(b.sign)
386 {
387  if (b.data) {
388  this->data = new Data[b.count]; // Allocate data
389  for (Counter i = 0; i < this->count; ++i) // Copy b data
390  this->data[i] = b.data[i];
391  }
392  else {
393  this->data = nullptr;
394  }
395 }
396 
397 //: Frees space for vnl_bignum.
398 
400 {
401  delete [] this->data; this->count = 0; // Delete any allocated data
402 }
403 
404 //: Copies rhs vnl_bignum to lhs vnl_bignum.
405 
407 {
408  if (this != &rhs) { // Avoid self-assignment
409  delete[] this->data; // Delete existing data
410  this->count = rhs.count; // Copy rhs's count
411  if (rhs.data) {
412  this->data = new Data[rhs.count]; // Allocate data if necessary
413  for (Counter i = 0; i < rhs.count; ++i) // Copy rhs's data
414  this->data[i] = rhs.data[i];
415  }
416  else {
417  this->data = nullptr;
418  }
419  this->sign = rhs.sign; // Copy rhs's sign
420  }
421  return *this; // Return reference
422 }
423 
424 //: Returns the negation of a vnl_bignum.
425 
427 {
428  vnl_bignum neg(*this);
429  if (neg.count) // So long as this is non-zero
430  neg.sign = -neg.sign; // Flip its sign
431  return neg;
432 }
433 
434 //: Prefix increment. Increments a vnl_bignum by 1, and returns it.
435 
437 {
438  if (this->is_infinity()) return *this;
439  if (this->count==0)
440  {
441  this->resize(1);
442  this->data[0] = 1;
443  this->sign = +1;
444  return *this;
445  }
446 
447  if (this->sign > 0) increment(*this);
448  else decrement(*this);
449 
450  return *this;
451 }
452 
453 //: Prefix decrement. Decrements a vnl_bignum by 1, and returns it.
454 
456 {
457  if (this->is_infinity()) return *this;
458  if (this->count==0)
459  {
460  this->resize(1);
461  this->data[0] = 1;
462  this->sign = -1;
463  return *this;
464  }
465 
466  if (this->sign < 0) increment(*this);
467  else decrement(*this);
468 
469  return *this;
470 }
471 
472 //: Adds two vnl_bignums, and returns new sum.
473 
475 {
476  // Infinity arithmetic:
477  assert (! b.is_minus_infinity() || ! this->is_plus_infinity() ); // +Inf-Inf
478  assert (! b.is_plus_infinity() || ! this->is_minus_infinity() ); // -Inf+Inf
479  if (b.is_infinity()) { return b; }
480  if (this->is_infinity()) { return *this; }
481 
482  vnl_bignum sum; // Init sum to zero
483  if (this->sign == b.sign) { // If both have same sign
484  add(*this,b,sum); // Do simple addition
485  sum.sign = this->sign; // Attach proper sign
486  }
487  else { // Else different signs
488  int mag = magnitude_cmp(*this,b); // Determine relative sizes
489  if (mag > 0) { // If abs(*this) > abs(b)
490  subtract(*this,b,sum); // sum = *this - b
491  sum.sign = this->sign; // Sign of sum follows *this
492  }
493  else if (mag < 0) { // Else if abs(*this) < abs(b)
494  subtract(b,*this,sum); // sum = b - *this
495  sum.sign = b.sign; // Sign of sum follows b
496  } // (Else abs(*this) == abs(b)
497  } // so sum must be zero)
498  return sum; // shallow swap on return
499 }
500 
501 //: Multiplies this with a vnl_bignum
502 
504 {
505  // Infinity arithmetic:
506  assert (! b.is_infinity() || this->count != 0 ); // multiplication 0*Inf
507  assert (! this->is_infinity() || b.count != 0 ); // multiplication Inf*0
508  if (b.is_infinity()) return (*this) = (this->sign<0 ? -b : b);
509  if (this->is_infinity()) return (*this) = (b.sign<0 ? -(*this) : *this);
510 
511  if (b.count == 0 || this->count == 0)
512  return (*this)=0L;
513  vnl_bignum prod;
514  prod.resize(this->count + b.count); // allocate data for product
515  for (Counter i = 0; i < b.count; i++) // multiply each b "digit"
516  multiply_aux(*this, b.data[i], prod, i); // times b1 and add to total
517  prod.sign = this->sign * b.sign; // determine correct sign
518  prod.trim(); // trim excess data and ret.
519  return (*this)=prod;
520 }
521 
522 //: Divides this by a vnl_bignum
523 
525 {
526  // Infinity arithmetic:
527  assert (! b.is_infinity() || ! this->is_infinity() ); // division Inf/Inf
528  if (b.is_infinity()) return (*this)=0L;
529  if (this->is_infinity()) return (*this) = (b.sign<0 ? -(*this) : *this);
530  assert (b.count!=0 || this->count != 0); // division 0/0
531  if (b.count == 0)
532  return (*this) = (this->sign < 0 ? vnl_bignum("-Inf") : vnl_bignum("+Inf"));
533 
534  vnl_bignum quot, r; // Quotient and remainder
535  divide(*this,b,quot,r); // Call divide fn
536  return (*this) = quot;
537 }
538 
539 //: Divides this by a vnl_bignum and replaces this by remainder.
540 
542 {
543  // Infinity arithmetic:
544  assert (! b.is_infinity() || ! this->is_infinity() ); // division Inf/Inf
545  if (b.is_infinity()) return *this; // remainder of x/Inf is x.
546  if (this->is_infinity()) return (*this) = 0L; // convention: remainder is 0
547  assert (b.count!=0 || this->count != 0); // division 0/0
548  if (b.count == 0) return (*this) = 0L; // convention: remainder is 0
549 
550  vnl_bignum remain, q; // Quotient and remainder
551  divide(*this,b,q,remain); // divide by b and save remainder
552  return (*this) = remain; // shallow swap on return
553 }
554 
555 //: Shifts bignum to the left l digits.
556 
558 {
559  // Infinity arithmetic:
560  if (this->is_infinity()) return *this;
561 
562  if (l == 0 || *this == 0L) // if either arg is zero
563  return *this;
564  if (l < 0) // if shift amt is negative
565  return right_shift(*this,-l); // do an actual right shift
566  else // otherwise
567  return left_shift(*this,l); // do a left shift
568 }
569 
570 //: Shifts bignum to the right l digits.
571 
573 {
574  // Infinity arithmetic:
575  if (this->is_infinity()) return *this;
576 
577  if (l == 0 || *this == 0L) // if either arg is zero
578  return *this;
579  if (l < 0) // if shift amt is negative
580  return left_shift(*this,-l); // do an actual left shift
581  else // else
582  return right_shift(*this,l); // do a right shift
583 }
584 
585 //: Two vnl_bignums are equal if and only if they have the same integer representation.
586 
587 bool vnl_bignum::operator==(const vnl_bignum& rhs) const
588 {
589  if (this != &rhs) { // Check address
590  if (this->sign != rhs.sign) return false; // Different sign implies !=
591  if (this->count != rhs.count) return false; // Different size implies !=
592  for (Counter i = 0; i < this->count; i++) // Each data element the same?
593  {
594  if ( ( ! this->data ) || ( ! rhs.data ) || (this->data[i] != rhs.data[i]))
595  {
596  return false; // No. Return !=
597  }
598  }
599  }
600  return true; // Yes. Return ==
601 }
602 
603 //: Compares two vnl_bignums.
604 
605 bool vnl_bignum::operator<(const vnl_bignum& rhs) const
606 {
607  if (this->sign < rhs.sign) return true; // Different signs?
608  if (this->sign > rhs.sign) return false;
609  if (this->sign == 1) // Both signs == 1
610  return magnitude_cmp(*this,rhs) < 0; // this must be smaller
611  else // Both signs == -1
612  return magnitude_cmp(*this,rhs) > 0; // this must be larger
613 }
614 
615 //: Formatted output for bignum.
616 
617 std::ostream& operator<<(std::ostream& os, const vnl_bignum& b)
618 {
619  vnl_bignum d = b; // Copy the input vnl_bignum
620  if (d.sign == -1) { // If it's negative
621  os << '-'; // Output leading minus sign
622  d.sign = 1; // Make d positive for divide
623  }
624  if (d.is_infinity()) return os<<"Inf";
625  vnl_bignum q,r; // Temp quotient and remainder
626  char *cbuf = new char[5 * (b.count+1)]; // Temp character buffer
627  Counter i = 0;
628  do { // repeat:
629  divide(d,10L,q,r); // Divide vnl_bignum by ten
630  cbuf[i++] = char(long(r) + '0'); // Get one's digit
631  d = q; // Then discard one's digit
632  q = r = 0L; // Prep for next divide
633  } while (d != 0L); // until no more one's digits
634  do { // repeat;
635  os << cbuf[--i]; // output char buf in reverse
636  } while (i); // until no more chars
637  delete [] cbuf; // delete temp char buf
638  return os; // return output stream
639 }
640 
641 //: Convert the number to a decimal representation in a string.
642 
643 std::string& vnl_bignum_to_string(std::string& s, const vnl_bignum& b)
644 {
645  s.erase();
646  std::string::size_type insert_point = 0; // keep record of location of first number.
647 
648  vnl_bignum d = b; // Copy the input vnl_bignum
649  if (d.sign == -1) { // If it's negative
650  s.insert(insert_point,"-"); // Output leading minus sign
651  d.sign = 1; // Make d positive for divide
652  ++insert_point; // keep record of location of first number.
653  }
654  if (d.is_infinity()) return s+="Inf";
655  vnl_bignum q,r; // Temp quotient and remainder
656  do { // repeat:
657  divide(d,10L,q,r); // Divide vnl_bignum by ten
658  s.insert(insert_point, 1, char('0'+long(r))); // Get one's digit, and insert it at head.
659  d = q; // Then discard one's digit
660  q = r = 0L; // Prep for next divide
661  } while (d != 0L); // until no more one's digits
662  return s;
663 }
664 
665 //: Convert the number from a decimal representation in a string.
666 
667 vnl_bignum& vnl_bignum_from_string(vnl_bignum& b, const std::string& s)
668 {
669  // decimal: "^ *[-+]?[1-9][0-9]*$"
670  // Infinity: "^ *[-+]?Inf(inity)?$"
671 
672  if (is_plus_inf(s.c_str()))
673  b=vnl_bignum("+Inf");
674  else if (is_minus_inf(s.c_str()))
675  b=vnl_bignum("-Inf");
676  else
677  b.dtoBigNum(s.c_str()); // convert decimal to vnl_bignum
678  return b;
679 }
680 
681 //: Implicit conversion from a vnl_bignum to a short.
682 
683 vnl_bignum::operator short() const
684 {
685  int j = this->operator int();
686  return (short)j;
687 }
688 
689 //: Implicit conversion from a vnl_bignum to an int.
690 
691 vnl_bignum::operator int() const
692 {
693  int j = 0;
694  for (Counter i = this->count; i > 0; )
695  j = int(j*0x10000 + this->data[--i]);
696  return (this->sign < 0) ? -j : j;
697 }
698 
699 //: Implicit conversion from a vnl_bignum to a long.
700 
701 vnl_bignum::operator long() const
702 {
703  long l = 0;
704  for (Counter i = this->count; i > 0; )
705  l = l*0x10000L + this->data[--i];
706  return (this->sign < 0) ? -l : l;
707 }
708 
709 //: Implicit conversion from a vnl_bignum to a float.
710 
711 vnl_bignum::operator float() const
712 {
713  float f = 0.0f;
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;
718 }
719 
720 //: Implicit conversion from a vnl_bignum to a double.
721 
722 vnl_bignum::operator double() const
723 {
724  double d = 0.0;
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;
729 }
730 
731 //: Implicit conversion from a vnl_bignum to a long double.
732 
733 vnl_bignum::operator long double() const
734 {
735  long double d = 0.0;
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;
740 }
741 
742 //: dump the contents of a vnl_bignum to a stream, default cout.
743 
744 void vnl_bignum::dump(std::ostream& os) const
745 {
746  os << "{count=" << this->count // output count field
747  << ", sign=" << this->sign // output sign field
748  << ", data=" << this->data // output data pointer
749  << ", value=" << *this
750  << ", {";
751  // format string == "%04X%s" or "%02X%s", etc.
752  // static char format_str[10] =
753  // {'%','0',char(2*2 + '0'),'X','%','s'};
754  // format_str[2] = char(2*2 + '0');
755  if (this->count > 0) { // output data array
756  os << std::hex << (this->data[this->count-1]);
757  for (Counter i = this->count - 1; i > 0; --i) {
758  os << ',';
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];
763  }
764  os << std::dec;
765  }
766  os << "}}\n"; // close brackets
767 }
768 
769 //: Converts decimal string to a vnl_bignum.
770 
771 int vnl_bignum::dtoBigNum(const char *s)
772 {
773  this->resize(0); this->sign = 1; // Reset number to 0.
774  Counter len = 0; // No chars converted yet
775  vnl_bignum sum;
776  while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') ++s; // skip whitespace
777  if (*s == '-' || *s == '+') ++len; // Skip over leading +,-
778  while (s[len]>='0' && s[len]<='9') { // While current char is digit
779  *this *= vnl_bignum(10L), // Shift vnl_bignum left a decimal
780  add(*this,vnl_bignum(long(s[len++]-'0')),sum), // digit and add new digit
781  *this = sum;
782  }
783  if (*s == '-') this->sign = -1; // If s had leading -, note it
784  return len; // Return # of chars processed
785 }
786 
787 //: convert exponential string to a vnl_bignum
788 
789 void vnl_bignum::exptoBigNum(const char *s)
790 {
791  while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') ++s; // skip whitespace
792  auto pos = Counter(this->dtoBigNum(s) + 1); // Convert the base, skip [eE]
793  long pow = std::atol(s + pos); // Convert the exponent to long
794  while (pow-- > 0) // Raise vnl_bignum to the given
795  *this = (*this) * 10L; // power
796 }
797 
798 //: convert hex character to integer hex value (ASCII or EBCDIC)
799 // - Inputs: character representation of a hex number
800 // - Outputs: integer value of the hex number
801 
802 unsigned int ctox(int c)
803 {
804  if ('0' <= c && c <= '9')
805  return c - '0';
806  if ('a' <= c && c <= 'f')
807  return c - 'a' + 10;
808  return c - 'A' + 10;
809 }
810 
811 //: convert hex string to vnl_bignum
812 
813 void vnl_bignum::xtoBigNum(const char *s)
814 {
815  this->resize(0); sign = 1; // Reset number to 0.
816  while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') ++s; // skip whitespace
817  auto size = Counter(std::strlen(s));
818  Counter len = 2; // skip leading "0x"
819  while (len < size) { // While there are more chars
820  (*this) = ((*this) * 16L) + // Shift vnl_bignum left one hex
821  vnl_bignum(long(ctox(s[len++]))); // digit and add next digit
822  }
823 }
824 
825 //: convert octal string to vnl_bignum
826 
827 void vnl_bignum::otoBigNum(const char *s)
828 {
829  this->resize(0); sign = 1; // Reset number to 0.
830  while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') ++s; // skip whitespace
831  auto size = Counter(std::strlen(s));
832  Counter len = 0; // No chars converted yet
833  while (len < size) { // While there are more chars
834  (*this) = ((*this) * 8L) + // Shift vnl_bignum left 1 oct dig.
835  vnl_bignum(long(s[len++] - '0')); // Add next character value
836  }
837 }
838 
839 //: change the data allotment for a vnl_bignum
840 
841 void vnl_bignum::resize(short new_count)
842 {
843  assert(new_count >= 0);
844  if (new_count == this->count) return;
845  Data *new_data = (new_count > 0 ? new Data[new_count] : nullptr); // Allocate data if necessary
846 
847  if (this->count <= new_count) { // Copy old data into new
848  short i = 0;
849  if( this->data && new_data )
850  {
851  for (; i < this->count; i++)
852  new_data[i] = this->data[i];
853  }
854  for (; i < new_count; i++)
855  new_data[i] = 0;
856  }
857  else {
858  for (short i = 0; i < new_count; i++)
859  new_data[i] = this->data[i];
860  }
861 
862  delete [] this->data; // Get rid of old data
863  this->data = new_data; // Point to new data
864  this->count = new_count; // Save new count
865 }
866 
867 //: trim non-infinite vnl_bignum of excess data allotment
868 
870 {
871  Counter i = this->count;
872  for (; i > 0; i--) // Skip over high-order words
873  if (this->data[i - 1] != 0) break; // that are zero
874  if (i < this->count) { // If there are some such words
875  this->count = i; // Update the count
876  Data *new_data = (i > 0 ? new Data[i] : nullptr); // Allocate data if necessary
877  for (; i > 0; i--) // Copy old data into new
878  new_data[i - 1] = this->data[i - 1];
879  delete [] this->data; // Delete old data
880  this->data = new_data; // Point to new data
881  }
882  return *this; // return reference to vnl_bignum
883 }
884 
885 //: add two non-infinite vnl_bignum values and save their sum
886 
887 void add(const vnl_bignum& b1, const vnl_bignum& b2, vnl_bignum& sum)
888 {
889  const vnl_bignum *bmax, *bmin; // Determine which of the two
890  if (b1.count >= b2.count) { // addends has the most
891  bmax = &b1; // data.
892  bmin = &b2;
893  }
894  else {
895  bmax = &b2;
896  bmin = &b1;
897  }
898  sum.resize(bmax->count); // Allocate data for their sum
899  unsigned long temp, carry = 0;
900  Counter i = 0;
901  if( b1.data )
902  {
903  while (i < bmin->count) { // Add, element by element.
904  // Add both elements and carry
905  temp = (unsigned long)b1.data[i] + (unsigned long)b2.data[i] + carry;
906  carry = temp/0x10000L; // keep track of the carry
907  sum.data[i] = Data(temp); // store sum
908  i++; // go to next element
909  }
910  }
911  if( bmax->data )
912  {
913  while (i < bmax->count ) { // bmin has no more elements
914  temp = bmax->data[i] + carry; // propagate the carry through
915  carry = temp/0x10000L; // the rest of bmax's elements
916  sum.data[i] = Data(temp); // store sum
917  i++;
918  }
919  }
920  if (carry) { // if carry left over
921  sum.resize(bmax->count + 1); // allocate another word
922  sum.data[bmax->count] = 1; // save the carry in it
923  }
924 }
925 
926 //: Add 1 to bnum (unsigned, non-infinite)
927 
929 {
930  Counter i = 0;
931  unsigned long carry = 1;
932  while (i < bnum.count && carry) { // increment, element by element.
933  unsigned long temp = (unsigned long)bnum.data[i] + carry;
934  carry = temp/0x10000L;
935  bnum.data[i] = (Data)temp;
936  ++i;
937  }
938  if (carry)
939  {
940  bnum.resize(bnum.count+1);
941  bnum.data[bnum.count-1] = 1;
942  }
943 }
944 
945 //: subtract bmin from bmax (unsigned, non-infinite), result in diff
946 
947 void subtract(const vnl_bignum& bmax, const vnl_bignum& bmin, vnl_bignum& diff)
948 {
949  diff.resize(bmax.count); // Allocate data for difference
950  unsigned long temp;
951  int borrow = 0;
952  Counter i = 0;
953  for (; i < bmin.count; i++) { // Subtract word by word.
954  temp = (unsigned long)bmax.data[i] + 0x10000L - borrow; // Add radix to bmax's data
955  temp -= (unsigned long)bmin.data[i]; // Subtract off bmin's data
956  borrow = (temp/0x10000L == 0); // Did we have to borrow?
957  diff.data[i] = (Data) temp; // Reduce modulo radix and save
958  }
959  for (; i < bmax.count; i++) { // No more data for bmin
960  temp = (unsigned long)bmax.data[i] + 0x10000L - borrow; // Propagate the borrow through
961  borrow = (temp/0x10000L == 0); // rest of bmax's data
962  diff.data[i] = (Data) temp;
963  }
964  diff.trim(); // Done. Now trim excess data
965 }
966 
967 //: Subtract 1 from bnum (unsigned, non-infinite, non-zero)
968 
970 {
971  Counter i = 0;
972  unsigned long borrow = 1;
973  while (i < bnum.count && borrow) { // decrement, element by element.
974  unsigned long temp = (unsigned long)bnum.data[i] + 0x10000L - borrow;
975  borrow = (temp/0x10000L == 0); // Did we have to borrow?
976  bnum.data[i] = (Data)temp; // Reduce modulo radix and save
977  ++i;
978  }
979  bnum.trim(); // Done. Now trim excess data
980  if (bnum.count==0) bnum.sign=+1; // Re-establish sign invariant
981 }
982 
983 //: compare absolute values of two vnl_bignums
984 // Outputs: result of comparison: -1 if abs(b1) < abs(b2)
985 // 0 if abs(b1) == abs(b2)
986 // +1 if abs(b1) > abs(b2)
987 
988 int magnitude_cmp(const vnl_bignum& b1, const vnl_bignum& b2)
989 {
990  if (b1.is_infinity()) return b2.is_infinity() ? 0 : 1;
991  if (b2.is_infinity()) return -1;
992  if (b1.count > b2.count) return 1; // If one has more data than
993  if (b2.count > b1.count) return -1; // the other, it wins
994  Counter i = b1.count; // Else same number of elements
995  while (i > 0) { // Do lexicographic comparison
996  if (b1.data[i - 1] > b2.data[i - 1])
997  return 1;
998  else if (b1.data[i - 1] < b2.data[i - 1])
999  return -1;
1000  i--;
1001  } // No data, or all elements same
1002  return 0; // so must be equal
1003 }
1004 
1005 //: multiply a non-infinite vnl_bignum by a "single digit"
1006 // - Inputs: vnl_bignum reference, single word multiplier, reference to the product,
1007 // and index of starting storage location to use in product
1008 
1009 void multiply_aux(const vnl_bignum& b, Data d, vnl_bignum& prod, Counter i)
1010 {
1011  // this function works just like normal multiplication by hand, in that the
1012  // top number is multiplied by the first digit of the bottom number, then the
1013  // second digit, and so on. The only difference is that instead of doing all
1014  // of the multiplication before adding the rows, addition is done
1015  // concurrently.
1016  if (i == 0) { // if index is zero
1017  Counter j = 0; // then zero out all of
1018  while (j < prod.count) // prod's data elements
1019  prod.data[j++] = 0;
1020  }
1021  if (d != 0) { // if d == 0, nothing to do
1022  unsigned long temp;
1023  Data carry = 0;
1024 
1025  Counter j = 0;
1026  for (; j < b.count; j++) {
1027  // for each of b's data elements, multiply times d and add running product
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); // store result in product
1031  carry = Data(temp/0x10000L); // keep track of carry
1032  }
1033  if (i+j < prod.count)
1034  prod.data[i + j] = carry; // Done. Store the final carry
1035  }
1036 }
1037 
1038 //: normalize two vnl_bignums
1039 // (Refer to Knuth, V.2, Section 4.3.1, Algorithm D for details.
1040 // A digit here is one data element in the radix 2**2.)
1041 // - Inputs: references to two vnl_bignums b1, b2
1042 // - Outputs: their normalized counterparts u and v,
1043 // and the integral normalization factor used
1044 
1046 {
1047  Data d = Data(0x10000L/((unsigned long)(b2.data[b2.count - 1]) + 1L)); // Calculate normalization factor.
1048  u.resize(b1.count + 1); // Get data for u (plus extra)
1049  v.resize(b2.count); // Get data for v
1050  u.data[b1.count] = 0; // Set u's leading digit to 0
1051  multiply_aux(b1,d,u,0); // u = b1 * d
1052  multiply_aux(b2,d,v,0); // v = b2 * d
1053  return d; // return normalization factor
1054 }
1055 
1056 //: divide a vnl_bignum by a "single digit"
1057 // (Refer to Knuth, V.2, Section 4.3.2, exercise 16 for details.
1058 // A digit here is one data element in the radix 2**2.)
1059 // - Inputs: reference to vnl_bignum dividend, single digit divisor d, vnl_bignum
1060 // quotient, and single digit remainder r
1061 
1062 void divide_aux(const vnl_bignum& b1, Data d, vnl_bignum& q, Data& r)
1063 {
1064  r = 0; // init remainder to zero
1065  unsigned long temp;
1066  for (Counter j = b1.count; j > 0; j--) {
1067  temp = (unsigned long)r*0x10000L + (unsigned long)b1.data[j - 1]; // get remainder, append next
1068  if (j < 1 + q.count)
1069  q.data[j - 1] = Data(temp/d); // digit, then divide
1070  r = Data(temp % d); // calculate new remainder
1071  }
1072 }
1073 
1074 //: estimate next dividend
1075 // (Refer to Knuth, V.2, Section 4.3.1, Algorithm D for details.
1076 // This function estimates how many times v goes into u, starting at u's
1077 // jth digit. A digit here is actually a data element, thought of as
1078 // being in the radix 2**2.)
1079 // - Inputs: reference to vnl_bignum dividend and divisor and starting digit j
1080 // - Outputs: estimated number of times v goes into u
1081 
1083 {
1084  Data q_hat,
1085  v1 = v.data[v.count - 1], // localize frequent data
1086  v2 = v.data[v.count - 2],
1087  u0 = u.data[u.count - 1 - j],
1088  u1 = u.data[u.count - 2 - j],
1089  u2 = u.data[u.count - 3 - j];
1090 
1091  // Initial Knuth estimate, usually correct
1092  q_hat = (u0 == v1 ? Data(0xffff) : Data(((unsigned long)u0 * 0x10000L + (unsigned long)u1) / (unsigned long)v1));
1093 
1094  // high speed test to determine most of the cases in which initial
1095  // estimate is too large. Eliminates most cases in which q_hat is one too
1096  // large. Eliminates all cases in which q_hat is two too large. The test
1097  // looks hairy because we have to watch out for overflow. In the book, this
1098  // test is the simple inequality:
1099  // v2*q_hat > (u0*0x10000L + u1 - q_hat*v1)*0x10000L + u2.
1100  // If the inequality is true, decrease q_hat by 1. If inequality is still
1101  // true, decrease q_hat again.
1102  unsigned long lhs, rhs; // lhs, rhs of Knuth inequality
1103  for (Counter i = 0; i < 2; i++) { // loop at most twice
1104  lhs = (unsigned long)v2 * (unsigned long)q_hat; // Calculate left-hand side of ineq.
1105  rhs = (unsigned long)u0 * 0x10000L +(unsigned long)u1;// Calculate part of right-hand side
1106  rhs -= ((unsigned long)q_hat * (unsigned long)v1); // Now subtract off part
1107 
1108  if ( rhs >= 0x10000L ) // if multiplication with 0x10000L causes overflow
1109  break; // then rhs > lhs, so test fails
1110  rhs *= 0x10000L; // No overflow: ok to multiply
1111 
1112  if (rhs > rhs + (unsigned long)u2) // if addition yields overflow
1113  break; // then rhs > lhs, so test fails
1114  rhs += u2; // No overflow: ok to add.
1115  if (lhs <= rhs) // if lhs <= rhs
1116  break; // test fails
1117  q_hat--; // Test passes: decrement q_hat
1118  } // Loop again
1119  return q_hat; // Return estimate
1120 }
1121 
1122 //: calculate u - v*q_hat
1123 // (Refer to Knuth, V. 2, Section 4.3.1, Algorithm D for details.
1124 // A digit here is a data element, thought of as being in the radix 2**2.)
1125 // - Inputs: reference to vnl_bignum dividend, divisor, estimated result, and index
1126 // into jth digit of dividend
1127 // - Outputs: true number of times v goes into u
1128 
1130 {
1131  // At this point it has been estimated that v goes into the jth and higher
1132  // digits of u about q_hat times, and in fact that q_hat is either the
1133  // correct number of times or one too large.
1134 
1135  if (q_hat == 0) return q_hat; // if q_hat 0, nothing to do
1136  vnl_bignum rslt; // create a temporary vnl_bignum
1137  Counter tmpcnt;
1138  rslt.resize(v.count + 1u); // allocate data for it
1139 
1140  // simultaneous computation of u - v*q_hat
1141  unsigned long prod, diff;
1142  Data carry = 0, borrow = 0;
1143  Counter i = 0;
1144  for (; i < v.count; ++i) {
1145  // for each digit of v, multiply it by q_hat and subtract the result
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); // form proper digit of u
1149  rslt.data[i] = Data(diff); // save the result
1150  borrow = (diff/0x10000L == 0) ? 1 : 0; // keep track of any borrows
1151  carry = Data(prod/0x10000L); // keep track of carries
1152  }
1153  tmpcnt = Counter(u.count - v.count + i - j - 1);
1154  diff = (unsigned long)u.data[tmpcnt] // special case for the last digit
1155  + (0x10000L - (unsigned long)borrow);
1156  diff -= (unsigned long)carry;
1157  rslt.data[i] = Data(diff);
1158  borrow = (diff/0x10000L == 0) ? 1 : 0;
1159 
1160  // A leftover borrow indicates that u - v*q_hat is negative, i.e., that
1161  // q_hat was one too large. So to get correct result, decrement q_hat and
1162  // add back one multiple of v
1163  if (borrow) {
1164  q_hat--;
1165  carry = 0;
1166  unsigned long sum;
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);
1170  u.data[u.count - v.count + i - 1 - j] = Data(sum);
1171  }
1172  u.data[u.count - v.count + i - 1 - j] = rslt.data[i] + carry;
1173  }
1174  else { // otherwise, result is ok
1175  for (i = 0; i < rslt.count; ++i) // store result back into u
1176  u.data[u.count - v.count + i - 1 - j] = rslt.data[i];
1177  }
1178  return q_hat; // return corrected q_hat
1179 }
1180 
1181 //: divide b2 into b1, getting quotient q and remainder r.
1182 // (Refer to Knuth, V.2, Section 4.3.1, Algorithm D for details.
1183 // This function implements Algorithm D.)
1184 // - Inputs: references to a vnl_bignum dividend b1, divisor b2, quotient q, and
1185 // remainder r.
1186 
1187 void divide(const vnl_bignum& b1, const vnl_bignum& b2, vnl_bignum& q, vnl_bignum& r)
1188 {
1189  // Note that q or r may *not* be identical to either b1 or b2 !
1190  assert(&b1 != &q && &b2 != &q && &b1 != &r && &b2 != &r);
1191  q = r = 0L;
1192  if (b1 == 0L) // If divisor is zero
1193  return; // return zero quotient and remainder
1194  int mag = magnitude_cmp(b1,b2); // Compare magnitudes
1195  if (mag < 0) // if abs(b1) < abs(b2)
1196  r = b1; // return zero quotient, b1 remainder
1197  else if (mag == 0) // if abs(b1) == abs(b2)
1198  q = 1L; // quotient is 1, remainder is 0
1199  else { // otherwise abs(b1) > abs(b2), so divide
1200  q.resize(b1.count + 1u - b2.count); // Allocate quotient
1201  r.resize(b2.count); // Allocate remainder
1202  if (b2.count == 1) { // Single digit divisor?
1203  divide_aux(b1,b2.data[0],q,r.data[0]); // Do single digit divide
1204  }
1205  else { // Else full-blown divide
1206  vnl_bignum u,v;
1207 #ifdef DEBUG
1208  std::cerr << "\nvnl_bignum::divide: b1 ="; b1.dump(std::cerr);
1209  std::cerr << "vnl_bignum::divide: b2 ="; b2.dump(std::cerr);
1210 #endif
1211  Data d = normalize(b1,b2,u,v); // Set u = b1*d, v = b2*d
1212 #ifdef DEBUG
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);
1216 #endif
1217  Counter j = 0;
1218  while (j <= b1.count - b2.count) { // Main division loop
1219  Data q_hat = estimate_q_hat(u,v,j); // Estimate # times v divides u
1220  q.data[q.count - 1 - j] = // Do division, get true answ.
1221  multiply_subtract(u,v,q_hat,j);
1222  j++;
1223 #ifdef DEBUG
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);
1226 #endif
1227  }
1228  static Data dufus; // dummy variable
1229  divide_aux(u,d,r,dufus); // Unnormalize u for remainder
1230 
1231 #ifdef DEBUG
1232  std::cerr << "vnl_bignum::divide: q = "; q.dump(std::cerr);
1233  std::cerr << "vnl_bignum::divide: r = "; r.dump(std::cerr);
1234 #endif
1235  }
1236  q.trim(); // Trim leading zeros of quot.
1237  r.trim(); // Trim leading zeros of rem.
1238  }
1239  q.sign = r.sign = b1.sign * b2.sign; // Calculate signs
1240 }
1241 
1242 //: left shift (arithmetic) non-infinite vnl_bignum by positive number.
1243 // - Inputs: reference to vnl_bignum, positive shift value
1244 // - Outputs: vnl_bignum, multiplied by the corresponding power of two
1245 
1247 {
1248  // to carry out this arithmetic left shift, we cheat. Instead of physically
1249  // shifting the data array l bits to the left, we shift just enough to get
1250  // the correct word alignment, and then pad the array on the right with as
1251  // many zeros as we need.
1252  vnl_bignum rslt; // result of shift
1253  rslt.sign = b1.sign; // result follows sign of input
1254  auto growth = Counter(l / 16); // # of words rslt will grow by
1255  Data shift = Data(l % 16); // amount to actually shift
1256  Data rshift = Data(16 - shift); // amount to shift next word by
1257  Data carry = Data( // value that will be shifted
1258  b1.data[b1.count - 1] >> (16 - shift));// out end of current array
1259  rslt.resize(b1.count + growth + (carry ? 1u : 0u)); // allocate new data array
1260  Counter i = 0;
1261  while (i < growth) // zero out padded elements
1262  rslt.data[i++] = 0;
1263  rslt.data[i++] = b1.data[0] << shift; // shift first non-zero element
1264  while (i < rslt.count - 1) { // for remaining data words
1265  rslt.data[i] = (b1.data[i - growth] << shift) + // shift current data word
1266  (b1.data[i - 1 - growth] >> rshift); // propagate adjacent
1267  i++; // carry into current word
1268  }
1269  if (i < rslt.count) {
1270  if (carry) // if last word had overflow
1271  rslt.data[i] = carry; // store it new data
1272  else // otherwise,
1273  rslt.data[i] = (b1.data[i - growth] << shift) // do like the rest
1274  + (b1.data[i - 1 - growth] >> rshift);
1275  }
1276  vnl_bignum& result = *((vnl_bignum*) &rslt);// same physical object
1277  return result; // shallow swap on return
1278 }
1279 
1280 //: right shift (arithmetic) non-infinite vnl_bignum by positive number.
1281 // - Inputs: reference to vnl_bignum, positive shift value
1282 // - Outputs: vnl_bignum, divided by the corresponding power of two
1283 
1285 {
1286  vnl_bignum rslt; // result of shift
1287  auto shrinkage = Counter(l / 16); // # of words rslt will shrink
1288  Data shift = Data(l % 16); // amount to actually shift
1289  Data dregs = Data(b1.data[b1.count-1] >> shift);// high end data to save
1290  if (shrinkage + (dregs == 0) < b1.count) { // if not all data shifted out
1291  rslt.sign = b1.sign; // rslt follows sign of input
1292  rslt.resize(b1.count - shrinkage - (dregs == 0 ? 1 : 0)); // allocate new data
1293  Data lshift = Data(16 - shift); // amount to shift high word
1294  Counter i = 0;
1295  while (i < rslt.count - 1) { // shift current word
1296  rslt.data[i] = (b1.data[i + shrinkage] >> shift) + // propagate adjacent
1297  (b1.data[i + shrinkage + 1u] << lshift); // word into current word
1298  i++;
1299  }
1300  if (dregs) // don't lose dregs
1301  rslt.data[i] = dregs;
1302  else {
1303  rslt.data[i] = (b1.data[i + shrinkage] >> shift) +
1304  (b1.data[i + shrinkage + 1u] << lshift);
1305  }
1306  }
1307  vnl_bignum& result = *((vnl_bignum*) &rslt); // same physical object
1308  return result; // shallow swap on return
1309 }
bool operator<(vnl_bignum const &) const
Compares two vnl_bignums.
Definition: vnl_bignum.cxx:605
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.
Definition: vnl_bignum.cxx:541
vnl_bignum & operator--()
decrement.
Definition: vnl_bignum.cxx:455
void resize(short)
change the data allotment for a vnl_bignum.
Definition: vnl_bignum.cxx:841
vnl_bignum()
Creates a zero vnl_bignum.
Definition: vnl_bignum.cxx:20
unsigned short Data
Definition: vnl_bignum.cxx:16
unsigned short count
Definition: vnl_bignum.h:146
void decrement(vnl_bignum &bnum)
Subtract 1 from bnum (unsigned, non-infinite, non-zero).
Definition: vnl_bignum.cxx:969
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.
Definition: vnl_bignum.cxx:524
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.
Definition: vnl_bignum.cxx:572
unsigned short Counter
Definition: vnl_bignum.cxx:15
bool is_infinity() const
Definition: vnl_bignum.h:234
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.
Definition: vnl_bignum.cxx:887
int dtoBigNum(const char *s)
Converts decimal string to a vnl_bignum.
Definition: vnl_bignum.cxx:771
int magnitude_cmp(const vnl_bignum &b1, const vnl_bignum &b2)
compare absolute values of two vnl_bignums.
Definition: vnl_bignum.cxx:988
void otoBigNum(const char *s)
convert octal string to vnl_bignum.
Definition: vnl_bignum.cxx:827
friend void add(const vnl_bignum &, const vnl_bignum &, vnl_bignum &)
add two non-infinite vnl_bignum values and save their sum.
Definition: vnl_bignum.cxx:887
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.
Definition: vnl_decnum.h:393
Infinite precision integers.
Definition: vnl_bignum.h:143
bool is_plus_infinity() const
Definition: vnl_bignum.h:235
#define v
Definition: vnl_vector.h:42
vnl_bignum operator+() const
Definition: vnl_bignum.h:176
void subtract(const vnl_bignum &bmax, const vnl_bignum &bmin, vnl_bignum &diff)
subtract bmin from bmax (unsigned, non-infinite), result in diff.
Definition: vnl_bignum.cxx:947
void exptoBigNum(const char *s)
convert exponential string to a vnl_bignum.
Definition: vnl_bignum.cxx:789
vnl_bignum operator-() const
Returns the negation of a vnl_bignum.
Definition: vnl_bignum.cxx:426
vnl_bignum & operator++()
prefix increment (++b).
Definition: vnl_bignum.cxx:436
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.
Definition: vnl_bignum.cxx:744
bool isfinite(vnl_bignum const &x)
Definition: vnl_bignum.h:436
void increment(vnl_bignum &bnum)
Add 1 to bnum (unsigned, non-infinite).
Definition: vnl_bignum.cxx:928
std::string & vnl_bignum_to_string(std::string &s, const vnl_bignum &b)
Convert the number to a decimal representation in a string.
Definition: vnl_bignum.cxx:643
vnl_decnum pow(vnl_decnum const &x, unsigned long p)
Definition: vnl_decnum.h:402
unsigned short * data
Definition: vnl_bignum.h:148
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.
Definition: vnl_bignum.cxx:667
friend void decrement(vnl_bignum &bnum)
Subtract 1 from bnum (unsigned, non-infinite, non-zero).
Definition: vnl_bignum.cxx:969
vnl_bignum & operator=(const vnl_bignum &)
Copies rhs vnl_bignum to lhs vnl_bignum.
Definition: vnl_bignum.cxx:406
friend void increment(vnl_bignum &bnum)
Add 1 to bnum (unsigned, non-infinite).
Definition: vnl_bignum.cxx:928
vnl_bignum & operator *=(vnl_bignum const &r)
Multiplies this with a vnl_bignum.
Definition: vnl_bignum.cxx:503
VNL_EXPORT std::istream & operator>>(std::istream &s, vnl_decnum &r)
decimal input.
Definition: vnl_decnum.cxx:411
void xtoBigNum(const char *s)
convert hex string to vnl_bignum.
Definition: vnl_bignum.cxx:813
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.
Definition: vnl_bignum.cxx:557
bool operator==(vnl_bignum const &) const
Two vnl_bignums are equal if and only if they have the same integer representation.
Definition: vnl_bignum.cxx:587
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).
Definition: vnl_bignum.cxx:802
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.
Definition: vnl_bignum.cxx:988
~vnl_bignum()
Frees space for vnl_bignum.
Definition: vnl_bignum.cxx:399
bool is_minus_infinity() const
Definition: vnl_bignum.h:236
friend void subtract(const vnl_bignum &, const vnl_bignum &, vnl_bignum &)
subtract bmin from bmax (unsigned, non-infinite), result in diff.
Definition: vnl_bignum.cxx:947
vnl_bignum & trim()
trim non-infinite vnl_bignum of excess data allotment.
Definition: vnl_bignum.cxx:869