plll  1.0
rational.hpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2011-2014 University of Zurich
3 
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21 */
22 
23 #ifndef PLLL_INCLUDE_GUARD__RATIONAL_HPP
24 #define PLLL_INCLUDE_GUARD__RATIONAL_HPP
25 
26 #include <plll/arithmetic.hpp>
27 #include "helper.hpp"
28 #include <sstream>
29 #include <cassert>
30 #include <cmath>
31 
42 namespace plll
43 {
44  namespace arithmetic
45  {
46  class Rational;
47  class RationalContext;
48 
58  inline bool isZero(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
59 
66  inline bool isOne(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
67 
74  inline bool isPositive(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
75 
82  inline bool isNonNegative(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
83 
90  inline bool isNegative(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
91 
98  inline bool isNonPositive(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
100 
111  inline void add(Rational & r, const Rational & a, const Rational & b);
112 
120  inline void sub(Rational & r, const Rational & a, const Rational & b);
121 
129  inline void addmul(Rational & r, const Rational & a, const Rational & b);
130 
138  inline void submul(Rational & r, const Rational & a, const Rational & b);
139 
147  inline void mul(Rational & r, const Rational & a, const Rational & b);
148 
156  inline void div(Rational & r, const Rational & a, const Rational & b);
157 
165  inline void mod(Rational & r, const Rational & a, const Rational & b);
166 
174  inline void shl(Rational & r, const Rational & a, long b);
175 
183  inline void shr(Rational & r, const Rational & a, long b);
184 
191  inline void increment(Rational & r, const Rational & a);
192 
199  inline void decrement(Rational & r, const Rational & a);
200 
207  inline void neg(Rational & r, const Rational & a);
208 
215  inline void abs(Rational & r, const Rational & a);
216 
223  inline void square(Rational & r, const Rational & a);
225 
234  inline void makeAbs(Rational & a) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
236 
243  std::ostream & operator << (std::ostream & s, const Rational & r);
244 
248  std::istream & operator >> (std::istream & s, Rational & r);
250 
263  inline void setZero(Rational & r, bool sign = true);
264 
270  inline void setOne(Rational & r);
272 
284  inline int compare(const Rational & a, const Rational & b);
285 
294  inline int compareAbsValues(const Rational & a, const Rational & b);
296 
307  inline int sign(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
309 
320  inline void power(Rational & r, const Rational & a, signed long e);
321 
329  inline void power(Rational & r, const Rational & a, unsigned long e);
330 
338  void power(Rational & r, const Rational & a, const Integer & e);
340 
347  inline void swap(Rational &, Rational &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
349 
356  // Emulates RealContext
357  {
358  friend class Rational;
359 
360  enum { d_precision = 21474836479 }; // should be std::numeric_limits<unsigned long>::max(), but that is not working in enums.
361 
362  public:
366  typedef Rational Real;
370  typedef Rational Type;
371 
375  enum { is_cputype = false, is_realtype = true, is_inttype = false, is_exact = true, is_variable_precision = false,
376  has_squareroot = false, has_full_power = false, has_special_fns = false, has_huge_exponent = true,
377  has_infinity = false, has_uniform_rng = false, has_constants = false, has_trigonometric = false };
378 
382  inline RationalContext() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
383  {
384  }
385 
393  static inline void setRealPrecision(unsigned long prec) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
394  {
395  }
396 
402  static inline unsigned long getRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
403  {
404  return d_precision;
405  }
406 
412  static inline unsigned long getMinRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
413  {
414  return d_precision;
415  }
416 
422  static inline unsigned long getMaxRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE // returns maximal value for precision
423  {
424  return d_precision;
425  }
426  };
427 
431  class Rational
432  {
433 #ifndef PLLL_INTERNAL_NO_TEMPLATE_FRIENDS
434  template<class X, class Y>
435  friend class implementation::conversion_impl;
436 
437  friend class implementation::nativeconversion_impl<Rational>;
438 
439  private:
440 #else
441  public:
442 #endif
443 
444  Integer d_num, d_denom; // the denominator is always positive (and in particular, non-zero!)
445 
446  inline void normalize()
447  {
448  Integer d = GCD(d_num, d_denom);
449  if (!isOne(d))
450  {
451  d_num /= d;
452  d_denom /= d;
453  }
454  }
455 
456  void initFromDouble(double d)
457  {
458  const int MantissaBitsInDouble = std::numeric_limits<double>::digits + 2;
459  int e;
460  d = std::frexp(d, &e);
461  // Now 0.5 <= d < 1
462  convert(d_num, std::ldexp(d, MantissaBitsInDouble), IntegerContext());
463  setOne(d_denom);
464  // Add exponent
465  shl(*this, *this, e - MantissaBitsInDouble);
466  }
467 
468  void initFromDouble(long double d)
469  {
470  const int MantissaBitsInDouble = std::numeric_limits<long double>::digits + 2;
471  int e;
472  d = std::frexp(d, &e);
473  // Now 0.5 <= d < 1
474  convert(d_num, std::ldexp(d, MantissaBitsInDouble), IntegerContext());
475  setOne(d_denom);
476  // Add exponent
477  shl(*this, *this, e - MantissaBitsInDouble);
478  }
479 
480  public:
481  typedef RationalContext Context;
482 
488  inline const Integer & numerator() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
489  {
490  return d_num;
491  }
492 
498  inline const Integer & denominator() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
499  {
500  return d_denom;
501  }
502 
506  inline Rational()
507  {
508  setZero(d_num);
509  setOne(d_denom);
510  }
511 
512 #if __cplusplus >= 201103L
513 
519  inline Rational(Rational && r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
520  : d_num(std::move(r.d_num)), d_denom(std::move(r.d_denom))
521  {
522  }
523 
529  Rational & operator = (Rational && r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
530  {
531  d_num = std::move(r.d_num);
532  d_denom = std::move(r.d_denom);
533  return *this;
534  }
535 #endif
536 
542  inline Rational(const RationalContext & rc)
543  {
544  setZero(d_num);
545  setOne(d_denom);
546  }
547 
553  inline Rational(const Rational & r)
554  : d_num(r.d_num), d_denom(r.d_denom)
555  {
556  }
557 
564  inline Rational(const Rational & r, const RationalContext & rc)
565  : d_num(r.d_num), d_denom(r.d_denom)
566  {
567  }
568 
574  template<class A, template<typename, typename> class O>
576  {
577  E.assignTo(*this);
578  }
579 
586  static inline unsigned long precision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
587  {
588  return RationalContext::d_precision;
589  }
590 
598  static inline void setContext(const RationalContext & rc) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
599  {
600  }
601 
607  inline explicit Rational(double d)
608  {
609  initFromDouble(d);
610  }
611 
618  inline explicit Rational(double d, const RationalContext & rc)
619  {
620  initFromDouble(d);
621  }
622 
628  inline explicit Rational(long double d)
629  {
630  initFromDouble(d);
631  }
632 
639  inline explicit Rational(long double d, const RationalContext & rc)
640  {
641  initFromDouble(d);
642  }
643 
649  inline explicit Rational(long i)
650  : d_num(i)
651  {
652  setOne(d_denom);
653  }
654 
661  inline explicit Rational(long i, const RationalContext & rc)
662  : d_num(i)
663  {
664  setOne(d_denom);
665  }
666 
672  inline explicit Rational(unsigned long i)
673  : d_num(i)
674  {
675  setOne(d_denom);
676  }
677 
684  inline explicit Rational(unsigned long i, const RationalContext & rc)
685  : d_num(i)
686  {
687  setOne(d_denom);
688  }
689 
695  inline explicit Rational(long long i)
696  : d_num(i)
697  {
698  setOne(d_denom);
699  }
700 
707  inline explicit Rational(long long i, const RationalContext & rc)
708  : d_num(i)
709  {
710  setOne(d_denom);
711  }
712 
720  inline explicit Rational(const Integer & n, const Integer & d)
721  : d_num(n), d_denom(d)
722  {
723  if (sign(d) < 0)
724  {
725  neg(d_denom, d_denom);
726  neg(d_num, d_num);
727  }
728  normalize();
729  }
730 
737  inline explicit Rational(const Integer & i)
738  : d_num(i)
739  {
740  setOne(d_denom);
741  }
742 
743  template<class Data, template<typename, typename> class Op>
745  : d_num(i)
746  {
747  setOne(d_denom);
748  }
749 
756  inline explicit Rational(const Integer & i, const RationalContext & rc)
757  : d_num(i)
758  {
759  setOne(d_denom);
760  }
761 
762  template<class Data, template<typename, typename> class Op>
763  inline explicit Rational(const expressions::Expression<IntegerContext, Data, Op> & i, const RationalContext & rc)
764  : d_num(i)
765  {
766  setOne(d_denom);
767  }
768 
775  inline Rational & operator = (const Rational & r)
776  {
777  d_num = r.d_num;
778  d_denom = r.d_denom;
779  return *this;
780  }
781 
788  template<class A, template<typename, typename> class O>
790  {
791  E.assignTo(*this);
792  return *this;
793  }
794 
801  template<class A, template<typename, typename> class O>
803  {
804  E.assignTo(d_num);
805  setOne(d_denom);
806  return *this;
807  }
808 
809  inline friend bool isZero(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
810  {
811  return isZero(r.d_num);
812  }
813 
814  inline friend bool isOne(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
815  {
816  return isOne(r.d_num) && isOne(r.d_denom);
817  }
818 
819  inline friend bool isPositive(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
820  {
821  return isPositive(r.d_num);
822  }
823 
824  inline friend bool isNonNegative(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
825  {
826  return isNonNegative(r.d_num);
827  }
828 
829  inline friend bool isNegative(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
830  {
831  return isNegative(r.d_num);
832  }
833 
834  inline friend bool isNonPositive(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
835  {
836  return isNonPositive(r.d_denom);
837  }
838 
839  private:
840  inline void add_r_neq_1st(const Rational & a, const Rational & b)
841  // Adds a and b and stores result in *this. Assumes that this != &a.
842  {
843  Integer g1;
844  GCD(g1, a.d_denom, b.d_denom);
845  if (isOne(g1))
846  {
847  d_num = b.d_num * a.d_denom;
848  d_num += a.d_num * b.d_denom;
849  d_denom = a.d_denom * b.d_denom;
850  }
851  else
852  {
853  Integer t = a.d_denom / g1;
854  d_num = b.d_num * t;
855  t = b.d_denom / g1;
856  d_num += a.d_num * t;
857  d_denom = a.d_denom * t;
858  }
859  normalize();
860  }
861 
862  inline void sub_r_neq_1st(const Rational & a, const Rational & b, bool compute_negative)
863  // Subtracts b from a and stores result in *this. Assumes that this != &a.
864  {
865  Integer g1;
866  GCD(g1, a.d_denom, b.d_denom);
867  if (isOne(g1))
868  {
869  d_num = b.d_num * a.d_denom;
870  d_num -= a.d_num * b.d_denom;
871  d_denom = a.d_denom * b.d_denom;
872  }
873  else
874  {
875  Integer t = a.d_denom / g1;
876  d_num = b.d_num * t;
877  t = b.d_denom / g1;
878  d_num -= a.d_num * t;
879  d_denom = a.d_denom * t;
880  }
881  if (!compute_negative)
882  d_num = -d_num;
883  normalize();
884  }
885 
886  public:
887  inline friend void add(Rational & r, const Rational & a, const Rational & b)
888  {
889  if (&r == &a)
890  {
891  if (&r == &b)
892  {
893  // r == a == b, i.e. multiply r by 2
894  if (bit(r.d_denom, 0))
895  r.d_denom >>= 1;
896  else
897  r.d_num <<= 1;
898  }
899  else
900  r.add_r_neq_1st(b, a);
901  }
902  else
903  r.add_r_neq_1st(a, b);
904  }
905 
906  template<typename IntIntExpr>
907  inline friend void add_z(Rational & r, const Rational & a, const IntIntExpr & b)
908  {
909  if (&r == &a)
910  r.d_num += b * r.d_denom;
911  else
912  {
913  r.d_num = a.d_num + b * a.d_denom;
914  r.d_denom = a.d_denom;
915  }
916  }
917 
918  inline friend void sub(Rational & r, const Rational & a, const Rational & b)
919  {
920  if (&r == &a)
921  {
922  if (&r == &b)
923  {
924  // r == a == b, i.e. set r to zero
925  setZero(r.d_num);
926  setOne(r.d_denom);
927  }
928  else
929  r.sub_r_neq_1st(b, a, true);
930  }
931  else
932  r.sub_r_neq_1st(a, b, false);
933  }
934 
935  template<typename IntIntExpr>
936  inline friend void sub_z(Rational & r, const Rational & a, const IntIntExpr & b)
937  {
938  if (&r == &a)
939  r.d_num -= b * r.d_denom;
940  else
941  {
942  r.d_num = a.d_num;
943  r.d_num -= b * a.d_denom;
944  r.d_denom = a.d_denom;
945  }
946  }
947 
948  template<typename IntIntExpr>
949  inline friend void z_sub(Rational & r, const IntIntExpr & a, const Rational & b)
950  {
951  if (&r == &b)
952  {
953  r.d_num -= a * r.d_denom;
954  neg(r.d_num, r.d_num);
955  }
956  else
957  {
958  r.d_num = a * b.d_denom;
959  r.d_num -= b.d_num;
960  r.d_denom = b.d_denom;
961  }
962  }
963 
964  inline friend void addmul(Rational & r, const Rational & a, const Rational & b);
965  inline friend void submul(Rational & r, const Rational & a, const Rational & b);
966 
967  template<typename IntIntExpr>
968  inline friend void addmul_z(Rational & r, const Rational & a, const IntIntExpr & b)
969  {
970  if (&r == &a)
971  {
972  r.d_denom *= r.d_num;
973  increment(r.d_num, b);
974  r.d_num = b + convert(1u, IntegerContext());
975  r.d_num *= r.d_denom;
976  }
977  else
978  {
979  Integer t = r.d_denom * a.d_num;
980  t *= b;
981  r.d_num *= a.d_denom;
982  r.d_num += t * b;
983  r.d_denom *= a.d_denom;
984  }
985  }
986 
987  template<typename IntIntExpr>
988  inline friend void submul_z(Rational & r, const Rational & a, const IntIntExpr & b)
989  {
990  if (&r == &a)
991  {
992  r.d_denom *= r.d_num;
993  decrement(r.d_num, b);
994  neg(r.d_num, r.d_num);
995  r.d_num = b + convert(1u, IntegerContext());
996  r.d_num *= r.d_denom;
997  }
998  else
999  {
1000  Integer t = r.d_denom * a.d_num;
1001  t *= b;
1002  r.d_num *= a.d_denom;
1003  r.d_num -= t * b;
1004  r.d_denom *= a.d_denom;
1005  }
1006  }
1007 
1008  inline friend void mul(Rational & r, const Rational & a, const Rational & b)
1009  {
1010  if (isZero(a.d_num) || isZero(b.d_num))
1011  {
1012  setZero(r.d_num);
1013  setOne(r.d_denom);
1014  }
1015  else
1016  {
1017  Integer g1, g2, t;
1018  GCD(g1, a.d_num, b.d_denom);
1019  GCD(g2, b.d_num, a.d_denom);
1020  if (isOne(g1))
1021  {
1022  if (isOne(g2))
1023  {
1024  r.d_num = a.d_num * b.d_num;
1025  r.d_denom = a.d_denom * b.d_denom;
1026  }
1027  else
1028  {
1029  t = b.d_num / g2;
1030  r.d_num = a.d_num * t;
1031  t = a.d_denom / g2;
1032  r.d_denom = b.d_denom * t;
1033  }
1034  }
1035  else
1036  {
1037  if (isOne(g2))
1038  {
1039  t = a.d_num / g1;
1040  r.d_num = b.d_num * t;
1041  t = b.d_denom / g1;
1042  r.d_denom = a.d_denom * t;
1043  }
1044  else
1045  {
1046  t = b.d_num / g2;
1047  r.d_num = a.d_num / g1;
1048  r.d_num *= t;
1049  t = a.d_denom / g2;
1050  r.d_denom = b.d_denom / g1;
1051  r.d_denom *= t;
1052  }
1053  }
1054 // r.normalize(); -- the above ensures that numerator and denominator are coprime
1055  }
1056  }
1057 
1058  template<typename IntIntExpr>
1059  inline friend void mul_z(Rational & r, const Rational & a, const IntIntExpr & b)
1060  {
1061  if (isZero(a.d_num))
1062  {
1063  setZero(r.d_num);
1064  setOne(r.d_denom);
1065  }
1066  else
1067  {
1068  Integer g;
1069  GCD(g, a.d_denom, b);
1070  if (isOne(g))
1071  r.d_num = a.d_num * b;
1072  else
1073  {
1074  g = b / g;
1075  r.d_num = a.d_num * g;
1076  }
1077  r.d_denom = a.d_denom;
1078  }
1079  }
1080 
1081  inline friend void div(Rational & r, const Rational & a, const Rational & b)
1082  {
1083  if (&r == &b)
1084  {
1085  if (&r == &a)
1086  {
1087  // Result is 1 (except if r == a == b == 0, but we ignore this case)
1088  setOne(r);
1089  return;
1090  }
1091  // r == a, but r != b
1092  swap(r.d_num, r.d_denom);
1093  if (sign(r.d_denom) < 0)
1094  r.d_denom = -r.d_denom;
1095  r.d_num *= a.d_num;
1096  r.d_denom *= a.d_denom;
1097  }
1098  else
1099  {
1100  if (&r == &a)
1101  {
1102  // r is not b, but a
1103  if (sign(b.d_num) < 0)
1104  {
1105  r.d_num *= b.d_denom;
1106  r.d_num = -r.d_num;
1107  r.d_denom *= b.d_num;
1108  r.d_denom = -r.d_denom;
1109  }
1110  else
1111  {
1112  r.d_num *= b.d_denom;
1113  r.d_denom *= b.d_num;
1114  }
1115  }
1116  else
1117  {
1118  // r is not b and not a
1119  if (sign(b.d_num) < 0)
1120  {
1121  r.d_num = a.d_num * b.d_denom;
1122  r.d_num = -r.d_num;
1123  r.d_denom = a.d_denom * b.d_num;
1124  r.d_denom = -r.d_denom;
1125  }
1126  else
1127  {
1128  r.d_num = a.d_num * b.d_denom;
1129  r.d_denom = a.d_denom * b.d_num;
1130  }
1131  }
1132  }
1133  r.normalize();
1134  }
1135 
1136  template<typename IntIntExpr>
1137  inline friend void div_z(Rational & r, const Rational & a, const IntIntExpr & b)
1138  {
1139  if (isZero(a.d_num))
1140  {
1141  setZero(r.d_num);
1142  setOne(r.d_denom);
1143  }
1144  else
1145  {
1146  Integer g;
1147  GCD(g, a.d_num, b);
1148  if (isOne(g))
1149  r.d_denom = a.d_denom * b;
1150  else
1151  {
1152  g = b / g;
1153  r.d_denom = a.d_denom * g;
1154  }
1155  r.d_num = a.d_num;
1156  }
1157  }
1158 
1159  template<typename IntIntExpr>
1160  inline friend void z_div(Rational & r, const IntIntExpr & a, const Rational & b)
1161  {
1162  div_z(r, b, a);
1163  swap(r.d_num, r.d_denom);
1164  if (sign(r.d_denom) < 0)
1165  {
1166  neg(r.d_num, r.d_num);
1167  makeAbs(r.d_denom);
1168  }
1169  }
1170 
1171  inline friend void mod(Rational & r, const Rational & a, const Rational & b)
1172  {
1173  arithmetic::mod(r.d_num, a.d_num * b.d_denom, b.d_num * a.d_denom);
1174  r.d_denom = a.d_denom * b.d_denom;
1175  r.normalize();
1176  }
1177 
1178  template<typename IntIntExpr>
1179  inline friend void mod_z(Rational & r, const Rational & a, const IntIntExpr & b)
1180  {
1181  arithmetic::mod(r.d_num, a.d_num, b * a.d_denom);
1182  r.d_denom = a.d_denom;
1183  r.normalize();
1184  }
1185 
1186  template<typename IntIntExpr>
1187  inline friend void z_mod(Rational & r, const IntIntExpr & a, const Rational & b)
1188  {
1189  arithmetic::mod(r.d_num, a * b.d_denom, b.d_num);
1190  r.d_denom = b.d_denom;
1191  r.normalize();
1192  }
1193 
1194  inline friend void shl(Rational & r, const Rational & a, long b)
1195  {
1196  if (b > 0)
1197  {
1198  r.d_num = a.d_num << b;
1199  r.d_denom = a.d_denom;
1200  }
1201  else
1202  {
1203  r.d_num = a.d_num;
1204  r.d_denom = a.d_denom << (-b);
1205  }
1206  r.normalize();
1207  }
1208 
1209  template<typename IntIntExpr>
1210  inline friend void shl_z(Rational & r, const IntIntExpr & a, long b)
1211  {
1212  if (b > 0)
1213  {
1214  r.d_num = a << b;
1215  setOne(r.d_denom);
1216  }
1217  else
1218  {
1219  r.d_num = a;
1220  setOne(r.d_denom);
1221  r.d_denom <<= -b;
1222  r.normalize();
1223  }
1224  }
1225 
1226  inline friend void shr(Rational & r, const Rational & a, long b)
1227  {
1228  if (b > 0)
1229  {
1230  r.d_num = a.d_num;
1231  r.d_denom = a.d_denom << b;
1232  }
1233  else
1234  {
1235  r.d_num = a.d_num << (-b);
1236  r.d_denom = a.d_denom;
1237  }
1238  r.normalize();
1239  }
1240 
1241  template<typename IntIntExpr>
1242  inline friend void shr_z(Rational & r, const IntIntExpr & a, long b)
1243  {
1244  if (b < 0)
1245  {
1246  r.d_num = a.d_num << -b;
1247  setOne(r.d_denom);
1248  }
1249  else
1250  {
1251  r.d_num = a.d_num;
1252  setOne(r.d_denom);
1253  r.d_denom <<= b;
1254  r.normalize();
1255  }
1256  }
1257 
1258  inline friend void increment(Rational & r, const Rational & a)
1259  {
1260  r.d_num = a.d_num + a.d_denom;
1261  r.d_denom = a.d_denom;
1262  r.normalize();
1263  }
1264 
1265  inline friend void decrement(Rational & r, const Rational & a)
1266  {
1267  r.d_num = a.d_num - a.d_denom;
1268  r.d_denom = a.d_denom;
1269  r.normalize();
1270  }
1271 
1272  inline friend void neg(Rational & r, const Rational & a)
1273  {
1274  neg(r.d_num, a.d_num);
1275  r.d_denom = a.d_denom;
1276  }
1277 
1278  template<typename IntIntExpr>
1279  inline friend void neg_z(Rational & r, const IntIntExpr & a)
1280  {
1281  neg(r.d_num, a);
1282  setOne(r.d_denom);
1283  }
1284 
1285  inline friend void abs(Rational & r, const Rational & a)
1286  {
1287  abs(r.d_num, a.d_num);
1288  r.d_denom = a.d_denom;
1289  }
1290 
1291  template<typename IntIntExpr>
1292  inline friend void abs_z(Rational & r, const IntIntExpr & a)
1293  {
1294  abs(r.d_num, a);
1295  setOne(r.d_denom);
1296  }
1297 
1298  inline friend void makeAbs(Rational & a) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1299  {
1300  makeAbs(a.d_num);
1301  }
1302 
1303  friend std::ostream & operator << (std::ostream & s, const Rational & r);
1304  friend std::istream & operator >> (std::istream & s, Rational & r);
1305 
1306  inline friend void setZero(Rational & r, bool sign)
1307  // Set to zero
1308  {
1309  setZero(r.d_num);
1310  setOne(r.d_denom);
1311  }
1312 
1313  inline friend void setOne(Rational & r)
1314  // Set to one
1315  {
1316  setOne(r.d_num);
1317  setOne(r.d_denom);
1318  }
1319 
1320  inline friend int compare(const Rational & a, const Rational & b)
1321  {
1322  return compare(a.d_num * b.d_denom, b.d_num * a.d_denom);
1323  }
1324 
1325  template<typename IntIntExpr>
1326  inline friend int compare_z(const Rational & a, const IntIntExpr & b)
1327  {
1328  return compare(a.d_num, b * a.d_denom);
1329  }
1330 
1331  inline friend int compareAbsValues(const Rational & a, const Rational & b)
1332  {
1333  return compareAbsValues(a.d_num * b.d_denom, b.d_num * a.d_denom);
1334  }
1335 
1336  template<typename IntIntExpr>
1337  inline friend int compareAbsValues_z(const Rational & a, const IntIntExpr & b)
1338  {
1339  return compareAbsValues(a.d_num, b * a.d_denom);
1340  }
1341 
1342  inline friend int sign(const Rational & r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1343  // Returns the sign (i.e. -1, 0, 1).
1344  {
1345  return sign(r.d_num);
1346  }
1347 
1348  inline friend void square(Rational & r, const Rational & a)
1349  {
1350  square(r.d_num, a.d_num);
1351  square(r.d_denom, a.d_denom);
1352  }
1353 
1354  template<typename IntIntExpr>
1355  inline friend void square_z(Rational & r, const IntIntExpr & a)
1356  {
1357  square(r.d_num, a);
1358  setOne(r.d_denom);
1359  }
1360 
1361  inline friend void power(Rational & r, const Rational & a, signed long e)
1362  {
1363  power(r, a, convert(e, IntegerContext()));
1364  }
1365 
1366  template<typename IntIntExpr>
1367  inline friend void power_z(Rational & r, const IntIntExpr & a, signed long e)
1368  {
1369  if (e >= 0)
1370  {
1371  power(r.d_num, a, e);
1372  setOne(r.d_denom);
1373  }
1374  else
1375  {
1376  power(r.d_denom, a, -e);
1377  setOne(r.d_num);
1378  }
1379  }
1380 
1381  inline friend void power(Rational & r, const Rational & a, unsigned long e)
1382  {
1383  power(r, a, convert(e, IntegerContext()));
1384  }
1385 
1386  template<typename IntIntExpr>
1387  inline friend void power_z(Rational & r, const IntIntExpr & a, unsigned long e)
1388  {
1389  power(r.d_num, a, e);
1390  setOne(r.d_denom);
1391  }
1392 
1393  friend void power(Rational & r, const Rational & a, const Integer & e);
1394 
1395  template<typename IntIntExpr>
1396  inline friend void power_z(Rational & r, const IntIntExpr & a, const Integer & e)
1397  {
1398  if (isNonNegative(e))
1399  {
1400  power(r.d_num, a, e);
1401  setOne(r.d_denom);
1402  }
1403  else
1404  {
1405  power(r.d_denom, a, -e);
1406  setOne(r.d_num);
1407  }
1408  }
1409 
1410  inline friend void arithmetic::swap(Rational &, Rational &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE;
1411 
1419  inline long getApproxExponent() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1420  {
1421  return isZero(d_num) ? std::numeric_limits<long>::min() : (ceilOfLog2(d_num) - ceilOfLog2(d_denom));
1422  }
1423  };
1424 
1425  template<typename IntIntExpr>
1426  inline void add_z(Rational & r, const Rational & a, const IntIntExpr & b);
1427 
1428  template<typename IntIntExpr>
1429  inline void sub_z(Rational & r, const Rational & a, const IntIntExpr & b);
1430 
1431  template<typename IntIntExpr>
1432  inline void z_sub(Rational & r, const IntIntExpr & a, const Rational & b);
1433 
1434  template<typename IntIntExpr>
1435  inline void addmul_z(Rational & r, const Rational & a, const IntIntExpr & b);
1436 
1437  template<typename IntIntExpr>
1438  inline void submul_z(Rational & r, const Rational & a, const IntIntExpr & b);
1439 
1440  template<typename IntIntExpr>
1441  inline void mul_z(Rational & r, const Rational & a, const IntIntExpr & b);
1442 
1443  template<typename IntIntExpr>
1444  inline void div_z(Rational & r, const Rational & a, const IntIntExpr & b);
1445 
1446  template<typename IntIntExpr>
1447  inline void z_div(Rational & r, const IntIntExpr & a, const Rational & b);
1448 
1449  template<typename IntIntExpr>
1450  inline void mod_z(Rational & r, const Rational & a, const IntIntExpr & b);
1451 
1452  template<typename IntIntExpr>
1453  inline void z_mod(Rational & r, const IntIntExpr & a, const Rational & b);
1454 
1455  template<typename IntIntExpr>
1456  inline void shl_z(Rational & r, const IntIntExpr & a, long b);
1457 
1458  template<typename IntIntExpr>
1459  inline void shr_z(Rational & r, const IntIntExpr & a, long b);
1460 
1461  template<typename IntIntExpr>
1462  inline void neg_z(Rational & r, const IntIntExpr & a);
1463 
1464  template<typename IntIntExpr>
1465  inline void abs_z(Rational & r, const IntIntExpr & a);
1466 
1467  template<typename IntIntExpr>
1468  inline int compare_z(const Rational & a, const IntIntExpr & b);
1469 
1470  template<typename IntIntExpr>
1471  inline int compareAbsValues_z(const Rational & a, const IntIntExpr & b);
1472 
1473  template<typename IntIntExpr>
1474  inline void square_z(Rational & r, const IntIntExpr & a);
1475 
1476  template<typename IntIntExpr>
1477  inline void power_z(Rational & r, const IntIntExpr & a, signed long e);
1478 
1479  template<typename IntIntExpr>
1480  inline void power_z(Rational & r, const IntIntExpr & a, unsigned long e);
1481 
1482  template<typename IntIntExpr>
1483  inline void power_z(Rational & r, const IntIntExpr & a, const Integer & e);
1484 
1485  inline void swap(Rational & a, Rational & b) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1486  {
1487  swap(a.d_num, b.d_num);
1488  swap(a.d_denom, b.d_denom);
1489  }
1490  }
1491 }
1492 
1493 #include "rational-ops.hpp"
1494 #include "rational-conv.hpp"
1495 
1496 #endif
friend void power(Rational &r, const Rational &a, signed long e)
Raises a to the power e and stores the result in r.
Definition: rational.hpp:1361
void submul(Integer &r, const Integer &a, const Integer &b)
Multiplies a and b and subtracts the result from r.
Rational(const Rational &r, const RationalContext &rc)
Creates a copy of the given rational number.
Definition: rational.hpp:564
Rational Real
The rational type.
Definition: rational.hpp:366
Rational(long long i)
Creates a rational number from the given native integer.
Definition: rational.hpp:695
long getApproxExponent() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns approximate e such that |x| is approximately .
Definition: rational.hpp:1419
friend bool isNegative(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given rational number for being strictly negative.
Definition: rational.hpp:829
Rational(const RationalContext &rc)
Creates a new rational number representing 0.
Definition: rational.hpp:542
bool isZero(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being zero.
Rational(const Rational &r)
Creates a copy of the given rational number.
Definition: rational.hpp:553
Rational(const Integer &i)
Creates a rational number from the given arbitrary precision integer expression.
Definition: rational.hpp:737
Rational(unsigned long i, const RationalContext &rc)
Creates a rational number from the given native integer.
Definition: rational.hpp:684
friend bool isNonNegative(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given rational number for being positive or zero.
Definition: rational.hpp:824
int bit(const Integer &x, long n) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the n bit of in the usual binary representation.
int compare(const Integer &a, const Integer &b)
Compares the two integers.
bool isNegative(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being strictly negative.
void setOne(Integer &)
Sets the given integer to one.
void shr(Integer &r, const Integer &a, long b)
Shifts a by b bits to the left and stores the result in r.
Rational(long double d, const RationalContext &rc)
Creates a rational number from the given native floating point value.
Definition: rational.hpp:639
friend void mul(Rational &r, const Rational &a, const Rational &b)
Multiplies a with b and stores the result in r.
Definition: rational.hpp:1008
Conversion definitions for rational numbers.
bool isOne(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being one.
friend void shl(Rational &r, const Rational &a, long b)
Multiplies a by and stores the result in r.
Definition: rational.hpp:1194
friend void setOne(Rational &r)
Sets the given rational number to one.
Definition: rational.hpp:1313
RationalContext() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Creates a new rational context.
Definition: rational.hpp:382
friend void increment(Rational &r, const Rational &a)
Increments a by one and stores the result in r.
Definition: rational.hpp:1258
expressions::Expression< IntegerContext, expressions::Wrapper< IntegerContext >, expressions::AbsOp > abs(const Integer &i)
Computes and returns the absolute value of i.
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::ShLOp > operator<<(const Integer &a, const Integer &b)
Computes the bitwise left shift of the first integer by the number of bits given by the second intege...
friend void square(Rational &r, const Rational &a)
Computes the square of a and stores the result in r.
Definition: rational.hpp:1348
Rational(long double d)
Creates a rational number from the given native floating point value.
Definition: rational.hpp:628
Rational(long i, const RationalContext &rc)
Creates a rational number from the given native integer.
Definition: rational.hpp:661
friend void makeAbs(Rational &a) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Makes the operand non-negative.
Definition: rational.hpp:1298
Operator definitions for rational numbers.
Rational & operator=(const Rational &r)
Assigns the given rational number r to this rational number.
Definition: rational.hpp:775
void setZero(Integer &)
Sets the given integer to zero.
void mul(Integer &r, const Integer &a, const Integer &b)
Multiplies a with b and stores the result in r.
Provides conversion implementation from type SourceType to DestContext::Type.
Definition: arithmetic.hpp:713
void div(Integer &r, const Integer &a, const Integer &b)
Divides a by b and stores the result in r.
friend int sign(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the sign of the given rational number.
Definition: rational.hpp:1342
void convert(typename DestContext::Type &dst, const SourceType &src, const DestContext &context)
Converts the value in src to the type described by context and stores the result in dst...
Definition: arithmetic.hpp:734
friend void div(Rational &r, const Rational &a, const Rational &b)
Divides a by b and stores the result in r.
Definition: rational.hpp:1081
void mod(Integer &r, const Integer &a, const Integer &b)
Takes the remainder of the division of a by b and stores it in r.
void increment(Integer &r, const Integer &a)
Increments a by one and stores the result in r.
friend void add(Rational &r, const Rational &a, const Rational &b)
Adds a and b and stores the result in r.
Definition: rational.hpp:887
Rational(long i)
Creates a rational number from the given native integer.
Definition: rational.hpp:649
friend void sub(Rational &r, const Rational &a, const Rational &b)
Subtracts b from a and stores the result in r.
Definition: rational.hpp:918
friend std::istream & operator>>(std::istream &s, Rational &r)
Reads the rational number from the given input stream.
static unsigned long getMaxRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the maximal possible precision for this context.
Definition: rational.hpp:422
Rational(const expressions::Expression< RationalContext, A, O > &E)
Evaluates the given rational expression into a new rational number.
Definition: rational.hpp:575
friend void neg(Rational &r, const Rational &a)
Negates a and stores the result in r.
Definition: rational.hpp:1272
Implementation backend for conversions from context types to native types.
Definition: arithmetic.hpp:994
Represents a rational number as a quotient of two arbitrary precision integers.
Definition: rational.hpp:431
void swap(plll::arithmetic::Integer &, plll::arithmetic::Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Swaps two plll::arithmetic::Integer objects.
const Integer & numerator() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Retrieves the numerator of this rational number.
Definition: rational.hpp:488
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::PowerOp > power(const Integer &a, const Integer &b)
Computes and returns a raised to the power of b.
Rational(const Integer &i, const RationalContext &rc)
Creates a rational number from the given arbitrary precision integer.
Definition: rational.hpp:756
Rational(unsigned long i)
Creates a rational number from the given native integer.
Definition: rational.hpp:672
int compareAbsValues(const Integer &a, const Integer &b)
Compares the two integers in absolute value.
bool isNonNegative(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being positive or zero.
friend void mod(Rational &r, const Rational &a, const Rational &b)
Takes the remainder of the division of a by b and stores it in r.
Definition: rational.hpp:1171
int sign(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the sign of the given integer.
friend std::ostream & operator<<(std::ostream &s, const Rational &r)
Outputs the rational number on the given output stream.
friend void abs(Rational &r, const Rational &a)
Takes the absolute value of a and stores the result in r.
Definition: rational.hpp:1285
friend bool isPositive(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given rational number for being strictly positive.
Definition: rational.hpp:819
static void setRealPrecision(unsigned long prec) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Sets the precision of this context. (Will do nothing.)
Definition: rational.hpp:393
friend bool isOne(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Real object for being zero.
Definition: rational.hpp:814
Helper templates.
void shl(Integer &r, const Integer &a, long b)
Shifts a by b bits to the left and stores the result in r.
friend void setZero(Rational &r, bool sign)
Sets the given rational number to .
Definition: rational.hpp:1306
static unsigned long precision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Retrieves the precision of the current rational number.
Definition: rational.hpp:586
static unsigned long getRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the precision of this context.
Definition: rational.hpp:402
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::ShROp > operator>>(const Integer &a, const Integer &b)
Computes the bitwise right shift of the first integer by the number of bits given by the second integ...
Rational()
Creates a new rational number representing 0.
Definition: rational.hpp:506
void neg(Integer &r, const Integer &a)
Negates a and stores the result in r.
Rational Type
The rational type.
Definition: rational.hpp:370
void addmul(Integer &r, const Integer &a, const Integer &b)
Multiplies a and b and adds the result to r.
Rational(double d, const RationalContext &rc)
Creates a rational number from the given native floating point value.
Definition: rational.hpp:618
friend bool isNonPositive(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given rational number for being negative or zero.
Definition: rational.hpp:834
bool isPositive(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being strictly positive.
friend void addmul(Rational &r, const Rational &a, const Rational &b)
Multiplies a and b and adds the result to r.
static void setContext(const RationalContext &rc) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Applies the given rational context to this number.
Definition: rational.hpp:598
void add(Integer &r, const Integer &a, const Integer &b)
Adds a and b and stores the result in r.
friend bool isZero(const Rational &r) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given rational number for being zero.
Definition: rational.hpp:809
Rational(const Integer &n, const Integer &d)
Creates a rational number from the given arbitrary precision integer pair of numerator and denominato...
Definition: rational.hpp:720
void makeAbs(Integer &a) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Makes the operand non-negative.
const Integer & denominator() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Retrieves the denominator of this rational number.
Definition: rational.hpp:498
expressions::Expression< IntegerContext, expressions::Wrapper< IntegerContext >, expressions::SquareOp > square(const Integer &i)
Computes and returns the square of i.
void decrement(Integer &r, const Integer &a)
Decrements a by one and stores the result in r.
bool isNonPositive(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Tests the given plll::arithmetic::Integer object for being negative or zero.
long ceilOfLog2(const Integer &x) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Computes and returns .
friend void submul(Rational &r, const Rational &a, const Rational &b)
Multiplies a and b and subtracts the result from r.
Rational(double d)
Creates a rational number from the given native floating point value.
Definition: rational.hpp:607
static unsigned long getMinRealPrecision() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the minimal possible precision for this context.
Definition: rational.hpp:412
Represents an arbitrary precision integer.
void assignTo(typename Context::Type &x) const
Evaluates the expression into the given object.
friend int compareAbsValues(const Rational &a, const Rational &b)
Compares the two rational numbers in absolute value.
Definition: rational.hpp:1331
friend int compare(const Rational &a, const Rational &b)
Compares the two rational numbers.
Definition: rational.hpp:1320
friend void shr(Rational &r, const Rational &a, long b)
Multiplies a by and stores the result in r.
Definition: rational.hpp:1226
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::GCDOp > GCD(const Integer &a, const Integer &b)
Computes and returns the non-negative Greatest Common Divisor of a and b.
Represents an arithmetic context for rational numbers.
Definition: rational.hpp:355
Represents an arithmetic context for arbitrary precision integer.
friend void decrement(Rational &r, const Rational &a)
Negates a and stores the result in r.
Definition: rational.hpp:1265
Main arithmetic header.
void sub(Integer &r, const Integer &a, const Integer &b)
Subtracts b from a and stores the result in r.
Rational(long long i, const RationalContext &rc)
Creates a rational number from the given native integer.
Definition: rational.hpp:707