Author Topic: decimal floating point  (Read 4396 times)

0 Members and 1 Guest are viewing this topic.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
decimal floating point
« on: June 12, 2021, 10:52:04 pm »
I am making progress, I implemented addition subtraction and multiplication
floating point multiplication should be working
sub's and functions
dim as decfloat x, y, result
dim as long n ' value restricted to 9 decimal digits, positive or negative
Call str2dec("123", x) ' converts string to decfloat and stores it in x
Print dec2str(x) ' converts a decfloat to string
Print dec2str_fix(x) ' converts a decfloat to string without scientific notation, not reccomended for very lare numbers
Call fpadd(result, x, y) ' adds: x + y into result
Call fpsub(result, x, y) ' subtracts: x - y into result
Call fpmul(result, x, y) ' multiplies: x * y into result
Call fpmul_si(result, x, n) ' multiplies by a long: x * n into result
n=cmp(x, y) 'function that compares x and y: returns -1 if x<y, 0 if x=y and 1 if x>y
Code: QB64: [Select]
  1. ''$Checking:Off
  2.  
  3. Const NUM_DIGITS = 9 * 312 '50731 '3963
  4. Const NUM_DWORDS = NUM_DIGITS \ 9
  5. Const NUM_BYTES = 2 + 4 * NUM_DWORDS
  6. Const BIAS = 1073741824 '2 ^ 30
  7.  
  8. ' Error definitions
  9.  
  10. Const DIVZ_ERR = 1 'Divide by zero
  11. Const EXPO_ERR = 2 'Exponent overflow error
  12. Const EXPU_ERR = 3 'Exponent underflow error
  13.  
  14. Type decfloat
  15.     sign As Integer
  16.     exponent As _Unsigned Long
  17.     mantissa As String * Num_bytes
  18.  
  19. Dim As decfloat x, y, z
  20.  
  21. Dim As Long i, j
  22. Dim As String fib, s
  23. fib = "999999999999999999999998999999999999999999999999"
  24. t = Timer
  25. Call str2dec(fib, x)
  26. Call recip(y, x)
  27. s = dec2str_fix(y)
  28. j = InStr(s, ".")
  29. s = Mid$(s, j + 1)
  30.  
  31. j = 1
  32. For i = 1 To 58
  33.     Print Mid$(s, j, 24), Mid$(s, j + 24, 24)
  34.     j = j + 48
  35. t = Timer - t
  36. Print "fib by reciprocal time is "; t; " seconds"
  37.  
  38. 'Call str2dec("1", x)
  39. 'z = x
  40.  
  41. 't = Timer
  42.  
  43. 'For i = 1 To 100000
  44. 'Call fpmul_si(z, z, i)
  45. 'Next
  46. 't = Timer - t
  47.  
  48. 'Print dec2str(z)
  49. 'Print "factorial 10000 in "; t; " seconds"
  50.  
  51. Sub str2dec (value As String, n As decfloat)
  52.     Dim As Long j, s, d, e, ep, ex, es, i, f, fp, fln
  53.     Dim As String c, f1, f2, f3, ts
  54.     Dim As _Unsigned Long ulng
  55.  
  56.     j = 1
  57.     s = 1
  58.     d = 0
  59.     e = 0
  60.     ep = 0
  61.     ex = 0
  62.     es = 1
  63.     i = 0
  64.     f = 0
  65.     fp = 0
  66.     f1 = ""
  67.  
  68.     f2 = ""
  69.     f3 = ""
  70.     value = UCase$(value)
  71.     fln = Len(value)
  72.  
  73.     While j <= fln
  74.         c = Mid$(value, j, 1)
  75.         If ep = 1 Then
  76.             If c = " " Then
  77.                 j = j + 1
  78.                 GoTo skip_while
  79.             End If
  80.             If c = "-" Then
  81.                 es = -es
  82.                 c = ""
  83.             End If
  84.             If c = "+" Then
  85.                 j = j + 1
  86.                 GoTo skip_while
  87.             End If
  88.             If (c = "0") And (f3 = "") Then
  89.                 j = j + 1
  90.                 GoTo skip_while
  91.             End If
  92.             If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  93.                 f3 = f3 + c
  94.                 ex = 10 * ex + (Asc(c) - 48)
  95.                 j = j + 1
  96.                 GoTo skip_while
  97.             End If
  98.         End If
  99.  
  100.         If c = " " Then
  101.             j = j + 1
  102.             GoTo skip_while
  103.         End If
  104.         If c = "-" Then
  105.             s = -s
  106.             j = j + 1
  107.             GoTo skip_while
  108.         End If
  109.         If c = "+" Then
  110.             j = j + 1
  111.             GoTo skip_while
  112.         End If
  113.         If c = "." Then
  114.             If d = 1 Then
  115.                 j = j + 1
  116.                 GoTo skip_while
  117.             End If
  118.             d = 1
  119.         End If
  120.         If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  121.             If ((c = "0") And (i = 0)) Then
  122.                 If d = 0 Then
  123.                     j = j + 1
  124.                     GoTo skip_while
  125.                 End If
  126.                 If (d = 1) And (f = 0) Then
  127.                     e = e - 1
  128.                     j = j + 1
  129.                     GoTo skip_while
  130.                 End If
  131.             End If
  132.             If d = 0 Then
  133.                 f1 = f1 + c
  134.                 i = i + 1
  135.             Else
  136.                 If (c > "0") Then
  137.                     fp = 1
  138.                 End If
  139.                 f2 = f2 + c
  140.                 f = f + 1
  141.             End If
  142.         End If
  143.         If c = "E" Or c = "D" Then
  144.             ep = 1
  145.         End If
  146.         j = j + 1
  147.         skip_while:
  148.     Wend
  149.     If fp = 0 Then
  150.         f = 0
  151.         f2 = ""
  152.     End If
  153.  
  154.     If s = -1 Then s = &H8000 Else s = 0
  155.     n.sign = s
  156.     ex = es * ex - 1 + i + e
  157.     f1 = f1 + f2
  158.     f1 = Mid$(f1, 1, 1) + Right$(f1, Len(f1) - 1)
  159.     fln = Len(f1)
  160.     If Len(f1) > ((NUM_DWORDS * 9) + 1) Then
  161.         f1 = Mid$(f1, 1, ((NUM_DWORDS * 9) + 1))
  162.     End If
  163.     While Len(f1) < ((NUM_DWORDS * 9) + 1)
  164.         f1 = f1 + "0"
  165.     Wend
  166.     j = 1
  167.     For i = 0 To NUM_DWORDS - 1
  168.         ts = Mid$(f1, j, 9)
  169.         ulng = Val(ts)
  170.         Mid$(n.mantissa, 4 * i + 1, 4) = MKL$(ulng)
  171.         If ulng <> 0 Then fp = 1
  172.         j = j + 9
  173.     Next
  174.     If fp Then n.exponent = (ex + BIAS + 1) Else n.exponent = 0
  175.  
  176. Function dec2str$ (n As decfloat)
  177.     Dim As Long i, ex
  178.     Dim As String v, f, ts
  179.     If n.exponent > 0 Then
  180.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  181.     Else
  182.         ex = 0
  183.     End If
  184.     If n.sign Then v = "-" Else v = " "
  185.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  186.     If Len(ts) < 9 Then
  187.         ts = ts + String$(9 - Len(ts), "0")
  188.     End If
  189.     v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
  190.     For i = 1 To NUM_DWORDS - 1
  191.         ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * i + 1, 4))))
  192.         If Len(ts) < 9 Then
  193.             ts = String$(9 - Len(ts), "0") + ts
  194.         End If
  195.         v = v + ts
  196.     Next
  197.     f = _Trim$(Str$(Abs(ex)))
  198.     f = String$(5 - Len(f), "0") + f
  199.     If ex < 0 Then v = v + "E-" Else v = v + "E+"
  200.     v = v + f
  201.     dec2str = v
  202.  
  203. Function dec2str_fix$ (n As decfloat)
  204.     Dim As Long i, ex
  205.     Dim As String v, ts, s
  206.     If n.exponent > 0 Then
  207.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  208.     Else
  209.         ex = 0
  210.     End If
  211.     If n.sign Then s = "-" Else s = " "
  212.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  213.     If Len(ts) < 9 Then
  214.         ts = ts + String$(9 - Len(ts), "0")
  215.     End If
  216.     v = ts
  217.     For i = 1 To NUM_DWORDS - 1
  218.         ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * i + 1, 4))))
  219.         If Len(ts) < 9 Then
  220.             ts = String$(9 - Len(ts), "0") + ts
  221.         End If
  222.         v = v + ts
  223.     Next
  224.     If ex = 0 Then
  225.         v = Left$(v, 1) + "." + Mid$(v, 2)
  226.     ElseIf ex < 0 Then
  227.         v = "0." + String$(Abs(ex) - 1, "0") + v
  228.     ElseIf ex > 0 Then
  229.         v = Left$(v, ex + 1) + "." + Mid$(v, ex + 2)
  230.     End If
  231.     dec2str_fix = s + v
  232.  
  233. Function dec2dbl# (n As decfloat)
  234.     Dim As Long ex
  235.     Dim As String v, f, ts
  236.     If n.exponent > 0 Then
  237.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  238.     Else
  239.         ex = 0
  240.     End If
  241.     If n.sign Then v = "-" Else v = " "
  242.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  243.     If Len(ts) < 9 Then
  244.         ts = ts + String$(9 - Len(ts), "0")
  245.     End If
  246.     v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
  247.  
  248.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 1 + 1, 4))))
  249.     If Len(ts) < 9 Then
  250.         ts = String$(9 - Len(ts), "0") + ts
  251.     End If
  252.     v = v + ts
  253.  
  254.     f = _Trim$(Str$(Abs(ex)))
  255.     f = String$(5 - Len(f), "0") + f
  256.     If ex < 0 Then v = v + "E-" Else v = v + "E+"
  257.     v = v + f
  258.     dec2dbl = Val(v)
  259.  
  260. Sub RSHIFT_1 (mantissa As decfloat)
  261.     Dim As _Unsigned Long v1, v2
  262.     Dim As Long i
  263.     For i = NUM_DWORDS - 1 To 1 Step -1
  264.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10
  265.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10
  266.         v2 = v2 * 100000000 + v1
  267.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  268.     Next
  269.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10)
  270.  
  271. Sub LSHIFT_1 (mantissa As decfloat)
  272.     Dim As _Unsigned Long v1, v2
  273.     Dim As Long i
  274.     For i = 0 To NUM_DWORDS - 2
  275.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100000000
  276.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100000000
  277.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10 + v2)
  278.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100000000)
  279.     Next
  280.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10 * CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100000000)
  281.  
  282. Sub RSHIFT_2 (mantissa As decfloat)
  283.     Dim As _Unsigned Long v1, v2
  284.     Dim As Long i
  285.     For i = NUM_DWORDS - 1 To 1 Step -1
  286.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100
  287.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100
  288.         v2 = v2 * 10000000 + v1
  289.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  290.     Next
  291.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100)
  292.  
  293. Sub LSHIFT_2 (mantissa As decfloat)
  294.     Dim As _Unsigned Long v1, v2
  295.     Dim As Long i
  296.     For i = 0 To NUM_DWORDS - 2
  297.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10000000
  298.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10000000
  299.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100 + v2)
  300.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10000000)
  301.     Next
  302.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10000000))
  303.  
  304. Sub RSHIFT_3 (mantissa As decfloat)
  305.     Dim As _Unsigned Long v1, v2
  306.     Dim As Long i
  307.     For i = NUM_DWORDS - 1 To 1 Step -1
  308.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 1000
  309.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 1000
  310.         v2 = v2 * 1000000 + v1
  311.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  312.     Next
  313.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 1000)
  314.  
  315. Sub LSHIFT_3 (mantissa As decfloat)
  316.     Dim As _Unsigned Long v1, v2
  317.     Dim As Long i
  318.     For i = 0 To NUM_DWORDS - 2
  319.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 1000000
  320.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 1000000
  321.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 1000 + v2)
  322.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 1000000)
  323.     Next
  324.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(1000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 1000000))
  325.  
  326. Sub RSHIFT_4 (mantissa As decfloat)
  327.     Dim As _Unsigned Long v1, v2
  328.     Dim As Long i
  329.     For i = NUM_DWORDS - 1 To 1 Step -1
  330.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10000
  331.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10000
  332.         v2 = v2 * 100000 + v1
  333.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  334.     Next
  335.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10000)
  336.  
  337. Sub LSHIFT_4 (mantissa As decfloat)
  338.     Dim As _Unsigned Long v1, v2
  339.     Dim As Long i
  340.     For i = 0 To NUM_DWORDS - 2
  341.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100000
  342.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100000
  343.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10000 + v2)
  344.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100000)
  345.     Next
  346.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100000))
  347.  
  348. Sub RSHIFT_5 (mantissa As decfloat)
  349.     Dim As _Unsigned Long v1, v2
  350.     Dim As Long i
  351.     For i = NUM_DWORDS - 1 To 1 Step -1
  352.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100000
  353.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100000
  354.         v2 = v2 * 10000 + v1
  355.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  356.     Next
  357.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100000)
  358.  
  359. Sub LSHIFT_5 (mantissa As decfloat)
  360.     Dim As _Unsigned Long v1, v2
  361.     Dim As Long i
  362.     For i = 0 To NUM_DWORDS - 2
  363.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10000
  364.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10000
  365.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100000 + v2)
  366.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10000)
  367.     Next
  368.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10000))
  369.  
  370. Sub RSHIFT_6 (mantissa As decfloat)
  371.     Dim As _Unsigned Long v1, v2
  372.     Dim As Long i
  373.     For i = NUM_DWORDS - 1 To 1 Step -1
  374.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 1000000
  375.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 1000000
  376.         v2 = v2 * 1000 + v1
  377.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  378.     Next
  379.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 1000000)
  380.  
  381. Sub LSHIFT_6 (mantissa As decfloat)
  382.     Dim As _Unsigned Long v1, v2
  383.     Dim As Long i
  384.     For i = 0 To NUM_DWORDS - 2
  385.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 1000
  386.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 1000
  387.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 1000000 + v2)
  388.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 1000)
  389.     Next
  390.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(1000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 1000))
  391.  
  392. Sub RSHIFT_7 (mantissa As decfloat)
  393.     Dim As _Unsigned Long v1, v2
  394.     Dim As Long i
  395.     For i = NUM_DWORDS - 1 To 1 Step -1
  396.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10000000
  397.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10000000
  398.         v2 = v2 * 100 + v1
  399.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  400.     Next
  401.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10000000)
  402.  
  403. Sub LSHIFT_7 (mantissa As decfloat)
  404.     Dim As _Unsigned Long v1, v2
  405.     Dim As Long i
  406.     For i = 0 To NUM_DWORDS - 2
  407.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100
  408.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100
  409.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10000000 + v2)
  410.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100)
  411.     Next
  412.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100))
  413.  
  414. Sub RSHIFT_8 (mantissa As decfloat)
  415.     Dim As _Unsigned Long v1, v2
  416.     Dim As Long i
  417.     For i = NUM_DWORDS - 1 To 1 Step -1
  418.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100000000
  419.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100000000
  420.         v2 = v2 * 10 + v1
  421.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  422.     Next
  423.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100000000)
  424.  
  425. Sub LSHIFT_8 (mantissa As decfloat)
  426.     Dim As _Unsigned Long v1, v2
  427.     Dim As Long i
  428.     For i = 0 To NUM_DWORDS - 2
  429.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10
  430.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10
  431.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100000000 + v2)
  432.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10)
  433.     Next
  434.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10))
  435.  
  436. Sub RSHIFT_9 (mantissa As decfloat)
  437.     Dim As Long i
  438.     For i = NUM_DWORDS - 1 To 1 Step -1
  439.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)
  440.     Next
  441.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(0)
  442.  
  443. Sub LSHIFT_9 (mantissa As decfloat)
  444.     Dim As Long i
  445.     For i = 0 To NUM_DWORDS - 2
  446.         Mid$(mantissa.mantissa, 4 * i + 1) = Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)
  447.     Next
  448.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(0)
  449.  
  450. Function cmp% (x As decfloat, y As decfloat)
  451.     Dim As Long c, i
  452.     If x.sign = y.sign Then
  453.         If x.exponent = y.exponent Then
  454.             For i = 0 To NUM_DWORDS - 1
  455.                 c = CVL(Mid$(x.mantissa, 4 * i + 1, 4)) - CVL(Mid$(y.mantissa, 4 * i + 1, 4))
  456.                 If c <> 0 Then Exit For
  457.             Next
  458.             If c < 0 Then
  459.                 cmp = -1
  460.                 Exit Function
  461.             ElseIf c = 0 Then
  462.                 cmp = 0
  463.                 Exit Function
  464.             ElseIf c > 0 Then
  465.                 cmp = 1
  466.                 Exit Function
  467.             End If
  468.         End If
  469.         If x.exponent < y.exponent Then
  470.             cmp = -1
  471.             Exit Function
  472.         End If
  473.         If x.exponent > y.exponent Then
  474.             cmp = 1
  475.             Exit Function
  476.         End If
  477.     End If
  478.     If x.sign Then cmp = -1
  479.  
  480. Function NORM_FAC1% (fac1 As decfloat)
  481.     ' normalize the number in fac1
  482.     ' all routines exit through this one.
  483.     ' we leave ax=0 if normalization was
  484.     ' ok...else ax = error code.
  485.  
  486.     'see if the mantissa is all zeros.
  487.     'if so, set the exponent and sign equal to 0.
  488.     Dim As Long i, er, f
  489.     er = 0: f = 0
  490.     For i = 0 To NUM_DWORDS - 1
  491.         If CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) > 0 Then f = 1
  492.     Next
  493.     If f = 0 Then
  494.         fac1.exponent = 0
  495.         fac1.sign = 0
  496.         Exit Function
  497.         'if the highmost nibble in fac1_man is nonzero,
  498.         'shift the mantissa right 1 nibble and
  499.         'increment the exponent
  500.     ElseIf CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) > 999999999 Then
  501.         Call RSHIFT_1(fac1)
  502.         fac1.exponent = fac1.exponent + 1
  503.     Else
  504.         'now shift fac1_man 1 to the left until a
  505.         'nonzero digit appears in the next-to-highest
  506.         'nibble of fac1_man.  decrement exponent for
  507.         'each shift.
  508.         While CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) < 100000000
  509.             Call LSHIFT_1(fac1)
  510.             fac1.exponent = fac1.exponent - 1
  511.             If fac1.exponent = 0 Then
  512.                 NORM_FAC1 = EXPU_ERR
  513.                 Exit Function
  514.             End If
  515.         Wend
  516.     End If
  517.     'check for overflow/underflow
  518.     If fac1.exponent < 0 Then
  519.         NORM_FAC1 = EXPO_ERR
  520.     End If
  521.  
  522. Sub fpadd_aux (fac1 As decfloat, fac2 As decfloat)
  523.     Dim As _Unsigned Long v, c, i
  524.     Dim As Integer er
  525.     c = 0
  526.     For i = NUM_DWORDS - 1 To 1 Step -1
  527.         v = CVL(Mid$(fac2.mantissa, 4 * i + 1, 4)) + CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) + c
  528.         If v > 999999999 Then
  529.             v = v - 1000000000
  530.             c = 1
  531.         Else
  532.             c = 0
  533.         End If
  534.         Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  535.     Next
  536.     v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + CVL(Mid$(fac2.mantissa, 4 * 0 + 1, 4)) + c
  537.     Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  538.  
  539.     er = NORM_FAC1%(fac1)
  540.  
  541.  
  542. Sub fpsub_aux (fac1 As decfloat, fac2 As decfloat)
  543.     Dim As Long v, c, i
  544.     c = 0
  545.     For i = NUM_DWORDS - 1 To 1 Step -1
  546.         v = CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) - CVL(Mid$(fac2.mantissa, 4 * i + 1, 4)) - c
  547.         If v < 0 Then
  548.             v = v + 1000000000
  549.             c = 1
  550.         Else
  551.             c = 0
  552.         End If
  553.         Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  554.     Next
  555.     v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) - CVL(Mid$(fac2.mantissa, 4 * 0 + 1, 4)) - c
  556.     Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  557.  
  558.     c = NORM_FAC1(fac1)
  559.  
  560. Sub fpadd (result As decfloat, x As decfloat, y As decfloat)
  561.  
  562.     Dim As decfloat fac1, fac2
  563.     Dim As Long t, c, xsign, ysign
  564.  
  565.     xsign = x.sign: x.sign = 0
  566.     ysign = y.sign: y.sign = 0
  567.     c = cmp(x, y)
  568.     x.sign = xsign
  569.     y.sign = ysign
  570.     If c < 0 Then
  571.         fac1 = y
  572.         fac2 = x
  573.     Else
  574.         fac1 = x
  575.         fac2 = y
  576.     End If
  577.     t = fac1.exponent - fac2.exponent
  578.  
  579.     If t < NUM_DIGITS Then
  580.         'The difference between the two
  581.         'exponents indicate how many times
  582.         'we have to multiply the mantissa
  583.         'of FAC2 by 10 (i.e., shift it right 1 place).
  584.         'If we have to shift more times than
  585.         'we have digits, the result is already in FAC1.
  586.         t = fac1.exponent - fac2.exponent
  587.         If t > 0 And t < (NUM_DIGITS) Then 'shift
  588.             While t
  589.                 Call RSHIFT_1(fac2)
  590.                 t = t - 1
  591.             Wend
  592.         End If
  593.         'See if the signs of the two numbers
  594.         'are the same.  If so, add; if not, subtract.
  595.         If fac1.sign = fac2.sign Then 'add
  596.             Call fpadd_aux(fac1, fac2)
  597.         Else
  598.             Call fpsub_aux(fac1, fac2)
  599.         End If
  600.     End If
  601.     result = fac1
  602.  
  603. Sub fpsub (result As decfloat, x As decfloat, y As decfloat)
  604.     Dim As decfloat fac1, fac2
  605.     fac1 = x
  606.     fac2 = y
  607.     fac2.sign = fac2.sign Xor &H8000
  608.     Call fpadd(result, fac1, fac2)
  609.  
  610. Sub fpmul_si (result As decfloat, x As decfloat, y As _Integer64)
  611.     Dim As decfloat fac1
  612.     Dim As Long count, ex, er, i
  613.     Dim As _Integer64 value, carry, digit, prod
  614.     fac1 = x
  615.     digit = Abs(y)
  616.     'check exponents.  if either is zero,
  617.     'the result is zero
  618.     If fac1.exponent = 0 Or y = 0 Then 'result is zero...clear fac1.
  619.         fac1.sign = 0
  620.         fac1.exponent = 0
  621.         For count = 0 To NUM_DWORDS - 1
  622.             Mid$(fac1.mantissa, 4 * count + 1, 4) = MKL$(0)
  623.         Next
  624.         er = NORM_FAC1(fac1)
  625.         result = fac1
  626.         Exit Sub
  627.     Else
  628.         If digit = 1 Then
  629.             If y < 0 Then
  630.                 fac1.sign = fac1.sign Xor &H8000
  631.             End If
  632.             result = fac1
  633.         End If
  634.         'now determine exponent of result.
  635.         'as you do...watch for overflow.
  636.         '        ex=fac2.exponent-BIAS+fac1.exponent-1
  637.  
  638.         If ex < 0 Then
  639.             er = EXPO_ERR
  640.             Exit Sub
  641.         End If
  642.         'for number of digits in the floating
  643.         'point number, add fac2 to fac1 number
  644.         'of times given by lowest nibble in
  645.         'fac3.  then shift fac1 and fac3
  646.         'right 1 digit and repeat.
  647.         'count=NUM_DIGITS-1
  648.  
  649.         carry = 0
  650.  
  651.         For i = NUM_DWORDS - 1 To 0 Step -1
  652.             prod = CVL(Mid$(fac1.mantissa, 4 * i + 1, 4))
  653.             prod = digit * prod + carry
  654.             value = (prod Mod 1000000000)
  655.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(value)
  656.             carry = prod \ 1000000000
  657.         Next
  658.  
  659.         If carry < 10 Then
  660.             Call RSHIFT_1(fac1)
  661.             fac1.exponent = fac1.exponent + 1
  662.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100000000)
  663.         ElseIf carry < 100 Then
  664.             Call RSHIFT_2(fac1)
  665.             fac1.exponent = fac1.exponent + 2
  666.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10000000)
  667.         ElseIf carry < 1000 Then
  668.             Call RSHIFT_3(fac1)
  669.             fac1.exponent = fac1.exponent + 3
  670.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 1000000)
  671.         ElseIf carry < 10000 Then
  672.             Call RSHIFT_4(fac1)
  673.             fac1.exponent = fac1.exponent + 4
  674.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100000)
  675.         ElseIf carry < 100000 Then
  676.             Call RSHIFT_5(fac1)
  677.             fac1.exponent = fac1.exponent + 5
  678.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10000)
  679.         ElseIf carry < 1000000 Then
  680.             Call RSHIFT_6(fac1)
  681.             fac1.exponent = fac1.exponent + 6
  682.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 1000)
  683.         ElseIf carry < 10000000 Then
  684.             Call RSHIFT_7(fac1)
  685.             fac1.exponent = fac1.exponent + 7
  686.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100)
  687.         ElseIf carry < 100000000 Then
  688.             Call RSHIFT_8(fac1)
  689.             fac1.exponent = fac1.exponent + 8
  690.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10)
  691.         ElseIf carry < 1000000000 Then
  692.             Call RSHIFT_9(fac1)
  693.             fac1.exponent = fac1.exponent + 9
  694.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry)
  695.         End If
  696.  
  697.     End If
  698.  
  699.     'fac1.exponent=fac2.exponent+fac1.exponent-BIAS-1
  700.     er = NORM_FAC1(fac1)
  701.     'fac1.exponent+=c 'ex
  702.     'if v>100000000 then fac1.exponent+=1
  703.     If y < 0 Then
  704.         fac1.sign = fac1.sign Xor &H8000
  705.     End If
  706.     result = fac1
  707.  
  708. Sub fpmul (result As decfloat, x As decfloat, y As decfloat)
  709.     Dim As decfloat fac1, fac2, fac3
  710.     Dim As Long i, j, ex, er
  711.     Dim As _Integer64 prod, digit, carry
  712.     Dim As _Unsigned Long c, v
  713.  
  714.     fac1 = x
  715.     fac2 = y
  716.     'check exponents.  if either is zero,
  717.     'the result is zero
  718.     If fac1.exponent = 0 Or fac2.exponent = 0 Then 'result is zero...clear fac1.
  719.         fac1.sign = 0
  720.         fac1.exponent = 0
  721.         For i = 0 To NUM_DWORDS - 1
  722.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(0)
  723.         Next
  724.         er = NORM_FAC1(fac1)
  725.         result = fac1
  726.         Exit Sub
  727.     Else
  728.  
  729.         'now determine exponent of result.
  730.         'as you do...watch for overflow.
  731.         ex = fac2.exponent - BIAS + fac1.exponent
  732.  
  733.         If ex < 0 Then
  734.             er = EXPO_ERR
  735.             Exit Sub
  736.         End If
  737.         fac1.exponent = ex
  738.         'determine the sign of the product
  739.         fac1.sign = fac1.sign Xor fac2.sign
  740.         'copy fac1 mantissa to fac3 and clear fac1's mantissa
  741.         For i = 0 To NUM_DWORDS - 1
  742.             Mid$(fac3.mantissa, 4 * i + 1, 4) = MKL$(0)
  743.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(0)
  744.         Next
  745.         'for number of digits in the floating
  746.         'point number, add fac2 to fac1 number
  747.         'of times given by lowest nibble in
  748.         'fac3.  then shift fac1 and fac3
  749.         'right 1 digit and repeat.
  750.  
  751.         For j = NUM_DWORDS - 1 To 0 Step -1
  752.             carry = 0
  753.             digit = CVL(Mid$(y.mantissa, 4 * j + 1, 4))
  754.             For i = NUM_DWORDS - 1 To 0 Step -1
  755.                 prod = digit * CVL(Mid$(x.mantissa, 4 * i + 1, 4)) + carry
  756.                 Mid$(fac3.mantissa, 4 * i + 1, 4) = MKL$(prod Mod 1000000000)
  757.                 carry = prod \ 1000000000
  758.  
  759.             Next
  760.  
  761.             Call RSHIFT_9(fac1)
  762.             Call RSHIFT_9(fac3)
  763.             Mid$(fac3.mantissa, 4 * 0 + 1, 4) = MKL$(carry)
  764.  
  765.             c = 0
  766.             For i = NUM_DWORDS - 1 To 1 Step -1
  767.                 v = CVL(Mid$(fac3.mantissa, 4 * i + 1, 4)) + CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) + c
  768.                 If v > 999999999 Then
  769.                     v = v - 1000000000
  770.                     c = 1
  771.                 Else
  772.                     c = 0
  773.                 End If
  774.                 Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  775.             Next
  776.             v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + CVL(Mid$(fac3.mantissa, 4 * 0 + 1, 4)) + c
  777.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  778.  
  779.         Next
  780.     End If
  781.  
  782.     er = NORM_FAC1(fac1)
  783.     result = fac1
  784.  
  785. Sub recip (result As decfloat, n As decfloat)
  786.     Dim As Double x: x = dec2dbl(n)
  787.     Dim As Long k, l
  788.     Dim As decfloat r, r2, two
  789.     l = Log(NUM_DIGITS * 0.0625) * 1.5
  790.     If x = 0 Then Print "Div 0": Exit Sub
  791.     If x = 1 Then
  792.         Call str2dec("1", r)
  793.         result = r
  794.         Exit Sub
  795.     End If
  796.  
  797.     x = 1# / x
  798.     Call str2dec(Str$(x), r)
  799.     Call str2dec("2", two)
  800.     For k = 1 To l
  801.         Call fpmul(r2, n, r)
  802.         Call fpsub(r2, two, r2)
  803.         Call fpmul(r, r, r2)
  804.     Next k
  805.  
  806.     result = r
  807.  
