Guest User

128-bit Forth floating point arithmetic package 2026-09-09

a guest
Sep 9th, 2026
24
0
316 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.55 KB | Source Code | 0 0
  1. \ Tested on Gforth, Win32Forth (8-byte floats).
  2.  
  3. \ Misc utilities
  4.  
  5. : DIGIT? ( char -- u true | 0 )
  6. [CHAR] 0 - DUP 10 17 WITHIN 0= IF
  7. DUP 16 U> IF 7 - THEN
  8. DUP BASE @ U< IF TRUE EXIT THEN
  9. THEN DROP FALSE ;
  10.  
  11. [DEFINED] DXFORTH [IF] AKA SHOLD HOLDS [ELSE]
  12.  
  13. : /SIGN ( a u -- a' u' f )
  14. DUP IF OVER C@ DUP [CHAR] + = SWAP [CHAR] - =
  15. DUP >R OR NEGATE /STRING R> EXIT THEN 0 ;
  16.  
  17. : /NUMBER ( a u -- a' u' d|ud )
  18. /SIGN >R 0 0 2SWAP >NUMBER 2SWAP R> IF DNEGATE THEN ;
  19.  
  20. [THEN]
  21.  
  22.  
  23. \ DDFLOAT.F
  24.  
  25. \ Doubled-precision floating point arithmetic
  26. \
  27. \ Reference
  28. \
  29. \ JVN's 128-bit Forth floating point arithmetic package:
  30. \ http://galileo.phys.virginia.edu/classes/551.jvn.fall01/ddarith.htm
  31. \ http://galileo.phys.virginia.edu/classes/551.jvn.fall01/dd_io.htm
  32. \
  33. \ 2026-09-09 changes:
  34. \
  35. \ - renamed package to DDFLOAT so you know who to blame
  36. \ - fix bugs in DDFS.
  37. \ - replace input routine >DD Note: now returns a flag
  38. \ - rename r128! r128@ real*16 to DD! DD@ DDVARIABLE
  39. \ - add DD< DD> DD= DDLITERAL (DDFS.) DD#
  40. \ - remove separate float stack requirement
  41. \
  42. \ Material not (c) Julian V. Noble is hereby placed
  43. \ in the PUBLIC DOMAIN. Use at your own risk.
  44.  
  45. \ ---------------------------------------------------
  46. \ (c) Copyright 2006 Julian V. Noble. \
  47. \ Permission is granted by the author to \
  48. \ use this software for any application pro- \
  49. \ vided this copyright notice is preserved. \
  50. \ ---------------------------------------------------
  51.  
  52. \ This is an ANS Forth program requiring the
  53. \ FLOAT, FLOAT EXT, FILE and TOOLS EXT wordsets.
  54. \
  55. \ Environmental dependences:
  56. \ Assumes independent floating point stack
  57. \ the fpu must be set to 64-bit internal operations
  58. \ ^^^^
  59.  
  60. CR .( Double-Double Precision FP) CR
  61.  
  62. 1 FLOATS 8 - [IF]
  63. CR .( ERROR: Requires Double-Precision FP system) ABORT
  64. [THEN]
  65.  
  66. MARKER -double
  67.  
  68. [UNDEFINED] F>S [IF] : F>S F>D D>S ; [THEN]
  69. [UNDEFINED] S>F [IF] : S>F S>D D>F ; [THEN]
  70. [UNDEFINED] FTUCK [IF] : FTUCK FSWAP FOVER ; [THEN]
  71. [UNDEFINED] F-ROT [IF] : F-ROT FROT FROT ; [THEN]
  72.  
  73.  
  74. \ ---------------------------------------- LOAD, STORE
  75. : DD@ ( adr -- dd ) DUP >R F@ R> FLOAT+ F@ ;
  76. : DD! ( dd adr -- ) DUP >R FLOAT+ F! R> F! ;
  77. \ ------------------------------------ END LOAD, STORE
  78.  
  79. \ ----------------------------------- data types ----
  80.  
  81. [DEFINED] DXFORTH [IF] SYSTEM [THEN]
  82.  
  83. : DDVARIABLE \ create a double-double variable
  84. FALIGN HERE 2 FLOATS ALLOT CONSTANT ;
  85.  
  86. : DDCONSTANT \ create a double-double constant
  87. CREATE FALIGN HERE 2 FLOATS ALLOT DD!
  88. DOES> FALIGNED DD@ ;
  89.  
  90. : DDLITERAL
  91. FSWAP POSTPONE FLITERAL POSTPONE FLITERAL
  92. ; IMMEDIATE
  93.  
  94. [DEFINED] DXFORTH [IF] APPLICATION [THEN]
  95.  
  96. \ ---------------------------------------------------
  97.  
  98. 3.1415926535897931e0 1.2246467991473532e-16 DDCONSTANT DDPI
  99.  
  100. \ = 3.141592653589793238462643383279
  101. \ pi = 3.1415926535897932384626433832795028841971693993751...
  102.  
  103.  
  104. \ based on "Software for Doubled-Precision Floating-Point Computations"
  105. \ by Seppo Linnainmaa
  106. \ ACM Transactions on Mathematical Software,
  107. \ Vol 7, No 3, September 1981, Pages 272-283
  108.  
  109. FALSE [IF] \ determine base and precision of fpu
  110.  
  111. 4e0 3e0 F/ 1e0 F- 3e0 F* 1e0 F- FVALUE u
  112. u 2e0 F/ 1e0 F+ 1e0 F- FVALUE r
  113. r F0= NOT [IF] r FTO u [THEN]
  114. 2e0 3e0 F/ 0.5e0 F- 3e0 F* 0.5e0 F- FVALUE uu
  115. uu 2e0 F/ 0.5e0 F+ 0.5e0 F- FVALUE rr
  116. rr F0= NOT [IF] rr FTO uu [THEN]
  117. u uu F/ ( f: -- beta)
  118. uu FLN FOVER FLN F/ FNEGATE 0.5e0 F+
  119. F>S F>S CR CR .( base = ) . .( precision = ) . FORGET u
  120.  
  121. [THEN]
  122.  
  123. \ Exact multiplication
  124.  
  125. 134217729. D>F FCONSTANT split
  126.  
  127. fvariable t fvariable a1 fvariable a2 fvariable b1
  128. fvariable b2 fvariable b21 fvariable b22 fvariable ta
  129. fvariable tb
  130.  
  131. fvariable q fvariable qq fvariable x fvariable xx
  132. fvariable y fvariable yy fvariable z1 fvariable z2
  133.  
  134. fvariable aaa fvariable bbb
  135.  
  136. : exactmul ( f: a b -- x xx) \ multiply 2 fp#'s to get ddfp#
  137. aaa F! bbb F!
  138. bbb F@ split F* t F!
  139. t F@ bbb F@ FOVER F- F+ FDUP a1 F! ( f: a1)
  140. FNEGATE bbb F@ F+ a2 F!
  141. aaa F@ FDUP split F* t F! ( f: aaa)
  142. t F@ ftuck F- F+ b1 F!
  143. aaa F@ b1 F@ F- FDUP FDUP b2 F! ( f: b2 b2)
  144. split F* t F!
  145. t F@ ftuck F- F+ FDUP b21 F! ( f: b21)
  146. FNEGATE b2 F@ F+ b22 F!
  147. bbb F@ aaa F@ F* FDUP t F!
  148. a1 F@ b1 F@ F* t F@ F- a1 F@ b2 F@ F*
  149. F+ b1 F@ a2 F@ F* F+
  150. b21 F@ a2 F@ F* F+ b22 F@ a2 F@ F* F+
  151. ;
  152.  
  153. : DD/ ( f: x xx y yy -- [x+xx]/[y+yy] )
  154. yy F! y F! xx F! x F!
  155. y F@ FABS F0= ABORT" Can't divide by 0!"
  156. x F@ y F@ F/ FDUP z1 F!
  157. y F@ exactmul qq F! FDUP q F! ( f: q)
  158. FNEGATE x F@ F+ qq F@ F-
  159. xx F@ F+ z1 F@ yy F@ F* F-
  160. y F@ yy F@ F+ F/ FDUP z2 F!
  161. z1 F@ F+ FDUP
  162. FNEGATE z1 F@ F+ z2 F@ F+
  163. ;
  164.  
  165. : DD* ( f: x xx y yy -- [x+xx]*[y+yy] )
  166. yy F! y F! xx F! x F!
  167. x F@ y F@ exactmul qq F! z1 F!
  168. x F@ xx F@ F+ yy F@ F*
  169. xx F@ y F@ F* F+ qq F@ F+ FDUP z2 F!
  170. z1 F@ F+ FDUP
  171. FNEGATE z1 F@ F+ z2 F@ F+
  172. ;
  173.  
  174. : DD+ ( f: x xx y yy -- [x+xx] + [y+yy] )
  175. yy F! y F! xx F! x F!
  176. x F@ y F@ F+ z1 F!
  177. x F@ z1 F@ F- FDUP q F!
  178. y F@ F+ ( f: q+y)
  179. x F@ q F@ z1 F@ F+ F- ( f: q+y x-[q+z1])
  180. F+ xx F@ F+ yy F@ F+ FDUP z2 F!
  181. z1 F@ F+ FDUP ( f: z1+z2 z1+z2)
  182. FNEGATE z1 F@ F+ z2 F@ F+
  183. ;
  184.  
  185. : DDNEGATE ( f: x xx -- -x -xx)
  186. FNEGATE FSWAP FNEGATE FSWAP
  187. ;
  188.  
  189. : DDABS ( f: x xx -- |x+xx|)
  190. FOVER F0< IF ddnegate THEN
  191. ;
  192.  
  193. : DD- ( f: x xx y yy -- [x+xx] - [y+yy] )
  194. DDNEGATE DD+
  195. ;
  196.  
  197. \ Square root based on T.J. Dekker,
  198. \ "A Floating-Point Technique for Extending the Available Precision"
  199. \ Numerische Mathematik 18 (1971) 224-242.
  200.  
  201. : DDSQRT ( f: x xx -- ddsqrt[x+xx])
  202. xx F! FDUP x F!
  203. F0< ABORT" Can't take sqrt of negative number!"
  204. x F@ FSQRT FDUP q F!
  205. FDUP exactmul yy F! FDUP y F!
  206. FNEGATE x F@ F+
  207. yy F@ F- xx F@ F+
  208. 0.5e0 F* q F@ F/ FDUP qq F!
  209. q F@ F+ FDUP
  210. FNEGATE q F@ F+ qq F@ F+
  211. ;
  212.  
  213. \ ----------------------------------- stack ops -----
  214. FVARIABLE dtemp
  215.  
  216. DDVARIABLE ddtemp DDVARIABLE ddtemp1
  217.  
  218. : DDSWAP ( f: x xx y yy -- y yy x xx )
  219. dtemp F! F-ROT dtemp F@ F-ROT ;
  220.  
  221. : DDDUP FOVER FOVER ;
  222.  
  223. : DDDROP FDROP FDROP ;
  224.  
  225. : DDOVER ddtemp DD! dddup ddtemp1 DD!
  226. ddtemp DD@ ddtemp1 DD@ ;
  227.  
  228. : DDTUCK ddtemp DD! ddtemp1 DD!
  229. ddtemp DD@ ddtemp1 DD@
  230. ddtemp DD@ ;
  231.  
  232. fvariable a3 fvariable a4 fvariable b3 fvariable b4
  233.  
  234. : ddcomp ( a3 a4 b3 b4 -- -1|0|1 )
  235. b4 F! b3 F! a4 F! a3 F!
  236. a3 F@ b3 F@ F< IF -1 EXIT THEN
  237. a3 F@ b3 F@ F= IF
  238. a4 F@ b4 F@ F< IF -1 EXIT THEN
  239. a4 F@ b4 F@ F= IF 0 EXIT THEN
  240. THEN 1 ;
  241.  
  242. : DD< ( dd1 dd2 -- f ) ddcomp -1 = ;
  243. : DD> ( dd1 dd2 -- f ) ddcomp 1 = ;
  244. : DD= ( dd1 dd2 -- f ) ddcomp 0= ;
  245.  
  246. \ ---------------------------------------------------
  247.  
  248. 1e0 0e0 DDCONSTANT dd1.
  249. 10e0 0e0 DDCONSTANT dd10.
  250.  
  251. : DD^2 ( x xx -- [x+xx]^2 )
  252. dddup dd* ;
  253.  
  254. : DD^N ( x xx n -- [x+xx]^n )
  255. \ raise dd to integer power
  256. \ return 1 if n=0, dd^{-|n|} if n<0
  257. >R
  258. dd1. DDSWAP ( f1e0 0e0 x xx )
  259. R> DUP 0= IF DROP DDDROP EXIT THEN
  260. DUP 0< >R ( sign) ABS ( |n| )
  261. BEGIN DUP 0> WHILE
  262. DUP >R 1 AND IF DDTUCK DD* DDSWAP THEN dd^2
  263. R> 2/
  264. REPEAT DROP DDDROP
  265. R> IF dd1. DDSWAP DD/ THEN
  266. ;
  267.  
  268. \ Input routine adapted from:
  269. \ http://dxforth.webhop.org/finput.html
  270.  
  271. VARIABLE exp \ exponent
  272. VARIABLE dpf \ decimal point
  273.  
  274. DDVARIABLE tmp
  275.  
  276. : /digs ( a u -- a' u' )
  277. BEGIN DUP WHILE
  278. OVER C@ DIGIT? WHILE
  279. S>F 0.0E tmp DD@ dd10. DD* DD+ tmp DD!
  280. dpf @ exp +! 1 /STRING
  281. REPEAT THEN ;
  282.  
  283. : /mant ( a u -- a' u' flag )
  284. TUCK /digs DUP IF
  285. OVER C@ [CHAR] . = IF
  286. -1 dpf ! 1 /STRING /digs
  287. THEN
  288. THEN ROT OVER - dpf @ + ;
  289.  
  290. : /exp ( a u -- a' u' )
  291. DUP IF
  292. OVER C@ 33 OR [CHAR] e = ( 'D' 'E' 'd' 'e')
  293. 1 AND /STRING
  294. THEN
  295. /NUMBER DROP exp @ +
  296. BEGIN ?DUP WHILE DUP 0<
  297. IF 1+ tmp DD@ dd10. DD/
  298. ELSE 1- tmp DD@ dd10. DD* THEN tmp DD!
  299. REPEAT ;
  300.  
  301. \ Like >FLOAT but returns a dd number
  302. : >DD ( c-addr u -- dd true | false )
  303. 0.0E 0.0E tmp DD! 0 exp ! 0 dpf !
  304. -TRAILING /SIGN >R DUP IF
  305. /mant IF /exp THEN
  306. ELSE 0= THEN
  307. NIP IF R> DROP 0 EXIT THEN
  308. tmp DD@ R> IF DDNEGATE THEN TRUE ;
  309.  
  310. [DEFINED] DXFORTH [IF] SYSTEM [THEN]
  311.  
  312. \ Interpret/compile dd number
  313. : DD# ( "number" )
  314. BL WORD COUNT >DD 0= ABORT" bad float"
  315. STATE @ IF POSTPONE DDLITERAL THEN ; IMMEDIATE
  316.  
  317. [DEFINED] DXFORTH [IF] APPLICATION [THEN]
  318.  
  319. \ This is an ANS Forth program requiring the
  320. \ FLOAT, FLOAT EXT, FILE and TOOLS EXT wordsets.
  321. \
  322. \ Environmental dependences:
  323. \ Assumes independent floating point stack
  324.  
  325. \ Based on I/O subroutines from
  326. \
  327. \ DDFUN: A Double-Double Floating Point Computation Package
  328. \ IEEE Fortran-90 version
  329. \ Version Date: 2005-01-26
  330. \
  331. \ Author:
  332. \
  333. \ David H. Bailey
  334. \ NERSC, Lawrence Berkeley Lab
  335. \ Mail Stop 50B-2239
  336. \ Berkeley, CA 94720
  337.  
  338. \ Output a dd# .
  339.  
  340. \ Algorithm:
  341. \
  342. \ 1. Determine sign and power of 10
  343. \ 2. Normalize so that significand lies between 1 and <10
  344. \ 3. Peel digits off from left by converting to integer
  345. \ multiplying by dd10 and repeating
  346. \ 4. Construct output string digit by digit, append
  347. \ sign and exponent, and display.
  348.  
  349. : getsign ( x xx -- x xx f )
  350. FOVER F0< ;
  351.  
  352. : getpower ( x xx -- x xx n)
  353. FOVER FABS FLOG
  354. FLOOR F>S ;
  355.  
  356. : normalize ( x xx n -- y yy n')
  357. >R
  358. DDABS ( |x| |xx| )
  359. dd10. R@ DD^N DD/ ( [|x|+|xx|]/10^n )
  360.  
  361. \ make sure it's between 1 and <10
  362. BEGIN DDDUP dd10. DD< 0=
  363. WHILE dd10. DD/ R> 1+ >R REPEAT
  364.  
  365. BEGIN DDDUP dd1. DD<
  366. WHILE dd10. DD* R> 1- >R REPEAT
  367. R>
  368. ;
  369.  
  370. 32 CONSTANT maxdig
  371.  
  372. CREATE peeled maxdig CELLS ALLOT
  373.  
  374. : peeldigits ( y yy -- ) \ to integer array
  375. maxdig 0 DO
  376. FOVER F>S DUP peeled maxdig 1- I - CELLS + !
  377. S>F 0e0 DD- dd10. DD*
  378. LOOP DDDROP
  379. ;
  380.  
  381. CREATE dig$ maxdig ALLOT
  382.  
  383. : copydigits ( -- ) \ to character array
  384. peeled maxdig 0 DO
  385. DUP CELL+ SWAP @ DUP 0< IF ( -ve fix-up)
  386. 10 + OVER -1 SWAP +!
  387. THEN [CHAR] 0 + dig$ maxdig 1- I - + C!
  388. LOOP DROP
  389. ;
  390.  
  391. : 0digit-fix ( a u -- a' u' n ) \ leading digit fix-up
  392. OVER C@ CASE
  393. [CHAR] 0 OF 1 /STRING -1 ENDOF
  394. [CHAR] 9 1+ OF OVER [CHAR] 1 SWAP C! 1 ENDOF
  395. 0 SWAP
  396. ENDCASE
  397. ;
  398.  
  399. : (DDFS.) ( dd -- c-addr u ) \ string double-double in E-format
  400. <# FOVER F0= IF DDDROP S" 0.E0" HOLDS ELSE
  401. getsign >R
  402. getpower ( x xx n)
  403. normalize >R ( y yy)
  404. peeldigits copydigits
  405. dig$ maxdig ( a u) 0digit-fix R> + \ adjust exp
  406. ( p) DUP ABS 0 #S 2DROP SIGN \ exponent
  407. [char] E HOLD ( a u)
  408. 1- OVER 1+ SWAP HOLDS [char] . HOLD C@ HOLD
  409. R> ( s) IF [char] - HOLD THEN
  410. THEN 0 0 #>
  411. ;
  412.  
  413. : DDFS. ( dd -- ) \ display double-double in E-format
  414. (DDFS.) TYPE SPACE ;
  415.  
  416. [DEFINED] DXFORTH [IF]
  417. BEHEAD split exactmul
  418. BEHEAD dtemp ddtemp1
  419. BEHEAD a3 ddcomp
  420. BEHEAD exp /exp
  421. BEHEAD dd1. dd10.
  422. BEHEAD getsign 0digit-fix
  423. [THEN]
  424.  
  425.  
  426. 0 [IF] CR .( Testing ) CR
  427.  
  428. : test ( a u -- ) 2DUP >DD
  429. CR IF DDFS. 2DROP ELSE TYPE ." failed" THEN ;
  430.  
  431. s" -11.1112222233333444445555566666d-45" test
  432.  
  433. s" +-11.1112222233333444445555566666d-45" test
  434. \ Error: >dd Non-digit in significand!
  435.  
  436. s" +11.1112222.233333444445555566666d-45" test
  437. \ Error: >dd One dp to a customer!
  438.  
  439. s" +11.1112222233333444445555566666d+45" test
  440. \ +1.1111222223333344444555556666604 dd 46 ok
  441.  
  442. s" +11.1112222233333444445555566666d" test
  443. \ +1.1111222223333344444555556666603 dd 1 ok
  444.  
  445. s" +11.1112222233333444445555566666D" test
  446. \ +1.1111222223333344444555556666603 dd 1 ok
  447.  
  448. s" 1111122.222333D" test
  449. \ +1.1111222223330000000000000000000 dd 6 ok
  450.  
  451. CR
  452.  
  453. DD# 0 CR DDFS.
  454. DD# 1.2345678901234567890123456789012e CR DDFS.
  455. DD# 2 DD# 3 DD/ CR DDFS.
  456. DD# 9.9999999999999999999999987654321e CR DDFS.
  457. DD# -9.9999999999999900000000123456789e CR DDFS.
  458. DD# -9.999999999999e CR DDFS.
  459. DD# 99999999999999999999999999999999.e CR DDFS.
  460.  
  461. [THEN]
  462.  
Advertisement
Add Comment
Please, Sign In to add comment