Thanks for all the comments Alex, we are still in an early stage and every input is useful for us. Sorry for the long delay in the reply.
I'm adding some context of our current work before going to the replies.
My motivation for the first implementation of this library was in the domain of Discrete-Event Simulation (DES). Looking for a representation for Time variables.
The main problem of using Floating point or other approximated data types in (some) DES is that errors of the approximations could not be bounded.
In the case of Time, only 3 operations were interesting for me, (+, <, =).
Each number was represented by a vector
What do you mean by restricting the set of numbers? Restricting the expressibility for the digit generating functions; e.g., providing some basic reals (pi, e, ...) and the only other way to generate new ones is by using arithmetic operations?
Yes. But, leaving the set open to be introduced by the user as template parameters. For example, e and pi is not proven to be linearly independent set of constants over Q, so it should not be used. However, pi and sq_rt(2), or e and sq_rt(2) are both valid sets of irrational constants.
In that setting, equality might indeed be decidable, but not by the algorithm you proposed. But I think you have to restrain to symbolic manipulations, most likely by finding some normal form for arithmetic expressions and comparing them. (Btw, that's what I meant by Computer Algebra System in my earlier message.)
Yes, It is a CAS then :)
For clarity, is the goal infinite precision equality?
Actually, my motivation was infinite precision of < comparison, but equality was required for getting that (at least using this solution).
Boost.Multiprecision also has infinite precision (in theory). The difference of your suggestion would be that as you do lazy-evaluation, you don't have to specify the precision a priori.
Here, multi precision needs the whole representation to be available for every operation. In the case of comparing using algorithms, you only have representation for the current digit dependencies. For example, if you have compared the first few digits in an operation and they are equal, then for comparing the following thousands you don’t need them (unless you require them to compare the following digits, but thats a problem with the algorithm used for the number, not with the approach). For example the binary number composed by all zeros, but positions p where p is power of 2. Only requires a counter for deciding each number. And the limitation of how many digits can be expanded is imposed by time, almost no space usage at all. It is a tradeoff between time/space.
I don't really understand. I see that for certain numbers the approach might work -- if, together with the number, you also provide implementations for equality and all the other relations and operations.
I don’t see how you distinguish (in multi precision) a very large rational from an irrational. Then, you cannot tell when digits are exhausted was because of an approximation of the true rational value. Also, you will operate with every digit in every operation. In our described approach, equality and addition only work with the coefficients with no requirement of a large representation (0.1pi == 0.1 pi only checks 0.1==0.1, and not every digit used if represented as MP, which we expect to be a lot of digits). In our case, expansion is only used for < comparison (only after checking != is true).
Let's make it more specific: You can generate pi, for example, by different series, some converging faster than others. Do you mean that by generator? Then, of course, the speed of the generators is the basis for the performance, but that's not my point.
Yes, I meant that.
Maybe I don't understand, so let's consider an example: Take any natural i and put y = x_i, where x_0=pi and x_i=((x_{i-1}+1)-1 for natural i>0. How do you implement deciding y == pi?
We take a set of constants including pi, for example, <1, pi, sqrt2> (the one is always implicitly included for representing rationals).
Something like this:
class pi : public irrational_constant{
…
};
class sqrt2 : public irrational_constant{
…
};
real