« Last Edit: June 16, 2021, 10:16:30 am by jack »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #1 on: June 13, 2021, 02:21:25 pm »
the addition and subtraction are now implemented, would someone give suggestions on the implementation of multiplication?
the old school method is probably the easiest, but I was hoping to implement the Karatsuba method
I saw no way to do subtraction without first determining which of the two numbers was smaller, it works fine but the time to do addition is doubled

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #2 on: June 15, 2021, 06:15:33 pm »
added multiply by signed integer, factorial 10000 takes about 10 seconds
Quote
2.8462596809170545189064132121198......00000000000000000000000000000E+35659
factorial 10000 in  9.9453125  seconds

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: decimal floating point
« Reply #3 on: June 15, 2021, 07:41:59 pm »
I would, but since I'm running on Linux, the $CONSOLE and destination CONSOLE does not work.

Looking at the code, it is somewhat similar to the code my friend and I wrote in SmartBASIC.

That code will not run in QB64 without some extensive modification (we developed it to run on mobile devices), but I could send you the program so you can look at it (BASIC is still BASIC, so you should be able to read it).



the addition and subtraction are now implemented, would someone give suggestions on the implementation of multiplication?
the old school method is probably the easiest, but I was hoping to implement the Karatsuba method
I saw no way to do subtraction without first determining which of the two numbers was smaller, it works fine but the time to do addition is doubled
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #4 on: June 15, 2021, 07:50:20 pm »
you could simply comment-out those instructions, I don't like the graphic screen because you can't copy from it like you can from a console

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #5 on: June 16, 2021, 06:40:18 am »
I finally got multiplication working
@bplus would you describe your nInverse function perhaps in pseudo code?
I like to implement that, I know that I can use the Newton-Raphson method but the exponent range of decfloat far surpasses that of double and so it would be restricted to the range of double
« Last Edit: June 16, 2021, 06:43:01 am by jack »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #6 on: June 16, 2021, 10:19:23 am »
using the Newton-Raphson for reciprocal
Code: [Select]
000000000000000000000000     000000000000000000000001
000000000000000000000001     000000000000000000000002
000000000000000000000003     000000000000000000000005
000000000000000000000008     000000000000000000000013
000000000000000000000021     000000000000000000000034
000000000000000000000055     000000000000000000000089
000000000000000000000144     000000000000000000000233
000000000000000000000377     000000000000000000000610
000000000000000000000987     000000000000000000001597
000000000000000000002584     000000000000000000004181
000000000000000000006765     000000000000000000010946
000000000000000000017711     000000000000000000028657
000000000000000000046368     000000000000000000075025
000000000000000000121393     000000000000000000196418
000000000000000000317811     000000000000000000514229
000000000000000000832040     000000000000000001346269
000000000000000002178309     000000000000000003524578
000000000000000005702887     000000000000000009227465
000000000000000014930352     000000000000000024157817
000000000000000039088169     000000000000000063245986
000000000000000102334155     000000000000000165580141
000000000000000267914296     000000000000000433494437
000000000000000701408733     000000000000001134903170
000000000000001836311903     000000000000002971215073
000000000000004807526976     000000000000007778742049
000000000000012586269025     000000000000020365011074
000000000000032951280099     000000000000053316291173
000000000000086267571272     000000000000139583862445
000000000000225851433717     000000000000365435296162
000000000000591286729879     000000000000956722026041
000000000001548008755920     000000000002504730781961
000000000004052739537881     000000000006557470319842
000000000010610209857723     000000000017167680177565
000000000027777890035288     000000000044945570212853
000000000072723460248141     000000000117669030460994
000000000190392490709135     000000000308061521170129
000000000498454011879264     000000000806515533049393
000000001304969544928657     000000002111485077978050
000000003416454622906707     000000005527939700884757
000000008944394323791464     000000014472334024676221
000000023416728348467685     000000037889062373143906
000000061305790721611591     000000099194853094755497
000000160500643816367088     000000259695496911122585
000000420196140727489673     000000679891637638612258
000001100087778366101931     000001779979416004714189
000002880067194370816120     000004660046610375530309
000007540113804746346429     000012200160415121876738
000019740274219868223167     000031940434634990099905
000051680708854858323072     000083621143489848422977
000135301852344706746049     000218922995834555169026
000354224848179261915075     000573147844013817084101
000927372692193078999176     001500520536206896083277
002427893228399975082453     003928413764606871165730
006356306993006846248183     010284720757613717413913
016641027750620563662096     026925748508234281076009
043566776258854844738105     070492524767089125814114
114059301025943970552219     184551825793033096366333
298611126818977066918552     483162952612010163284885
fib by reciprocal time is  .55078125  seconds

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: decimal floating point
« Reply #7 on: June 16, 2021, 11:55:50 am »
Quote
@bplus would you describe your nInverse function perhaps in pseudo code?

