23#ifndef __GNC_RATIONAL_ROUNDING_HPP__
24#define __GNC_RATIONAL_ROUNDING_HPP__
26#include "gnc-int128.hpp"
28template <
typename T>
inline bool
29quotient_is_positive(T dividend, T divisor)
31 return (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
57template <RoundType rt>
66template <
typename T>
inline T
71 throw std::domain_error(
"Rounding required when 'never round' specified.");
74template <
typename T>
inline T
82 if (num < 0 || (num == 0 && !quotient_is_positive(rem, den)))
101template <
typename T>
inline T
106 if (num > 0 || (num == 0 && quotient_is_positive(rem, den)))
122template <
typename T>
inline T
128template <
typename T>
inline T
134 return (!quotient_is_positive(rem, den) ? -1 : 1);
135 return num + (num < 0 ? -1 : 1);
144 return num + (num.isNeg() ? -1 : 1);
147template <
typename T>
inline T
152 if (std::abs(rem * 2) > std::abs(den))
155 return (!quotient_is_positive(rem, den) ? -1 : 1);
156 return num + (num < 0 ? -1 : 1);
167 if (rem.abs() * 2 > den.abs())
168 return num + (num.isNeg() ? -1 : 1);
172template <
typename T>
inline T
177 if (std::abs(rem) * 2 >= std::abs(den))
180 return (!quotient_is_positive(rem, den) ? -1 : 1);
181 return num + (num < 0 ? -1 : 1);
192 if (rem.abs() * 2 >= den.abs())
193 return num + (num.isNeg() ? -1 : 1);
197template <
typename T>
inline T
202 if (std::abs(rem * 2) > std::abs(den) ||
203 (std::abs(rem * 2) == std::abs(den) && num % 2))
206 return (!quotient_is_positive(rem, den) ? -1 : 1);
207 return num + (num < 0 ? -1 : 1);
218 if (rem.abs() * 2 > den.abs() ||
219 (rem.abs() * 2 == den.abs() && num % 2))
220 return num + (num.isNeg() ? -1 : 1);
An exact-rational-number library for gnucash.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
@ GNC_HOW_RND_ROUND_HALF_DOWN
Round to the nearest integer, rounding toward zero when there are two equidistant nearest integers.
@ GNC_HOW_RND_FLOOR
Round toward -infinity.
@ GNC_HOW_RND_PROMOTE
Promote fractions (round away from zero)
@ GNC_HOW_RND_NEVER
Never round at all, and signal an error if there is a fractional result in a computation.
@ GNC_HOW_RND_CEIL
Round toward +infinity.
@ GNC_HOW_RND_TRUNC
Truncate fractions (round toward zero)
@ GNC_HOW_RND_ROUND
Use unbiased ("banker's") rounding.
@ GNC_HOW_DENOM_REDUCE
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
@ GNC_HOW_DENOM_FIXED
All arguments are required to have the same denominator, that denominator is to be used in the output...
@ GNC_HOW_DENOM_LCD
Find the least common multiple of the arguments' denominators and use that as the denominator of the ...
@ GNC_HOW_DENOM_SIGFIG
Round to the number of significant figures given in the rounding instructions by the GNC_HOW_DENOM_SI...
@ GNC_HOW_DENOM_EXACT
Use any denominator which gives an exactly correct ratio of numerator to denominator.