plll  1.0
rational-conv.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_CONV_HPP
24 #define PLLL_INCLUDE_GUARD__RATIONAL_CONV_HPP
25 
33 namespace plll
34 {
35  namespace arithmetic
36  {
37  namespace implementation
38  {
39  // Implementation for RationalContext
40 
41  template<> class conversion_impl<float, RationalContext>
42  {
43  public:
45  typedef Rational RetVal_Frac;
46  typedef void RetVal_Floor;
47  typedef void RetVal_Ceil;
48  typedef void RetVal_Round;
49  typedef void RetVal_Round2;
50 
51  static void convert(Rational & d, float v, const RationalContext & c)
52  {
53  d.initFromDouble(v);
54  }
55 
56  static RetVal convert(float v, const RationalContext & c)
57  {
58  return RetVal(v, c);
59  }
60 
61  static void convert_frac(Rational & d, float v1, float v2, const RationalContext & c)
62  {
63  convert(d, v1, c);
64  Rational tmp;
65  convert(tmp, v2, c);
66  d /= tmp;
67  }
68 
69  static RetVal_Frac convert_frac(float v1, float v2, const RationalContext & c)
70  {
71  Rational res, tmp;
72  convert(res, v1, c);
73  convert(tmp, v2, c);
74  return res /= tmp;
75  }
76  };
77 
78  template<> class conversion_impl<double, RationalContext>
79  {
80  public:
82  typedef Rational RetVal_Frac;
83  typedef void RetVal_Floor;
84  typedef void RetVal_Ceil;
85  typedef void RetVal_Round;
86  typedef void RetVal_Round2;
87 
88  static void convert(Rational & d, double v, const RationalContext & c)
89  {
90  d.initFromDouble(v);
91  }
92 
93  static RetVal convert(double v, const RationalContext & c)
94  {
95  return RetVal(v, c);
96  }
97 
98  static void convert_frac(Rational & d, double v1, double v2, const RationalContext & c)
99  {
100  convert(d, v1, c);
101  Rational tmp;
102  convert(tmp, v2, c);
103  d /= tmp;
104  }
105 
106  static RetVal_Frac convert_frac(double v1, double v2, const RationalContext & c)
107  {
108  Rational res, tmp;
109  convert(res, v1, c);
110  convert(tmp, v2, c);
111  return res /= tmp;
112  }
113  };
114 
115  template<> class conversion_impl<long double, RationalContext>
116  {
117  public:
119  typedef Rational RetVal_Frac;
120  typedef void RetVal_Floor;
121  typedef void RetVal_Ceil;
122  typedef void RetVal_Round;
123  typedef void RetVal_Round2;
124 
125  static void convert(Rational & d, long double v, const RationalContext & c)
126  {
127  d.initFromDouble(v);
128  }
129 
130  static RetVal convert(long double v, const RationalContext & c)
131  {
132  return RetVal(v, c);
133  }
134 
135  static void convert_frac(Rational & d, long double v1, long double v2, const RationalContext & c)
136  {
137  convert(d, v1, c);
138  Rational tmp;
139  convert(tmp, v2, c);
140  d /= tmp;
141  }
142 
143  static RetVal_Frac convert_frac(long double v1, long double v2, const RationalContext & c)
144  {
145  Rational res, tmp;
146  convert(res, v1, c);
147  convert(tmp, v2, c);
148  return res /= tmp;
149  }
150  };
151 
152  template<> class conversion_impl<signed int, RationalContext>
153  {
154  private:
156 
157  public:
159  typedef Rational RetVal_Frac;
160  typedef void RetVal_Floor;
161  typedef void RetVal_Ceil;
162  typedef void RetVal_Round;
163  typedef void RetVal_Round2;
164 
165  static void convert(Rational & d, signed int v, const RationalContext & c)
166  {
167  IntegerContext ic;
168  arithmetic::convert(d.d_num, v, ic);
169  setOne(d.d_denom);
170  }
171 
172  static RetVal convert(signed int v, const RationalContext & c)
173  {
174  return RetVal(Expr(v, g_intcontext), c);
175  }
176 
177  static void convert_frac(Rational & d, signed int v1, signed int v2, const RationalContext & c)
178  {
179  arithmetic::convert(d.d_num, v1, IntegerContext());
180  arithmetic::convert(d.d_denom, v2, IntegerContext());
181  d.normalize();
182  // Make sign correct
183  if (sign(d.d_denom) < 0)
184  {
185  neg(d.d_denom, d.d_denom);
186  neg(d.d_num, d.d_num);
187  }
188  }
189 
190  static RetVal_Frac convert_frac(signed int v1, signed int v2, const RationalContext & c)
191  {
192  Rational r;
193  convert_frac(r, v1, v2, c);
194  return r;
195  }
196  };
197 
198  template<> class conversion_impl<unsigned int, RationalContext>
199  {
200  private:
202 
203  public:
205  typedef Rational RetVal_Frac;
206  typedef void RetVal_Floor;
207  typedef void RetVal_Ceil;
208  typedef void RetVal_Round;
209  typedef void RetVal_Round2;
210 
211  static void convert(Rational & d, unsigned int v, const RationalContext & c)
212  {
213  IntegerContext ic;
214  arithmetic::convert(d.d_num, v, ic);
215  setOne(d.d_denom);
216  }
217 
218  static RetVal convert(unsigned int v, const RationalContext & c)
219  {
220  return RetVal(Expr(v, g_intcontext), c);
221  }
222 
223  static void convert_frac(Rational & d, unsigned int v1, unsigned int v2, const RationalContext & c)
224  {
225  arithmetic::convert(d.d_num, v1, IntegerContext());
226  arithmetic::convert(d.d_denom, v2, IntegerContext());
227  d.normalize();
228  // Make sign correct
229  if (sign(d.d_denom) < 0)
230  {
231  neg(d.d_denom, d.d_denom);
232  neg(d.d_num, d.d_num);
233  }
234  }
235 
236  static RetVal_Frac convert_frac(unsigned int v1, unsigned int v2, const RationalContext & c)
237  {
238  Rational r;
239  convert_frac(r, v1, v2, c);
240  return r;
241  }
242  };
243 
244  template<> class conversion_impl<signed long, RationalContext>
245  {
246  private:
248 
249  public:
251  typedef Rational RetVal_Frac;
252  typedef void RetVal_Floor;
253  typedef void RetVal_Ceil;
254  typedef void RetVal_Round;
255  typedef void RetVal_Round2;
256 
257  static void convert(Rational & d, signed long v, const RationalContext & c)
258  {
259  IntegerContext ic;
260  arithmetic::convert(d.d_num, v, ic);
261  setOne(d.d_denom);
262  }
263 
264  static RetVal convert(signed long v, const RationalContext & c)
265  {
266  return RetVal(Expr(v, g_intcontext), c);
267  }
268 
269  static void convert_frac(Rational & d, signed long v1, signed long v2, const RationalContext & c)
270  {
271  arithmetic::convert(d.d_num, v1, IntegerContext());
272  arithmetic::convert(d.d_denom, v2, IntegerContext());
273  d.normalize();
274  // Make sign correct
275  if (sign(d.d_denom) < 0)
276  {
277  neg(d.d_denom, d.d_denom);
278  neg(d.d_num, d.d_num);
279  }
280  }
281 
282  static RetVal_Frac convert_frac(signed long v1, signed long v2, const RationalContext & c)
283  {
284  Rational r;
285  convert_frac(r, v1, v2, c);
286  return r;
287  }
288  };
289 
290  template<> class conversion_impl<unsigned long, RationalContext>
291  {
292  private:
294 
295  public:
297  typedef Rational RetVal_Frac;
298  typedef void RetVal_Floor;
299  typedef void RetVal_Ceil;
300  typedef void RetVal_Round;
301  typedef void RetVal_Round2;
302 
303  static void convert(Rational & d, unsigned long v, const RationalContext & c)
304  {
305  IntegerContext ic;
306  arithmetic::convert(d.d_num, v, ic);
307  setOne(d.d_denom);
308  }
309 
310  static RetVal convert(unsigned long v, const RationalContext & c)
311  {
312  return RetVal(Expr(v, g_intcontext), c);
313  }
314 
315  static void convert_frac(Rational & d, unsigned long v1, unsigned long v2, const RationalContext & c)
316  {
317  arithmetic::convert(d.d_num, v1, IntegerContext());
318  arithmetic::convert(d.d_denom, v2, IntegerContext());
319  d.normalize();
320  // Make sign correct
321  if (sign(d.d_denom) < 0)
322  {
323  neg(d.d_denom, d.d_denom);
324  neg(d.d_num, d.d_num);
325  }
326  }
327 
328  static RetVal_Frac convert_frac(unsigned long v1, unsigned long v2, const RationalContext & c)
329  {
330  Rational r;
331  convert_frac(r, v1, v2, c);
332  return r;
333  }
334  };
335 
336  template<> class conversion_impl<long long, RationalContext>
337  {
338  private:
340 
341  public:
343  typedef Rational RetVal_Frac;
344  typedef void RetVal_Floor;
345  typedef void RetVal_Ceil;
346  typedef void RetVal_Round;
347  typedef void RetVal_Round2;
348 
349  static void convert(Rational & d, long long v, const RationalContext & c)
350  {
351  IntegerContext ic;
352  arithmetic::convert(d.d_num, v, ic);
353  setOne(d.d_denom);
354  }
355 
356  static RetVal convert(long long v, const RationalContext & c)
357  {
358  return RetVal(Expr(v, g_intcontext), c);
359  }
360 
361  static void convert_frac(Rational & d, long long v1, long long v2, const RationalContext & c)
362  {
363  arithmetic::convert(d.d_num, v1, IntegerContext());
364  arithmetic::convert(d.d_denom, v2, IntegerContext());
365  d.normalize();
366  // Make sign correct
367  if (sign(d.d_denom) < 0)
368  {
369  neg(d.d_denom, d.d_denom);
370  neg(d.d_num, d.d_num);
371  }
372  }
373 
374  static RetVal_Frac convert_frac(long long v1, long long v2, const RationalContext & c)
375  {
376  Rational r;
377  convert_frac(r, v1, v2, c);
378  return r;
379  }
380  };
381 
383  {
384  public:
385  typedef Real RetVal;
386  typedef Real RetVal_Frac;
387  typedef void RetVal_Floor;
388  typedef void RetVal_Ceil;
389  typedef void RetVal_Round;
390  typedef void RetVal_Round2;
391 
392  static void convert(Real & res, const Rational & r, const RealContext & rc)
393  {
394  arithmetic::convert(res, r.numerator(), rc);
395  Real tmp(r.denominator(), rc);
396  res /= tmp;
397  }
398 
399  static Real convert(const Rational & r, const RealContext & rc)
400  {
401  Real res(r.numerator(), rc), tmp(r.denominator(), rc);
402  res /= tmp;
403  return res;
404  }
405 
406  static void convert_frac(Real & res, const Rational & r1, const Rational & r2, const RealContext & rc)
407  {
408  arithmetic::convert(res, r1.numerator() * r2.denominator(), rc);
409  Real tmp(r1.denominator() * r2.numerator(), rc);
410  res /= tmp;
411  }
412 
413  static Real convert_frac(const Rational & r1, const Rational & r2, const RealContext & rc)
414  {
415  Real res(r1.numerator() * r2.denominator(), rc), tmp(r1.denominator() * r2.numerator(), rc);
416  return res /= tmp;
417  }
418  };
419 
421  {
422  public:
423  typedef Rational RetVal;
424  typedef Rational RetVal_Frac;
425  typedef void RetVal_Floor;
426  typedef void RetVal_Ceil;
427  typedef void RetVal_Round;
428  typedef void RetVal_Round2;
429 
430  static void convert(Rational & res, const Real & r, const RationalContext & rc)
431  {
432  setOne(res.d_denom);
433  mpfr_exp_t exp = mpfr_get_z_2exp(res.d_num.d_value, r.d_value);
434  if (exp > 0)
435  res.d_num <<= exp;
436  else if (exp < 0)
437  res.d_denom <<= -exp;
438  }
439 
440  static Rational convert(const Real & r, const RationalContext & rc)
441  {
442  Rational res;
443  convert(res, r, rc);
444  return res;
445  }
446 
447  static void convert_frac(Rational & res, const Real & r1, const Real & r2, const RationalContext & rc)
448  {
449  setOne(res.d_denom);
450  mpfr_exp_t exp1 = mpfr_get_z_2exp(res.d_num.d_value, r1.d_value);
451  mpfr_exp_t exp2 = mpfr_get_z_2exp(res.d_denom.d_value, r2.d_value);
452  if (exp1 > exp2)
453  res.d_num <<= exp1 - exp2;
454  else if (exp1 < exp2)
455  res.d_denom <<= exp2 - exp1;
456  res.normalize();
457  // Make sign correct
458  if (sign(res.d_denom) < 0)
459  {
460  neg(res.d_denom, res.d_denom);
461  neg(res.d_num, res.d_num);
462  }
463  }
464 
465  static Rational convert_frac(const Real & r1, const Real & r2, const RationalContext & rc)
466  {
467  Rational res;
468  convert_frac(res, r1, r2, rc);
469  return res;
470  }
471  };
472 
474  {
475 #ifndef PLLL_INTERNAL_NO_TEMPLATE_FRIENDS
476  friend class nativeconversion_impl<Rational>;
477 
478  private:
479 #else
480  public:
481 #endif
482  static inline void toint(Integer & r, const Rational & v)
483  {
484  r = v.d_num / v.d_denom;
485  }
486 
487  static inline void toint_floor(Integer & r, const Rational & v)
488  {
489  floorDiv(r, v.d_num, v.d_denom);
490  }
491 
492  static inline void toint_round(Integer & r, const Rational & v)
493  {
494  Integer rr;
495  euclideanDivisionPos(r, rr, v.d_num, v.d_denom);
496  rr <<= 1;
497  if (rr >= v.d_denom)
498  ++r;
499  }
500 
501  static inline void toint_round(Integer & r, const Rational & v, bool & up)
502  {
503  Integer rr;
504  euclideanDivisionPos(r, rr, v.d_num, v.d_denom);
505  rr <<= 1;
506  if ((up = (rr >= v.d_denom)) == true)
507  ++r;
508  }
509 
510  static inline void toint_ceil(Integer & r, const Rational & v)
511  {
512  ceilDiv(r, v.d_num, v.d_denom);
513  }
514 
515  public:
518  typedef void RetVal_Frac;
527 
528  static void convert(Integer & res, const Rational & v, const IntegerContext &)
529  {
530  toint(res, v);
531  }
532 
533  static RetVal convert(const Rational & v, const IntegerContext & c)
534  {
535  return RetVal(expressions::make_expression<RationalContext>(v), c);
536  }
537 
538  static void floor(Integer & res, const Rational & v, const IntegerContext &)
539  {
540  toint_floor(res, v);
541  }
542 
543  static RetVal_Floor floor(const Rational & v, const IntegerContext & c)
544  {
545  return RetVal_Floor(expressions::make_expression<RationalContext>(v), c);
546  }
547 
548  static void round(Integer & res, const Rational & v, const IntegerContext &)
549  {
550  toint_round(res, v);
551  }
552 
553  static RetVal_Round round(const Rational & v, const IntegerContext & c)
554  {
555  return RetVal_Round(expressions::make_expression<RationalContext>(v), c);
556  }
557 
558  static void round(Integer & res, const Rational & v, bool & up, const IntegerContext &)
559  {
560  toint_round(res, v, up);
561  }
562 
563  static RetVal_Round2 round(const Rational & v, bool & up, const IntegerContext & c)
564  {
565  return RetVal_Round2(expressions::make_expression<RationalContext>(v),
568  expressions::NoneOp> >(up, c));
569  }
570 
571  static void ceil(Integer & res, const Rational & v, const IntegerContext &)
572  {
573  toint_ceil(res, v);
574  }
575 
576  static RetVal_Ceil ceil(const Rational & v, const IntegerContext & c)
577  {
578  return RetVal_Ceil(expressions::make_expression<RationalContext>(v), c);
579  }
580  };
581 
583  {
584  public:
587  typedef Rational RetVal_Frac;
588  typedef void RetVal_Floor;
589  typedef void RetVal_Ceil;
590  typedef void RetVal_Round;
591  typedef void RetVal_Round2;
592 
593  static void convert(Rational & res, const Integer & v, const RationalContext & rc)
594  {
595  res.d_num = v;
596  setOne(res.d_denom);
597  }
598 
599  static RetVal convert(const arithmetic::Integer & v, const RationalContext & c)
600  {
601  return RetVal(expressions::make_expression<IntegerContext>(v), c);
602  }
603 
604  static void convert_frac(Rational & res, const Integer & v1, const Integer & v2, const RationalContext & rc)
605  {
606  if (&res.d_num == &v2)
607  {
608  if (&res.d_denom == &v1)
609  {
610  swap(res.d_num, res.d_denom);
611  }
612  else
613  {
614  res.d_denom = v2; // v2 == res.d_num
615  res.d_num = v1;
616  res.normalize();
617  }
618  }
619  else
620  {
621  res.d_num = v1;
622  res.d_denom = v2;
623  res.normalize();
624  }
625  // Make sign correct
626  if (sign(res.d_denom) < 0)
627  {
628  neg(res.d_denom, res.d_denom);
629  neg(res.d_num, res.d_num);
630  }
631  }
632 
633  static RetVal_Frac convert_frac(const Integer & v1, const Integer & v2, const RationalContext & rc)
634  {
635  return Rational(v1, v2);
636  }
637  };
638 
639  template<class Data, template<typename, typename> class Op>
640  class conversion_impl<expressions::Expression<IntegerContext, Data, Op>, RationalContext>
641  {
642  private:
644 
645  public:
647  typedef Rational RetVal_Frac;
648  typedef void RetVal_Floor;
649  typedef void RetVal_Ceil;
650  typedef void RetVal_Round;
651  typedef void RetVal_Round2;
652 
653  static void convert(Rational & res, const Expr & v, const RationalContext & rc)
654  {
655  res.d_num = v;
656  setOne(res.d_denom);
657  }
658 
659  static RetVal convert(const Expr & v, const RationalContext & c)
660  {
661  return RetVal(v);
662  }
663 
664  static void convert_frac(Rational & res, const Integer & v1, const Integer & v2, const RationalContext & rc)
665  {
667  }
668 
669  static RetVal_Frac convert_frac(const Integer & v1, const Integer & v2, const RationalContext & rc)
670  {
672  }
673  };
674 
675  template<> class nativeconversion_impl<Rational>
676  {
677  public:
678  static int toInt(const Rational & v)
679  {
680  Integer r;
682  return convert<int>(r);
683  }
684 
685  static int toInt_Floor(const Rational & v)
686  {
687  Integer r;
689  return convert<int>(r);
690  }
691 
692  static int toInt_Round(const Rational & v)
693  {
694  Integer r;
696  return convert<int>(r);
697  }
698 
699  static int toInt_Round(const Rational & v, bool & up)
700  {
701  Integer r;
703  return convert<int>(r);
704  }
705 
706  static int toInt_Ceil(const Rational & v)
707  {
708  Integer r;
710  return convert<int>(r);
711  }
712 
713  static unsigned int toUInt(const Rational & v)
714  {
715  Integer r;
717  return convert<unsigned int>(r);
718  }
719 
720  static unsigned int toUInt_Floor(const Rational & v)
721  {
722  Integer r;
724  return convert<unsigned int>(r);
725  }
726 
727  static unsigned int toUInt_Round(const Rational & v)
728  {
729  Integer r;
731  return convert<unsigned int>(r);
732  }
733 
734  static unsigned int toUInt_Round(const Rational & v, bool & up)
735  {
736  Integer r;
738  return convert<unsigned int>(r);
739  }
740 
741  static unsigned int toUInt_Ceil(const Rational & v)
742  {
743  Integer r;
745  return convert<unsigned int>(r);
746  }
747 
748  static long toLong(const Rational & v)
749  {
750  Integer r;
752  return convert<long>(r);
753  }
754 
755  static long toLong_Floor(const Rational & v)
756  {
757  Integer r;
759  return convert<long>(r);
760  }
761 
762  static long toLong_Round(const Rational & v)
763  {
764  Integer r;
766  return convert<long>(r);
767  }
768 
769  static long toLong_Round(const Rational & v, bool & up)
770  {
771  Integer r;
773  return convert<long>(r);
774  }
775 
776  static long toLong_Ceil(const Rational & v)
777  {
778  Integer r;
780  return convert<long>(r);
781  }
782 
783  static unsigned long toULong(const Rational & v)
784  {
785  Integer r;
787  return convert<unsigned long>(r);
788  }
789 
790  static unsigned long toULong_Floor(const Rational & v)
791  {
792  Integer r;
794  return convert<unsigned long>(r);
795  }
796 
797  static unsigned long toULong_Round(const Rational & v)
798  {
799  Integer r;
801  return convert<unsigned long>(r);
802  }
803 
804  static unsigned long toULong_Round(const Rational & v, bool & up)
805  {
806  Integer r;
808  return convert<unsigned long>(r);
809  }
810 
811  static unsigned long toULong_Ceil(const Rational & v)
812  {
813  Integer r;
815  return convert<unsigned long>(r);
816  }
817 
818  static long long toLongLong(const Rational & v)
819  {
820  Integer r;
822  return convert<long long>(r);
823  }
824 
825  static long long toLongLong_Floor(const Rational & v)
826  {
827  Integer r;
829  return convert<long long>(r);
830  }
831 
832  static long long toLongLong_Round(const Rational & v)
833  {
834  Integer r;
836  return convert<long long>(r);
837  }
838 
839  static long long toLongLong_Round(const Rational & v, bool & up)
840  {
841  Integer r;
843  return convert<long long>(r);
844  }
845 
846  static long long toLongLong_Ceil(const Rational & v)
847  {
848  Integer r;
850  return convert<long long>(r);
851  }
852 
853  static float toFloat(const Rational & v)
854  {
855  return toDouble(v);
856  }
857 
858  static double toDouble(const Rational & v)
859  {
860  long n = approxLog2(v.d_num), d = approxLog2(v.d_denom);
861  if ((n < std::numeric_limits<double>::max_exponent) && (d < std::numeric_limits<double>::max_exponent))
862  return convert<double>(v.d_num) / convert<double>(v.d_denom);
863  else
864  {
865  long nr = n - std::numeric_limits<double>::digits - 4, dr = d - std::numeric_limits<double>::digits - 4;
866  if (nr < 0) nr = 0;
867  if (dr < 0) dr = 0;
868  Integer N = v.d_num >> nr, D = v.d_denom >> dr;
869  double r = convert<double>(N) / convert<double>(D);
870  return ldexp(r, nr - dr);
871  }
872  }
873 
874  static long double toLongDouble(const Rational & v)
875  {
876  long n = approxLog2(v.d_num), d = approxLog2(v.d_denom);
877  if ((n < std::numeric_limits<long double>::max_exponent) && (d < std::numeric_limits<long double>::max_exponent))
878  return convert<long double>(v.d_num) / convert<long double>(v.d_denom);
879  else
880  {
881  long nr = n - std::numeric_limits<long double>::digits - 4, dr = d - std::numeric_limits<long double>::digits - 4;
882  if (nr < 0) nr = 0;
883  if (dr < 0) dr = 0;
884  Integer N = v.d_num >> nr, D = v.d_denom >> dr;
885  long double r = convert<long double>(N) / convert<long double>(D);
886  return ldexp(r, nr - dr);
887  }
888  }
889  };
890  }
891 
892  namespace traits
893  {
894  template<>
896  {
897  enum
898  {
899  is_number = true,
900  is_cputype = false,
901  is_realtype = true,
902  is_inttype = false,
903  is_string = false,
904  is_cpp_string = false,
905  is_c_string = false,
906  is_exact = true,
907  has_context = true,
908  is_native = false,
909  is_modulo = false,
910  has_infinity = false,
911  is_variable_precision = false,
912  has_squareroot = false,
913  has_full_power = false,
914  has_special_fns = false,
915  has_huge_exponent = true,
916  has_uniform_rng = false,
917  has_constants = false,
918  has_trigonometric = false
919  };
920 
921  typedef RationalContext Context;
922  typedef Rational PromoteType;
923  typedef const Rational & ConstReferenceType;
924  };
925 
926  template<class Data, template<typename, typename> class Op>
927  struct type_traits<expressions::Expression<RationalContext, Data, Op> >
928  {
929  enum
930  {
931  is_number = true,
932  is_cputype = false,
933  is_realtype = true,
934  is_inttype = false,
935  is_string = false,
936  is_cpp_string = false,
937  is_c_string = false,
938  is_exact = true,
939  has_context = true,
940  is_native = false,
941  is_modulo = false,
942  has_infinity = false,
943  is_variable_precision = false,
944  has_squareroot = false,
945  has_full_power = false,
946  has_special_fns = false,
947  has_huge_exponent = true,
948  has_uniform_rng = false,
949  has_constants = false,
950  has_trigonometric = false
951  };
952 
953  typedef RationalContext Context;
954  typedef Rational PromoteType;
956  };
957  }
958 
959  namespace implementation
960  {
961  #define MAKE_RATIONAL_DEFS(Op1, Op2) \
962  template<> \
963  struct binary_operation_impl<Rational, Rational, Op1> \
964  { \
965  enum { supported = true, intermediate_expression = true }; \
966  typedef expressions::Expression<RationalContext, std::pair<expressions::Wrapper<RationalContext>, \
967  expressions::Wrapper<RationalContext> >, Op2> IntermediateType; \
968  typedef Rational ResultType; \
969  }; \
970  \
971  template<template<typename, typename> class O1, typename D1> \
972  struct binary_operation_impl<expressions::Expression<RationalContext, D1, O1>, Rational, Op1> \
973  { \
974  enum { supported = true, intermediate_expression = true }; \
975  typedef expressions::Expression<RationalContext, std::pair<expressions::Expression<RationalContext, D1, O1>, \
976  expressions::Wrapper<RationalContext> >, Op2> IntermediateType; \
977  typedef Rational ResultType; \
978  }; \
979  \
980  template<template<typename, typename> class O2, typename D2> \
981  struct binary_operation_impl<Rational, expressions::Expression<RationalContext, D2, O2>, Op1> \
982  { \
983  enum { supported = true, intermediate_expression = true }; \
984  typedef expressions::Expression<RationalContext, std::pair<expressions::Wrapper<RationalContext>, \
985  expressions::Expression<RationalContext, D2, O2> >, Op2> IntermediateType; \
986  typedef Rational ResultType; \
987  }; \
988  \
989  template<template<typename, typename> class O1, typename D1, template<typename, typename> class O2, typename D2> \
990  struct binary_operation_impl<expressions::Expression<RationalContext, D1, O1>, expressions::Expression<RationalContext, D2, O2>, Op1> \
991  { \
992  enum { supported = true, intermediate_expression = true }; \
993  typedef expressions::Expression<RationalContext, std::pair<expressions::Expression<RationalContext, D1, O1>, \
994  expressions::Expression<RationalContext, D2, O2> >, Op2> IntermediateType; \
995  typedef Rational ResultType; \
996  }; \
997 
998  MAKE_RATIONAL_DEFS(arithmetic::op::addition, expressions::AddOp)
999  MAKE_RATIONAL_DEFS(arithmetic::op::subtraction, expressions::SubOp)
1000  MAKE_RATIONAL_DEFS(arithmetic::op::multiplication, expressions::MulOp)
1001  MAKE_RATIONAL_DEFS(arithmetic::op::division, expressions::DivOp)
1002  MAKE_RATIONAL_DEFS(arithmetic::op::modulo, expressions::ModOp)
1003  #undef MAKE_RATIONAL_DEFS
1004 
1005  template<>
1007  {
1008  enum { supported = true, intermediate_expression = true };
1011  typedef Rational ResultType;
1012  };
1013 
1014  template<template<typename, typename> class O, class D>
1015  struct unary_operation_impl<expressions::Expression<RationalContext, D, O>, arithmetic::op::negation>
1016  {
1017  enum { supported = true, intermediate_expression = true };
1020  typedef Rational ResultType;
1021  };
1022  }
1023  }
1024 }
1025 
1026 #endif
Returns the sum of the operands.
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::FloorDivOp > floorDiv(const Integer &a, const Integer &b)
Computes and returns .
Converts the argument to the destination type. Uses the context stored in the operator.
void euclideanDivisionPos(Integer &q, Integer &r, const Integer &a, const Integer &b)
Computes an Euclidean Division of a by b.
expressions::Expression< RealContext, expressions::Wrapper< RealContext >, expressions::ExpOp > exp(const Real &i)
Returns the exponential function evaluated at the given floating point number.
Simply provides the data without any modifications.
Provides information on the result of an unary arithmetic operation.
Definition: arithmetic.hpp:138
void setOne(Integer &)
Sets the given integer to one.
Returns the negative of the operand.
expressions::Expression< IntegerContext, std::pair< expressions::Wrapper< IntegerContext >, expressions::Wrapper< IntegerContext > >, expressions::CeilDivOp > ceilDiv(const Integer &a, const Integer &b)
Computes and returns .
long approxLog2(const Integer &x) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Quickly approximates and returns the approximation.
Provides conversion implementation from type SourceType to DestContext::Type.
Definition: arithmetic.hpp:713
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
Converts the argument to the destination type by rounding. Uses the context stored in the operator an...
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
Converts the argument to the destination type by rounding down (floor). Uses the context stored in th...
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
Represents an arbitrary precision floating point value.
Converts the argument to the destination type by rounding up (ceil). Uses the context stored in the o...
int sign(const Integer &) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Returns the sign of the given integer.
Represents an arithmetic context for arbitrary precision floating point values.
void neg(Integer &r, const Integer &a)
Negates a and stores the result in r.
Converts the argument to the destination type by rounding. Uses the context stored in the operator...
const Integer & denominator() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Retrieves the denominator of this rational number.
Definition: rational.hpp:498
Provides information on arithmetic (and string) types.
Definition: arithmetic.hpp:184
Represents an arbitrary precision integer.
Wraps a variable to behave similarly to an Expression<> object.
Represents an arithmetic context for rational numbers.
Definition: rational.hpp:355
Represents an arithmetic context for arbitrary precision integer.