Guest User

Double Extended-precision floating point arithmetic - 2026-09-27

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