23 #ifndef PLLL_INCLUDE_GUARD__RATIONAL_CONV_HPP
24 #define PLLL_INCLUDE_GUARD__RATIONAL_CONV_HPP
37 namespace implementation
46 typedef void RetVal_Floor;
47 typedef void RetVal_Ceil;
48 typedef void RetVal_Round;
49 typedef void RetVal_Round2;
83 typedef void RetVal_Floor;
84 typedef void RetVal_Ceil;
85 typedef void RetVal_Round;
86 typedef void RetVal_Round2;
120 typedef void RetVal_Floor;
121 typedef void RetVal_Ceil;
122 typedef void RetVal_Round;
123 typedef void RetVal_Round2;
160 typedef void RetVal_Floor;
161 typedef void RetVal_Ceil;
162 typedef void RetVal_Round;
163 typedef void RetVal_Round2;
183 if (
sign(d.d_denom) < 0)
185 neg(d.d_denom, d.d_denom);
186 neg(d.d_num, d.d_num);
193 convert_frac(r, v1, v2, c);
206 typedef void RetVal_Floor;
207 typedef void RetVal_Ceil;
208 typedef void RetVal_Round;
209 typedef void RetVal_Round2;
229 if (
sign(d.d_denom) < 0)
231 neg(d.d_denom, d.d_denom);
232 neg(d.d_num, d.d_num);
239 convert_frac(r, v1, v2, c);
252 typedef void RetVal_Floor;
253 typedef void RetVal_Ceil;
254 typedef void RetVal_Round;
255 typedef void RetVal_Round2;
275 if (
sign(d.d_denom) < 0)
277 neg(d.d_denom, d.d_denom);
278 neg(d.d_num, d.d_num);
285 convert_frac(r, v1, v2, c);
298 typedef void RetVal_Floor;
299 typedef void RetVal_Ceil;
300 typedef void RetVal_Round;
301 typedef void RetVal_Round2;
321 if (
sign(d.d_denom) < 0)
323 neg(d.d_denom, d.d_denom);
324 neg(d.d_num, d.d_num);
331 convert_frac(r, v1, v2, c);
344 typedef void RetVal_Floor;
345 typedef void RetVal_Ceil;
346 typedef void RetVal_Round;
347 typedef void RetVal_Round2;
367 if (
sign(d.d_denom) < 0)
369 neg(d.d_denom, d.d_denom);
370 neg(d.d_num, d.d_num);
377 convert_frac(r, v1, v2, c);
387 typedef void RetVal_Floor;
388 typedef void RetVal_Ceil;
389 typedef void RetVal_Round;
390 typedef void RetVal_Round2;
425 typedef void RetVal_Floor;
426 typedef void RetVal_Ceil;
427 typedef void RetVal_Round;
428 typedef void RetVal_Round2;
433 mpfr_exp_t
exp = mpfr_get_z_2exp(res.d_num.d_value, r.d_value);
437 res.d_denom <<= -
exp;
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);
453 res.d_num <<= exp1 - exp2;
454 else if (exp1 < exp2)
455 res.d_denom <<= exp2 - exp1;
458 if (
sign(res.d_denom) < 0)
460 neg(res.d_denom, res.d_denom);
461 neg(res.d_num, res.d_num);
468 convert_frac(res, r1, r2, rc);
475 #ifndef PLLL_INTERNAL_NO_TEMPLATE_FRIENDS
482 static inline void toint(
Integer & r,
const Rational & v)
484 r = v.d_num / v.d_denom;
487 static inline void toint_floor(
Integer & r,
const Rational & v)
492 static inline void toint_round(
Integer & r,
const Rational & v)
501 static inline void toint_round(
Integer & r,
const Rational & v,
bool & up)
506 if ((up = (rr >= v.d_denom)) ==
true)
510 static inline void toint_ceil(
Integer & r,
const Rational & v)
512 ceilDiv(r, v.d_num, v.d_denom);
518 typedef void RetVal_Frac;
535 return RetVal(expressions::make_expression<RationalContext>(v), c);
545 return RetVal_Floor(expressions::make_expression<RationalContext>(v), c);
555 return RetVal_Round(expressions::make_expression<RationalContext>(v), c);
560 toint_round(res, v, up);
565 return RetVal_Round2(expressions::make_expression<RationalContext>(v),
578 return RetVal_Ceil(expressions::make_expression<RationalContext>(v), c);
588 typedef void RetVal_Floor;
589 typedef void RetVal_Ceil;
590 typedef void RetVal_Round;
591 typedef void RetVal_Round2;
601 return RetVal(expressions::make_expression<IntegerContext>(v), c);
606 if (&res.d_num == &v2)
608 if (&res.d_denom == &v1)
610 swap(res.d_num, res.d_denom);
626 if (
sign(res.d_denom) < 0)
628 neg(res.d_denom, res.d_denom);
629 neg(res.d_num, res.d_num);
639 template<
class Data,
template<
typename,
typename>
class Op>
648 typedef void RetVal_Floor;
649 typedef void RetVal_Ceil;
650 typedef void RetVal_Round;
651 typedef void RetVal_Round2;
678 static int toInt(
const Rational & v)
682 return convert<int>(r);
685 static int toInt_Floor(
const Rational & v)
689 return convert<int>(r);
692 static int toInt_Round(
const Rational & v)
696 return convert<int>(r);
699 static int toInt_Round(
const Rational & v,
bool & up)
703 return convert<int>(r);
706 static int toInt_Ceil(
const Rational & v)
710 return convert<int>(r);
713 static unsigned int toUInt(
const Rational & v)
717 return convert<unsigned int>(r);
720 static unsigned int toUInt_Floor(
const Rational & v)
724 return convert<unsigned int>(r);
727 static unsigned int toUInt_Round(
const Rational & v)
731 return convert<unsigned int>(r);
734 static unsigned int toUInt_Round(
const Rational & v,
bool & up)
738 return convert<unsigned int>(r);
741 static unsigned int toUInt_Ceil(
const Rational & v)
745 return convert<unsigned int>(r);
748 static long toLong(
const Rational & v)
752 return convert<long>(r);
755 static long toLong_Floor(
const Rational & v)
759 return convert<long>(r);
762 static long toLong_Round(
const Rational & v)
766 return convert<long>(r);
769 static long toLong_Round(
const Rational & v,
bool & up)
773 return convert<long>(r);
776 static long toLong_Ceil(
const Rational & v)
780 return convert<long>(r);
783 static unsigned long toULong(
const Rational & v)
787 return convert<unsigned long>(r);
790 static unsigned long toULong_Floor(
const Rational & v)
794 return convert<unsigned long>(r);
797 static unsigned long toULong_Round(
const Rational & v)
801 return convert<unsigned long>(r);
804 static unsigned long toULong_Round(
const Rational & v,
bool & up)
808 return convert<unsigned long>(r);
811 static unsigned long toULong_Ceil(
const Rational & v)
815 return convert<unsigned long>(r);
818 static long long toLongLong(
const Rational & v)
822 return convert<long long>(r);
825 static long long toLongLong_Floor(
const Rational & v)
829 return convert<long long>(r);
832 static long long toLongLong_Round(
const Rational & v)
836 return convert<long long>(r);
839 static long long toLongLong_Round(
const Rational & v,
bool & up)
843 return convert<long long>(r);
846 static long long toLongLong_Ceil(
const Rational & v)
850 return convert<long long>(r);
853 static float toFloat(
const Rational & v)
858 static double toDouble(
const Rational & v)
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);
865 long nr = n - std::numeric_limits<double>::digits - 4, dr = d - std::numeric_limits<double>::digits - 4;
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);
874 static long double toLongDouble(
const Rational & v)
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);
881 long nr = n - std::numeric_limits<long double>::digits - 4, dr = d - std::numeric_limits<long double>::digits - 4;
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);
904 is_cpp_string =
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
926 template<
class Data,
template<
typename,
typename>
class Op>
927 struct type_traits<expressions::Expression<RationalContext, Data, Op> >
936 is_cpp_string =
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
959 namespace implementation
961 #define MAKE_RATIONAL_DEFS(Op1, Op2) \
963 struct binary_operation_impl<Rational, Rational, Op1> \
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; \
971 template<template<typename, typename> class O1, typename D1> \
972 struct binary_operation_impl<expressions::Expression<RationalContext, D1, O1>, Rational, Op1> \
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; \
980 template<template<typename, typename> class O2, typename D2> \
981 struct binary_operation_impl<Rational, expressions::Expression<RationalContext, D2, O2>, Op1> \
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; \
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> \
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; \
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
1008 enum { supported =
true, intermediate_expression =
true };
1014 template<
template<
typename,
typename>
class O,
class D>
1017 enum { supported =
true, intermediate_expression =
true };
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.
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.
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...
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.
Represents a rational number as a quotient of two arbitrary precision integers.
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.
Represents an expression.
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.
Provides information on arithmetic (and string) types.
Represents an arbitrary precision integer.
Wraps a variable to behave similarly to an Expression<> object.
Represents an arithmetic context for rational numbers.
Represents an arithmetic context for arbitrary precision integer.