Guest User

32MATH.SEQ

a guest
Jul 10th, 2024
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.25 KB | Software | 0 0
  1. \ 32 bit integer, fixed and floating point arithmetic.
  2. comment:
  3. The 32 bit integer and fixed point maths is by:-
  4. Prof Tim Hendtlass, Physics Department, Swinburne University of Technology,
  5. P.O.BOX 218 Hawthorn 3122 Australia. Voice 61 3 819 8863 Fax 61 3 818 3645.
  6. Please let me know of any bugs, fixes, add ons, add ins etc. The 32 bit
  7. floating point routines are slightly reworked from the originals by Martin
  8. Tracy. The cute little transcindental package is by Nathaniel Grossman.
  9. This code originally appeared in Forth Dimensions in an article entitled
  10. "Maths - Who needs it?" As well as some explanation, the article contains
  11. timing data and space requirments.
  12. My code is hereby placed in the public domain, I believe all the other code
  13. in this file to have also been placed in the public doimain by the authors.
  14. Happy Forthing. Tim. 18/8/92
  15. comment;
  16. \ *********************************************************
  17. \ * 32 bit Integer Arithmetic *
  18. \ *********************************************************
  19. \ Don't forget that the normal D+ and D- and DABS work for 32 bit integer
  20. \ and fixed point numbers too!
  21. \ *********************************
  22. \ * 32 bit Integer Multiplication *
  23. \ *********************************
  24.  
  25. \ Unsigned double * unsigned double = unsigned double (No overflow check)
  26. : UD* \ unsigned 32 bit answer, no overflow check
  27. rot >r over >r >r over >r \ put c b a d on return stack
  28. um* \ b*d = part of 32 bit answer
  29. 2r> * 2r> * + + \ a*d+b*c= addition to top 16 bits
  30. ;
  31. \ Signed double * signed double = signed double (No overflow check)
  32. : D* \ signed, no overflow check
  33. dup>r dabs 2swap dup>r dabs \ #s +ve, keep info to work out final sign
  34. ud* \ get 32 bit answer
  35. 2r> xor ?dnegate \ work out and apply final sign
  36. ;
  37. \ Unsigned double * unsigned double = unsigned double (with overflow check)
  38. : UD*C \ unsigned, with overflow check
  39. dup>r rot dup>r >r over >r \ put a c c b on return stack
  40. >r swap dup>r \ put a d onto return stack
  41. um* \ b*d
  42. 0 2r> um* d+ 2r> um* d+ \ offset 16 bits, add on a*d+b*c
  43. 0 2r> um* d+ \ off another 16 bits, add on a*c
  44. or 0<> abort" D* overflow" \ check for overflow
  45. ;
  46. \ ***************************
  47. \ * 32 bit Integer Division *
  48. \ ***************************
  49. \ Use fast algorithm, remainder requires an additional 32 bit multiplication
  50. \ and sutraction.
  51. \ Unsigned double * unsigned single = unsigned triple
  52. : T* ( ud un -- ut )
  53. dup \ ud un un
  54. rot \ udl un un udh
  55. um* \ udl un high-ans
  56. 2>r \ udl un
  57. um* 0 2r> d+ \ low-ans then add on high-answer after ofsetting it 16 bits
  58. ;
  59. \ Unsigned triple / unsigned single = unsigned double
  60. : T/ ( ut un -- ud )
  61. >r r@ um/mod swap \ divisor to r, divide top two words, rem to top
  62. rot 0 r@ um/mod swap \
  63. rot r> um/mod swap drop
  64. 0 2swap swap d+
  65. ;
  66. \ Calculate ud * un1 / un2. Triple intermediate product.
  67. : U*/ ( ud un1 un2 -- ud2 )
  68. >r t* r> t/
  69. ;
  70. \ Unsigned 32 bit by 32 bit divide. No remainder.
  71. : UD/ ( ud1 ud2 -- ud3 )
  72. dup 0= \ top 16 bits of divisor = 0?
  73. if swap t/ \ make it a triple, do the division
  74. else
  75. dup 65536. rot 1+ um/mod >r \ work out scaling factor,copy to return stack
  76. drop r@ t* drop 2>r \ scale denominator, move to return stack
  77. dup 0 2r@ u*/ d- \ calculate (U-U0*W1/W0)
  78. 2r> r> -rot nip u*/ \ multiply by (D/W0)
  79. nip 0 \ /2^16 (use top 16bits only),make ans double
  80. then
  81. ;
  82. \ Divides two double numbers. All numbers are signed doubles.
  83. : D/MOD ( dn1 dn2 -- drem dquot )
  84. 2 pick over xor >r \ work out sign of answer
  85. dabs 2swap dabs 2swap \ convert numbers to positive
  86. 4dup ud/ 2dup 2>r \ do the division, save copy ans
  87. ud* d- \ calculate remainder
  88. 2r> r> ?dnegate \ retrieve answer,apply final sign
  89. ;
  90. : D/ ( dn1 dn2 -- dquot )
  91. 2 pick over xor >r \ work out sign of answer
  92. dabs 2swap dabs 2swap \ convert numbers to positive
  93. ud/ \ do the division
  94. r> ?dnegate \ retrieve answer,apply final sign
  95. ;
  96.  
  97. \ *********************************************************
  98. \ * 32 bit Fixed Point Arithmetic *
  99. \ *********************************************************
  100.  
  101. \ *****************************************
  102. \ * Defining the fixed point structure *
  103. \ *****************************************
  104. variable fdpl variable fscl
  105. : FPLACES ( -- n ) fdpl @ ; \ number of implied decimal places
  106. : FSCALE ( -- n ) fscl @ ; \ scaling factor we are using
  107. : FIXED ( n -- )
  108. 0 max 4 min fdpl ! \ clip to between 0 and 4 decimal places
  109. 1 fplaces 0 ?do 10 * loop fscl ! \ store scaling factor
  110. ;
  111. 3 FIXED \ default to three decimal places
  112. \ *****************************************
  113. \ * Outputting numbers *
  114. \ *****************************************
  115. : (F.) ( fn -- adr len ) \ prepare fixed point # ready to output
  116. tuck \ keep copy of top byte so we know sign
  117. dabs \ convert to positive number
  118. <# bl hold \ start conversion with a leading blank
  119. fplaces 0 ?do # loop \ convert places after decimal point
  120. ascii . hold \ put a decimal point in place
  121. #s \ convert integer part
  122. rot sign #> \ put sign in place, tidy stack
  123. ;
  124. : FIX. ( fn -- ) (f.) type ; \ print fixed point number
  125. : FIX.R ( fn p -- ) \ right justify in a field of p places
  126. >r (f.) \ convert number
  127. r> over - 0 ?do bl emit loop type \ pad with blanks as needed
  128. ;
  129. \ *****************************************
  130. \ * Inputting numbers *
  131. \ *****************************************
  132. : D10* ( d1 -- 10*d1) \ multiply a 32 bit number by 10
  133. d2* 2dup d2* d2* d+ \ 8*d+2*d=10*d
  134. ;
  135. \ Convert number to fixed point number - no check made for numbers too large
  136. \ Example 1234.5 FIX. To compile a fixed point number in a : definition use
  137. \ [ 1234.5 FIX ] DLITERAL
  138. : FIX ( dn -- fn )
  139. dpl @ 0< \ single or double number?
  140. if s>d 0 dpl ! then \ if single convert to double
  141. dpl @ fplaces <> \ # decimal places entered not fplaces?
  142. if dpl @ fplaces < \ too few places specified?
  143. if fplaces dpl @ ?do d10* loop \ yes, too few so scale the number up
  144. else abort" Too mnay decimal places" \ no, too many - we can't handle this
  145. then
  146. then
  147. ;
  148. \ *****************************************
  149. \ * 32 bit Fixed Point Multiply *
  150. \ *****************************************
  151. \ Multiply two fixed point numbers producing a fixed point result.
  152. : FIX* ( f1 f2 -- f1*f2 )
  153. rot 2dup xor >r \ sign of answer to return stack
  154. -rot dabs 2swap dabs \ make both numbers positive
  155. dup>r rot dup>r >r over >r \ put a c c b on return stack
  156. >r swap dup>r \ put a d onto return stack
  157. um* \ b*d
  158. 0 2r> um* d+ 2r> um* d+ \ offset 16 bits, add on a*d+b*c
  159. 2r> * + \ add on low byte of a*c
  160. fscale mu/mod \ divide ms32 bits, ans to R.
  161. 0<> abort" Fixed * Overflow!" >r \ unless overflow quotient to R
  162. fscale mu/mod rot drop \ divide remainder and last 16 bits
  163. r> + r> ?dnegate \ assemble final answer, negate if required
  164. ;
  165. \ *****************************************
  166. \ * 32 bit Fixed Point Divide *
  167. \ *****************************************
  168. : FIX/ ( f1 f2 -- fquot=f1/f2 ) \ Divide two numbers
  169. 2 pick over xor >r \ work out sign of answer and save
  170. dabs 2swap dabs 2swap \ make all numbers positive
  171. 2dup >r >r \ keep copy of divisor
  172. d/mod fscale 0 d* \ scale integer part of answer
  173. 2swap fscale 0 d* \ and then scale remainder
  174. r> r> d/ \ divide remainder by divisor
  175. d+ \ add fract part of ans
  176. r> ?dnegate \ put on final sign
  177. ;
  178. : FIX>INT ( fn -- dn ) \ get 32 bit integer from a fixed point number
  179. fscale s>d d/ \ just add drop to get a 16 bit integer
  180. ;
  181. \ *********************************************************
  182. \ * 32 bit Floating Point Arithmetic *
  183. \ * Based on Zen Math by Martin Tracy *
  184. \ *********************************************************
  185.  
  186. \ Trim a double-number mantissa and an exponent of ten to a floating number.
  187. : TRIM ( dn n = f)
  188. >r \ exponent to return stack
  189. tuck dabs \ save copy of high word for sign, make double positive
  190. begin over 0< over 0<> or \ MSB low word set or top 16 bits no zero?
  191. \ if so too big to fit into 16bits when signed
  192. while
  193. 0 10 um/mod >r 10 um/mod nip r> \ divide 32 bit mantissa by 10
  194. r> 1+ >r \ and increase exponent
  195. repeat rot ?dnegate drop r> \ apply sign and final exponent
  196. ;
  197. \ ****************************************************
  198. \ * 32 bit Floating Point Addition and Subtraction *
  199. \ ****************************************************
  200. : F+
  201. rot 2dup - dup 0< \ work out difference in exponents
  202. if \ top number has the larger exponent
  203. negate rot >r nip >r swap r> \ keep larger (on return stack) and diff, swap mantissas
  204. else \ top has a smaller or equal exponent
  205. swap >r nip \ keep larger (on return stack) and diff
  206. then
  207. >r s>d r> dup 0 \ convert mantissa to be shift to double
  208. ?do >r d10* r> 1- \ multiply mantissa by 10, decrement exponent
  209. over abs 6553 > \ would a *10 cause overflow of these 16 bits?
  210. if leave then \ prematurely terminate loop if so
  211. loop
  212. r> over + >r \ calculate final exponent
  213. if rot drop \
  214. else rot s>d d+
  215. then r> trim \ get final exponent and trim
  216. ;
  217. : FNEGATE >r negate r> ;
  218. : F- fnegate f+ ; \ add negative of the top value
  219. \ ****************************************
  220. \ * 32 bit Floating Point Multiplication *
  221. \ ****************************************
  222. : F* ( f1 f2 -- f3 )
  223. rot + >r \ calc exp of answer,save on return stack
  224. 2dup xor >r \ save xor of mantissas too (sign of answer)
  225. abs swap abs um* \ make mantissas positive and multiply
  226. r> ?dnegate r> trim \ apply sign and then get exponent and trim
  227. ;
  228. \ ***********************************
  229. \ * 32 bit Floating Point Division *
  230. \ ***********************************
  231. : F/
  232. over 0= abort" d/0 error!" \ check for divide by zero
  233. rot swap - >r \ get exponent of answer, put on return stack
  234. 2dup xor -rot \ get sign of answer, tuck down on stack
  235. abs dup 6553 min rot abs 0 \
  236. begin 2dup d10* nip 3 pick < \
  237. while d10* r> 1- >r \
  238. repeat 2swap drop um/mod \ now do the division
  239. nip 0 rot ?dnegate r> trim \ lose remainder, apply sign get exp and trim
  240. ;
  241. \ ******************************************
  242. \ * 32 bit Floating Point Input and Output *
  243. \ ******************************************
  244. \ Numbers to be floated must include a decimal point when entered.
  245. \ DPL contains the number of digits entered after the decimal point.
  246.  
  247. : FLOAT ( n -- f) \ float the last entered number.
  248. dpl @ negate trim
  249. ;
  250.  
  251. : F. ( f --) \ print a floating number in fixed format.
  252. >r dup abs 0
  253. <# r@ 0 max 0 ?do ascii 0 hold loop
  254. r@ 0<
  255. if r@ negate 0 max 0 ?do # loop ascii . hold
  256. then r> drop #s rot sign
  257. #> type space
  258. ;
  259. \ *********************************************************
  260. \ * 32 bit Floating Point Transcindental Functions *
  261. \ * Based on Zen sliderule by Nathaniel Grossman *
  262. \ *********************************************************
  263. comment:
  264. These functions are calculated to an accuracy of about one or two units in the
  265. third decimal place. Domains of the functions - scale input if needs be to
  266. keep within range. The CORDIC algorithm is used so these routines are not fast.
  267. SQRT 0.03 - 2.42
  268. LN 0.10 - 9.58
  269. SIN,COS,TAN -1.74 - 1.74
  270. ATAN -infinity - +infinity
  271. SINH,COSH,TANH -1.13 - 1.13
  272. ATANH -0.81 - 0.81
  273. comment;
  274.  
  275. : F2* 2dup f+ ;
  276. : F/2 swap s>d 2dup d2* d2* d+ rot 1- trim ; \ mantissa * 5, dec exp by 1
  277. : F/2^N ( r n --- r/2^n) 0 ?do f/2 loop ; \ divide by 2, n times
  278.  
  279. \ Convience renaming of existing words. Either these or original names work.
  280. ' 2DROP alias FDROP
  281. ' 2DUP alias FDUP
  282. ' 2OVER alias FOVER
  283. ' 2SWAP alias FSWAP
  284. ' 2ROT alias FROT
  285. ' 2! alias F!
  286. ' 2@ alias F@
  287. ' 2VARIABLE alias FVARIABLE
  288.  
  289. \ Extra floating point words
  290. : F0< DROP 0< ;
  291. : F, FLOAT , , ;
  292. : FCONSTANT FLOAT 2CONSTANT ;
  293.  
  294. \ Constants, Variables, Deferred Words and Arrays
  295. 4 CONSTANT F#BYTES VARIABLE MODE_FLAG
  296. 0.6073 FCONSTANT 1/K VARIABLE DELTA_FLAG
  297. 1.2076 FCONSTANT 1/K' VARIABLE NDX
  298. 0.0000 FCONSTANT F0 FVARIABLE F-BIN
  299. 1.0000 FCONSTANT F1 FVARIABLE XX
  300. 0.2500 FCONSTANT F1/4 FVARIABLE YY
  301. FVARIABLE ZZ
  302. DEFER EPS \ it will be either +EPS OR -EPS
  303. DEFER !STACK \ it will be R-STORE or V-STORE
  304. DEFER DO-IT \ it will be either ROT'ING or VEC'ING
  305. : FARRAY \ array building word
  306. CREATE \ ( -- ) compile time stack
  307. DOES> \ ( n --- adr ) run time stack
  308. swap f#bytes * + f@ \ calc address of nth entry
  309. ;
  310. FARRAY +EPS .7854 F, .4636 F, .2450 F, .1244 F, .06242 F,
  311. .03124 F, .05162 F, .007812 F, .003906 F, .001953 F,
  312. .0009766 F, .0004883 F, .0002441 F, .0001221 F, .00006104 F,
  313. FARRAY -EPS .0000 F, .5493 F, .2554 F, .1257 F, .06258 F,
  314. .03126 F, .01563 F, .007813 F, .003906 F, .001953 F,
  315. .0009766 F, .0004883 F, .0002441 F, .0001221 F, .00006104 F,
  316.  
  317. : DELTA_SIGN delta_flag @ if fnegate then ;
  318. : MODE_SIGN mode_flag @ if fnegate then ;
  319. : R-DELTA= ( r --- r ) fdup f0< delta_flag ! ;
  320. : V-DELTA= ( r --- r ) fdup f0< not delta_flag ! ;
  321. : R-STORE ( x y z --- ) r-delta= zz f! yy f! xx f! ;
  322. : V-STORE ( x y z --- ) zz f! v-delta= yy f! xx f! ;
  323. : NEW_Z zz f@ ndx @ eps delta_sign f- ;
  324. : NEW_X xx f@ yy f@ ndx @ f/2^n delta_sign mode_sign f+ ;
  325. : NEW_Y yy f@ xx f@ ndx @ f/2^n delta_sign f+ ;
  326. : ROT'ING new_x new_y new_z r-store ;
  327. : VEC'ING new_x new_y new_z v-store ;
  328. : MODE=+1 -1 mode_flag ! ['] +eps is eps ;
  329. : MODE=-1 0 mode_flag ! ['] -eps is eps ;
  330.  
  331. : CORDIC ( xstart ystart zstart --- xend yend zend )
  332. !stack mode_flag @ dup 0= >r
  333. if 0 ndx ! do-it then
  334. 4 1 do i ndx ! do-it loop
  335. r@ if 4 ndx ! do-it then
  336. 14 4 do i ndx ! do-it loop
  337. r> if 13 ndx ! do-it then
  338. 14 ndx ! do-it xx f@ yy f@ zz f@
  339. ;
  340. : FCOS&SIN ( r --- cos{r} sin{r} f )
  341. 1/k fswap f0 fswap ['] r-store is !stack
  342. mode=+1 ['] rot'ing is do-it cordic
  343. ;
  344. : FCOS ( r --- cos{r}) fcos&sin fdrop fdrop ;
  345. : FSIN ( r --- sin{r}) fcos&sin fdrop fswap fdrop ;
  346. : FTAN ( r --- tan{r}) fcos&sin fdrop fswap f/ ;
  347. : FCOSH&SINH ( r --- cosh{r} sinh{r} f )
  348. 1/k' fswap f0 fswap ['] r-store is !stack
  349. mode=-1 ['] rot'ing is do-it cordic
  350. ;
  351. : FCOSH ( r --- cosh{r}) fcosh&sinh fdrop fdrop ;
  352. : FSINH ( r --- sinh{r}) fcosh&sinh fdrop fswap fdrop ;
  353. : FTANH ( r --- tanh{r}) fcosh&sinh fdrop fswap f/ ;
  354. : FALN ( r --- exp{r}) fcosh&sinh fdrop f+ ;
  355.  
  356. : FLN ( r --- ln{r} )
  357. fdup f1 f+ fswap f1 f- f0 ['] v-store is !stack
  358. mode=-1 ['] vec'ing is do-it cordic
  359. fswap fdrop fswap fdrop f2*
  360. ;
  361. : FSQRT ( r --- sqrt{r} )
  362. fdup f1/4 f+ fswap f1/4 f- f0 ['] v-store is !stack
  363. mode=-1 ['] vec'ing is do-it cordic
  364. fdrop fdrop 1/k' f*
  365. ;
  366. : R>P ( x y --- {x^2 + y^2}^1/2 arctan{y/x} )
  367. 1/k f* fswap 1/k f* fswap f0 ['] v-store is !stack
  368. mode=+1 ['] vec'ing is do-it cordic fswap fdrop
  369. ;
  370. : P>R ( radius angle --- x y )
  371. fover fswap fcos&sin fdrop frot f* frot frot f* fswap
  372. ;
  373. : FATAN ( r --- arctan{r}) f1 fswap r>p fswap fdrop ;
  374. : FATANH ( r --- argtanh{r}) f1 fswap f0 mode=-1
  375. ['] vec'ing is do-it cordic fswap fdrop fswap fdrop
  376. ;
  377.  
Tags: Forth
Advertisement
Add Comment
Please, Sign In to add comment