Same as you learned in school how to divide only the denominator is integer > 1 and you are dividing into 1

Assume a decimal at the start output$ = "."  let's take 15 as example

and now remainder r is 10 'it always starts like this
loop start
is divisor <= remainder?
no
15 is greater than 10 so output$ = output$ + "0" and now make remainder r = 100
loop back

yes
15 does go into 100 6 times so output$ = output$ +"6"
(for this part in string math I made a table (0 to 9) * denominator and go back from 9, 8, 7 until have highest mult <= remainder for 15 the table is 0, 15, 30, 45, 60, 75, 90, 105, 120, 135 in string form)
calc new remainder 100 -90 (15*6) = 10 new remainder is 10 again.
(So for String math I had to have Mult and Subtr for strings ready before attempting Inverse.)
say is remainder 0? if yes then division is done set function and exit
say is output$ long enough? if yes ie 100 digits long then set function and exit
else
add 0 to end of remainder and loop back to decision point

No estimation at all you just write out the inverse until you get exact 0 remainder or reach a string length limit.

When I did String Math I needed a Function that could compare 2 number strings and say which is the greater number, first compare lengths size matters the bigger is greater, if sizes match then go down strings and compare each digit the string having the greater or lesser digit. (if digit strings start with 0's remove them before testing lengths, so I needed a trim leading 0's function.)


