Documentation of CSL
precision_int.h
Go to the documentation of this file.
1 // This file is part of MARTY.
2 //
3 // MARTY is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // MARTY is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with MARTY. If not, see <https://www.gnu.org/licenses/>.
15 
23 #ifndef PRECISION_H_INCLUDED
24 #define PRECISION_H_INCLUDED
25 
26 #include <vector>
27 #include <iostream>
28 #include <cmath>
29 #include <csignal>
30 
31 namespace csl {
32 
33 extern size_t PRECISION;
34 
35 extern bool WARN_OVERFLOW;
36 
37 void fillDigits(const std::vector<short>& digits,
38  std::vector<short>& receiver);
39 
40 template<const size_t base>
41 long double log(long double x)
42 {
43 #include "math.h"
44  return log(x)/log((long double)base);
45 }
46 
47 char convertDigit(short digit);
48 
49 template<size_t base = 10>
50 class float_sap;
51 
52 template<size_t base = 10>
53 class int_ap{
54 
55  template<size_t t_base>
56  friend class float_sap;
57 
58  public:
59 
60  bool minusSign = false;
61 
62  std::vector<short> digits;
63 
64  public:
65 
66  int_ap();
67 
68  explicit
69  int_ap(long long int value);
70 
71  explicit
72  int_ap(const std::vector<short>& t_digits);
73 
74  explicit
75  int_ap(bool t_minusSign,
76  const std::vector<short>& t_digits);
77 
78  int_ap(const int_ap& other) = default;
79 
80  ~int_ap(){};
81 
82  int_ap<base>& operator=(long long int value);
83 
84  int_ap<base>& operator=(const int_ap<base>& value);
85 
86  template<size_t targetBase>
87  int_ap<targetBase> convert() const
88  {
89  int_ap<targetBase> res(0);
90  int_ap<base> target_ap(targetBase);
91  int_ap<targetBase> targetBasePower(1);
92  int_ap<base> X = *this;
93 
94  bool sign = false;
95  if (X.minusSign) {
96  sign = true;
97  X.setMinusSign(false);
98  }
99  while (X != 0) {
100  int_ap<base> divisor, rest;
101  divide(X, target_ap, divisor, rest);
102  X = divisor;
103  res += int_ap<targetBase>(rest.toCInteger()) * targetBasePower;
104  targetBasePower.shiftLeft();
105  }
106  res.setMinusSign(sign);
107 
108  return res;
109  }
110 
111  size_t size() const;
112 
113  bool empty() const;
114 
115  short operator[](size_t i) const;
116 
117  bool getMinusSign() const;
118 
119  void setMinusSign(bool t_minusSign);
120 
121  void flipSign();
122 
123  void flip(size_t i);
124 
125  int_ap flip() const;
126 
127  int_ap all() const;
128 
129  void shiftLeft(size_t n = 1);
130 
131  void shiftRight(size_t n = 1);
132 
133  void cut();
134 
135  void cutRight();
136 
137  long long int toCInteger() const;
138 
139  friend
140  std::ostream& operator<<(std::ostream& fout, const int_ap<base>& integer)
141  {
142  if (integer.minusSign)
143  fout << "-";
144  if (base == 16)
145  fout << "0x";
146  for (auto digit = integer.digits.rbegin();
147  digit != integer.digits.rend();
148  ++digit)
149  fout << convertDigit(*digit);
150 
151  return fout;
152  }
153 
154  friend
155  int_ap<base> operator+(long long int a, const int_ap<base>& b)
156  {
157  return int_ap<base>(a)+b;
158  }
159 
160  friend
161  int_ap<base> operator+(const int_ap<base>& a, long long int b)
162  {
163  return a+int_ap<base>(b);
164  }
165 
166  friend
167  int_ap<base> operator+(const int_ap<base>& a, const int_ap<base>& b)
168  {
169  int_ap<base> c = a;
170  return c += b;
171  }
172 
173  friend
174  int_ap<base>& operator+=(int_ap<base>& a, int_ap<base> b)
175  {
176  if (a.minusSign xor b.minusSign) {
177  if (b.minusSign) {
178  return a -= (-b);
179  }
180  else {
181  a.setMinusSign(false);
182  a -= b;
183  a.flipSign();
184  return a;
185  }
186  }
187  if (a.minusSign) {
188  a.setMinusSign(false);
189  a += (-b);
190  a = -a;
191  return a;
192  }
193  if (a.size() < b.size()) {
194  int_ap<base> c = std::move(a);
195  a = b;
196  return a += c;
197  }
198 
199  short retenue = 0;
200  const int n = b.digits.size();
201 
202  for (int i = 0; i < n; ++i) {
203  short sum = retenue + a.digits[i] + b.digits[i];
204  if (sum > (int)base-1) {
205  retenue = 1;
206  sum = sum % base;
207  }
208  else
209  retenue = 0;
210  a.digits[i] = sum;
211  }
212  for (int i = n; i < (int)a.digits.size(); ++i) {
213  short sum = retenue + a.digits[i];
214  if (sum > (int)base-1) {
215  retenue = 1;
216  sum = sum % base;
217  }
218  else
219  retenue = 0;
220  a.digits[i] = sum;
221  }
222  if (retenue != 0)
223  a.digits.push_back(retenue);
224 
225  return a;
226  }
227 
228  friend
229  int_ap<base>& operator+=(int_ap<base>& a, long long int b)
230  {
231  return a += int_ap<base>(b);
232  }
233 
234  friend
235  int_ap<base> operator-(long long int a, const int_ap<base>& b)
236  {
237  return int_ap<base>(a) - b;
238  }
239 
240  friend
241  int_ap<base> operator-(const int_ap<base>& a, long long int b)
242  {
243  return a - int_ap<base>(b);
244  }
245 
246  friend
247  int_ap<base> operator-(const int_ap<base>& a, const int_ap<base>& b)
248  {
249  int_ap<base> c = a;
250  return c -= b;
251  }
252 
253  friend
254  int_ap<base>& operator-=(int_ap<base>& a, int_ap<base> b)
255  {
256  if (a.minusSign xor b.minusSign) {
257  if (a.minusSign) {
258  a.setMinusSign(false);
259  a += b;
260  a.flipSign();
261  return a;
262  }
263  else {
264  return a += (-b);
265  }
266  }
267  if (a.minusSign) {
268  a.setMinusSign(false);
269  a -= (-b);
270  a.flipSign();
271  return a;
272  }
273  if (not (a > b)) {
274  if (a == b) {
275  a = 0;
276  return a;
277  }
278  int_ap<base> c = std::move(a);
279  a = b;
280  a -= c;
281  a.flipSign();
282  return a;
283  }
284  // Here a > 0, b > 0 and a > b
285  short retenue = 0;
286  for (size_t i = 0; i != b.size(); ++i) {
287  short res = base + a[i] - (b[i] + retenue);
288  a.digits[i] = res % base;
289  retenue = res < (int)base;
290  }
291  if (a.size() > b.size()) {
292  for (size_t j = b.size(); j != a.size(); ++j) {
293  if (retenue) {
294  if (a[j] == 0)
295  a.digits[j] = base - 1;
296  else {
297  a.digits[j] = a[j] - 1;
298  retenue = 0;
299  }
300  }
301  }
302  }
303  a.cut();
304 
305  return a;
306  }
307 
308  friend
309  int_ap<base>& operator-=(int_ap<base>& a, long long int b)
310  {
311  return a -= int_ap<base>(b);
312  }
313 
314  friend
315  int_ap<base> operator++(int_ap<base>& a, int)
316  {
317  int_ap<base> b = a;
318  a += 1;
319  return b;
320  }
321 
322  friend
323  int_ap<base>& operator++(int_ap<base>& a)
324  {
325  a += 1;
326  return a;
327  }
328 
329  friend
330  int_ap<base> operator--(int_ap<base>& a, int)
331  {
332  int_ap<base> b = a;
333  a -= 1;
334  return b;
335  }
336 
337  friend
338  int_ap<base>& operator--(int_ap<base>& a)
339  {
340  a -= 1;
341  return a;
342  }
343 
344  friend
345  int_ap<base> operator-(const int_ap<base>& a)
346  {
347  return int_ap<base>(not a.minusSign or a == 0,
348  a.digits);
349  }
350 
351  friend
352  int_ap<base> operator*(long long int a, const int_ap<base>& b)
353  {
354  return int_ap<base>(a)*b;
355  }
356 
357  friend
358  int_ap<base> operator*(const int_ap<base>& a, long long int b)
359  {
360  return a*int_ap<base>(b);
361  }
362 
363  friend
364  int_ap<base> operator*(const int_ap<base>& a, const int_ap<base>& b)
365  {
366  int_ap<base> c = a;
367  return c *= b;
368  }
369 
370  friend
371  int_ap<base>& operator*=(int_ap<base>& a, long long int b)
372  {
373  return a *= int_ap<base>(b);
374  }
375 
376  friend
377  int_ap<base>& operator*=(int_ap<base>& a, int_ap<base> b)
378  {
379  std::vector<short> newDigits(0);
380  int_ap<base> res;
381  for (size_t i = 0; i != a.digits.size(); ++i) {
382  std::vector<short> intermediateDigits(i,0);
383  short retenue = 0;
384  for (size_t j = 0; j != b.digits.size(); ++j) {
385  int product = retenue + a.digits[i]*b.digits[j];
386  if (product > (int)base-1) {
387  retenue = product / base;
388  product = product % base;
389  }
390  else
391  retenue = 0;
392  intermediateDigits.push_back(product);
393  }
394  if (retenue != 0)
395  intermediateDigits.push_back(retenue);
396 
397  res += int_ap<base>(intermediateDigits);
398  }
399  a.digits = res.digits;
400  a.setMinusSign(a.minusSign xor b.minusSign);
401 
402  return a;
403  }
404 
405  friend
406  int_ap<base> operator/(const int_ap<base>& a, const int_ap<base>& b)
407  {
408  int_ap<base> res, rest;
409  divide(a, b, res, rest);
410  return res;
411  }
412 
413  friend
414  void divide(int_ap<base> a,
415  int_ap<base> b,
416  int_ap<base>& result,
417  int_ap<base>& rest)
418  {
419  if (abs(a) < abs(b)) {
420  result = int_ap<base>(0);
421  rest = a;
422  return;
423  }
424  if (b == 0) {
425  std::cout << "Division by 0 encountered in int_ap<"
426  << base << ">.\n";
427  std::raise(SIGFPE);
428  }
429  bool sign = a.minusSign xor b.minusSign;
430  bool signA = a.minusSign;
431  a.minusSign = false;
432  b.minusSign = false;
433 
434  std::vector<short> a_digits;
435  b.shiftLeft();
436  int nDigits = 0;
437  while (a > b) {
438  a_digits.push_back(a.digits[0]);
439  a.shiftRight();
440  ++nDigits;
441  }
442  b.shiftRight();
443 
444  int_ap<base> prod(0);
445  int_ap<base> divisor(0);
446  for (size_t i = 0; i != base; ++i) {
447  int_ap<base> foo = prod + b;
448  if (foo > a)
449  break;
450  prod = foo;
451  ++divisor;
452  }
453  rest = a - prod;
454 
455  rest.shiftLeft(nDigits);
456  divisor.shiftLeft(nDigits);
457 
458  if (a_digits.empty()) {
459  result = divisor;
460  }
461  else {
462  rest += int_ap(a_digits);
463  divide(rest, b, result, rest);
464  result += divisor;
465  }
466  result.setMinusSign(sign);
467  rest .setMinusSign(signA);
468  }
469 
470  friend
471  void dividePrecision(int_ap<base> a,
472  int_ap<base> b,
473  int_ap<base>& result,
474  int_ap<base>& exponent)
475  {
476  result = int_ap<base>(0);
477  int_ap<base> rest;
478  // std::cout << "b = " << b << std::endl;
479  divide(a, b, result, rest);
480  exponent = int_ap<base>(result.size());
481  while (rest != 0 and result.digits.size()+1 < PRECISION) {
482  --exponent;
483  result.shiftLeft();
484  rest.shiftLeft();
485  int_ap<base> intermediate;
486  divide(rest, b, intermediate, rest);
487  result += intermediate;
488  }
489  }
490 
491  friend
492  int_ap<base> operator/(const int_ap<base>& a, long long int b)
493  {
494  return a / int_ap<base>(b);
495  }
496 
497  friend
498  int_ap<base> operator/(long long int a, const int_ap<base>& b)
499  {
500  return int_ap<base>(a) / b;
501  }
502 
503  friend
504  int_ap<base>& operator/=(int_ap<base>& a, long long int b)
505  {
506  return a /= int_ap<base>(b);
507  }
508 
509  friend
510  int_ap<base>& operator/=(int_ap<base>& a, const int_ap<base>& b)
511  {
512  return a = (a / b);
513  }
514 
515  friend
516  int_ap<base> operator%(const int_ap<base>& a, const int_ap<base>& b)
517  {
518  int_ap<base> divisor, rest;
519  divide(a, b, divisor, rest);
520 
521  return rest;
522  }
523 
524  friend
525  int_ap<base> operator%(const int_ap<base>& a, long long int b)
526  {
527  return a % int_ap<base>(b);
528  }
529 
530  friend
531  int_ap<base> operator%(long long int a, const int_ap<base>& b)
532  {
533  return int_ap<base>(a) % b;
534  }
535 
536  friend
537  int_ap<base>& operator%=(int_ap<base>& a, long long int b)
538  {
539  return a %= int_ap<base>(b);
540  }
541 
542  friend
543  int_ap<base>& operator%=(int_ap<base>& a, const int_ap<base>& b)
544  {
545  return a = (a % b);
546  }
547 
548  friend
549  int_ap<base> pow(long long int a, const int_ap<base>& b)
550  {
551  return pow(int_ap<base>(a), b);
552  }
553 
554  friend
555  int_ap<base> pow(const int_ap<base>& a, long long int b)
556  {
557  return pow(a, int_ap<base>(b));
558  }
559 
560  friend
561  int_ap<base> pow(const int_ap<base>& a, const int_ap<base>& b)
562  {
563  if (b <= 0) {
564  if (a != 0 and b == 0)
565  return int_ap<base>(1);
566  return int_ap<base>(0);
567  }
568  if (b == 1)
569  return a;
570  int_ap<base> res = a;
571  int_ap<base> totalPow(1);
572  while (true) {
573  if (totalPow*2 <= b) {
574  res *= res;
575  totalPow *= 2;
576  }
577  else if (totalPow == b)
578  return res;
579  else {
580  return res *= pow(a, b-totalPow);
581  }
582  }
583  }
584 
585  friend
586  int_ap<base> abs(const int_ap<base>& a)
587  {
588  int_ap<base> b(a);
589  b.minusSign = false;
590  return b;
591  }
592 
593  friend
594  bool operator==(long long int a, const int_ap<base>& b)
595  {
596  return int_ap<base>(a)==b;
597  }
598 
599  friend
600  bool operator==(const int_ap<base>& a, long long int b)
601  {
602  return a==int_ap<base>(b);
603  }
604 
605  friend
606  bool operator==(const int_ap<base>& a, const int_ap<base>& b)
607  {
608  if (a.minusSign != b.minusSign)
609  return false;
610  if (a.digits.size() != b.digits.size())
611  return false;
612 
613  for (size_t i = 0; i != a.digits.size(); ++i)
614  if (a.digits[i] != b.digits[i])
615  return false;
616  return true;
617  }
618 
619  friend
620  bool operator!=(long long int a, const int_ap<base>& b)
621  {
622  return int_ap<base>(a)!=b;
623  }
624 
625  friend
626  bool operator!=(const int_ap<base>& a, long long int b)
627  {
628  return a!=int_ap<base>(b);
629  }
630 
631  friend
632  bool operator!=(const int_ap<base>& a, const int_ap<base>& b)
633  {
634  return not (a == b);
635  }
636 
637  friend
638  bool operator<(long long int a, const int_ap<base>& b)
639  {
640  return int_ap<base>(a)<b;
641  }
642 
643  friend
644  bool operator<(const int_ap<base>& a, long long int b)
645  {
646  return a<int_ap<base>(b);
647  }
648 
649  friend
650  bool operator<(const int_ap<base>& a, const int_ap<base>& b)
651  {
652  if (a.minusSign != b.minusSign)
653  return a.minusSign;
654  if (a.minusSign)
655  return -a > -b;
656  if (a.digits.size() < b.digits.size())
657  return true;
658  if (b.digits.size() < a.digits.size())
659  return false;
660  for (size_t i = a.size(); i --> 0 ;) {
661  if (a.digits[i] < b.digits[i])
662  return true;
663  else if (b.digits[i] != a.digits[i])
664  return false;
665  }
666  return false;
667  }
668 
669  friend
670  bool operator<=(long long int a, const int_ap<base>& b)
671  {
672  return (a<b or a==b);
673  }
674 
675  friend
676  bool operator<=(const int_ap<base>& a, long long int b)
677  {
678  return (a<b or a==b);
679  }
680 
681  friend
682  bool operator<=(const int_ap<base>& a, const int_ap<base>& b)
683  {
684  return (a<b or a==b);
685  }
686 
687  friend
688  bool operator>(long long int a, const int_ap<base>& b)
689  {
690  return int_ap<base>(a)>b;
691  }
692 
693  friend
694  bool operator>(const int_ap<base>& a, long long int b)
695  {
696  return a>int_ap<base>(b);
697  }
698 
699  friend
700  bool operator>(const int_ap<base>& a, const int_ap<base>& b)
701  {
702  return b < a;
703  }
704 
705  friend
706  bool operator>=(long long int a, const int_ap<base>& b)
707  {
708  return (a>b or a==b);
709  }
710 
711  friend
712  bool operator>=(const int_ap<base>& a, long long int b)
713  {
714  return (a>b or a==b);
715  }
716 
717  friend
718  bool operator>=(const int_ap<base>& a, const int_ap<base>& b)
719  {
720  return (a>b or a==b);
721  }
722 
723 };
724 
725 template<size_t base>
726 int_ap<base>::int_ap(): digits(std::vector<short>(1,0)){}
727 
728 template<size_t base>
729 int_ap<base>::int_ap(long long int value)
730 {
731  *this = value;
732  cut();
733 }
734 
735 template<size_t base>
736 int_ap<base>::int_ap(const std::vector<short>& t_digits)
737 {
738  fillDigits(t_digits, digits);
739  cut();
740 }
741 
742 template<size_t base>
743 int_ap<base>::int_ap(bool t_minusSign,
744  const std::vector<short>& t_digits)
745 {
746  fillDigits(t_digits, digits);
747  cut();
748  setMinusSign(t_minusSign);
749 }
750 
751 template<size_t base>
752 size_t int_ap<base>::size() const
753 {
754  return digits.size();
755 }
756 
757 template<size_t base>
758 bool int_ap<base>::empty() const
759 {
760  return digits.empty();
761 }
762 
763 template<size_t base>
764 short int_ap<base>::operator[](size_t i) const
765 {
766  return digits[i];
767 }
768 
769 template<size_t base>
770 bool int_ap<base>::getMinusSign() const
771 {
772  return minusSign;
773 }
774 
775 template<size_t base>
776 void int_ap<base>::setMinusSign(bool t_minusSign)
777 {
778  minusSign = t_minusSign;
779  if (minusSign and digits.size() == 1 and digits[0] == 0)
780  // -0 = 0
781  minusSign = false;
782 }
783 
784 template<size_t base>
786 {
787  setMinusSign(not minusSign);
788 }
789 
790 template<size_t base>
791 void int_ap<base>::flip(size_t i)
792 {
793  digits[i] = base - digits[i];
794 }
795 
796 template<size_t base>
798 {
799  std::vector<short> newDigits(digits.size());
800  for (size_t i = 0; i != digits.size(); ++i)
801  newDigits[i] = base - digits[i];
802  return int_ap<base>(minusSign, newDigits);
803 }
804 
805 template<size_t base>
807 {
808  return int_ap<base>(minusSign, std::vector<short>(digits.size(), base-1));
809 }
810 
811 template<size_t base>
812 void int_ap<base>::cut()
813 {
814  for (size_t i = digits.size(); i --> 0 ;)
815  if (digits[i] != 0) {
816  if (i+1 <= digits.size()-1)
817  digits.erase(digits.begin()+i+1,digits.end());
818  return;
819  }
820  digits = std::vector<short>(1, 0);
821 }
822 
823 template<size_t base>
825 {
826  for (size_t i = 0; i != digits.size(); ++i)
827  if (digits[i] != 0) {
828  if (i > 0)
829  digits.erase(digits.begin(), digits.begin()+i);
830  return;
831  }
832  digits = std::vector<short>(1, 0);
833 }
834 
835 template<size_t base>
836 void int_ap<base>::shiftLeft(size_t n)
837 {
838  if (*this == 0)
839  return;
840  std::vector<short> newDigits = std::vector<short>(n ,0);
841  digits.insert(digits.begin(), newDigits.begin(), newDigits.end());
842 }
843 
844 template<size_t base>
845 void int_ap<base>::shiftRight(size_t n)
846 {
847  if (n > digits.size())
848  n = digits.size();
849  digits.erase(digits.begin(), digits.begin()+n);
850 }
851 
852 template<size_t base>
853 int_ap<base>& int_ap<base>::operator=(long long int value)
854 {
855  digits.clear();
856  minusSign = false;
857  if (value < 0) {
858  value = -value;
859  minusSign = true;
860  }
861  if (value < (int)base)
862  digits = std::vector<short>(1);
863  else if (value != 0)
864  digits = std::vector<short>(1 + floor(log<base>((value))));
865  for (size_t i = 0; i != digits.size(); ++i) {
866  int digit = value % base;
867  digits[i] = digit;
868  value -= digit;
869  value /= base;
870  }
871 
872  return *this;
873 }
874 
875 template<size_t base>
877 {
878  minusSign = value.minusSign;
879  digits = value.digits;
880  return *this;
881 }
882 
883 template<size_t base>
884 int_ap<base> factorial(const int_ap<base>& number)
885 {
886  int_ap<base> res(1);
887  for (int_ap<base> i(2); i <= number; i = i+1)
888  res = i*res;
889 
890  return res;
891 }
892 
893 template<size_t base>
894 long long int int_ap<base>::toCInteger() const
895 {
896  if (abs(*this) > pow(int_ap<base>(2), int_ap<base>(63))) {
897  std::cout << "Error: getting C++ integer for a number bigger than"
898  << " 2^63.";
899  std::raise(SIGTERM);
900  }
901  long long int res = 0;
902  for (auto iter = digits.rbegin(); iter != digits.rend(); ++iter)
903  res = base * res + *iter;
904 
905  return res;
906 }
907 
908 template<>
909 class int_ap<0> {
910  public:
911  int_ap<0>() = delete;
912 };
913 
914 template<>
915 class int_ap<1> {
916  public:
917  int_ap<1>() = delete;
918 };
919 
920 } // End of namespace csl
921 
922 #endif
Namespace for csl library.
Definition: abreviation.h:34
Definition: precision_int.h:53
Expr operator+(const Expr &a, const Expr &b)
Shortcut function that allows to use arithmetic operator + with Expr (== shared_ptr<Abstract>).
Definition: abstract.cpp:1298
Definition: precision_int.h:915
bool operator>(const Expr &a, const Expr &b)
see Abstract::operator>()
Definition: abstract.cpp:1419
bool operator>=(const Expr &a, const Expr &b)
see Abstract::operator>=()
Definition: abstract.cpp:1413
Definition: precision_int.h:909
Definition: precision_float.h:63
Expr operator/(const Expr &a, const Expr &b)
Shortcut function that allows to use arithmetic operator / with Expr (== shared_ptr<Abstract>).
Definition: abstract.cpp:1372
Expr operator*(const Expr &a, const Expr &b)
Shortcut function that allows to use arithmetic operator * with Expr (== shared_ptr<Abstract>).
Definition: abstract.cpp:1351
bool operator==(const Expr &a, const Expr &b)
see Abstract::operator==()
Definition: abstract.cpp:1398
bool operator!=(const Expr &a, const Expr &b)
see Abstract::operator!=()
Definition: abstract.cpp:1404