Guest User

Prospective bug-fixes for DD-IO.4TH (KForth) 2026-09-07 dxf

a guest
Sep 6th, 2026
36
0
313 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.74 KB | Source Code | 0 0
  1. \ Prospective bug-fixes for DD-IO.4TH (KForth) 2026-09-07 dxf
  2.  
  3. \ Double Double-precision arithmetic I/O words
  4. \
  5. \ ---------------------------------------------------
  6. \ (c) Copyright 2006 Julian V. Noble. \
  7. \ Permission is granted by the author to \
  8. \ use this software for any application pro- \
  9. \ vided this copyright notice is preserved. \
  10. \ ---------------------------------------------------
  11.  
  12. \ This is an ANS Forth program requiring the
  13. \ FLOAT, FLOAT EXT, FILE and TOOLS EXT wordsets.
  14. \
  15. \ Environmental dependences:
  16. \ Assumes independent floating point stack
  17.  
  18. \ Based on I/O subroutines from
  19. \
  20. \ DDFUN: A Double-Double Floating Point Computation Package
  21. \ IEEE Fortran-90 version
  22. \ Version Date: 2005-01-26
  23. \
  24. \ Author:
  25. \
  26. \ David H. Bailey
  27. \ NERSC, Lawrence Berkeley Lab
  28. \ Mail Stop 50B-2239
  29. \ Berkeley, CA 94720
  30. \
  31. \ GLOSSARY:
  32. \
  33. \ DD>$ ( F: x xx -- ) ( -- caddr u ) convert dd# to string
  34. \ DDFS. ( F: x xx -- ) output the dd#
  35. \
  36. \ Notes:
  37. \
  38. \ 1. DD>$ has been modified to use PRECISION setting.
  39. \
  40. \ Requires:
  41. \ ans-words
  42. \ ddarith
  43.  
  44. [UNDEFINED] f>s [IF] : f>s f>d d>s ; [THEN]
  45. [UNDEFINED] tab [IF] : tab 9 emit ; [THEN]
  46.  
  47. \ Output a dd# .
  48.  
  49. \ Algorithm:
  50. \
  51. \ 1. Determine sign and power of 10
  52. \ 2. Normalize so that significand lies between 1 and 10
  53. \ 3. Peel digits off from left by converting to integer
  54. \ multiplying by dd10 and repeating
  55. \ 4. Construct output string digit by digit, append
  56. \ sign and exponent, and display.
  57.  
  58. 10e0 0e0 ddconstant dd10
  59.  
  60. : getSign ( f: x xx -- x xx) ( -- f)
  61. FOVER F0< ;
  62.  
  63. : getPower ( f: x xx -- x xx) ( -- n)
  64. FOVER FABS FLOG
  65. ( FDUP F0< )
  66. ( IF 1e0 F- F>S ELSE THEN )
  67. F>S
  68. ;
  69.  
  70. fp-stack? [IF]
  71. : normalize ( f: x xx -- y yy) ( n -- n')
  72. ddabs ( f: |x+xx| )
  73. DUP dd10 dd^n dd/ ( f: [|x|+|xx|]/10^n ) ( n)
  74.  
  75. \ make sure it's between 1 and 10
  76. BEGIN FOVER 10e0 F>
  77. WHILE dd10 dd/ 1 + REPEAT
  78.  
  79. BEGIN FOVER 1e0 F<
  80. WHILE dd10 dd* 1 - REPEAT
  81. ; ( f: [y+yy] = [x+xx]/10^n' ) ( n')
  82. [ELSE]
  83. variable temp
  84. : normalize ( f: x xx -- y yy) ( n -- n')
  85. temp !
  86. ddabs ( f: |x+xx| )
  87. dd10 temp @ dd^n dd/ ( [|x|+|xx|]/10^n ) \ ( f: [|x|+|xx|]/10^n ) ( n)
  88.  
  89. \ make sure it's between 1 and 10
  90. BEGIN FOVER 10e0 F>
  91. WHILE dd10 dd/ 1 temp +! REPEAT
  92.  
  93. BEGIN FOVER 1e0 F<
  94. WHILE dd10 dd* -1 temp +! REPEAT
  95. temp @
  96. ; ( f: [y+yy] = [x+xx]/10^n' ) ( n')
  97. [THEN]
  98.  
  99. fp-stack? [IF]
  100. : peelDigit ( f: y yy -- y' yy') ( -- digit)
  101. FOVER ( f: y yy y)
  102. 1e-10 F+ ( f: y yy y+epsilon)
  103. \ fixes rounding problem
  104. F>D 2DUP D>F 0e0 dd-
  105. D>S
  106. ;
  107. [ELSE]
  108. : peelDigit ( f: y yy -- y' yy') ( -- digit)
  109. FOVER ( f: y yy y)
  110. 1e-10 F+ ( f: y yy y+epsilon)
  111. \ fixes rounding problem
  112. F>D 2DUP 2>R D>F 0e0 dd-
  113. 2R> D>S
  114. ;
  115. [THEN]
  116.  
  117. \ ******** bug in peelDigit fixed Wednesday, March 08 2006 by JVN
  118. \ thanks to M. Hendrix for finding it
  119.  
  120. : shiftBy10 dd10 dd* ;
  121.  
  122. \ Convert a double double to a string
  123.  
  124. create ddout_digits 32 CELLS allot
  125. fp-stack? [IF]
  126. : dd>$ ( F: x xx -- ) ( -- caddr u )
  127. FOVER F0= IF dddrop s" 0.0 DD 0" EXIT THEN \ handle 0
  128. getSign
  129. getPower normalize
  130. S>D SWAP OVER DABS \ convert exponent
  131. <# #S ROT SIGN \ append digits of exponent
  132. BL HOLD
  133. [char] d HOLD
  134. [char] d HOLD
  135. BL HOLD \ append dd
  136. PRECISION 1- 0 ?DO
  137. peelDigit
  138. ddout_digits PRECISION 1- I - CELLS + !
  139. shiftBy10
  140. LOOP peelDigit ddout_digits !
  141. ddout_digits PRECISION 1- 0 ?DO
  142. DUP CELL+ SWAP @
  143. DUP 0< IF ( fix-up) 10 + OVER -1 SWAP +! THEN
  144. S>D # 2DROP
  145. LOOP
  146. [char] . HOLD ( a) @ S>D # 2DROP
  147. ROT IF [char] - ELSE [char] + THEN HOLD
  148. #> f2drop
  149. ;
  150. [ELSE]
  151. : dd>$ ( x xx -- caddr u )
  152. FOVER F0= IF dddrop s" 0.0 DD 0" EXIT THEN \ handle 0
  153. getSign >R
  154. getPower normalize R> SWAP
  155. S>D SWAP OVER DABS \ convert exponent
  156. <# #S ROT SIGN \ append digits of exponent
  157. BL HOLD
  158. [char] d HOLD
  159. [char] d HOLD
  160. BL HOLD 2>R >R \ append dd
  161. PRECISION 1- 0 ?DO
  162. peelDigit
  163. ddout_digits PRECISION 1- I - CELLS + !
  164. shiftBy10
  165. LOOP peelDigit ddout_digits !
  166. R> 2R>
  167. ddout_digits PRECISION 1- 0 ?DO
  168. DUP CELL+ SWAP @
  169. DUP 0< IF ( fix-up) 10 + OVER -1 SWAP +! THEN
  170. S>D # 2DROP
  171. LOOP
  172. [char] . HOLD ( a) @ S>D # 2DROP
  173. ROT IF [char] - ELSE [char] + THEN HOLD
  174. #> 2>R f2drop 2R>
  175. ;
  176. [THEN]
  177.  
  178. : ddfs. ( f: x xx -- ) \ display double-double in E-format
  179. dd>$ type ;
  180.  
  181. 32 SET-PRECISION
  182.  
  183. : test
  184. SWAP DO 1e0 0e0 3e0 0e0 dd/ dd10 I dd^n dd*
  185. CR I . TAB TAB ddfs. LOOP
  186. ;
  187.  
  188. : test1
  189. SWAP DO 1e0 0e0 6e0 0e0 dd/ dd10 I dd^n dd*
  190. CR I . TAB TAB ddfs. LOOP
  191. ;
  192.  
  193.  
  194. \ Convert a string representing a dd# to internal form
  195. \ as 2 IEEE 64-bit floats
  196.  
  197. \ Algorithm:
  198. \
  199. \ 0. initialize buffers hi$ and lo$
  200. \ 1. skip leading + sign, leave - flag on stack.
  201. \ 2. copy digits to hi$ buffer until dp found;
  202. \ let L be # digits to left of dp.
  203. \ 3. continue copying until #digits = MaxPlaces/2
  204. \ or string is exhausted.
  205. \ 4. IF (string is exhausted) set lo$ to 0e0
  206. \ ELSE append remaining digits to lo$
  207. \ until #digits = MaxPlaces THEN
  208. \ 5. hi$ >FLOAT 1e0 exactmul
  209. \ lo$ >FLOAT 1e0 exactmul
  210. \ dd+
  211. \ 6. get p = power of 10, let p' = p + L - MaxPlaces/2
  212. \ 7. p' dd10 dd^n dd*
  213.  
  214. \ : $ends ( c-adr u -- end beg) \ convert c-adr u to ends
  215. \ OVER + 1- SWAP ; ( end beg)
  216.  
  217. \ : ends->count ( end beg -- c-adr u) TUCK - 1+ ;
  218.  
  219. \ needs vector1.f ( include)
  220. \ needs fsm2.f ( include)
  221.  
  222.  
  223. 30 CONSTANT MaxPlaces
  224.  
  225. CREATE lo# MaxPlaces CHARS ALLOT \ numerical string buffers
  226. CREATE hi# MaxPlaces CHARS ALLOT
  227.  
  228. : digit? ( c -- f) \ test for digit
  229. [ CHAR 0 ] LITERAL [ CHAR 9 1+ ] LITERAL WITHIN
  230. ;
  231.  
  232. : dp? [CHAR] . = ;
  233.  
  234. : dDeE? ( c -- f)
  235. [CHAR] d OVER =
  236. OVER [CHAR] D = OR
  237. OVER [CHAR] e = OR
  238. SWAP [CHAR] E = OR
  239. ;
  240.  
  241. : |power| ( c-addr count -- |p|) \ abs value of pwr of 10
  242. 0 0 2SWAP >NUMBER ( -- ud2 c-addr2 u2)
  243. 0= IF DROP D>S ELSE ." Bad exponent" ABORT THEN
  244. ;
  245.  
  246. 0 ptr beg
  247. 0 ptr end
  248.  
  249. : do_exponent ( end beg -- p end') \ peel exponent from right
  250. to beg to end \ LOCALS| beg end |
  251. 0 \ count on stack
  252. BEGIN end beg > ( n f1)
  253. end C@ digit? ( n f1 f2)
  254. AND
  255. WHILE end 1- TO end \ dec adr
  256. 1+ \ inc count
  257. REPEAT
  258.  
  259. end 1+ SWAP |power| ( |p|)
  260. end C@ [char] - = \ get sign of p
  261. IF NEGATE end 1- TO end THEN ( -- p)
  262.  
  263. end C@ [char] + = \ bypass + sign
  264. IF end 1- TO end THEN
  265.  
  266. end C@ dDeE? -1 AND end + TO end \ advance past dDeE
  267. end C@ dDeE? -1 AND end + ( -- p end')
  268.  
  269. DUP C@ DUP digit? SWAP dp? OR \ digit|dp are legal
  270. 0= ABORT" Bad exponent" \ anything else n.g.
  271.  
  272. \ end C@ dDeE? -1 AND ( DUP >R)
  273. \ end + TO end \ advance past dDeE
  274. \ end C@ dDeE? -1 AND ( DUP) end + ( -- p end')
  275. \ ( SWAP R> OR 0= ABORT" Bad exponent" ) \ no dDeE !
  276.  
  277. ;
  278.  
  279.  
  280. : [dig|dp] ( char -- col#) \ 0 = "other", 1 = digit, 2 = dp
  281. DUP digit? 1 AND SWAP dp? 2 AND +
  282. ;
  283.  
  284. : init_buffer ( c-addr -- ) \ initialize a string buffer
  285. 0 OVER C! 1+ MaxPlaces 1- [CHAR] 0 FILL
  286. ;
  287.  
  288. : +char ( c-addr c -- ) \ append char to counted $
  289. OVER COUNT + ( c-addr c c-addr+u)
  290. C! DUP C@ 1+ SWAP C! \ store c, inc $len
  291. ;
  292.  
  293. 0 VALUE pre_dp \ # of digits to left of dp
  294. 0 VALUE post_dp \ # of digits to right of dp
  295.  
  296. : +hi ( c -- )
  297. hi# SWAP +char \ append character
  298. pre_dp 1+ TO pre_dp \ increment count
  299. ;
  300.  
  301. : +hi|lo ( c -- )
  302. pre_dp post_dp + MaxPlaces 2/ <
  303. IF hi# ELSE lo# THEN
  304. SWAP +char \ append character
  305. post_dp 1+ TO post_dp \ increment post_dp
  306. ;
  307.  
  308. : err1 TRUE ABORT" Non-digit in significand!" ;
  309. : err2 TRUE ABORT" One dp to a customer!" ;
  310.  
  311.  
  312. FALSE [IF]
  313. 3 wide fsm: <<hi/lo>> ( c col# --)
  314. \ input other | digit | dp |
  315. \ state -------------------------------------------
  316. ( 0) || err1 >2 || +hi >0 || DROP >1
  317. ( 1) || err1 >2 || +hi|lo >1 || err2 >3
  318. ( 2) ( abnormal termination w/ error1 )
  319. ( 3) ( abnormal termination w/ error2 )
  320. ;fsm
  321. [THEN]
  322.  
  323. \ FALSE [IF]
  324. 0 VALUE (state) : >state TO (state) ;
  325.  
  326. : <<hi/lo>> ( c col# --)
  327. (state) 3 * + ( c cell#)
  328. case
  329. 0 OF err1 2 >state ENDOF
  330. 1 OF +hi 0 >state ENDOF
  331. 2 OF drop 1 >state ENDOF
  332. 3 OF err1 2 >state ENDOF
  333. 4 OF +hi|lo 1 >state ENDOF
  334. 5 OF err2 3 >state ENDOF
  335. endcase
  336. ;
  337. \ [THEN]
  338.  
  339. : leadingSign ( end beg -- sgn end beg')
  340. DUP C@ [CHAR] - OVER = ( end beg c f1)
  341. >R [CHAR] + = R@ OR ( end beg f2+f1)
  342. 1 AND + R> -ROT
  343. ;
  344.  
  345. : initialize
  346. hi# init_buffer \ buffers
  347. lo# init_buffer
  348. lo# [CHAR] 0 +char \ required for >FLOAT
  349. lo# [CHAR] . +char
  350. 0 TO pre_dp 0 TO post_dp \ counts
  351. 0 >state ( <<hi/lo>>) \ fsm
  352. ;
  353.  
  354. : >(hi/lo) ( end beg -- ) \ digits to hi# and lo#
  355. BEGIN 2DUP >= ( end beg f)
  356. pre_dp post_dp + MaxPlaces <= AND
  357. WHILE DUP C@ DUP [dig|dp] <<hi/lo>>
  358. 1+ ( end beg+1)
  359. REPEAT 2DROP
  360. ;
  361.  
  362. : buf->dd ( c_addr ) ( f: x xx) \ convert buffer to dd
  363. COUNT >FLOAT 0= ABORT" Float conversion failed"
  364. 1e0 exactmul
  365. ;
  366.  
  367. fp-stack? [IF]
  368. : adjustExponent ( pwr) ( f: |y+yy| -- |x+xx|)
  369. pre_dp + ( p+n1)
  370. pre_dp post_dp + ( p+n1 n1+n2)
  371. MaxPlaces 2/ MIN - ( p'=p+n1-MIN[n1+n2,MaxP/2] )
  372. dd10 dd^n dd*
  373. ;
  374. [ELSE]
  375. : adjustExponent ( pwr) ( f: |y+yy| -- |x+xx|)
  376. pre_dp + ( p+n1)
  377. pre_dp post_dp + ( p+n1 n1+n2)
  378. MaxPlaces 2/ MIN - ( p'=p+n1-MIN[n1+n2,MaxP/2] )
  379. >R dd10 R> dd^n dd*
  380. ;
  381. [THEN]
  382.  
  383. fp-stack? [IF]
  384. : >dd ( c-addr u -- ) ( f: -- x xx)
  385. OVER + 1- SWAP ( end beg) \ $ends
  386. initialize ( end beg)
  387. leadingSign ( sgn end beg')
  388. TUCK do_exponent ROT ( sgn pwr end' beg')
  389. >(hi/lo) \ digits -> hi/lo buffers
  390. hi# buf->dd lo# buf->dd dd+ ( f: |y+yy|)
  391. ( s p) adjustExponent ( s)
  392. IF ddnegate THEN \ adjust sign
  393. ;
  394. [ELSE]
  395. : >dd ( c-addr u -- ) ( f: -- x xx)
  396. OVER + 1- SWAP ( end beg) \ $ends
  397. initialize ( end beg)
  398. leadingSign ( sgn end beg')
  399. TUCK do_exponent ROT ( sgn pwr end' beg')
  400. >(hi/lo) \ digits -> hi/lo buffers
  401. 2>R
  402. hi# buf->dd lo# buf->dd dd+ ( f: |y+yy|)
  403. R> ( p) adjustExponent
  404. R> ( s) IF ddnegate THEN \ adjust sign
  405. ;
  406. [THEN]
  407.  
  408.  
  409. false [IF]
  410.  
  411. cr .( Examples: ) cr
  412.  
  413. s" -11.1112222233333444445555566666dd-45" >dd cr ddfs.
  414. cr .( -1.1111222223333344444555556666603 dd -44 ok )
  415.  
  416. s" +-11.1112222233333444445555566666dd-45" >dd cr ddfs.
  417. cr .( Error: >dd Non-digit in significand! )
  418.  
  419. s" +11.1112222.233333444445555566666dd-45" >dd cr ddfs.
  420. cr .( Error: >dd One dp to a customer! )
  421.  
  422. s" +11.1112222233333444445555566666dd+45" >dd cr ddfs.
  423. cr .( +1.1111222223333344444555556666604 dd 46 ok )
  424.  
  425. s" +11.1112222233333444445555566666" >dd cr ddfs.
  426. cr .( +0.0000000000000000000000000000000 dd 0 ok <- Must have exponent field)
  427.  
  428. s" +11.1112222233333444445555566666dd" >dd cr ddfs.
  429. cr .( +1.1111222223333344444555556666603 dd 1 ok )
  430.  
  431. s" +11.1112222233333444445555566666D" >dd cr ddfs.
  432. cr .( +1.1111222223333344444555556666603 dd 1 ok )
  433.  
  434. s" 1111122.222333D" >dd cr ddfs.
  435. cr .( +1.1111222223330000000000000000000 dd 6 ok )
  436.  
  437. [THEN]
  438.  
  439.  
Advertisement
Add Comment
Please, Sign In to add comment