include lib/range.4th include lib/pickroll.4th \ Linear Interpolation \ Copyright 2002, Chris Jakeman \ 4tH version - Copyright 2009, Hans Bezemer \ The new Source Code Index lists several ways to extract data from a table of \ data points and estimate the values in between the entries. In this example, \ the data points provide the sine of an angle, with 8 data points are used to \ span a full right-angle. (Linear Interpolation is fast and suitable for any \ function, but do check that your Forth doesn't provide the function \ (eg FSIN) already.) \ For the scheme to work, the X interval between data points must be a power \ of 2. In this example, it is 24 or 16. We do as much work as possible at \ compile time. Each entry in the data table contains 2 values, the Y value \ corresponding to X and also the Y' - Y value, dY, which is the increase in \ Y to reach the next data point. We can fetch both values at once using 2@c. 4 CONSTANT Bits/Step \ 2^4 = 16 15 CONSTANT BitMask \ Ie. Binary 00001111 create SinTable \ Sample table for 2^10 x Sin(X*128/90) \ Preamble BitMask , Bits/Step , \ used by Interpolate 0 , 129 , \ Min and max+1 limits to X \ Data Points \ Y X X' 200 , 0 , 192 , 200 , 177 , 392 , 155 , 569 , 127 , 724 , 95 , 851 , 58 , 946 , 20 , 1004 , 0 , 1024 , : 2@c dup cell+ @c swap @c ; : Interpolate ( X*128/90 Table -- result*2^10 ) swap \ -- Table X over 2@c \ Get Bits/Step and BitMask from table 2 pick and \ Extract lower bits over >r >r \ Stash them and Bits/Step rshift \ Fast divide of higher bits gets index 2 cells * \ Index down the table 4 cells + \ Skip past the preamble + 2@c \ Get pair of values for entry r> * \ Calc interpolation r> 1- rshift 1+ 1 rshift \ Add 1 during division to round result + \ Add dY to Y ; : SafeInterpolate ( X &Table -- Result ) 2dup 2 cells + 2@c within abort" Outside range of look-up table" Interpolate ; : Sin ( Angle*8/90 – Sin{A}*1024 ) SinTable SafeInterpolate ; 39 Sin . .( should = 469 )