[[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 ||