From
Krishna Myneni@21:1/5 to
All on Wed Jul 6 20:03:45 2022
Below is a draft of a paper which Forth system developers and
practitioners of numerical computing in Forth may find useful.
--
Krishna Myneni
Range reduction using double-double arithmetic in Forth
K. Myneni, 06 July 2022 (Draft version)
Introduction
The accuracy of the native Intel/AMD floating point unit (fpu)
instructions for the primitive trigonometric functions, sin(x) and
cos(x), degrades rapidly with increasing magnitude of the argument, x.
We illustrate this decrease with the sin(x) function, by comparing the
result from the native instruction with the result from first
subtracting an appropriate multiple of 2pi, and then applying the native
fpu FSIN instruction. The subtraction of a multiple of 2pi, to bring the argument into a small magnitude argument, is called "range reduction."
Range reduction must be performed using higher precision floating point arithmetic than the precision of the floating point arithmetic at which
the argument is represented. In this paper, we use double-double arithmetic[1--2], for which a Forth implementation is available[3]. We demonstrate that performing range reduction with double-double
arithmetic prior to calling the native fpu FSIN instruction provides 15 significant digits in the result, for |x| <= 1e-15. The floating point
format of the argument is assumed to be IEEE double-precision.
Some Forth systems which implement the standard trig functions directly
call the native fpu instructions, while others may use a library call
which performs range reduction on the argument prior to calling the fpu instruction. The word FSIN-NATIVE is defined to directly use the native
fpu instruction. The definition will be specific to an individual Forth
system, but, as an example, we show the definition which has this
behavior under kForth[4]. The word FSIN-RR is defined to perform range reduction of the argument and then calling the native instruction. The definition specific to kForth is shown below as an example. For kForth
under Linux, FSIN-RR calls the GCC math library's sin() function.
---
: fsin-native ( F: r1 -- r2 ) \ Forth-specific definition
fsincos fdrop ; \ this defn is specific to kForth
: fsin-rr ( F: r1 -- r2 ) fsin ; \ specific to kForth
17 set-precision
ok
\ x = 1,000,000.
1.0e6 fsin-rr fs.
-3.4999350217129294e-01 ok \ with range reduction
1.0e6 fsin-native fs.
-3.4999350217129177e-01 ok \ native fpu instruction
---
For an argument of 1.0e6 radians, we observe that FSIN-RR gives a result
which provides 17 significant digits, while FSIN-NATIVE instruction,
using 1e6, gives approximately 15 significant digits.
Even when no external library may be accessed to obtain higher accuracy
results for the trigonometric functions than provided by native fpu instructions, higher precision floating point arithmetic, over typical
double precision float implementations, may be performed in Forth using double-double arithmetic. This allows for improving the accuracy of the
basic trig functions. For example, for x = 1e6, which has an exact
binary represen