« Last Edit: June 16, 2021, 12:33:52 pm by bplus »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #8 on: June 16, 2021, 12:07:46 pm »
thank you bplus, much appreciated

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: decimal floating point
« Reply #9 on: June 16, 2021, 12:18:11 pm »
One of these days I am going to get around to digging into what you and Luke are doing.

I suspect one of you is going to take advantage of binary math, you multiple and divide by shift 0's and 1's left and right. The addition and subtraction tables are pretty sweet too. But this involves an extra steps of converting to and from binary and decimal.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #10 on: June 16, 2021, 01:19:36 pm »
I need to describe in comments what the code is supposed to doing, without clear comments it's hard to decipher the code

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: decimal floating point
« Reply #11 on: June 16, 2021, 06:11:06 pm »
432 Fibonacci numbers via reciprocal in 145 seconds
Code: QB64: [Select]
  1. ''$Checking:Off
  2.  
  3. Const NUM_DIGITS = 9 * 4301 '4301 '312 '50731 '3963
  4. Const NUM_DWORDS = NUM_DIGITS \ 9
  5. Const NUM_BYTES = 2 + 4 * NUM_DWORDS
  6. Const BIAS = 1073741824 '2 ^ 30
  7.  
  8. ' Error definitions
  9.  
  10. Const DIVZ_ERR = 1 'Divide by zero
  11. Const EXPO_ERR = 2 'Exponent overflow error
  12. Const EXPU_ERR = 3 'Exponent underflow error
  13.  
  14. Type decfloat
  15.     sign As Integer
  16.     exponent As _Unsigned Long
  17.     mantissa As String * Num_bytes
  18.  
  19. Dim As decfloat x, y, z
  20.  
  21. Dim As Long i, j
  22. Dim As String fib, s
  23. fib = String$(89, "9") + "8" + String$(90, "9")
  24.  
  25. t = Timer
  26. Call str2dec(fib, x)
  27. Call recip(y, x)
  28. s = dec2str_fix(y)
  29. j = InStr(s, ".")
  30. s = Mid$(s, j + 1)
  31.  
  32. j = 1
  33. For i = 1 To 432
  34.     Print Mid$(s, j, 90)
  35.     j = j + 90
  36. t = Timer - t
  37. Print "fib by reciprocal time is "; t; " seconds"
  38.  
  39. 'Call str2dec("1", x)
  40. 'z = x
  41.  
  42. 't = Timer
  43.  
  44. 'For i = 1 To 100000
  45. 'Call fpmul_si(z, z, i)
  46. 'Next
  47. 't = Timer - t
  48.  
  49. 'Print dec2str(z)
  50. 'Print "factorial 10000 in "; t; " seconds"
  51.  
  52. Sub str2dec (value As String, n As decfloat)
  53.     Dim As Long j, s, d, e, ep, ex, es, i, f, fp, fln
  54.     Dim As String c, f1, f2, f3, ts
  55.     Dim As _Unsigned Long ulng
  56.  
  57.     j = 1
  58.     s = 1
  59.     d = 0
  60.     e = 0
  61.     ep = 0
  62.     ex = 0
  63.     es = 1
  64.     i = 0
  65.     f = 0
  66.     fp = 0
  67.     f1 = ""
  68.  
  69.     f2 = ""
  70.     f3 = ""
  71.     value = UCase$(value)
  72.     fln = Len(value)
  73.  
  74.     While j <= fln
  75.         c = Mid$(value, j, 1)
  76.         If ep = 1 Then
  77.             If c = " " Then
  78.                 j = j + 1
  79.                 GoTo skip_while
  80.             End If
  81.             If c = "-" Then
  82.                 es = -es
  83.                 c = ""
  84.             End If
  85.             If c = "+" Then
  86.                 j = j + 1
  87.                 GoTo skip_while
  88.             End If
  89.             If (c = "0") And (f3 = "") Then
  90.                 j = j + 1
  91.                 GoTo skip_while
  92.             End If
  93.             If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  94.                 f3 = f3 + c
  95.                 ex = 10 * ex + (Asc(c) - 48)
  96.                 j = j + 1
  97.                 GoTo skip_while
  98.             End If
  99.         End If
  100.  
  101.         If c = " " Then
  102.             j = j + 1
  103.             GoTo skip_while
  104.         End If
  105.         If c = "-" Then
  106.             s = -s
  107.             j = j + 1
  108.             GoTo skip_while
  109.         End If
  110.         If c = "+" Then
  111.             j = j + 1
  112.             GoTo skip_while
  113.         End If
  114.         If c = "." Then
  115.             If d = 1 Then
  116.                 j = j + 1
  117.                 GoTo skip_while
  118.             End If
  119.             d = 1
  120.         End If
  121.         If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  122.             If ((c = "0") And (i = 0)) Then
  123.                 If d = 0 Then
  124.                     j = j + 1
  125.                     GoTo skip_while
  126.                 End If
  127.                 If (d = 1) And (f = 0) Then
  128.                     e = e - 1
  129.                     j = j + 1
  130.                     GoTo skip_while
  131.                 End If
  132.             End If
  133.             If d = 0 Then
  134.                 f1 = f1 + c
  135.                 i = i + 1
  136.             Else
  137.                 If (c > "0") Then
  138.                     fp = 1
  139.                 End If
  140.                 f2 = f2 + c
  141.                 f = f + 1
  142.             End If
  143.         End If
  144.         If c = "E" Or c = "D" Then
  145.             ep = 1
  146.         End If
  147.         j = j + 1
  148.         skip_while:
  149.     Wend
  150.     If fp = 0 Then
  151.         f = 0
  152.         f2 = ""
  153.     End If
  154.  
  155.     If s = -1 Then s = &H8000 Else s = 0
  156.     n.sign = s
  157.     ex = es * ex - 1 + i + e
  158.     f1 = f1 + f2
  159.     f1 = Mid$(f1, 1, 1) + Right$(f1, Len(f1) - 1)
  160.     fln = Len(f1)
  161.     If Len(f1) > ((NUM_DWORDS * 9) + 1) Then
  162.         f1 = Mid$(f1, 1, ((NUM_DWORDS * 9) + 1))
  163.     End If
  164.     While Len(f1) < ((NUM_DWORDS * 9) + 1)
  165.         f1 = f1 + "0"
  166.     Wend
  167.     j = 1
  168.     For i = 0 To NUM_DWORDS - 1
  169.         ts = Mid$(f1, j, 9)
  170.         ulng = Val(ts)
  171.         Mid$(n.mantissa, 4 * i + 1, 4) = MKL$(ulng)
  172.         If ulng <> 0 Then fp = 1
  173.         j = j + 9
  174.     Next
  175.     If fp Then n.exponent = (ex + BIAS + 1) Else n.exponent = 0
  176.  
  177. Function dec2str$ (n As decfloat)
  178.     Dim As Long i, ex
  179.     Dim As String v, f, ts
  180.     If n.exponent > 0 Then
  181.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  182.     Else
  183.         ex = 0
  184.     End If
  185.     If n.sign Then v = "-" Else v = " "
  186.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  187.     If Len(ts) < 9 Then
  188.         ts = ts + String$(9 - Len(ts), "0")
  189.     End If
  190.     v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
  191.     For i = 1 To NUM_DWORDS - 1
  192.         ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * i + 1, 4))))
  193.         If Len(ts) < 9 Then
  194.             ts = String$(9 - Len(ts), "0") + ts
  195.         End If
  196.         v = v + ts
  197.     Next
  198.     f = _Trim$(Str$(Abs(ex)))
  199.     f = String$(5 - Len(f), "0") + f
  200.     If ex < 0 Then v = v + "E-" Else v = v + "E+"
  201.     v = v + f
  202.     dec2str = v
  203.  
  204. Function dec2str_fix$ (n As decfloat)
  205.     Dim As Long i, ex
  206.     Dim As String v, ts, s
  207.     If n.exponent > 0 Then
  208.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  209.     Else
  210.         ex = 0
  211.     End If
  212.     If n.sign Then s = "-" Else s = " "
  213.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  214.     If Len(ts) < 9 Then
  215.         ts = ts + String$(9 - Len(ts), "0")
  216.     End If
  217.     v = ts
  218.     For i = 1 To NUM_DWORDS - 1
  219.         ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * i + 1, 4))))
  220.         If Len(ts) < 9 Then
  221.             ts = String$(9 - Len(ts), "0") + ts
  222.         End If
  223.         v = v + ts
  224.     Next
  225.     If ex = 0 Then
  226.         v = Left$(v, 1) + "." + Mid$(v, 2)
  227.     ElseIf ex < 0 Then
  228.         v = "0." + String$(Abs(ex) - 1, "0") + v
  229.     ElseIf ex > 0 Then
  230.         v = Left$(v, ex + 1) + "." + Mid$(v, ex + 2)
  231.     End If
  232.     dec2str_fix = s + v
  233.  
  234. Function dec2dbl# (n As decfloat)
  235.     Dim As Long ex
  236.     Dim As String v, f, ts
  237.     If n.exponent > 0 Then
  238.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  239.     Else
  240.         ex = 0
  241.     End If
  242.     If n.sign Then v = "-" Else v = " "
  243.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  244.     If Len(ts) < 9 Then
  245.         ts = ts + String$(9 - Len(ts), "0")
  246.     End If
  247.     v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
  248.  
  249.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 1 + 1, 4))))
  250.     If Len(ts) < 9 Then
  251.         ts = String$(9 - Len(ts), "0") + ts
  252.     End If
  253.     v = v + ts
  254.  
  255.     f = _Trim$(Str$(Abs(ex)))
  256.     f = String$(5 - Len(f), "0") + f
  257.     If ex < 0 Then v = v + "E-" Else v = v + "E+"
  258.     v = v + f
  259.     dec2dbl = Val(v)
  260.  
  261. Sub RSHIFT_1 (mantissa As decfloat)
  262.     Dim As _Unsigned Long v1, v2
  263.     Dim As Long i
  264.     For i = NUM_DWORDS - 1 To 1 Step -1
  265.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10
  266.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10
  267.         v2 = v2 * 100000000 + v1
  268.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  269.     Next
  270.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10)
  271.  
  272. Sub LSHIFT_1 (mantissa As decfloat)
  273.     Dim As _Unsigned Long v1, v2
  274.     Dim As Long i
  275.     For i = 0 To NUM_DWORDS - 2
  276.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100000000
  277.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100000000
  278.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10 + v2)
  279.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100000000)
  280.     Next
  281.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10 * CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100000000)
  282.  
  283. Sub RSHIFT_2 (mantissa As decfloat)
  284.     Dim As _Unsigned Long v1, v2
  285.     Dim As Long i
  286.     For i = NUM_DWORDS - 1 To 1 Step -1
  287.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100
  288.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100
  289.         v2 = v2 * 10000000 + v1
  290.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  291.     Next
  292.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100)
  293.  
  294. Sub LSHIFT_2 (mantissa As decfloat)
  295.     Dim As _Unsigned Long v1, v2
  296.     Dim As Long i
  297.     For i = 0 To NUM_DWORDS - 2
  298.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10000000
  299.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10000000
  300.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100 + v2)
  301.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10000000)
  302.     Next
  303.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10000000))
  304.  
  305. Sub RSHIFT_3 (mantissa As decfloat)
  306.     Dim As _Unsigned Long v1, v2
  307.     Dim As Long i
  308.     For i = NUM_DWORDS - 1 To 1 Step -1
  309.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 1000
  310.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 1000
  311.         v2 = v2 * 1000000 + v1
  312.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  313.     Next
  314.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 1000)
  315.  
  316. Sub LSHIFT_3 (mantissa As decfloat)
  317.     Dim As _Unsigned Long v1, v2
  318.     Dim As Long i
  319.     For i = 0 To NUM_DWORDS - 2
  320.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 1000000
  321.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 1000000
  322.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 1000 + v2)
  323.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 1000000)
  324.     Next
  325.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(1000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 1000000))
  326.  
  327. Sub RSHIFT_4 (mantissa As decfloat)
  328.     Dim As _Unsigned Long v1, v2
  329.     Dim As Long i
  330.     For i = NUM_DWORDS - 1 To 1 Step -1
  331.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10000
  332.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10000
  333.         v2 = v2 * 100000 + v1
  334.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  335.     Next
  336.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10000)
  337.  
  338. Sub LSHIFT_4 (mantissa As decfloat)
  339.     Dim As _Unsigned Long v1, v2
  340.     Dim As Long i
  341.     For i = 0 To NUM_DWORDS - 2
  342.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100000
  343.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100000
  344.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10000 + v2)
  345.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100000)
  346.     Next
  347.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100000))
  348.  
  349. Sub RSHIFT_5 (mantissa As decfloat)
  350.     Dim As _Unsigned Long v1, v2
  351.     Dim As Long i
  352.     For i = NUM_DWORDS - 1 To 1 Step -1
  353.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100000
  354.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100000
  355.         v2 = v2 * 10000 + v1
  356.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  357.     Next
  358.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100000)
  359.  
  360. Sub LSHIFT_5 (mantissa As decfloat)
  361.     Dim As _Unsigned Long v1, v2
  362.     Dim As Long i
  363.     For i = 0 To NUM_DWORDS - 2
  364.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10000
  365.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10000
  366.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100000 + v2)
  367.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10000)
  368.     Next
  369.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10000))
  370.  
  371. Sub RSHIFT_6 (mantissa As decfloat)
  372.     Dim As _Unsigned Long v1, v2
  373.     Dim As Long i
  374.     For i = NUM_DWORDS - 1 To 1 Step -1
  375.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 1000000
  376.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 1000000
  377.         v2 = v2 * 1000 + v1
  378.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  379.     Next
  380.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 1000000)
  381.  
  382. Sub LSHIFT_6 (mantissa As decfloat)
  383.     Dim As _Unsigned Long v1, v2
  384.     Dim As Long i
  385.     For i = 0 To NUM_DWORDS - 2
  386.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 1000
  387.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 1000
  388.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 1000000 + v2)
  389.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 1000)
  390.     Next
  391.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(1000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 1000))
  392.  
  393. Sub RSHIFT_7 (mantissa As decfloat)
  394.     Dim As _Unsigned Long v1, v2
  395.     Dim As Long i
  396.     For i = NUM_DWORDS - 1 To 1 Step -1
  397.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10000000
  398.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10000000
  399.         v2 = v2 * 100 + v1
  400.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  401.     Next
  402.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10000000)
  403.  
  404. Sub LSHIFT_7 (mantissa As decfloat)
  405.     Dim As _Unsigned Long v1, v2
  406.     Dim As Long i
  407.     For i = 0 To NUM_DWORDS - 2
  408.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100
  409.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100
  410.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10000000 + v2)
  411.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100)
  412.     Next
  413.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100))
  414.  
  415. Sub RSHIFT_8 (mantissa As decfloat)
  416.     Dim As _Unsigned Long v1, v2
  417.     Dim As Long i
  418.     For i = NUM_DWORDS - 1 To 1 Step -1
  419.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 100000000
  420.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 100000000
  421.         v2 = v2 * 10 + v1
  422.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  423.     Next
  424.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 100000000)
  425.  
  426. Sub LSHIFT_8 (mantissa As decfloat)
  427.     Dim As _Unsigned Long v1, v2
  428.     Dim As Long i
  429.     For i = 0 To NUM_DWORDS - 2
  430.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 10
  431.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 10
  432.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 100000000 + v2)
  433.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 10)
  434.     Next
  435.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(100000000 * (CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 10))
  436.  
  437. Sub RSHIFT_9 (mantissa As decfloat)
  438.     Dim As Long i
  439.     For i = NUM_DWORDS - 1 To 1 Step -1
  440.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)
  441.     Next
  442.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(0)
  443.  
  444. Sub LSHIFT_9 (mantissa As decfloat)
  445.     Dim As Long i
  446.     For i = 0 To NUM_DWORDS - 2
  447.         Mid$(mantissa.mantissa, 4 * i + 1) = Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)
  448.     Next
  449.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(0)
  450.  
  451. Function cmp% (x As decfloat, y As decfloat)
  452.     Dim As Long c, i
  453.     If x.sign = y.sign Then
  454.         If x.exponent = y.exponent Then
  455.             For i = 0 To NUM_DWORDS - 1
  456.                 c = CVL(Mid$(x.mantissa, 4 * i + 1, 4)) - CVL(Mid$(y.mantissa, 4 * i + 1, 4))
  457.                 If c <> 0 Then Exit For
  458.             Next
  459.             If c < 0 Then
  460.                 cmp = -1
  461.                 Exit Function
  462.             ElseIf c = 0 Then
  463.                 cmp = 0
  464.                 Exit Function
  465.             ElseIf c > 0 Then
  466.                 cmp = 1
  467.                 Exit Function
  468.             End If
  469.         End If
  470.         If x.exponent < y.exponent Then
  471.             cmp = -1
  472.             Exit Function
  473.         End If
  474.         If x.exponent > y.exponent Then
  475.             cmp = 1
  476.             Exit Function
  477.         End If
  478.     End If
  479.     If x.sign Then cmp = -1
  480.  
  481. Function NORM_FAC1% (fac1 As decfloat)
  482.     ' normalize the number in fac1
  483.     ' all routines exit through this one.
  484.     ' we leave ax=0 if normalization was
  485.     ' ok...else ax = error code.
  486.  
  487.     'see if the mantissa is all zeros.
  488.     'if so, set the exponent and sign equal to 0.
  489.     Dim As Long i, er, f
  490.     er = 0: f = 0
  491.     For i = 0 To NUM_DWORDS - 1
  492.         If CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) > 0 Then f = 1
  493.     Next
  494.     If f = 0 Then
  495.         fac1.exponent = 0
  496.         fac1.sign = 0
  497.         Exit Function
  498.         'if the highmost nibble in fac1_man is nonzero,
  499.         'shift the mantissa right 1 nibble and
  500.         'increment the exponent
  501.     ElseIf CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) > 999999999 Then
  502.         Call RSHIFT_1(fac1)
  503.         fac1.exponent = fac1.exponent + 1
  504.     Else
  505.         'now shift fac1_man 1 to the left until a
  506.         'nonzero digit appears in the next-to-highest
  507.         'nibble of fac1_man.  decrement exponent for
  508.         'each shift.
  509.         While CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) < 100000000
  510.             Call LSHIFT_1(fac1)
  511.             fac1.exponent = fac1.exponent - 1
  512.             If fac1.exponent = 0 Then
  513.                 NORM_FAC1 = EXPU_ERR
  514.                 Exit Function
  515.             End If
  516.         Wend
  517.     End If
  518.     'check for overflow/underflow
  519.     If fac1.exponent < 0 Then
  520.         NORM_FAC1 = EXPO_ERR
  521.     End If
  522.  
  523. Sub fpadd_aux (fac1 As decfloat, fac2 As decfloat)
  524.     Dim As _Unsigned Long v, c, i
  525.     Dim As Integer er
  526.     c = 0
  527.     For i = NUM_DWORDS - 1 To 1 Step -1
  528.         v = CVL(Mid$(fac2.mantissa, 4 * i + 1, 4)) + CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) + c
  529.         If v > 999999999 Then
  530.             v = v - 1000000000
  531.             c = 1
  532.         Else
  533.             c = 0
  534.         End If
  535.         Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  536.     Next
  537.     v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + CVL(Mid$(fac2.mantissa, 4 * 0 + 1, 4)) + c
  538.     Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  539.  
  540.     er = NORM_FAC1%(fac1)
  541.  
  542.  
  543. Sub fpsub_aux (fac1 As decfloat, fac2 As decfloat)
  544.     Dim As Long v, c, i
  545.     c = 0
  546.     For i = NUM_DWORDS - 1 To 1 Step -1
  547.         v = CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) - CVL(Mid$(fac2.mantissa, 4 * i + 1, 4)) - c
  548.         If v < 0 Then
  549.             v = v + 1000000000
  550.             c = 1
  551.         Else
  552.             c = 0
  553.         End If
  554.         Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  555.     Next
  556.     v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) - CVL(Mid$(fac2.mantissa, 4 * 0 + 1, 4)) - c
  557.     Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  558.  
  559.     c = NORM_FAC1(fac1)
  560.  
  561. Sub fpadd (result As decfloat, x As decfloat, y As decfloat)
  562.  
  563.     Dim As decfloat fac1, fac2
  564.     Dim As Long t, c, xsign, ysign
  565.  
  566.     xsign = x.sign: x.sign = 0
  567.     ysign = y.sign: y.sign = 0
  568.     c = cmp(x, y)
  569.     x.sign = xsign
  570.     y.sign = ysign
  571.     If c < 0 Then
  572.         fac1 = y
  573.         fac2 = x
  574.     Else
  575.         fac1 = x
  576.         fac2 = y
  577.     End If
  578.     t = fac1.exponent - fac2.exponent
  579.  
  580.     If t < NUM_DIGITS Then
  581.         'The difference between the two
  582.         'exponents indicate how many times
  583.         'we have to multiply the mantissa
  584.         'of FAC2 by 10 (i.e., shift it right 1 place).
  585.         'If we have to shift more times than
  586.         'we have digits, the result is already in FAC1.
  587.         t = fac1.exponent - fac2.exponent
  588.         If t > 0 And t < (NUM_DIGITS) Then 'shift
  589.             While t
  590.                 Call RSHIFT_1(fac2)
  591.                 t = t - 1
  592.             Wend
  593.         End If
  594.         'See if the signs of the two numbers
  595.         'are the same.  If so, add; if not, subtract.
  596.         If fac1.sign = fac2.sign Then 'add
  597.             Call fpadd_aux(fac1, fac2)
  598.         Else
  599.             Call fpsub_aux(fac1, fac2)
  600.         End If
  601.     End If
  602.     result = fac1
  603.  
  604. Sub fpsub (result As decfloat, x As decfloat, y As decfloat)
  605.     Dim As decfloat fac1, fac2
  606.     fac1 = x
  607.     fac2 = y
  608.     fac2.sign = fac2.sign Xor &H8000
  609.     Call fpadd(result, fac1, fac2)
  610.  
  611. Sub fpmul_si (result As decfloat, x As decfloat, y As _Integer64)
  612.     Dim As decfloat fac1
  613.     Dim As Long count, ex, er, i
  614.     Dim As _Integer64 value, carry, digit, prod
  615.     fac1 = x
  616.     digit = Abs(y)
  617.     'check exponents.  if either is zero,
  618.     'the result is zero
  619.     If fac1.exponent = 0 Or y = 0 Then 'result is zero...clear fac1.
  620.         fac1.sign = 0
  621.         fac1.exponent = 0
  622.         For count = 0 To NUM_DWORDS - 1
  623.             Mid$(fac1.mantissa, 4 * count + 1, 4) = MKL$(0)
  624.         Next
  625.         er = NORM_FAC1(fac1)
  626.         result = fac1
  627.         Exit Sub
  628.     Else
  629.         If digit = 1 Then
  630.             If y < 0 Then
  631.                 fac1.sign = fac1.sign Xor &H8000
  632.             End If
  633.             result = fac1
  634.         End If
  635.         'now determine exponent of result.
  636.         'as you do...watch for overflow.
  637.         '        ex=fac2.exponent-BIAS+fac1.exponent-1
  638.  
  639.         If ex < 0 Then
  640.             er = EXPO_ERR
  641.             Exit Sub
  642.         End If
  643.         'for number of digits in the floating
  644.         'point number, add fac2 to fac1 number
  645.         'of times given by lowest nibble in
  646.         'fac3.  then shift fac1 and fac3
  647.         'right 1 digit and repeat.
  648.         'count=NUM_DIGITS-1
  649.  
  650.         carry = 0
  651.  
  652.         For i = NUM_DWORDS - 1 To 0 Step -1
  653.             prod = CVL(Mid$(fac1.mantissa, 4 * i + 1, 4))
  654.             prod = digit * prod + carry
  655.             value = (prod Mod 1000000000)
  656.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(value)
  657.             carry = prod \ 1000000000
  658.         Next
  659.  
  660.         If carry < 10 Then
  661.             Call RSHIFT_1(fac1)
  662.             fac1.exponent = fac1.exponent + 1
  663.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100000000)
  664.         ElseIf carry < 100 Then
  665.             Call RSHIFT_2(fac1)
  666.             fac1.exponent = fac1.exponent + 2
  667.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10000000)
  668.         ElseIf carry < 1000 Then
  669.             Call RSHIFT_3(fac1)
  670.             fac1.exponent = fac1.exponent + 3
  671.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 1000000)
  672.         ElseIf carry < 10000 Then
  673.             Call RSHIFT_4(fac1)
  674.             fac1.exponent = fac1.exponent + 4
  675.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100000)
  676.         ElseIf carry < 100000 Then
  677.             Call RSHIFT_5(fac1)
  678.             fac1.exponent = fac1.exponent + 5
  679.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10000)
  680.         ElseIf carry < 1000000 Then
  681.             Call RSHIFT_6(fac1)
  682.             fac1.exponent = fac1.exponent + 6
  683.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 1000)
  684.         ElseIf carry < 10000000 Then
  685.             Call RSHIFT_7(fac1)
  686.             fac1.exponent = fac1.exponent + 7
  687.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 100)
  688.         ElseIf carry < 100000000 Then
  689.             Call RSHIFT_8(fac1)
  690.             fac1.exponent = fac1.exponent + 8
  691.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry * 10)
  692.         ElseIf carry < 1000000000 Then
  693.             Call RSHIFT_9(fac1)
  694.             fac1.exponent = fac1.exponent + 9
  695.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + carry)
  696.         End If
  697.  
  698.     End If
  699.  
  700.     'fac1.exponent=fac2.exponent+fac1.exponent-BIAS-1
  701.     er = NORM_FAC1(fac1)
  702.     'fac1.exponent+=c 'ex
  703.     'if v>100000000 then fac1.exponent+=1
  704.     If y < 0 Then
  705.         fac1.sign = fac1.sign Xor &H8000
  706.     End If
  707.     result = fac1
  708.  
  709. Sub fpmul (result As decfloat, x As decfloat, y As decfloat)
  710.     Dim As decfloat fac1, fac2, fac3
  711.     Dim As Long i, j, ex, er
  712.     Dim As _Integer64 prod, digit, carry
  713.     Dim As _Unsigned Long c, v
  714.  
  715.     fac1 = x
  716.     fac2 = y
  717.     'check exponents.  if either is zero,
  718.     'the result is zero
  719.     If fac1.exponent = 0 Or fac2.exponent = 0 Then 'result is zero...clear fac1.
  720.         fac1.sign = 0
  721.         fac1.exponent = 0
  722.         For i = 0 To NUM_DWORDS - 1
  723.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(0)
  724.         Next
  725.         er = NORM_FAC1(fac1)
  726.         result = fac1
  727.         Exit Sub
  728.     Else
  729.  
  730.         'now determine exponent of result.
  731.         'as you do...watch for overflow.
  732.         ex = fac2.exponent - BIAS + fac1.exponent
  733.  
  734.         If ex < 0 Then
  735.             er = EXPO_ERR
  736.             Exit Sub
  737.         End If
  738.         fac1.exponent = ex
  739.         'determine the sign of the product
  740.         fac1.sign = fac1.sign Xor fac2.sign
  741.         'copy fac1 mantissa to fac3 and clear fac1's mantissa
  742.         For i = 0 To NUM_DWORDS - 1
  743.             Mid$(fac3.mantissa, 4 * i + 1, 4) = MKL$(0)
  744.             Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(0)
  745.         Next
  746.         'for number of digits in the floating
  747.         'point number, add fac2 to fac1 number
  748.         'of times given by lowest nibble in
  749.         'fac3.  then shift fac1 and fac3
  750.         'right 1 digit and repeat.
  751.  
  752.         For j = NUM_DWORDS - 1 To 0 Step -1
  753.             carry = 0
  754.             digit = CVL(Mid$(y.mantissa, 4 * j + 1, 4))
  755.             For i = NUM_DWORDS - 1 To 0 Step -1
  756.                 prod = digit * CVL(Mid$(x.mantissa, 4 * i + 1, 4)) + carry
  757.                 Mid$(fac3.mantissa, 4 * i + 1, 4) = MKL$(prod Mod 1000000000)
  758.                 carry = prod \ 1000000000
  759.  
  760.             Next
  761.  
  762.             Call RSHIFT_9(fac1)
  763.             Call RSHIFT_9(fac3)
  764.             Mid$(fac3.mantissa, 4 * 0 + 1, 4) = MKL$(carry)
  765.  
  766.             c = 0
  767.             For i = NUM_DWORDS - 1 To 1 Step -1
  768.                 v = CVL(Mid$(fac3.mantissa, 4 * i + 1, 4)) + CVL(Mid$(fac1.mantissa, 4 * i + 1, 4)) + c
  769.                 If v > 999999999 Then
  770.                     v = v - 1000000000
  771.                     c = 1
  772.                 Else
  773.                     c = 0
  774.                 End If
  775.                 Mid$(fac1.mantissa, 4 * i + 1, 4) = MKL$(v)
  776.             Next
  777.             v = CVL(Mid$(fac1.mantissa, 4 * 0 + 1, 4)) + CVL(Mid$(fac3.mantissa, 4 * 0 + 1, 4)) + c
  778.             Mid$(fac1.mantissa, 4 * 0 + 1, 4) = MKL$(v)
  779.  
  780.         Next
  781.     End If
  782.  
  783.     er = NORM_FAC1(fac1)
  784.     result = fac1
  785.  
  786. Sub recip (result As decfloat, n As decfloat)
  787.     Dim As Double x: x = dec2dbl(n)
  788.     Dim As Long k, l
  789.     Dim As decfloat r, r2, two
  790.     l = Log(NUM_DIGITS * 0.0625) * 1.5
  791.     If x = 0 Then Print "Div 0": Exit Sub
  792.     If x = 1 Then
  793.         Call str2dec("1", r)
  794.         result = r
  795.         Exit Sub
  796.     End If
  797.  
  798.     x = 1# / x
  799.     Call str2dec(Str$(x), r)
  800.     Call str2dec("2", two)
  801.     For k = 1 To l
  802.         Call fpmul(r2, n, r)
  803.         Call fpsub(r2, two, r2)
  804.         Call fpmul(r, r, r2)
  805.     Next k
  806.     Print
  807.     result = r
  808.  
  809. Function fpdiv (result As decfloat, x As decfloat, y As decfloat)
  810.     Dim As decfloat fac1, fac2
  811.     fac1 = x
  812.     fac2 = y
  813.     Call recip(fac2, fac2)
  814.     Call fpmul(fac1, fac1, fac2)
  815.     result = fac1
  816.