Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
rational.hpp
Go to the documentation of this file.
1/*
2 RATIONAL.hpp - support for precise rational arithmetics
3
4 Copyright (C)
5 2022, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
58#ifndef LIB_RATIONAL_H
59#define LIB_RATIONAL_H
60
61
62#include "lib/integral.hpp"
63#include "lib/util-quant.hpp"
64
65#include <cmath>
66#include <limits>
67#include <stdint.h>
68#include <boost/rational.hpp>
69
70
71namespace util {
72
73 using Rat = boost::rational<int64_t>;
74 using boost::rational_cast;
75 using std::abs;
76
77
78
79 inline bool
80 can_represent_Product (int64_t a, int64_t b)
81 {
82 return ilog2(abs(a))+1
83 + ilog2(abs(b))+1
84 < 63;
85 }
86
87 inline bool
89 {
90 return can_represent_Product(a.numerator(), b.numerator())
91 and can_represent_Product(a.denominator(), b.denominator());
92 }
93
94 inline bool
96 {
97 return can_represent_Product(a.numerator(), b.denominator())
98 and can_represent_Product(b.numerator(), a.denominator());
99 }
100
101
119 inline int64_t
120 reQuant (int64_t num, int64_t den, int64_t u)
121 {
122 u = 0!=u? u:1;
123 auto [d,r] = util::iDiv (num, den);
124 // round to smallest integer fraction, to shake off "number dust"
125 f128 const ROUND_ULP = 1 + 1/(f128(std::numeric_limits<int64_t>::max()) * 2);
126
127 // construct approximation quantised to 1/u
128 f128 frac = f128(r) / den;
129 int64_t res = d*u + int64_t(frac*u * ROUND_ULP);
130 ENSURE (abs (f128(res)/u - rational_cast<f128>(Rat{num,den})) <= 1.0/abs(u)
131 ,"Requantisation error exceeded num=%li / den=%li -> res=%li / quant=%li"
132 , num, den, res, u);
133 return res;
134 }
135
149 inline Rat
150 reQuant (Rat src, int64_t u)
151 {
152 return Rat{reQuant (src.numerator(), src.denominator(), u), u};
153 }
154} // namespace util
155
156
157
164inline util::Rat
165operator""_r (ullong num)
166{
167 return util::Rat{num};
168}
169
170
171#endif /*LIB_RATIONAL_H*/
Inclusion for common place integral types and constants.
unsigned long long int ullong
Definition integral.hpp:33
long double f128
Definition integral.hpp:36
constexpr int ilog2(I num)
Integral binary logarithm (disregarding fractional part)
IDiv< I > iDiv(I num, I den)
boost::rational< int64_t > Rat
Definition rational.hpp:73
bool can_represent_Product(int64_t a, int64_t b)
Definition rational.hpp:80
int64_t reQuant(int64_t num, int64_t den, int64_t u)
Re-Quantise a number into a new grid, truncating to the next lower grid point.
Definition rational.hpp:120
bool can_represent_Sum(Rat a, Rat b)
Definition rational.hpp:95
Utilities for quantisation (grid alignment) and comparisons.