Author: wmb Date: Fri Jun 1 20:31:33 2012 New Revision: 2995 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2995
Log: isin.fth - before svn 2994, the calculation in set-period was using */, which is supposed to use a double-precision intermediate value to avoid overflow. However, */ is not a primitive FCode, so the FCode tokenizer was synthesizing it (incorrectly) using (overflowing) * and /. The correct fix, to retain precision, is to implement "u*/" using (double-precision) um* and um/mod .
Modified: forth/lib/isin.fth
Modified: forth/lib/isin.fth ============================================================================== --- forth/lib/isin.fth Fri Jun 1 14:21:35 2012 (r2994) +++ forth/lib/isin.fth Fri Jun 1 20:31:33 2012 (r2995) @@ -27,17 +27,17 @@ 2/ dup to #cycle/2 2/ to #cycle/4 ; +: u*/ ( u1 unum udenom -- u2 ) >r um* r> um/mod nip ; : set-period ( cycle/4 -- ) dup to #cycle/4 ( cycle/4 ) 2* dup to #cycle/2 ( cycle/2 ) 2* dup to #cycle ( cycle ) fs over / to freq ( period ) - pi swap / fs * to fstep ( ) + pi fs rot u*/ to fstep ( ) ;
\ Multiply two fractional numbers where the scale factor is 2^15 -\ : times ( n1 n2 -- n3 ) d# 32767 */ ; \ Insignificantly more accurate, but slower -: times ( n1 n2 -- n3 ) * d# 15 rshift ; +: times ( n1 n2 -- n3 ) d# 32767 u*/ ;
\ Computes (1 - (theta^2 / divisor) * last) : sin-step ( last divisor -- next ) thetasq swap / times one min one swap - ; @@ -48,7 +48,7 @@ \ 1 - (t^2/(1*2)) * (1 - (t^2/(3*4)) * (1 - (t^2/(5*6)) * (1 - (t^2/(7*8))))
: icos ( index -- frac ) - fstep fs 2/ */ to theta + fstep fs 2/ u*/ to theta theta dup times to thetasq one d# 90 cos-step d# 56 cos-step d# 30 cos-step d# 12 cos-step 2 cos-step one min ; @@ -59,7 +59,7 @@ \ theta * (1 - (theta^2/(2*3)) * (1 - (theta^2/(4*5)) * (1 - (theta^2/(6*7)) * (1 - (theta^2/(8*9)))))) \ This is good for the first quadrant only, i.e. 0 <= index <= fs / freq / 4 : calc-sin ( index -- frac ) - fstep fs 2/ */ to theta + fstep fs 2/ u*/ to theta theta dup times to thetasq one d# 72 sin-step d# 42 sin-step d# 20 sin-step 6 sin-step theta times one min ;
openfirmware@openfirmware.info