[[TOC]]
= =
View this file in the source browser: [browser:trunk/src/lol/math/real.h]
Real numbers are a custom class that stores floating-point numbers with approximately 150 digits of precision.
'''Bug warning''': it is not yet possible to change the precision without recompiling everything.
Care has been taken to make the use of the `real` object as close as possible to `float` or `double`.
== Usage ==
Support for real numbers is straightforward:
{{{
#!cpp
#include
using lol::real;
}}}
If you are not using the full Lol Engine but a stripped down version such as LolRemez, make sure you compile `real.cpp` together with your application.
If you do not wish to have a `using` declaration, simply use `lol::real` everywhere instead of `real`.
== Creation ==
You can create a real number using numeric literals:
{{{
#!cpp
real x = 1.25, y = 2.0f;
real z = 0x100000;
real w(5);
}}}
It is also possible to use a string representation:
{{{
#!cpp
real w = "1.202056903159594285399738161511449990764986292";
}}}
'''Warning''': it is critical that you understand the difference between `"0.1"` and `0.1` here:
{{{
#!cpp
real correct = "0.1";
real wrong = 0.1;
}}}
When you write `0.1` the compiler understands this as a ''double precision floating point literal'' whose actual value is `0.1000000000000000055511151231257827021181583404541015625`, so you only get 17 digits of precision. When you write `"0.1"` the real number constructor will understand what you mean and will create an object with the highest possible precision.
Note that parsing a string to build a real number is '''expensive'''. Whenever possible, try to initialise reused variables only once, or use the constants provided by the `real` class.
== Constants ==
Some commonly used constants are provided by the `real` class. They are similar to the `M_PI`, `M_E` etc. variables provided by the `` header except they have the `R_` prefix for “real”.
|| `R_0` || the integer value 0 ||
|| `R_1` || the integer value 1 ||
|| `R_2` || the integer value 2 ||
|| `R_3` || the integer value 3 ||
|| `R_10` || the integer value 10 ||
|| `R_E` || Euler’s number ''e'' ||
|| `R_LOG2E` || the reciprocal of ''ln(2)'' ||
|| `R_LOG10E` || the reciprocal of ''ln(10)'' ||
|| `R_LN2` || ''ln(2)'', the natural logarithm of 2 ||
|| `R_LN10` || ''ln(10)'', the natural logarithm of 10 ||
|| `R_PI` || Archimede’s constant ''pi'' ||
|| `R_PI_2` || ''pi'' divided by 2 ||
|| `R_PI_3` || ''pi'' divided by 3 ||
|| `R_PI_4` || ''pi'' divided by 4 ||
|| `R_1_PI` || the reciprocal of ''pi'' ||
|| `R_2_PI` || 2 divided by ''pi'' ||
|| `R_2_SQRTPI` || 2 divided by the square root of ''pi'' ||
|| `R_SQRT2` || Pythagoras’ constant, the square root of 2 ||
|| `R_SQRT3` || Theodorus’ constant, the square root of 3 ||
|| `R_SQRT1_2` || the square root of 1/2 ||
All these constants are accurate up to the full precision of the real number class.
== Conversions ==
Real numbers can be cast implicitly to numeric types with basically the same rules as `float` or `double`:
{{{
#!cpp
real r ("1.5");
float f = r;
double d = real::R_LN10;
}}}
You can also print a real number to `stdout` with an arbitrary number of decimals:
{{{
#!cpp
real r("3.1415");
r.print(10);
}}}
{{{
3.141500000
}}}
'''Bug warning''': it is not yet possible to output a real number to a standard C++ stream.
== Operators ==
Most expected operators are available for real numbers:
* `+`, `-`, `*`, `/`
* unary `+`, unary `-`
* `+=`, `-=`, `*=`, `/=`
* `==`, `!=`, `<`, `<=`, `>`, `>=`
* implicit boolean conversion and `!` operator
=== Example ===
Compute the first 150 digits of the golden ratio as the quotient of two very large Fibonacci numbers:
{{{
#!cpp
real a0(1), a1(1);
for (int i = 0; i < 400; i++)
{
real tmp = a0 + a1;
a0 = a1; a1 = tmp;
}
(a0 / a1).print(150);
}}}
{{{
6.18033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137484754088075386891752126633862223536931793180060766e-1
}}}
== Functions ==
Most expected `` functions are available for real numbers, even those only introduced in the C99 standard.
=== Trigonometric functions ===
|| `sin` || sine function ||
|| `cos` || cosine function ||
|| `tan` || tangent function ||
|| `asin` || arcsine function ||
|| `acos` || arccosine function ||
|| `atan` || arctangent function ||
|| `atan2` || two-argument arctangent ||
=== Hyperbolic functions ===
|| `sinh` || hyperbolic sine ||
|| `cosh` || hyperbolic cosine ||
|| `tanh` || hyperbolic tangent ||
=== Exponentials and logarithms ===
|| `exp(x)` || exponential ||
|| `exp2(x)` || base-2 exponential ||
|| `log(x)` || natural logarithm ||
|| `log2(x)` || base-2 logarithm ||
|| `log10(x)` || base-10 logarithm ||
|| `frexp(x,&exp)` || split number into a normalised fraction and an exponent ||
|| `ldexp(x,exp)` || multiply ''x'' by two to the power of ''exp'' ||
|| `modf(x)` || split ''x'' into an integral part and a fractional part ||
|| `ulp(x)` || return the smallest real ''e'' such that ''x+e != x'' ||
|| `nextafter(x,y)` || return the next representable real following ''x'' in the direction of ''y'' ||
=== Power functions ===
|| `re` || reciprocal: 1 divided by ''x'' ||
|| `sqrt` || square root ||
|| `cbrt` || cubic root ||
|| `pow` || ''x'' raised to the power ''y'' ||
|| `gamma` || the gamma function ||
'''Bug warning''': as of now, the gamma function is only accurate to about 100 decimals instead of the expected 150.
=== Rounding, absolute value, remainder etc. ===
|| `ceil` || the ceiling function ||
|| `copysign` || copy ''x''’s sign to ''y'' ||
|| `floor` || the floor function ||
|| `fabs` || absolute value ||
|| `round` || the rounding function ||
|| `fmod` || modulo: remainder of dividing ''x'' by ''y'' ||
=== Example ===
Find the solution to ''cos(x) = x³'' using [http://en.wikipedia.org/wiki/Newton's_method#Solution_of_cos.28x.29_.3D_x3 Newton-Raphson]:
{{{
#!cpp
real x(0.5);
for (int i = 0; i < 10; i++)
x = x - (cos(x) - x * x * x) / (-sin(x) - real::R_3 * x * x);
x.print(150);
}}}
{{{
8.65474033101614446620685901186228747792911931818935500889279915855447006056021560514064272319562802280528781987092146472497110319687730308211712150975e-1
}}}
== Tips ==
=== Multiplication by powers of two ===
For fast multiplication or division by a power of two, use `ldexp` or integer operands:
{{{
#!cpp
real a = real::R_PI * (real)8; /* DO NOT USE: SLOW! */
real b = real::R_PI * 8.0f; /* DO NOT USE: SLOW! */
real c = real::R_PI * 8; /* OK, will be optimised */
real d = ldexp(real::R_PI, 3); /* OK, even better than above */
}}}
Multiplication by an integer type (`int`, `long int` etc.) detects powers of two automatically.
=== General speed observations ===
The Lol Engine real numbers target accuracy rather than speed: we expect functions such as `sin`, `exp` or `pow` to always be accurate to the last digit of precision. However, they may be very slow.
The table shows the relative timings you may expect from various operations:
|| '''operation''' || '''speed''' (milliseconds) ||
|| `+` (real) || 0.14 ||
|| `*` (real) || 0.54 ||
|| `/` (real) || 6.50 ||
|| `sin` (real) || 90.00 ||
|| `exp` (real) || 160.00 ||
As a comparison, here are some values for floats:
|| '''operation''' || '''speed''' (milliseconds) ||
|| `/` (float) || 0.001 ||
|| `sin` (float) || 0.40 ||
|| `exp` (float) || 0.08 ||