Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 497
» Latest member: VikRam2025
» Forum threads: 2,851
» Forum posts: 26,698

Full Statistics

Latest Threads
Most efficient way to bui...
Forum: General Discussion
Last Post: ahenry3068
3 minutes ago
» Replies: 9
» Views: 82
QBJS - ANSI Draw
Forum: QBJS, BAM, and Other BASICs
Last Post: madscijr
15 minutes ago
» Replies: 4
» Views: 112
Who wants to PLAY?
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
2 hours ago
» Replies: 4
» Views: 83
_CONSOLEINPUT is blocking
Forum: General Discussion
Last Post: mdijkens
5 hours ago
» Replies: 6
» Views: 77
Fun with Ray Casting
Forum: a740g
Last Post: a740g
Today, 05:50 AM
» Replies: 10
» Views: 223
Very basic key mapping de...
Forum: SMcNeill
Last Post: a740g
Today, 02:33 AM
» Replies: 1
» Views: 51
Methods in types
Forum: General Discussion
Last Post: bobalooie
Today, 01:02 AM
» Replies: 0
» Views: 50
Cautionary tale of open, ...
Forum: General Discussion
Last Post: doppler
Yesterday, 10:23 AM
» Replies: 3
» Views: 109
Extended KotD #23 and #24...
Forum: Keyword of the Day!
Last Post: SMcNeill
Yesterday, 09:51 AM
» Replies: 0
» Views: 53
Big problem for me.
Forum: General Discussion
Last Post: JRace
Yesterday, 05:11 AM
» Replies: 11
» Views: 203

 
  Directory Create Utility
Posted by: eoredson - 09-16-2022, 02:58 AM - Forum: Utilities - Replies (6)

Hi,

Instead of a directory delete utility like Silent,
why not build a directory create utility.

Attached is a directory create utility.

The difference between MKdir and MD is that
MD creates a directory and Makedir.bas makes an entire path..

For example, you could create \temp\newdir\nextdir\

Erik.



Attached Files
.zip   MAKEDIR.ZIP (Size: 1.81 KB / Downloads: 46)
Print this item

Thumbs Up He is come back!
Posted by: Kernelpanic - 09-15-2022, 10:14 PM - Forum: General Discussion - Replies (16)

Hello Steve, risen from the dead?  Tongue

Good to see!

Print this item

  Minimal Text Animator
Posted by: James D Jarvis - 09-15-2022, 08:42 PM - Forum: Works in Progress - Replies (5)

Minimal Text Animator is exactly what this is. This is a very simple program to create and playback animations in 80x25 text mode. 
It's simply structured with a main input loop, functions and subroutines are called from that loop. I want beginners to be able to look at this and modify it for their own needs. Currently there isn't much in the way of comments and there's a couple other commands I want to add but it certainly is a Minimal Text Animator right now. 

Currently the user can Save and Load files, change the pen foreground and background color, change the character being drawn, and change the framerate. It's currently limited to 200 frames but that can easily be modified (just keep memory use and file size in mind). 

Code: (Select All)
'Minimal Text Animator
'by James D. Jarvis Sept 15,2022   v 0.1
'
' a very minimal program to create and playback simple text screen animations
'S - Save file
'L - load file
'use mosue to draw
'N,n - create a new frame    (limited to 200 as coded but you can edit that if you wish
'P,p - play animation
'F,f - change pen foreground color , you'll have to enter color number afterward
'B,b - change pen background color, you'll have to enter color number afterward
'esc - to quit program.... be careful this just dumps you out and you'll lose any work currently
'
'nothing fancy here at all, just a minimal program that functions

Screen _NewImage(80, 25, 0)
_Title "Minimal Text Animator"
Type gcelltype
    t As String * 1
    fgk As _Byte
    bgk As _Byte
End Type
Dim Shared maxtx, maxty, maxframes, pen$, fg_klr, bg_klr, pen_klr
Dim Shared showonion, framerate, lastframe
framerate = 20
maxtx = _Width
maxty = _Height
maxframes = 200
pen$ = "*"
showonion = 0
Print "Minimal Text Animator"
_ControlChr Off
Dim Shared gcell(maxframes, maxtx, maxty) As gcelltype
For f = 1 To maxframes
    For y = 1 To _Height
        For x = 1 To _Width
            gcell(f, x, y).t = " "
            gcell(f, x, y).fgk = 15
            gcell(f, x, y).bgk = 0
        Next x
    Next y
Next f
frameno = 1
fg_klr = 15
bg_klr = 0
pen_klr = 15
Color fg_klr, bg_klr
'main program loop
Do
    _Limit 60
    Do While _MouseInput '      Check the mouse status
        If _MouseButton(1) Then 'draw that square if the
            mx = _MouseX: my = _MouseY
            gcell(frameno, mx, my).t = pen$
            gcell(frameno, mx, my).fgk = pen_klr
            gcell(frameno, mx, my).bgk = bg_klr
            Color pen_klr, gcell(frameno, mx, my).bgk
            _PrintString (mx, my), gcell(frameno, mx, my).t
        End If
        Color 15, 0
    Loop
    Select Case kk$
        Case "n", "N"
            Cls
            frameno = frameno + 1
            If frameno > maxframes Then frameno = 1
            If showonion = 1 And frameno > 1 Then drawonion (frameno - 1)
            drawframe frameno
            lastframe = frameno
        Case "o", "O"
            If showonion = 0 Then
                Cls
                showonion = 1
                drawonion (frameno - 1)
                drawframe frameno
            Else
                showonion = 0
            End If
        Case "p", "P" 'play the animation
            playanimation 1, lastframe

        Case ",", "<" 'cycle down through drawn frames
            frameno = frameno - 1
            If frameno < 1 Then frameno = lastframe
            drawframe frameno
        Case ".", ">" 'cycle up through drawn frames
            frameno = frameno + 1
            If frameno > lastframe Then frameno = 1
            Cls
            drawframe frameno
        Case "f", "F"
            pen_klr = select_pencolor
            Cls
            drawframe frameno
        Case "b", "B"
            bg_klr = select_backgroundcolor
            Cls
            drawframe frameno
        Case "S"
            savefile
            Cls
            drawframe frameno
        Case "L"
            loadfile
            Cls
            playanimation 1, lastframe
            frameno = 1
        Case "h", "H", "?"
            helpme
            Cls
            drawframe frameno
        Case "r", "R"
            framerate = newrate
            Cls
            drawframe frameno
        Case "c", "C"
            pen$ = Chr$(newchar)
            Cls
            drawframe frameno
    End Select
    kk$ = InKey$
    If kk$ = "f" Then _PrintString (1, 1), Str$(frameno)
Loop Until kk$ = Chr$(27)
Sub drawframe (f As Integer)
    For y = 1 To _Height
        For x = 1 To _Width
            If onion = 0 Then
                Color gcell(f, x, y).fgk, gcell(f, x, y).bgk
                _PrintString (x, y), gcell(f, x, y).t
            Else
                If gcell(f, x, y).t <> " " Then
                    Color gcell(f, x, y).fgk, gcell(f, x, y).bgk
                    _PrintString (x, y), gcell(f, x, y).t
                End If
            End If
        Next
    Next
    Color 15, 0
End Sub
Sub drawonion (f As Integer)
    For y = 1 To _Height
        For x = 1 To _Width
            Color 8, 0
            _PrintString (x, y), gcell(f, x, y).t
        Next
    Next
    Color 15, 0
End Sub
Sub playanimation (ff, lf)
    For f = ff To lf
        Cls
        _Limit framerate
        For y = 1 To _Height
            For x = 1 To _Width
                Color gcell(f, x, y).fgk, gcell(f, x, y).bgk
                _PrintString (x, y), gcell(f, x, y).t
            Next
        Next
        _Display
    Next f
    _AutoDisplay
    Color 15, 0
End Sub
Function select_pencolor
    Cls
    Color 15, 0
    Print "SELECT PEN COLOR"
    Print
    Print " 0.",: Color 0, 0: Print Chr$(219),: Color 15, 0: Print "16.",: Color 16, 0: Print Chr$(219): Color 15, 0
    Print " 1.",: Color 1, 0: Print Chr$(219),: Color 15, 0: Print "17.",: Color 17, 0: Print Chr$(219): Color 15, 0
    Print " 2.",: Color 2, 0: Print Chr$(219),: Color 15, 0: Print "18.",: Color 18, 0: Print Chr$(219): Color 15, 0
    Print " 3.",: Color 3, 0: Print Chr$(219),: Color 15, 0: Print "19.",: Color 19, 0: Print Chr$(219): Color 15, 0
    Print " 4.",: Color 4, 0: Print Chr$(219),: Color 15, 0: Print "20.",: Color 20, 0: Print Chr$(219): Color 15, 0
    Print " 5.",: Color 5, 0: Print Chr$(219),: Color 15, 0: Print "21.",: Color 21, 0: Print Chr$(219): Color 15, 0
    Print " 6.",: Color 6, 0: Print Chr$(219),: Color 15, 0: Print "22.",: Color 22, 0: Print Chr$(219): Color 15, 0
    Print " 7.",: Color 7, 0: Print Chr$(219),: Color 15, 0: Print "23.",: Color 23, 0: Print Chr$(219): Color 15, 0
    Print " 8.",: Color 8, 0: Print Chr$(219),: Color 15, 0: Print "24.",: Color 24, 0: Print Chr$(219): Color 15, 0
    Print " 9.",: Color 9, 0: Print Chr$(219),: Color 15, 0: Print "25.",: Color 25, 0: Print Chr$(219): Color 15, 0
    Print "10.",: Color 10, 0: Print Chr$(219),: Color 15, 0: Print "26.",: Color 26, 0: Print Chr$(219): Color 15, 0
    Print "11.",: Color 11, 0: Print Chr$(219),: Color 15, 0: Print "27.",: Color 27, 0: Print Chr$(219): Color 15, 0
    Print "12.",: Color 12, 0: Print Chr$(219),: Color 15, 0: Print "28.",: Color 28, 0: Print Chr$(219): Color 15, 0
    Print "13.",: Color 13, 0: Print Chr$(219),: Color 15, 0: Print "29.",: Color 29, 0: Print Chr$(219): Color 15, 0
    Print "14.",: Color 14, 0: Print Chr$(219),: Color 15, 0: Print "30.",: Color 30, 0: Print Chr$(219): Color 15, 0
    Print "15.",: Color 15, 0: Print Chr$(219),: Color 15, 0: Print "31.",: Color 31, 0: Print Chr$(219): Color 15, 0
    Do
        Locate 20, 3: Input "enter color from 0 to 31 ", kk$
    Loop Until Val(kk$) > -1 Or Val(kk$) < 32
    select_pencolor = Val(kk$)
End Function
Function newrate
    Cls
    Print "Change Frame Rate ?"
    Print
    Print "Current frame rate is "; framerate
    Print
    Do
        Locate 20, 3: Input "enter color from 1 to 60 ", kk$
    Loop Until Val(kk$) > 0 Or Val(kk$) < 61
    newrate = Val(kk$)
End Function

Function select_backgroundcolor
    Cls
    Color 15, 0
    Print "SELECT Background COLOR"
    Print
    Print " 0.",: Color 0, 0: Print Chr$(219),: Color 15, 0
    Print " 1.",: Color 1, 0: Print Chr$(219): Color 15, 0
    Print " 2.",: Color 2, 0: Print Chr$(219),: Color 15, 0
    Print " 3.",: Color 3, 0: Print Chr$(219): Color 15, 0
    Print " 4.",: Color 4, 0: Print Chr$(219),: Color 15, 0
    Print " 5.",: Color 5, 0: Print Chr$(219): Color 15, 0
    Print " 6.",: Color 6, 0: Print Chr$(219),: Color 15, 0
    Print " 7.",: Color 7, 0: Print Chr$(219): Color 15, 0
    Print " 8.",: Color 8, 0: Print Chr$(219),: Color 15, 0
    Print " 9.",: Color 9, 0: Print Chr$(219): Color 15, 0
    Print "10.",: Color 10, 0: Print Chr$(219),: Color 15, 0
    Print "11.",: Color 11, 0: Print Chr$(219): Color 15, 0
    Print "12.",: Color 12, 0: Print Chr$(219),: Color 15, 0
    Print "13.",: Color 13, 0: Print Chr$(219): Color 15, 0
    Print "14.",: Color 14, 0: Print Chr$(219),: Color 15, 0
    Print "15.",: Color 15, 0: Print Chr$(219): Color 15, 0
    Do
        Locate 20, 1: Input "enter color from 0 to 31", kk$
    Loop Until Val(kk$) > -1 Or Val(kk$) < 32
    select_backgroundcolor = Val(kk$)
End Function
Sub helpme
    Cls
    Print "HELP"
    Print
    Print "S - Save file   "
    Print "L - load file   "
    Print "use mosue to draw"
    Print "N,n - create a new frame    (limited to 200 as coded but you can edit that if you wish"
    Print "P,p - play animation"
    Print "C,c - change pen foreground color , you'll have to enter color number afterward"
    Print "B,b - change pen background color, you'll have to enter color number afterward"
    Print "R,r - change framerate for animation"
    Print "esc - to quit program.... be careful this just dumps you out and you'll lose any work currently"
    Print
    Print "Press any key to continue"
    any$ = Input$(1)
End Sub
Function newchar
    Dim mc(0 To 256, 2)
    Cls
    x = 0
    y = 3
    newc = -1
    Print "Click on the Character you wish to use."
    For c = 0 To 255
        x = x + 2
        If x > 60 Then
            x = 2
            y = y + 2
        End If
        _PrintString (x, y), Chr$(c)
        mc(c, 1) = x
        mc(c, 2) = y
    Next c
    Do
        _Limit 60
        Do While _MouseInput '      Check the mouse status
            If _MouseButton(1) Then 'draw that square if the
                mx = _MouseX: my = _MouseY
                c = 0
                Do
                    If mc(c, 1) = mx And mc(c, 2) = my Then newc = c
                    c = c + 1
                    If c = 256 Then newc = -2
                Loop Until newc <> -1
                If newc = -2 Then newc = -1

            End If
            Color 15, 0
        Loop
    Loop Until newc <> -1
    newchar = newc
End Function

Sub savefile
    Locate 1, 1
    Print "Enter file name "
    Locate 2, 1
    Input filename$
    Open filename$ For Output As #1
    Write #1, framerate, maxtx, maxty, lastframe
    For f = 1 To lastframe
        For y = 1 To maxty
            For x = 1 To maxtx
                Write #1, gcell(f, x, y).t, gcell(f, x, y).fgk, gcell(f, x, y).bgk
                Print gcell(f, x, y).t, gcell(f, x, y).fgk, gcell(f, x, y).bgk
            Next x
        Next y

    Next f
    Close #1
    Locate 3, 1
    Print filename$; " saved"
    Print "press any key to continue"
    any$ = Input$(1)
End Sub
Sub loadfile
    Locate 1, 1
    Print "Enter file name "
    Locate 2, 1
    Input filename$
    Open filename$ For Input As #1
    Input #1, framerate, maxtx, maxty, lastframe
    For f = 1 To lastframe
        For y = 1 To maxty
            For x = 1 To maxtx
                Input #1, gcell(f, x, y).t, gcell(f, x, y).fgk, gcell(f, x, y).bgk
                Print gcell(f, x, y).t, gcell(f, x, y).fgk, gcell(f, x, y).bgk
            Next x
        Next y
    Next f
    Close #1
    Locate 3, 1
    Print filename$; " loaded"
    Print "press any key to continue"
    any$ = Input$(1)
End Sub

Print this item

  Lakeshore 218 Temperature Monitor
Posted by: CJAlva - 09-15-2022, 03:46 PM - Forum: Help Me! - Replies (14)

Hey all!

I'm currently using a Lakeshore 218 Temperature monitor and was hoping to be able to grab readings using QBasic. Here's what I have so far:

CLS 'Clear screen
PRINT " SERIAL COMMUNICATION PROGRAM"
PRINT
TIMEOUT = 2000 'Read timeout (may need more)
BAUD$ = "9600"
TERM$ = CHR$(13) + CHR$(10) 'Terminators are <CR><LF>
OPEN "COM1:" + BAUD$ + ",O,7,1,RS" FOR RANDOM AS #1 LEN = 256
LOOP1: LINE INPUT "ENTER COMMAND (or EXIT):"; CMD$ 'Get command from keyboard
CMD$ = UCASE$(CMD$) 'Change input to upper case
IF CMD$ = "EXIT" THEN CLOSE #1: END 'Get out on Exit
CMD$ = CMD$ + TERM$
PRINT #1, CMD$; 'Send command to instrument
IF INSTR(CMD$, "?") <> 0 THEN 'Test for query
RS$ = "" 'If query, read response
N = 0 'Clr return string and count
WHILE (N < TIMEOUT) AND (INSTR(RS$, TERM$) = 0) 'Wait for response
IN$ = INPUT$(LOC(1), #1) 'Get one character at a time
IF IN$ = "" THEN N = N + 1 ELSE N = 0 'Add 1 to timeout if no chr
RS$ = RS$ + IN$ 'Add next chr to string
WEND 'Get chrs until terminators
IF RS$ <> "" THEN 'See if return string is empty
RS$ = MID$(RS$, 1, (INSTR(RS$, TERM$) - 1))'Strip off terminators
PRINT "RESPONSE:"; RS$ 'Print response to query
ELSE
PRINT "NO RESPONSE" 'No response to query
END IF
END IF 'Get next command
GOTO LOOP1

When I compile and run, I get an error calling out line 17 (IN$ = INPUT$(LOC(1), #1) 'Get one character at a time) and saying "Input past end of file". No clue how to mitigate this. Can anyone help out?


   

Print this item

  Nasty Directory Delete Function
Posted by: eoredson - 09-14-2022, 05:51 AM - Forum: Utilities - Replies (8)

Find attached the directory delete function.

This is a nasty directory delete function.

It deletes a directory and all subdirectories and files.

It doesn't care what the directory is.

Erik.



Attached Files
.zip   SILENT.ZIP (Size: 2.47 KB / Downloads: 42)
Print this item

  Our 200th user registered today.
Posted by: Pete - 09-14-2022, 01:51 AM - Forum: General Discussion - Replies (19)

That makes this place about half the size of the hussel and bussel busy off the carts QBasic Forum! I swear over there there are days Bob and I can barely wake keep up. Kidding aside, nice to see folks are still finding us here. I think our 200th member is from my old haunt, Italy.

Pete

Print this item

  bug when using _Dest _Console
Posted by: Jack - 09-13-2022, 10:18 PM - Forum: General Discussion - Replies (27)

this works Ok, you are prevented from entering a number that's too large for a long

Code: (Select All)
Dim As Long n
Input "n "; n
Print n
however that's not the case here
Code: (Select All)
$Console:Only
_Dest _Console

Dim As Long n
Input "n "; n
Print n
sample run
Code: (Select All)
n ? 99999999999999999999
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 999999999

Press any key to continue

Print this item

  decfloat -- again
Posted by: Jack - 09-13-2022, 08:45 PM - Forum: Programs - Replies (42)

Code: (Select All)
_Title "decfloat-offset-v2 by Jack"

$Console:Only
_Dest _Console
Option _Explicit

Declare CustomType Library
    Sub memcpy Alias "memmove" (ByVal dest As _Offset, ByVal source As _Offset, ByVal bytes As Long)
End Declare

Const NUMBER_OF_DIGITS = 10000
Const NUM_DIGITS = 8 * (1 + NUMBER_OF_DIGITS \ 8)
Const NUM_DWORDS = NUM_DIGITS \ 8
Const BIAS = 1073741824 '2 ^ 30
Const MANTISSA_BYTES = (NUM_DWORDS + 1) * 4

Type decfloat
    As Long sign
    As _Unsigned Long exponent
    As String * Mantissa_bytes mantissa
End Type

' Error definitions

Const DIVZ_ERR = 1 'Divide by zero
Const EXPO_ERR = 2 'Exponent overflow error
Const EXPU_ERR = 3 'Exponent underflow error
Dim Shared As decfloat pi_dec, tan_half_num(15), tan_half_den(14)
Dim As decfloat p1, p2, p3
Dim As Double t1, t2, t3
Dim As Long i, n
Dim As String pie

initialize_fp

t1 = Timer(.0001)
pi_brent_salamin p1, NUM_DIGITS
t1 = Timer(.0001) - t1

t2 = Timer(.0001)
Pi_Ramanujan p2, NUM_DIGITS
t2 = Timer(.0001) - t2

t3 = Timer(.0001)
pi_chudnovsky_bs p3, NUM_DIGITS
t3 = Timer(.0001) - t3

pie = fp2str(p1, NUMBER_OF_DIGITS)
Print Left$(pie, 22); "..."; Right$(pie, 20)
pie = fp2str(p2, NUMBER_OF_DIGITS)
Print Left$(pie, 22); "..."; Right$(pie, 20)
pie = fp2str(p3, NUMBER_OF_DIGITS)
Print Left$(pie, 22); "..."; Right$(pie, 20)
Print
Print "Pi to "; NUMBER_OF_DIGITS; "digits"
Print "elapsed time for pi_brent_salamin "; t1; " seconds"
Print "elapsed time for Pi_Ramanujan     "; t2; " seconds"
Print "elapsed time for pi_chudnovsky_bs "; t3; " seconds"

Sub str2fp (result As decfloat, value As String)
    Dim As Long j, s, d, e, ep, ex, es, i, f, fp, fln, ln
    Dim As String c, f1, f2, f3, ts
    Dim n As decfloat
    Dim As _Offset no, lno

    no = _Offset(n.mantissa)
    lno = _Offset(ln)
    j = 1
    s = 1
    d = 0
    e = 0
    ep = 0
    ex = 0
    es = 1
    i = 0
    f = 0
    fp = 0
    f1 = ""
    f2 = ""
    f3 = ""
    value = UCase$(value)
    fln = Len(value)

    While j <= fln
        c = Mid$(value, j, 1)
        If ep = 1 Then
            If c = " " Then
                j = j + 1
                GoTo skip_while
            End If
            If c = "-" Then
                es = -es
                c = ""
            End If
            If c = "+" Then
                j = j + 1
                GoTo skip_while
            End If
            If (c = "0") And (f3 = "") Then
                j = j + 1
                GoTo skip_while
            End If
            If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
                f3 = f3 + c
                ex = 10 * ex + (Asc(c) - 48)
                j = j + 1
                GoTo skip_while
            End If
        End If

        If c = " " Then
            j = j + 1
            GoTo skip_while
        End If
        If c = "-" Then
            s = -s
            j = j + 1
            GoTo skip_while
        End If
        If c = "+" Then
            j = j + 1
            GoTo skip_while
        End If
        If c = "." Then
            If d = 1 Then
                j = j + 1
                GoTo skip_while
            End If
            d = 1
        End If
        If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
            If ((c = "0") And (i = 0)) Then
                If d = 0 Then
                    j = j + 1
                    GoTo skip_while
                End If
                If (d = 1) And (f = 0) Then
                    e = e - 1
                    j = j + 1
                    GoTo skip_while
                End If
            End If
            If d = 0 Then
                f1 = f1 + c
                i = i + 1
            Else
                If (c > "0") Then
                    fp = 1
                End If
                f2 = f2 + c
                f = f + 1
            End If
        End If
        If c = "E" Or c = "D" Then
            ep = 1
        End If
        j = j + 1
        skip_while:
    Wend
    If fp = 0 Then
        f = 0
        f2 = ""
    End If

    If s = -1 Then s = &H8000 Else s = 0
    n.sign = s
    ex = es * ex - 1 + i + e
    f1 = f1 + f2
    f1 = Mid$(f1, 1, 1) + Right$(f1, Len(f1) - 1)
    fln = Len(f1)
    If Len(f1) > (NUM_DIGITS + 1 + 8) Then
        f1 = Mid$(f1, 1, (NUM_DIGITS + 1 + 8))
    End If
    While Len(f1) < (NUM_DIGITS + 1 + 8)
        f1 = f1 + "0"
    Wend
    j = 1
    For i = 0 To NUM_DWORDS
        ts = Mid$(f1, j, 8)
        ln = Val(ts)
        memcpy no, lno, 4
        If ln <> 0 Then fp = 1
        no = no + 4
        j = j + 8
    Next
    If fp Then n.exponent = (ex + BIAS + 1) Else n.exponent = 0
    result = n
End Sub

Function fp2str_exp$ (n As decfloat, places As Long)
    Dim As Long i, ex, ln
    Dim As String v, f, ts
    Dim As _Offset no, lno

    no = _Offset(n.mantissa)
    lno = _Offset(ln)
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If
    If n.sign Then v = "-" Else v = " "
    memcpy lno, no, 4
    ts = Str$(ln)
    ts = _Trim$(ts)
    If Len(ts) < 8 Then
        ts = ts + String$(8 - Len(ts), "0")
    End If
    v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
    For i = 1 To NUM_DWORDS - 1
        no = no + 4
        memcpy lno, no, 4
        ts = Str$(ln)
        ts = _Trim$(ts)
        If Len(ts) < 8 Then
            ts = String$(8 - Len(ts), "0") + ts
        End If
        v = v + ts
    Next
    v = Left$(v, places + 3)
    f = _Trim$(Str$(Abs(ex)))
    f = String$(5 - Len(f), "0") + f
    If ex < 0 Then v = v + "E-" Else v = v + "E+"
    v = v + f
    fp2str_exp$ = v
End Function

Function fp2str_fix$ (n As decfloat, places As Long)
    Dim As Long i, ex, ln
    Dim As String v, ts, s
    Dim As _Offset no, lno

    no = _Offset(n.mantissa)
    lno = _Offset(ln)
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If
    If n.sign Then s = "-" Else s = " "
    memcpy lno, no, 4
    ts = _Trim$(Str$(ln))
    If Len(ts) < 8 Then
        ts = ts + String$(8 - Len(ts), "0")
    End If
    v = ts
    For i = 1 To NUM_DWORDS - 1
        no = no + 4
        memcpy lno, no, 4
        ts = _Trim$(Str$(ln))
        If Len(ts) < 8 Then
            ts = String$(8 - Len(ts), "0") + ts
        End If
        v = v + ts
    Next
    If places < NUM_DIGITS Then
        v = Left$(v, places)
    End If
    If ex = 0 Then
        v = Left$(v, 1) + "." + Mid$(v, 2)
    ElseIf ex < 0 Then
        v = "0." + String$(Abs(ex) - 1, "0") + v
    ElseIf ex > 0 Then
        v = Left$(v, ex + 1) + "." + Mid$(v, ex + 2)
    End If
    fp2str_fix$ = s + v
End Function

Function fp2str$ (n As decfloat, places As Long)
    Dim As Long ex
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If
    If Abs(ex) < places Then
        fp2str = fp2str_fix(n, places)
    Else
        fp2str = fp2str_exp(n, places)
    End If
End Function

'long part of num
Sub fpfix (result As decfloat, num As decfloat)
    Dim As decfloat ip
    Dim As Long ex, ex2, j, k, ln
    Dim As _Offset ipo, no, lno

    no = _Offset(num.mantissa)
    ipo = _Offset(ip.mantissa)
    lno = _Offset(ln)
    ex = (num.exponent And &H7FFFFFFF) - BIAS
    If ex < 1 Then
        result = ip: Exit Sub
    End If
    If ex >= (NUM_DIGITS) Then
        result = num: Exit Sub
    End If
    ex2 = ex \ 8
    k = ex2
    j = ex Mod 8
    While ex2 > 0
        ex2 = ex2 - 1
        memcpy lno, no + ex2 * 4, 4
        memcpy ipo + ex2 * 4, lno, 4
    Wend
    If j = 1 Then
        memcpy lno, no + k * 4, 4
        ln = 10000000 * (ln \ 10000000)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 2 Then
        memcpy lno, no + k * 4, 4
        ln = 1000000 * (ln \ 1000000)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 3 Then
        memcpy lno, no + k * 4, 4
        ln = 100000 * (ln \ 100000)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 4 Then
        memcpy lno, no + k * 4, 4
        ln = 10000 * (ln \ 10000)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 5 Then
        memcpy lno, no + k * 4, 4
        ln = 1000 * (ln \ 1000)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 6 Then
        memcpy lno, no + k * 4, 4
        ln = 100 * (ln \ 100)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 7 Then
        memcpy lno, no + k * 4, 4
        ln = 10 * (ln \ 10)
        memcpy ipo + k * 4, lno, 4
    ElseIf j = 8 Then
        memcpy lno, no + k * 4, 4
        memcpy ipo + k * 4, lno, 4
    End If
    ip.exponent = ex + BIAS
    ip.sign = num.sign
    result = ip
End Sub

Function fpfix_is_odd& (num As decfloat)
    Dim As Long ex, j, k, ln
    Dim As _Offset no, lno

    no = _Offset(num.mantissa)
    lno = _Offset(ln)
    ex = (num.exponent And &H7FFFFFFF) - BIAS
    If ex < 1 Then
        fpfix_is_odd = 0: Exit Function
    End If
    If ex >= (NUM_DIGITS) Then
        Print "error in function fpfix_is_odd"
        fpfix_is_odd = 99999999: Exit Function
    End If
    k = ex \ 8
    j = ex Mod 8

    If j = 1 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 10000000) And 1: Exit Function
    ElseIf j = 2 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 1000000) And 1: Exit Function
    ElseIf j = 3 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 100000) And 1: Exit Function
    ElseIf j = 4 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 10000) And 1: Exit Function
    ElseIf j = 5 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 1000) And 1: Exit Function
    ElseIf j = 6 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 100) And 1: Exit Function
    ElseIf j = 7 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = (ln \ 10) And 1: Exit Function
    ElseIf j = 8 Then
        memcpy lno, no + k * 4, 4
        fpfix_is_odd = ln And 1: Exit Function
    End If
    fpfix_is_odd = 0
End Function

Function fp2dbl# (n As decfloat)
    Dim As Long ex, ln
    Dim As String v, f, ts
    Dim As _Offset no, lno

    no = _Offset(n.mantissa)
    lno = _Offset(ln)
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If
    If n.sign Then v = "-" Else v = " "
    memcpy lno, no, 4
    ts = _Trim$(Str$(ln))
    If Len(ts) < 8 Then
        ts = ts + String$(8 - Len(ts), "0")
    End If
    v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
    memcpy lno, no + 4, 4
    ts = _Trim$(Str$(ln))
    If Len(ts) < 8 Then
        ts = String$(8 - Len(ts), "0") + ts
    End If
    v = v + ts

    f = Str$(Abs(ex))
    f = String$(5 - Len(f), "0") + f
    If ex < 0 Then v = v + "E-" Else v = v + "E+"
    v = v + f
    fp2dbl# = Val(v)
End Function

'Sub si2fp (result As decfloat, m As _Integer64, digits_in As Long)
'    Dim As Long digits
'    digits = digits_in
'    If digits > NUM_DWORDS Then digits = NUM_DWORDS
'    Dim As decfloat fac1
'    Dim As Long i, ln
'    Dim As _Integer64 n
'    Dim As _Offset no, lno

'    no = _Offset(fac1.mantissa)
'    lno = _Offset(ln)
'    n = Abs(m)

'    If n > 9999999999999999 Then
'        str2fp fac1, Str$(m)
'        result = fac1: Exit Sub
'    End If

'    ln = 0
'    For i = 1 To digits
'        memcpy no + i * 4, lno, 4
'    Next

'    If m = 0 Then
'        fac1.exponent = 0
'        fac1.sign = 0
'        result = fac1: Exit Sub
'    End If

'    fac1.exponent = BIAS
'    If n < 100000000 Then
'        If n < 10 Then
'            ln = n * 10000000
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 1
'        ElseIf n < 100 Then
'            ln = n * 1000000
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 2
'        ElseIf n < 1000 Then
'            ln = n * 100000
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 3
'        ElseIf n < 10000 Then
'            ln = n * 10000
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 4
'        ElseIf n < 100000 Then
'            ln = n * 1000
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 5
'        ElseIf n < 1000000 Then
'            ln = n * 100
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 6
'        ElseIf n < 10000000 Then
'            ln = n * 10
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 7
'        ElseIf n < 100000000 Then
'            ln = n
'            memcpy no, lno, 4
'            fac1.exponent = fac1.exponent + 8
'        End If
'    End If
'    If n > 99999999 Then
'        fac1.exponent = fac1.exponent + 8
'        If n < 1000000000 Then
'            ln = n \ 10
'            memcpy no, lno, 4
'            ln = (n Mod 10) * 100000000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 1
'        ElseIf n < 10000000000 Then
'            ln = n \ 100
'            memcpy no, lno, 4
'            ln = (n Mod 100) * 10000000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 2
'        ElseIf n < 100000000000 Then
'            ln = n \ 1000
'            memcpy no, lno, 4
'            ln = (n Mod 1000) * 1000000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 3
'        ElseIf n < 1000000000000 Then
'            ln = n \ 10000
'            memcpy no, lno, 4
'            ln = (n Mod 10000) * 100000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 4
'        ElseIf n < 10000000000000 Then
'            ln = n \ 100000
'            memcpy no, lno, 4
'            ln = (n Mod 100000) * 10000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 5
'        ElseIf n < 100000000000000 Then
'            ln = n \ 1000000
'            memcpy no, lno, 4
'            ln = (n Mod 1000000) * 1000
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 6
'        ElseIf n < 1000000000000000 Then
'            ln = n \ 10000000
'            memcpy no, lno, 4
'            ln = (n Mod 10000000) * 100
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 7
'        ElseIf n < 10000000000000000 Then
'            ln = n \ 100000000
'            memcpy no, lno, 4
'            ln = (n Mod 100000000) * 10
'            memcpy no + 4, lno, 4
'            fac1.exponent = fac1.exponent + 8
'        End If
'    End If
'    If m < 0 Then
'        fac1.sign = &H8000
'    Else
'        fac1.sign = 0
'    End If
'    result = fac1
'End Sub

Sub si2fp (result As decfloat, m As _Integer64, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1
    Dim As Long i, ln
    Dim As _Integer64 n
    Dim As _Offset no, lno

    no = _Offset(fac1.mantissa)
    lno = _Offset(ln)
    n = Abs(m)

    If n > 9999999999999999 Then
        str2fp fac1, Str$(m)
        result = fac1: Exit Sub
    End If

    ln = 0
    For i = 1 To digits
        memcpy no + i * 4, lno, 4
    Next

    If m = 0 Then
        fac1.exponent = 0
        fac1.sign = 0
        result = fac1: Exit Sub
    End If

    fac1.exponent = BIAS
    If n < 100000000 Then
        If n < 10 Then
            ln = n * 10000000
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 1
        ElseIf n < 100 Then
            ln = n * 1000000
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 2
        ElseIf n < 1000 Then
            ln = n * 100000
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 3
        ElseIf n < 10000 Then
            ln = n * 10000
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 4
        ElseIf n < 100000 Then
            ln = n * 1000
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 5
        ElseIf n < 1000000 Then
            ln = n * 100
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 6
        ElseIf n < 10000000 Then
            ln = n * 10
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 7
        ElseIf n < 100000000 Then
            ln = n
            memcpy no, lno, 4
            fac1.exponent = fac1.exponent + 8
        End If
    End If
    If n > 99999999 Then
        fac1.exponent = fac1.exponent + 8
        If n < 1000000000 Then
            ln = n \ 10
            memcpy no, lno, 4
            ln = (n Mod 10) * 10000000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 1
        ElseIf n < 10000000000 Then
            ln = n \ 100
            memcpy no, lno, 4
            ln = (n Mod 100) * 1000000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 2
        ElseIf n < 100000000000 Then
            ln = n \ 1000
            memcpy no, lno, 4
            ln = (n Mod 1000) * 100000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 3
        ElseIf n < 1000000000000 Then
            ln = n \ 10000
            memcpy no, lno, 4
            ln = (n Mod 10000) * 10000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 4
        ElseIf n < 10000000000000 Then
            ln = n \ 100000
            memcpy no, lno, 4
            ln = (n Mod 100000) * 1000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 5
        ElseIf n < 100000000000000 Then
            ln = n \ 1000000
            memcpy no, lno, 4
            ln = (n Mod 1000000) * 100
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 6
        ElseIf n < 1000000000000000 Then
            ln = n \ 10000000
            memcpy no, lno, 4
            ln = (n Mod 10000000) * 10
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 7
        ElseIf n < 10000000000000000 Then
            ln = n \ 100000000
            memcpy no, lno, 4
            ln = n Mod 100000000
            memcpy no + 4, lno, 4
            fac1.exponent = fac1.exponent + 8
        End If
    End If
    If m < 0 Then
        fac1.sign = &H8000
    Else
        fac1.sign = 0
    End If
    result = fac1
End Sub


Sub RSHIFT_1 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 10
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 10
        v2 = v2 * 10000000 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 10
    memcpy no, lno, 4
End Sub

Sub LSHIFT_1 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 10000000
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 10000000
        ln = v1 * 10 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 10000000
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 10 * (ln Mod 10000000)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_2 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 100
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 100
        v2 = v2 * 1000000 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 100
    memcpy no, lno, 4
End Sub

Sub LSHIFT_2 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 1000000
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 1000000
        ln = v1 * 100 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 1000000
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 100 * (ln Mod 1000000)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_3 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 1000
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 1000
        v2 = v2 * 100000 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 1000
    memcpy no, lno, 4
End Sub

Sub LSHIFT_3 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 100000
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 100000
        ln = v1 * 1000 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 100000
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 1000 * (ln Mod 100000)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_4 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 10000
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 10000
        v2 = v2 * 10000 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 10000
    memcpy no, lno, 4
End Sub

Sub LSHIFT_4 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 10000
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 10000
        ln = v1 * 10000 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 10000
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 10000 * (ln Mod 10000)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_5 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 100000
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 100000
        v2 = v2 * 1000 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 100000
    memcpy no, lno, 4
End Sub

Sub LSHIFT_5 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 1000
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 1000
        ln = v1 * 100000 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 1000
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 100000 * (ln Mod 1000)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_6 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 1000000
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 1000000
        v2 = v2 * 100 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 1000000
    memcpy no, lno, 4
End Sub

Sub LSHIFT_6 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 100
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 100
        ln = v1 * 1000000 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 100
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 1000000 * (ln Mod 100)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_7 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * i, 4
        v1 = ln \ 10000000
        memcpy lno, no + 4 * (i - 1), 4
        v2 = ln Mod 10000000
        v2 = v2 * 10 + v1
        ln = v2
        memcpy no + 4 * i, lno, 4
    Next
    memcpy lno, no, 4
    ln = ln \ 10000000
    memcpy no, lno, 4
End Sub

Sub LSHIFT_7 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As _Unsigned Long v1, v2
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * i, 4
        v1 = ln Mod 10
        memcpy lno, no + 4 * (i + 1), 4
        v2 = ln \ 10
        ln = v1 * 10000000 + v2
        memcpy no + 4 * i, lno, 4
        memcpy lno, no + 4 * (i + 1), 4
        ln = ln Mod 10
        memcpy no + 4 * (i + 1), lno, 4
    Next
    memcpy lno, no + 4 * digits, 4
    ln = 10000000 * (ln Mod 10)
    memcpy no + 4 * digits, lno, 4
End Sub

Sub RSHIFT_8 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = digits To 1 Step -1
        memcpy lno, no + 4 * (i - 1), 4
        memcpy no + 4 * i, lno, 4
    Next
    ln = 0
    memcpy no, lno, 4
End Sub

Sub LSHIFT_8 (mantissa As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As Long i, ln
    Dim As _Offset no, lno

    no = _Offset(mantissa.mantissa)
    lno = _Offset(ln)
    For i = 0 To digits - 1
        memcpy lno, no + 4 * (i + 1), 4
        memcpy no + 4 * i, lno, 4
    Next
    ln = 0
    memcpy no + 4 * digits, lno, 4
End Sub

Function fpcmp& (x As decfloat, y As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As Long c, i, lx, ly
    Dim As _Offset xo, yo, lxo, lyo

    If x.sign < y.sign Then fpcmp = -1: Exit Function
    If x.sign > y.sign Then fpcmp = 1: Exit Function
    xo = _Offset(x.mantissa)
    yo = _Offset(y.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    If x.sign = y.sign Then
        If x.exponent = y.exponent Then
            For i = 0 To digits
                memcpy lxo, xo + 4 * i, 4
                memcpy lyo, yo + 4 * i, 4
                c = lx - ly
                If c <> 0 Then Exit For
            Next
            If c < 0 Then fpcmp = -1: Exit Function
            If c = 0 Then fpcmp = 0: Exit Function
            If c > 0 Then fpcmp = 1: Exit Function
        End If
        If x.exponent < y.exponent Then fpcmp = -1: Exit Function
        If x.exponent > y.exponent Then fpcmp = 1: Exit Function
    End If
    ' if we reach this point it means that the signs are different
    ' and if the sign of x is set meaning that x is negative then x < y

End Function

Sub NORM_FAC1 (fac1 As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    ' normalize the number in fac1
    ' all routines exit through this one.

    'see if the mantissa is all zeros.
    'if so, set the exponent and sign equal to 0.
    Dim As Long i, er, f, ln
    Dim As _Offset no, lno

    no = _Offset(fac1.mantissa)
    lno = _Offset(ln)
    er = 0: f = 0
    For i = 0 To digits
        memcpy lno, no + 4 * i, 4
        If ln > 0 Then f = 1
    Next
    memcpy lno, no, 4
    If f = 0 Then
        fac1.exponent = 0
        fac1.sign = 0
        Exit Sub
        'if the highmost Digit in fac1_man is nonzero,
        'shift the mantissa right 1 Digit and
        'increment the exponent
    ElseIf ln > 99999999 Then
        RSHIFT_1 fac1, digits
        fac1.exponent = fac1.exponent + 1
    Else
        memcpy lno, no, 4
        'now shift fac1_man 1 to the left until a
        'nonzero digit appears in the next-to-highest
        'Digit of fac1_man. decrement exponent for
        'each shift.
        While ln = 0
            LSHIFT_8 fac1, digits
            fac1.exponent = fac1.exponent - 8
            If fac1.exponent = 0 Then
                Print "NORM_FAC1=EXPU_ERR"
                Exit Sub
            End If
            memcpy lno, no, 4
        Wend
        memcpy lno, no, 4
        If ln < 10 Then
            LSHIFT_7 fac1, digits
            fac1.exponent = fac1.exponent - 7
        ElseIf ln < 100 Then
            LSHIFT_6 fac1, digits
            fac1.exponent = fac1.exponent - 6
        ElseIf ln < 1000 Then
            LSHIFT_5 fac1, digits
            fac1.exponent = fac1.exponent - 5
        ElseIf ln < 10000 Then
            LSHIFT_4 fac1, digits
            fac1.exponent = fac1.exponent - 4
        ElseIf ln < 100000 Then
            LSHIFT_3 fac1, digits
            fac1.exponent = fac1.exponent - 3
        ElseIf ln < 1000000 Then
            LSHIFT_2 fac1, digits
            fac1.exponent = fac1.exponent - 2
        ElseIf ln < 10000000 Then
            LSHIFT_1 fac1, digits
            fac1.exponent = fac1.exponent - 1
        End If
    End If
    'check for overflow/underflow
    If fac1.exponent < 0 Then
        Print "NORM_FAC1=EXPO_ERR"
    End If
End Sub

Sub fpadd_aux (fac1 As decfloat, fac2 As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As _Unsigned Long v, c, i
    Dim As Long lx, ly
    Dim As _Offset xo, yo, lxo, lyo

    xo = _Offset(fac1.mantissa)
    yo = _Offset(fac2.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    c = 0
    For i = digits To 1 Step -1
        memcpy lxo, xo + 4 * i, 4
        memcpy lyo, yo + 4 * i, 4
        v = lx + ly + c
        If v > 99999999 Then
            v = v - 100000000
            c = 1
        Else
            c = 0
        End If
        lx = v
        memcpy xo + 4 * i, lxo, 4
    Next
    memcpy lxo, xo, 4
    memcpy lyo, yo, 4
    lx = lx + ly + c
    memcpy xo, lxo, 4

    NORM_FAC1 fac1, digits

End Sub

Sub fpsub_aux (fac1 As decfloat, fac2 As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As Long v, c, i
    Dim As Long lx, ly
    Dim As _Offset xo, yo, lxo, lyo

    xo = _Offset(fac1.mantissa)
    yo = _Offset(fac2.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    c = 0
    For i = digits To 1 Step -1
        memcpy lxo, xo + 4 * i, 4
        memcpy lyo, yo + 4 * i, 4
        v = lx - ly - c
        If v < 0 Then
            v = v + 100000000
            c = 1
        Else
            c = 0
        End If
        lx = v
        memcpy xo + 4 * i, lxo, 4
    Next
    memcpy lxo, xo, 4
    memcpy lyo, yo, 4
    lx = lx - ly - c
    memcpy xo, lxo, 4

    NORM_FAC1 fac1, digits
End Sub

Sub fpadd (result As decfloat, x As decfloat, y As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS

    Dim As decfloat fac1, fac2
    Dim As Long i, t, c, xsign, ysign

    xsign = x.sign: x.sign = 0
    ysign = y.sign: y.sign = 0
    c = fpcmp(x, y, digits)

    x.sign = xsign
    y.sign = ysign
    If c < 0 Then
        fac1 = y
        fac2 = x
    Else
        fac1 = x
        fac2 = y
    End If
    t = fac1.exponent - fac2.exponent
    t = ((fac1.exponent And &H7FFFFFFF) - BIAS - 1) - ((fac2.exponent And &H7FFFFFFF) - BIAS - 1)

    If t < (NUM_DIGITS + 8) Then
        'The difference between the two
        'exponents indicate how many times
        'we have to multiply the mantissa
        'of FAC2 by 10 (i.e., shift it right 1 place).
        'If we have to shift more times than
        'we have digits, the result is already in FAC1.
        t = fac1.exponent - fac2.exponent
        If t > 0 And t < (NUM_DIGITS + 8) Then 'shift

            i = t \ 8
            While i > 0
                RSHIFT_8 fac2, digits
                t = t - 8
                i = i - 1
            Wend
            If t = 7 Then
                RSHIFT_7 fac2, digits
            ElseIf t = 6 Then
                RSHIFT_6 fac2, digits
            ElseIf t = 5 Then
                RSHIFT_5 fac2, digits
            ElseIf t = 4 Then
                RSHIFT_4 fac2, digits
            ElseIf t = 3 Then
                RSHIFT_3 fac2, digits
            ElseIf t = 2 Then
                RSHIFT_2 fac2, digits
            ElseIf t = 1 Then
                RSHIFT_1 fac2, digits
            End If
        End If
        'See if the signs of the two numbers
        'are the same. If so, add; if not, subtract.
        If fac1.sign = fac2.sign Then 'add
            fpadd_aux fac1, fac2, digits
        Else
            fpsub_aux fac1, fac2, digits
        End If
    End If
    result = fac1
End Sub

Sub fpsub (result As decfloat, x As decfloat, y As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1, fac2
    fac1 = x
    fac2 = y
    fac2.sign = fac2.sign Xor &H8000
    fpadd fac1, fac1, fac2, digits
    result = fac1
End Sub

Sub fpmul (result As decfloat, x As decfloat, y As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1, fac2
    Dim As Long i, j, ex, er, den, num
    Dim As _Integer64 digit, carry
    Dim As _Unsigned _Integer64 fac3(0 To digits)
    Dim As Long lx, ly
    Dim As _Offset xo, yo, lxo, lyo

    xo = _Offset(fac1.mantissa)
    yo = _Offset(fac2.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    fac1 = x
    fac2 = y
    'check exponents. if either is zero,
    'the result is zero
    lx = 0
    If fac1.exponent = 0 Or fac2.exponent = 0 Then 'result is zero...clear fac1.
        fac1.sign = 0
        fac1.exponent = 0
        For i = 0 To digits
            memcpy xo + 4 * i, lxo, 4
        Next
        'NORM_FAC1(fac1)
        result = fac1: Exit Sub
    Else

        If ex < 0 Then
            er = EXPO_ERR
            result = fac1: Exit Sub
        End If

        'clear fac3 mantissa
        For i = 0 To digits
            fac3(i) = 0
        Next

        den = digits
        memcpy lyo, yo + 4 * den, 4
        While ly = 0
            den = den - 1
            memcpy lyo, yo + 4 * den, 4
        Wend
        num = digits
        memcpy lxo, xo + 4 * num, 4
        While lx = 0
            num = num - 1
            memcpy lxo, xo + 4 * num, 4
        Wend

        If num < den Then
            Swap fac1, fac2
            'fac1=y
            'fac2=x
            Swap den, num
        End If

        For j = den To 0 Step -1
            carry = 0
            memcpy lyo, yo + 4 * j, 4
            digit = ly
            For i = num To 0 Step -1
                memcpy lxo, xo + 4 * i, 4
                fac3(i) = fac3(i) + digit * lx
            Next
            For i = num To 0 Step -1
                fac3(i) = fac3(i) + carry
                carry = fac3(i) \ 100000000
                fac3(i) = (fac3(i) Mod 100000000)
            Next

            For i = digits To 1 Step -1
                fac3(i) = fac3(i - 1)
            Next
            fac3(0) = carry
        Next

        For i = 0 To digits
            lx = fac3(i)
            memcpy xo + 4 * i, lxo, 4
        Next
    End If
    'now determine exponent of result.
    'as you do...watch for overflow.
    ex = fac2.exponent - BIAS + fac1.exponent
    fac1.exponent = ex
    'determine the sign of the product
    fac1.sign = fac1.sign Xor fac2.sign
    NORM_FAC1 fac1, digits
    result = fac1
End Sub

Sub fpmul_si (result As decfloat, x As decfloat, y As _Integer64, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1, fac2
    Dim As Long count, ex, er, i, lx, ly
    Dim As _Integer64 carry, digit, prod, value
    Dim As _Offset xo, yo, lxo, lyo

    xo = _Offset(fac1.mantissa)
    yo = _Offset(fac2.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    fac1 = x
    digit = Abs(y)
    If digit > 99999999 Then
        si2fp fac2, y, digits
        fpmul fac1, fac1, fac2, digits
        result = fac1: Exit Sub
    End If
    'check exponents. if either is zero,
    'the result is zero
    If fac1.exponent = 0 Or y = 0 Then 'result is zero...clear fac1.
        fac1.sign = 0
        fac1.exponent = 0
        lx = 0
        For count = 0 To digits
            memcpy xo + 4 * count, lxo, 4
        Next
        NORM_FAC1 fac1, digits
        result = fac1: Exit Sub
    Else
        If digit = 1 Then
            If y < 0 Then
                fac1.sign = fac1.sign Xor &H8000
            End If
            result = fac1: Exit Sub
        End If
        'now determine exponent of result.
        'as you do...watch for overflow.

        If ex < 0 Then
            er = EXPO_ERR
            result = fac1: Exit Sub
        End If

        carry = 0

        For i = digits To 0 Step -1
            memcpy lxo, xo + 4 * i, 4
            prod = digit * lx + carry
            value = (prod Mod 100000000)
            lx = value
            memcpy xo + 4 * i, lxo, 4
            carry = prod \ 100000000
        Next

        If carry < 10 Then
            RSHIFT_1 fac1, digits
            fac1.exponent = fac1.exponent + 1
            memcpy lxo, xo, 4
            lx = lx + carry * 10000000
            memcpy xo, lxo, 4
        ElseIf carry < 100 Then
            RSHIFT_2 fac1, digits
            fac1.exponent = fac1.exponent + 2
            memcpy lxo, xo, 4
            lx = lx + carry * 1000000
            memcpy xo, lxo, 4
        ElseIf carry < 1000 Then
            RSHIFT_3 fac1, digits
            fac1.exponent = fac1.exponent + 3
            memcpy lxo, xo, 4
            lx = lx + carry * 100000
            memcpy xo, lxo, 4
        ElseIf carry < 10000 Then
            RSHIFT_4 fac1, digits
            fac1.exponent = fac1.exponent + 4
            memcpy lxo, xo, 4
            lx = lx + carry * 10000
            memcpy xo, lxo, 4
        ElseIf carry < 100000 Then
            RSHIFT_5 fac1, digits
            fac1.exponent = fac1.exponent + 5
            memcpy lxo, xo, 4
            lx = lx + carry * 1000
            memcpy xo, lxo, 4
        ElseIf carry < 1000000 Then
            RSHIFT_6 fac1, digits
            fac1.exponent = fac1.exponent + 6
            memcpy lxo, xo, 4
            lx = lx + carry * 100
            memcpy xo, lxo, 4
        ElseIf carry < 10000000 Then
            RSHIFT_7 fac1, digits
            fac1.exponent = fac1.exponent + 7
            memcpy lxo, xo, 4
            lx = lx + carry * 10
            memcpy xo, lxo, 4
        ElseIf carry < 100000000 Then
            RSHIFT_8 fac1, digits
            fac1.exponent = fac1.exponent + 8
            memcpy lxo, xo, 4
            lx = lx + carry
            memcpy xo, lxo, 4
        End If

    End If

    NORM_FAC1 fac1, digits

    If y < 0 Then
        fac1.sign = fac1.sign Xor &H8000
    End If
    result = fac1
End Sub

Function min& (a As Long, b As Long)
    If a < b Then min& = a Else min& = b
End Function

Function RealW# (w() As Double, j As Long)
    Dim wx As Double
    wx = ((w(j - 1) * 10000 + w(j)) * 10000 + w(j + 1)) * 10000
    If UBound(w) >= (j + 2) Then wx = wx + w(j + 2)
    RealW# = wx
End Function

Sub subtract (w() As Double, q As Long, d() As Double, ka As Long, kb As Long)
    Dim As Long j
    For j = ka To kb
        w(j) = w(j) - q * d(j - ka + 2)
    Next
End Sub

Sub normalize (w() As Double, ka As Long, q As Long)
    w(ka) = w(ka) + w(ka - 1) * 10000
    w(ka - 1) = q
End Sub

Sub finalnorm (w() As Double, kb As Long)
    Dim As Long carry, j
    For j = kb To 3 Step -1
        If w(j) < 0 Then
            carry = ((-w(j) - 1) \ 10000) + 1
        Else
            If w(j) >= 10000 Then
                carry = -(w(j) \ 10000)
            Else
                carry = 0
            End If
        End If
        w(j) = w(j) + carry * 10000
        w(j - 1) = w(j - 1) - carry
    Next
End Sub

Sub fpdiv (result As decfloat, x As decfloat, y As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1, fac2
    Dim As Long i, er, is_power_of_ten
    Dim As Long lx, ly
    Dim As _Offset xo, yo, lxo, lyo

    xo = _Offset(fac1.mantissa)
    yo = _Offset(fac2.mantissa)
    lxo = _Offset(lx)
    lyo = _Offset(ly)
    fac1 = x
    fac2 = y

    lx = 99999999
    If fac2.exponent = 0 Then ' if fac2 = 0, return
        ' a divide-by-zero error and
        ' bail out.
        For i = 0 To digits
            memcpy xo + 4 * i, lxo, 4
        Next
        fac1.exponent = 99999 + BIAS + 1
        er = DIVZ_ERR
        result = fac1
        Exit Sub
    ElseIf fac1.exponent = 0 Then 'fact1=0, just return
        er = 0
        result = fac1
        Exit Sub
    Else
        'check to see if fac2 is a power of ten
        is_power_of_ten = 0
        memcpy lyo, yo, 4
        If ly = 10000000 Then
            is_power_of_ten = 1
            For i = 1 To digits
                memcpy lyo, yo + 4 * i, 4
                If ly <> 0 Then
                    is_power_of_ten = 0
                    Exit For
                End If
            Next
        End If
        'if fac2 is a power of ten then all we need to do is to adjust the sign and exponent and we are finished
        If is_power_of_ten = 1 Then
            fac1.sign = fac1.sign Xor fac2.sign
            fac1.exponent = fac1.exponent - fac2.exponent + BIAS + 1
            result = fac1
            Exit Sub
        End If

        Dim As Double result(1 To 2 * digits + 3), n(1 To 2 * digits + 3), d(1 To 2 * digits + 3)
        Const b = 10000
        Dim As Long j, last, laststep, q, t
        Dim As Long stp
        Dim As Double xd, xn, rund
        Dim As Double w(1 To UBound(n) + 4)

        For j = 0 To digits
            memcpy lxo, xo + 4 * j, 4
            n(2 * j + 2) = lx \ 10000
            n(2 * j + 3) = lx Mod 10000
            memcpy lyo, yo + 4 * j, 4
            d(2 * j + 2) = ly \ 10000
            d(2 * j + 3) = ly Mod 10000
        Next
        n(1) = (fac1.exponent And &H7FFFFFFF) - BIAS - 1
        d(1) = (fac2.exponent And &H7FFFFFFF) - BIAS - 1
        For j = UBound(n) To UBound(w)
            w(j) = 0
        Next
        t = UBound(n) - 1
        w(1) = n(1) - d(1) + 1
        w(2) = 0
        For j = 2 To UBound(n)
            w(j + 1) = n(j)
        Next
        xd = (d(2) * b + d(3)) * b + d(4) + d(5) / b
        laststep = t + 2
        For stp = 1 To laststep
            xn = RealW(w(), (stp + 2))
            q = Int(xn / xd)
            last = min(stp + t + 1, UBound(w))
            subtract w(), q, d(), (stp + 2), last
            normalize w(), (stp + 2), q
        Next
        finalnorm w(), (laststep + 1)
        If w(2) <> 0 Then laststep = laststep - 1
        rund = w(laststep + 1) / b
        If rund >= 0.5 Then w(laststep) = w(laststep) + 1
        If w(2) = 0 Then
            For j = 1 To t + 1
                result(j) = w(j + 1)
            Next
        Else
            For j = 1 To t + 1
                result(j) = w(j)
            Next
        End If
        If w(2) = 0 Then result(1) = w(1) - 1 Else result(1) = w(1)

        For j = 0 To digits
            lx = result(2 * j + 2) * 10000 + result(2 * j + 3)
            memcpy xo + 4 * j, lxo, 4
        Next
        NORM_FAC1 fac1, digits
        fac1.exponent = (result(1) + BIAS)
    End If
    fac1.sign = fac1.sign Xor fac2.sign
    result = fac1
End Sub

Sub fpdiv_si (result As decfloat, num As decfloat, den As Long, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat fac1
    Dim As _Unsigned _Integer64 carry, remder
    Dim As _Integer64 i, divisor
    Dim As _Integer64 quotient
    remder = 0
    divisor = Abs(den)
    fac1 = num
    If divisor = 0 Then
        Print "error: divisor = 0"
        result = fac1: Exit Sub
    End If
    If divisor > 99999999 Then
        Dim As decfloat fac2
        si2fp fac2, divisor, digits
        fpdiv result, fac1, fac2, digits
        Exit Sub
    End If

    Dim As Long lx
    Dim As _Offset xo, lxo

    xo = _Offset(fac1.mantissa)
    lxo = _Offset(lx)
    For i = 0 To digits
        memcpy lxo, xo + 4 * i, 4
        quotient = lx + remder * 100000000
        remder = quotient Mod divisor
        lx = quotient \ divisor
        memcpy xo + 4 * i, lxo, 4
    Next
    quotient = remder * 100000000
    quotient = quotient \ divisor
    memcpy lxo, xo, 4
    carry = lx

    If carry = 0 Then
        LSHIFT_8 fac1, digits
        fac1.exponent = fac1.exponent - 8
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 10 Then
        LSHIFT_7 fac1, digits
        fac1.exponent = fac1.exponent - 7
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 10
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 100 Then
        Call LSHIFT_6(fac1, digits)
        fac1.exponent = fac1.exponent - 6
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 100
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 1000 Then
        Call LSHIFT_5(fac1, digits)
        fac1.exponent = fac1.exponent - 5
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 1000
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 10000 Then
        Call LSHIFT_4(fac1, digits)
        fac1.exponent = fac1.exponent - 4
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 10000
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 100000 Then
        Call LSHIFT_3(fac1, digits)
        fac1.exponent = fac1.exponent - 3
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 100000
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 1000000 Then
        Call LSHIFT_2(fac1, digits)
        fac1.exponent = fac1.exponent - 2
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 1000000
        memcpy xo + 4 * digits, lxo, 4
    ElseIf carry < 10000000 Then
        Call LSHIFT_1(fac1, digits)
        fac1.exponent = fac1.exponent - 1
        memcpy lxo, xo + 4 * digits, 4
        lx = lx + quotient \ 10000000
        memcpy xo + 4 * digits, lxo, 4
    End If

    'NORM_FAC1(fac1)
    If den < 0 Then
        fac1.sign = fac1.sign Xor &H8000
    End If
    result = fac1
End Sub

' sqrt(num)
Sub fpsqr (result As decfloat, num As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat r, r2, tmp, n, half
    Dim As Long ex, k, l, prec
    Dim As String ts, v
    Dim As Double x
    l = Log((NUM_DIGITS + 8) * 0.0625) * 1.5
    'l=estimated number of iterations needed
    'first estimate is accurate to about 16 digits
    'l is approximatly = to log2((NUM_DIGITS+9)/16)
    'NUM_DIGITS+9 because decfloat has an extra 9 guard digits
    n = num
    si2fp tmp, 0, digits
    If fpcmp(n, tmp, digits) = 0 Then
        si2fp r, 0, digits
        result = r
        Exit Sub
    End If
    si2fp tmp, 1, digits
    If fpcmp(n, tmp, digits) = 0 Then
        si2fp r, 1, digits
        result = r
        Exit Sub
    End If
    si2fp tmp, 0, digits
    If fpcmp(n, tmp, digits) < 0 Then
        si2fp r, 0, digits
        result = r
        Exit Sub
    End If
    Dim As Long lx
    Dim As _Offset xo, lxo

    xo = _Offset(n.mantissa)
    lxo = _Offset(lx)
    '=====================================================================
    'hack to bypass the limitation of double exponent range
    'in case the number is larger than what a double can handle
    'for example, if the number is 2e500
    'we separate the exponent and mantissa in this case 2
    'if the exponent is odd then multiply the mantissa by 10
    'take the square root and assign it to decfloat
    'divide the exponent in half for square root
    'in this case 1.414213562373095e250
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If
    memcpy lxo, xo, 4
    ts = _Trim$(Str$(lx))
    If Len(ts) < 8 Then
        ts = ts + String$(8 - Len(ts), "0")
    End If
    v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
    memcpy lxo, xo + 4, 4
    ts = _Trim$(Str$(lx))
    If Len(ts) < 8 Then
        ts = String$(8 - Len(ts), "0") + ts
    End If
    v = v + ts
    x = Val(v)
    If x = 0 Then Print "Div 0": result = r: Exit Sub
    If x = 1 And ex = 0 Then
        si2fp r, 1, digits
        result = r
        Exit Sub
    End If
    If Abs(ex) And 1 Then
        x = x * 10
        ex = ex - 1
    End If
    x = Sqr(x) 'approximation
    v = _Trim$(Str$(x))
    k = InStr(v, ".")
    str2fp r, v
    r.exponent = ex \ 2 + BIAS + 1
    If Len(v) > 1 And k = 0 Then r.exponent = r.exponent + 1
    str2fp half, "0.5"
    '=====================================================================
    'Newton-Raphson method
    prec = 3
    For k = 1 To l + 1
        prec = 2 * prec - 1
        fpdiv tmp, n, r, prec
        fpadd r2, r, tmp, prec
        fpmul r, r2, half, prec
    Next
    result = r
End Sub

Sub fpinv (result As decfloat, m As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As Double x
    Dim As Long k, l, ex
    Dim As Long prec
    Dim As decfloat r, r2, one, n
    Dim As Long lx
    Dim As _Offset xo, lxo

    xo = _Offset(n.mantissa)
    lxo = _Offset(lx)
    n = m
    l = Log((NUM_DIGITS + 8) * 0.0625) * 1.5
    Dim As String v, ts
    If n.exponent > 0 Then
        ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
    Else
        ex = 0
    End If

    If n.sign Then v = "-" Else v = " "
    memcpy lxo, xo, 4
    ts = Str$(lx)
    If Len(ts) < 8 Then
        ts = ts + String$(8 - Len(ts), "0")
    End If
    v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
    memcpy lxo, xo + 4, 4
    ts = Str$(lx)
    If Len(ts) < 8 Then
        ts = String$(8 - Len(ts), "0") + ts
    End If
    v = v + ts
    x = Val(v)
    If x = 0 Then Print "Div 0": result = r: Exit Sub
    If x = 1 And ex = 0 Then
        str2fp r, "1"
        result = r: Exit Sub
    ElseIf x = 1 Then
        x = 10
        ex = ex - 1
    End If
    ex = (-1) - ex
    x = 1 / x
    str2fp r, Str$(x)
    r.exponent = ex + BIAS + 1
    si2fp one, 1, digits
    r2 = r
    prec = 3
    For k = 1 To l
        prec = 2 * prec - 1
        fpmul r2, n, r, prec
        fpsub r2, one, r2, prec
        fpmul r2, r, r2, prec
        fpadd r, r, r2, prec
    Next
    result = r
End Sub

'fractional part of num
Sub fpfrac (result As decfloat, num As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat n
    fpfix n, num
    fpsub n, num, n, digits
    result = n
End Sub

'returns the positive of n
Sub fpabs (result As decfloat, n As decfloat)
    Dim As decfloat x
    x = n
    x.sign = 0
    result = x
End Sub

'changes the sign of n, if n is positive then n will be negative & vice versa
Sub fpneg (result As decfloat, n As decfloat)
    Dim As decfloat x
    x = n
    x.sign = x.sign Xor &H8000
    result = x
End Sub

'returns the negative of n regardless of the sign of n
Sub fpnegative (result As decfloat, n As decfloat)
    Dim As decfloat x
    x = n
    x.sign = &H8000
    result = x
End Sub

Sub fpfmod (quotient As decfloat, f_mod As decfloat, num As decfloat, denom As decfloat, digits As Long)
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat q, fm 'make copy in case the _destination and source are the same
    fpdiv fm, num, denom, digits
    fpfix q, fm
    fpsub fm, fm, q, digits
    fpmul fm, fm, denom, digits
    quotient = q
    f_mod = fm
End Sub

Sub fpeps (result As decfloat, digits As Long)
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat ep
    si2fp ep, 1, digits
    ep.exponent = (-(NUM_DIGITS) + BIAS + 1)
    result = ep
End Sub

Sub fpipow (result As decfloat, x As decfloat, e As _Integer64, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    'take x to an Long power
    Dim As decfloat one, y, z
    Dim As _Integer64 n, c

    c = 0
    y = x
    n = Abs(e)
    si2fp z, 1, digits
    one = z
    While n > 0
        While (n And 1) = 0
            n = n \ 2
            fpmul y, y, y, digits
            c = c + 1
        Wend
        n = n - 1
        fpmul z, y, z, digits
        c = c + 1
    Wend
    If e < 0 Then
        fpdiv z, one, z, digits
    End If
    result = z
End Sub

Sub fpfactorial (result As decfloat, n As Long, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    Dim As Long i
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat f
    If n < 0 Then Print "inf": result = f: Exit Sub
    If n = 0 Or n = 1 Then
        si2fp f, 1, digits
        result = f: Exit Sub
    End If
    si2fp f, 2, digits
    If n = 2 Then result = f: Exit Sub
    For i = 3 To n
        fpmul_si f, f, i, digits
    Next
    result = f
End Sub

Sub fplogTaylor (result As decfloat, x As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    'taylor series
    '====================Log Guard==================
    Dim As decfloat g, zero
    fpabs g, x
    si2fp zero, 0, digits
    If fpcmp(g, x, digits) <> 0 Then result = zero: Exit Sub
    If fpcmp(x, zero, digits) = 0 Then result = zero: Exit Sub
    '=============================================
    Dim As Long invflag
    Dim As decfloat XX, Term, Accum, x9, tmp, tmp2
    Dim As decfloat T, B, one, Q, two

    si2fp one, 1, digits
    si2fp two, 2, digits
    x9 = x
    If fpcmp(x, one, digits) < 0 Then
        invflag = 1
        fpdiv x9, one, x9, digits
    End If
    fpsub T, x9, one, digits
    fpadd B, x9, one, digits
    fpdiv Accum, T, B, digits
    fpdiv Q, T, B, digits
    tmp = Q
    fpmul XX, Q, Q, digits
    Dim As Long c
    c = 1
    Do
        c = c + 2
        tmp2 = tmp
        fpmul Q, Q, XX, digits
        fpdiv_si Term, Q, c, digits
        fpadd Accum, tmp, Term, digits
        Swap tmp, Accum
    Loop Until fpcmp(tmp, tmp2, digits) = 0
    fpmul_si Accum, Accum, 2, digits
    If invflag Then
        fpneg Accum, Accum
        result = Accum: Exit Sub
    End If
    result = Accum
End Sub

Sub fplog (result As decfloat, x As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    '====================Log Guard==================
    Dim As decfloat g, one, zero
    Dim As Long factor
    si2fp zero, 0, digits
    si2fp one, 1, digits
    fpabs g, x
    If fpcmp(g, x, digits) <> 0 Then result = zero: Exit Sub
    If fpcmp(x, zero, digits) = 0 Then result = zero: Exit Sub
    If fpcmp(x, one, digits) = 0 Then result = zero: Exit Sub
    '=============================================
    Dim As decfloat approx, ans, logx
    approx = x
    factor = 4096
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fpsqr approx, approx, digits
    fplogTaylor logx, approx, digits
    fpmul_si ans, logx, factor, digits
    result = ans
End Sub

Sub fpexp (result As decfloat, x As decfloat, digits_in As Long)
    Dim As Long digits
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    'taylor series
    Dim As decfloat fac, x9, temp, accum, p, term
    Dim As Long i, c
    si2fp temp, 0, digits
    si2fp fac, 1, digits
    If fpcmp(x, temp, digits) = 0 Then result = fac: Exit Sub
    c = 1
    fpdiv_si x9, x, 8192, digits 'fpdiv_si(x, 67108864) '
    p = x9
    fpadd accum, fac, x9, digits '1 + x

    Do
        c = c + 1
        temp = accum
        fpdiv_si fac, fac, c, digits
        fpmul p, p, x9, digits
        fpmul term, p, fac, digits
        fpadd accum, temp, term, digits
    Loop Until fpcmp(accum, temp, digits) = 0
    For i = 1 To 13
        fpmul accum, accum, accum, digits
    Next
    result = accum
End Sub

Sub fppow (result As decfloat, lhs As decfloat, rhs As decfloat)
    Dim As decfloat lhs2
    fplog lhs2, lhs, NUM_DWORDS
    fpmul lhs2, lhs2, rhs, NUM_DWORDS
    fpexp lhs2, lhs2, NUM_DWORDS
    result = lhs2
End Sub

Sub fpnroot (result As decfloat, x As decfloat, p_in As Long, digits_in As Long)
    Dim As Long digits, p, psign
    digits = digits_in
    If digits > NUM_DWORDS Then digits = NUM_DWORDS
    Dim As decfloat ry, tmp, tmp2
    Dim As Double t, t2
    Dim As Long i, ex, l, prec, lx
    Dim As _Offset lxo, xo

    xo = _Offset(x.mantissa)
    lxo = _Offset(lx)
    x.sign = 0
    psign = Sgn(p_in)
    p = Abs(p_in)
    l = Log((NUM_DIGITS + 8) * 0.0625) * 1.5 'calculate the number of iterations needed
    ex = (x.exponent And &H7FFFFFFF) - BIAS - 1 'extract the exponent
    memcpy lxo, xo, 4
    t = lx
    memcpy lxo, xo + 4, 4
    t = t + lx / 100000000
    'get 16 digits from x.mantissa
    'for example, if x = 3.1415926535897932384626433832795028842 then the above would give
    't = 31415926.53589793 because the mantissa doesn't have a decimal point, it's an integer
    'each element of the mantissa holds 8 digits
    'in this example ex = 0
    t = t / 10000000 'now t = 3.141592653589793
    t2 = Log(t) / p '+ Log(10) * ex / p 'log(t ^ (1/p)) = log(t)/p + Log(10) * ex / p
    'in this example since ex = 0, it becomes: log(t ^ (1/p)) = log(t)/p
    t2 = Exp(t2) 't2=t ^ (1/p)
    str2fp ry, Str$(t2) 'convert the double t2 to decfloat in ry
    t = Log(10) * ex / p
    t2 = Exp(t - Fix(t))
    str2fp tmp, Str$(t2) 'convert the double t2 to decfloat in tmp
    fpmul ry, ry, tmp, prec 'ry = ry * Log(10) * ex / p
    str2fp tmp, "2.7182818284590452353602874713527"
    fpipow tmp, tmp, Fix(t), 24
    fpmul ry, ry, tmp, 24
    prec = 3 '3 * 8 = 24 digits, prec here means number of 8 digit elements

    fpipow tmp, ry, p - 1, prec 'tmp = ry ^ (p-1)
    fpdiv tmp, x, tmp, prec 'tmp = x * tmp
    fpmul_si tmp2, ry, p - 1, prec 'tmp2 = ry * (p-1)
    fpadd tmp2, tmp2, tmp, prec 'tmp2 = tmp2 + tmp
    fpdiv_si ry, tmp2, p, prec 'ry = tmp2 / p
    For i = 1 To l + 1
        prec = 2 * prec - 1
        fpipow tmp, ry, p - 1, prec 'tmp = ry^(p-1)
        fpdiv tmp, x, tmp, prec 'tmp = x/tmp
        fpmul_si tmp2, ry, p - 1, prec 'tmp2 = ry*(p-1)
        fpadd tmp2, tmp2, tmp, prec 'tmp2 = tmp2+tmp
        fpdiv_si ry, tmp2, p, prec 'ry = tmp2/p
    Next
    If psign < 0 Then
        si2fp tmp, 1, digits
        fpdiv ry, tmp, ry, digits
    End If
    result = ry
End Sub

Sub fpsin (result As decfloat, x As decfloat, digits_in As _Unsigned Long)
    Dim As decfloat XX, Term, Accum, p, temp2, fac, x_2
    Dim As decfloat pi2, circ, Ab
    Dim As Long precision
    precision = digits_in

    x_2 = x
    pi2 = pi_dec
    fpmul_si circ, pi2, 2, precision
    fpabs Ab, x
    If fpcmp(Ab, circ, precision) > 0 Then
        '======== CENTRALIZE ==============
        'floor/ceil to centralize
        Dim As decfloat tmp, tmp2
        If precision > 20 Then
            pi2 = pi_dec
        End If
        fpmul_si pi2, pi2, 2, precision 'got 2*pi
        fpdiv tmp, x_2, pi2, precision
        tmp2 = tmp
        fpfix tmp, tmp 'int part
        fpsub tmp, tmp2, tmp, precision 'frac part
        fpmul tmp, tmp, pi2, precision
        x_2 = tmp
    End If

    Dim As Long lm, limit2, i
    Dim As decfloat factor
    lm = precision
    limit2 = Int(-0.45344993886092585968 + 0.022333002852398072433 * lm + 5.0461814408333079844E-7 * lm * lm - 4.2338453039804235772E-11 * lm * lm * lm)

    si2fp factor, 5, precision
    fpipow factor, factor, limit2, precision
    fpdiv x_2, x_2, factor, precision 'x_=x_/5^limit2
    '==================================
    Dim As Long sign(3): sign(3) = 1
    Dim As Long c: c = 1

    Accum = x_2
    si2fp fac, 1, precision
    p = x_2
    fpmul XX, x_2, x_2, precision
    Do
        c = c + 2
        temp2 = Accum
        fpmul_si fac, fac, c * (c - 1), precision
        fpmul p, p, XX, precision
        fpdiv Term, p, fac, precision
        If sign(c And 3) Then
            fpsub Accum, temp2, Term, precision
        Else
            fpadd Accum, temp2, Term, precision
        End If
    Loop Until fpcmp(Accum, temp2, precision) = 0
    'multiply the result by 5^limit2

    For i = 1 To limit2
        fpmul p, Accum, Accum, precision
        fpmul temp2, Accum, p, precision
        '*** sin(5*x) = 5 * sin(x) - 20 * sin(x)^3 + 16 * sin(x)^5
        fpmul_si Accum, Accum, 5, precision
        fpmul_si Term, temp2, 20, precision
        fpmul_si XX, temp2, 16, precision
        fpmul XX, XX, p, precision
        fpsub Accum, Accum, Term, precision
        fpadd Accum, Accum, XX, precision
    Next i
    result = Accum
End Sub

Sub fpcos (result As decfloat, z As decfloat, digits_in As _Unsigned Long)
    Dim As decfloat x_2, pi2
    Dim As Long precision
    precision = digits_in
    fpdiv_si pi2, pi_dec, 2, precision
    fpsub x_2, pi2, z, precision

    fpsin result, x_2, precision
End Sub

Sub fptan (result As decfloat, z As decfloat, digits_in As _Unsigned Long)
    Dim As decfloat x_2, s, c
    Dim As Long precision
    precision = digits_in
    x_2 = z
    fpsin s, x_2, precision
    x_2 = z
    fpcos c, x_2, precision
    fpdiv result, s, c, precision
End Sub

Sub fpatn (result As decfloat, x As decfloat, digits_in As _Unsigned Long)
    Dim As Long precision, z
    precision = digits_in
    Dim As Long sign(3): sign(3) = 1
    Dim As _Unsigned Long c: c = 1
    Dim As decfloat XX, Term, Accum, strC, x_2, mt, mt2, p
    Dim As decfloat decnum, one, decnum2, factor

    decnum2 = x
    decnum2.sign = 0
    si2fp one, 1, precision
    If fpcmp(decnum2, one, precision) = 0 Then
        fpdiv_si result, pi_dec, 4, precision
        result.sign = x.sign
        Exit Sub
    End If
    decnum2.sign = x.sign
    Dim As Long limit2: limit2 = 16
    si2fp factor, _ShL(2, limit2 - 1), precision
    For z = 1 To limit2
        fpmul decnum, decnum2, decnum2, precision
        fpadd decnum, decnum, one, precision
        fpsqr decnum, decnum, precision
        fpadd decnum, decnum, one, precision
        fpdiv decnum, decnum2, decnum, precision
        decnum2 = decnum
    Next z

    mt = decnum
    x_2 = decnum
    p = decnum
    fpmul XX, x_2, x_2, precision
    Do
        c = c + 2
        mt2 = mt
        si2fp strC, c, precision
        fpmul p, p, XX, precision
        fpdiv Term, p, strC, precision
        If sign(c And 3) Then
            fpsub Accum, mt, Term, precision
        Else
            fpadd Accum, mt, Term, precision
        End If
        Swap mt, Accum
    Loop Until fpcmp(mt, mt2, precision) = 0
    fpmul result, factor, mt, precision
End Sub

Sub fpasin (result As decfloat, x As decfloat, digits_in As _Unsigned Long)
    Dim As Long precision
    precision = digits_in
    Dim As Double num
    ' ARCSIN = ATN(x / SQR(-x * x + 1))
    '============= ARCSIN GUARD =========
    num = fp2dbl(x)
    If num > 1 Then Exit Sub
    If num < -1 Then Exit Sub
    '========================
    Dim As decfloat one, T, B, term1, minusone
    si2fp one, 1, precision
    si2fp minusone, -1, precision
    T = x
    fpmul B, x, x, precision 'x*x
    'for 1 and -1
    If fpcmp(B, one, precision) = 0 Then
        Dim As decfloat two, atn1
        si2fp two, 2, precision
        fpatn atn1, one, precision
        If fpcmp(x, minusone, precision) = 0 Then
            fpmul two, two, atn1, precision
            fpmul result, two, minusone, precision
            Exit Sub
        Else
            fpmul result, two, atn1, precision
            Exit Sub
        End If
    End If
    fpsub B, one, B, precision '1-x*x
    fpsqr B, B, precision 'sqr(1-x*x)
    fpdiv term1, T, B, precision
    fpatn result, term1, precision
End Sub

Sub fpacos (result As decfloat, x As decfloat, digits_in As _Unsigned Long)
    Dim As Long precision
    precision = digits_in
    Dim As decfloat one, minusone, two, atn1, tail, T, B, term1, atnterm1 ',_x,temp
    Dim As Double num
    'ARCCOS = ATN(-x / SQR(-x * x + 1)) + 2 * ATN(1)
    '============= ARCCOS GUARD =========
    num = fp2dbl(x)
    If num > 1 Then Exit Sub
    If num < -1 Then Exit Sub
    '========================
    si2fp one, 1, precision
    si2fp minusone, -1, precision
    si2fp two, 2, precision
    fpatn atn1, one, precision
    fpmul tail, two, atn1, precision '2*atn(1)
    fpmul T, minusone, x, precision '-x
    fpmul B, x, x, precision 'x*x
    If fpcmp(B, one, precision) = 0 Then
        'for 1 and -1
        If fpcmp(x, minusone, precision) = 0 Then
            Dim As decfloat four
            si2fp four, 4, precision
            fpmul result, four, atn1, precision
            Exit Sub
        Else
            si2fp result, 0, precision
            Exit Sub
        End If
    End If
    fpsub B, one, B, precision '1-x*x
    fpsqr B, B, precision 'sqr(1-x*x)
    fpdiv term1, T, B, precision
    fpatn atnterm1, term1, precision
    fpadd result, atnterm1, tail, precision
End Sub

Sub initialize_fp
    Print "initializing constants: please wait"
    'pi_brent_salamin pi_dec, NUM_DIGITS
    pi_chudnovsky_bs pi_dec, NUM_DIGITS
    si2fp tan_half_num(0), 992, NUM_DIGITS
    str2fp tan_half_num(1), "161388480"
    str2fp tan_half_num(2), "7686610525440"
    str2fp tan_half_num(3), "-167256984742848000"
    str2fp tan_half_num(4), "2000393537524462080000"
    str2fp tan_half_num(5), "-14467646220791919547392000"
    str2fp tan_half_num(6), "66677300813465118447390720000"
    str2fp tan_half_num(7), "-201117789910786072985458237440000"
    str2fp tan_half_num(8), "400342706504764747636935691468800000"
    str2fp tan_half_num(9), "-521967288977995909272835160309760000000"
    str2fp tan_half_num(10), "435052278687602761865918494187323392000000"
    str2fp tan_half_num(11), "-221463964316902607512694240578598338560000000"
    str2fp tan_half_num(12), "63663507608965602906315837691661069058048000000"
    str2fp tan_half_num(13), "-8994510946805140308046160658488525397688320000000"
    str2fp tan_half_num(14), "470550277118574335327341015729793791741132800000000"
    str2fp tan_half_num(15), "-3827142253897737927329040261268989506161213440000000"

    si2fp tan_half_den(0), 491040, NUM_DIGITS
    str2fp tan_half_den(1), "39540177600"
    str2fp tan_half_den(2), "-1232419887578880"
    str2fp tan_half_den(3), "19569067214913216000"
    str2fp tan_half_den(4), "-180435497084706479616000"
    str2fp tan_half_den(5), "1036847979156754234229760000"
    str2fp tan_half_den(6), "-3857758118493338995884748800000"
    str2fp tan_half_den(7), "9452536125806945430316537159680000"
    str2fp tan_half_den(8), "-15257505370126034271052104685977600000"
    str2fp tan_half_den(9), "15972199042726674823748755905478656000000"
    str2fp tan_half_den(10), "-10480804895655884717678945541785518080000000"
    str2fp tan_half_den(11), "4060172679143214471066061077274302873600000000"
    str2fp tan_half_den(12), "-837419984702547545921539095790310985302016000000"
    str2fp tan_half_den(13), "75810877980214754024960496978688999780515840000000"
    str2fp tan_half_den(14), "-1913571126948868963664520130634494753080606720000000"
    Cls
End Sub

Sub bs (a As _Unsigned _Integer64, b As _Unsigned _Integer64, pab As decfloat, qab As decfloat, tab1 As decfloat, digits As Long)

    'computes the terms for binary splitting the chudnovsky infinite series

    'a(a) = +/- (13591409 + 545140134*a)
    'p(a) = (6*a-5)*(2*a-1)*(6*a-1)
    'b(a) = 1
    'q(a) = a*a*a*c3_over_24

    'returns p(a,b), q(a,b) and t(a,b)
    Static As decfloat c545140134
    Static As decfloat c13591409
    Static As decfloat c640320
    Static As decfloat temp, c3_over_24
    Dim As _Unsigned _Integer64 m, t
    Dim As Long dwords
    dwords = digits / 8 + 1
    si2fp c545140134, 545140134, dwords
    si2fp c13591409, 13591409, dwords
    si2fp c640320, 640320, dwords
    c3_over_24 = c640320
    fpmul temp, c3_over_24, c3_over_24, dwords
    fpmul c3_over_24, temp, c3_over_24, dwords
    fpdiv_si c3_over_24, c3_over_24, 24, dwords

    If b - a = 1 Then
        ' directly compute p(a,a+1), q(a,a+1) and t(a,a+1)
        If a = 0 Then
            si2fp pab, 1, dwords
            si2fp qab, 1, dwords
        Else
            t = 6 * a
            si2fp pab, t - 1, dwords
            fpmul_si pab, pab, a + a - 1, dwords
            fpmul_si pab, pab, t - 5, dwords
            si2fp temp, a, dwords
            fpmul qab, temp, temp, dwords
            fpmul qab, qab, temp, dwords
            fpmul qab, qab, c3_over_24, dwords
        End If
        tab1 = c545140134
        fpmul_si tab1, tab1, a, dwords
        fpadd tab1, tab1, c13591409, dwords
        fpmul tab1, tab1, pab, dwords ' a(a) * p(a)
        If a And 1 Then
            tab1.sign = tab1.sign Xor &H8000 ' = -tab
        End If
    Else
        Dim As decfloat pam, qam, tam, pmb, qmb, tmb

        ' recursively compute p(a,b), q(a,b) and t(a,b)
        ' m is the midpoint of a and b
        m = (a + b) / 2
        ' recursively calculate p(a,m), q(a,m) and t(a,m)
        bs a, m, pam, qam, tam, digits
        ' recursively calculate p(m,b), q(m,b) and t(m,b)
        bs m, b, pmb, qmb, tmb, digits
        ' now combine
        fpmul pab, pam, pmb, dwords
        fpmul qab, qam, qmb, dwords
        fpmul temp, qmb, tam, dwords
        fpmul tab1, pam, tmb, dwords
        fpadd tab1, tab1, temp, dwords
    End If

End Sub

Sub pi_chudnovsky_bs (pi1 As decfloat, digits As Long)

    'compute pi

    'this is done using chudnovsky's series with binary splitting

    Dim As decfloat p, q, sqrtc, t ', one_squared
    Static As decfloat c640320
    Static As decfloat temp, c3_over_24
    Dim As _Unsigned _Integer64 n
    Dim As Double digits_per_term
    Dim As Long dwords
    dwords = digits / 8 + 1
    si2fp c640320, 640320, dwords
    c3_over_24 = c640320
    fpmul temp, c3_over_24, c3_over_24, dwords
    fpmul c3_over_24, temp, c3_over_24, dwords
    fpdiv_si c3_over_24, c3_over_24, 24, dwords

    ' how many terms to compute
    digits_per_term = Log(fp2dbl(c3_over_24) / 6 / 2 / 6) * 0.4342944819032518
    n = Int(digits / digits_per_term + 1)
    Rem    ?"n=";n
    ' calclate p(0,n) and q(0,n)
    bs 0, n, p, q, t, digits
    si2fp sqrtc, 10005, dwords
    fpsqr sqrtc, sqrtc, dwords
    fpmul_si pi1, sqrtc, 426880, dwords
    fpmul pi1, pi1, q, dwords
    fpdiv pi1, pi1, t, dwords

End Sub

Sub binarysplittingRamanujanPI (a As _Unsigned _Integer64, b As _Unsigned _Integer64, p As decfloat, q As decfloat, r As decfloat)
    Dim As decfloat pp, qq, rr, one, three, bb
    Dim As _Unsigned _Integer64 n1, n2, n3, md
    si2fp one, 1, NUM_DIGITS
    si2fp three, 3, NUM_DIGITS
    If (b - a) = 1 Then
        If b <= 832256 Then
            n1 = (2 * b) - 1
            n2 = (4 * b) - 3
            n3 = (4 * b) - 1
            si2fp r, n1, NUM_DIGITS
            fpmul_si r, r, n2, NUM_DIGITS
            fpmul_si r, r, n3, NUM_DIGITS
        Else
            si2fp bb, b, NUM_DIGITS
            fpmul_si r, bb, 4, NUM_DIGITS
            fpsub r, r, three, NUM_DIGITS
            fpmul_si p, bb, 4, NUM_DIGITS
            fpsub p, p, one, NUM_DIGITS
            fpmul r, r, p, NUM_DIGITS
            fpmul_si p, bb, 2, NUM_DIGITS
            fpsub p, p, one, NUM_DIGITS
            fpmul r, r, p, NUM_DIGITS
        End If
        si2fp p, b, NUM_DIGITS
        fpmul_si p, p, 26390, NUM_DIGITS
        si2fp one, 1103, NUM_DIGITS
        fpadd p, p, one, NUM_DIGITS
        fpmul p, p, r, NUM_DIGITS
        si2fp q, b, NUM_DIGITS
        fpmul one, q, q, NUM_DIGITS
        fpmul q, q, one, NUM_DIGITS
        si2fp one, 3073907232, NUM_DIGITS
        fpmul q, q, one, NUM_DIGITS
        Exit Sub
    End If
    md = (a + b) / 2
    binarysplittingRamanujanPI a, md, p, q, r
    binarysplittingRamanujanPI md, b, pp, qq, rr
    fpmul pp, pp, r, NUM_DIGITS
    fpmul p, p, qq, NUM_DIGITS
    fpadd p, p, pp, NUM_DIGITS
    fpmul q, q, qq, NUM_DIGITS
    fpmul r, r, rr, NUM_DIGITS
End Sub

Sub Pi_Ramanujan (pi1 As decfloat, digits As Long)
    Dim As Long prec
    prec = digits
    If prec > NUM_DIGITS Then prec = NUM_DIGITS
    Dim As _Unsigned _Integer64 k
    Dim As decfloat p, q, r
    k = -Int(-(prec * Log(10) / Log(96059301)))
    binarysplittingRamanujanPI 0, k, p, q, r
    si2fp r, 8, prec
    fpsqr r, r, prec
    fpmul_si pi1, q, 1103, prec
    fpadd pi1, pi1, p, prec
    fpmul pi1, pi1, r, prec
    fpmul_si q, q, 9801, prec
    fpdiv pi1, q, pi1, prec
End Sub

Sub pi_brent_salamin (pi_bs As decfloat, digits_in As _Unsigned Long)
    Dim As _Unsigned Long digits
    digits = digits_in
    If digits > NUM_DIGITS Then digits = NUM_DIGITS

    Dim As Long limit2
    Dim As decfloat c0, c1, c2, c05
    Dim As decfloat a, b, sum
    Dim As decfloat ak, bk, ck
    Dim As decfloat ab, asq
    Dim As decfloat pow2, tmp

    limit2 = -digits + BIAS + 1
    si2fp c0, 0, NUM_DIGITS: ak = c0: bk = c0: ab = c0: asq = c0
    si2fp c1, 1, NUM_DIGITS: a = c1: ck = c1: pow2 = c1
    si2fp c2, 2, NUM_DIGITS: b = c2
    str2fp c05, ".5": sum = c05
    si2fp pi_bs, 3, NUM_DIGITS

    fpsqr b, b, NUM_DIGITS
    fpdiv b, c1, b, NUM_DIGITS
    While fpcmp(ck, c0, NUM_DIGITS) <> 0 And ck.exponent > limit2
        fpadd ak, a, b, NUM_DIGITS
        fpmul ak, c05, ak, NUM_DIGITS
        fpmul ab, a, b, NUM_DIGITS
        fpsqr bk, ab, NUM_DIGITS
        fpmul asq, ak, ak, NUM_DIGITS
        fpsub ck, asq, ab, NUM_DIGITS
        fpmul pow2, pow2, c2, NUM_DIGITS
        fpmul tmp, pow2, ck, NUM_DIGITS
        fpsub sum, sum, tmp, NUM_DIGITS
        a = ak: b = bk
    Wend
    fpdiv tmp, asq, sum, NUM_DIGITS
    fpmul pi_bs, c2, tmp, NUM_DIGITS
End Sub

Print this item

  Newton had a fun way to approximate general roots...
Posted by: Pete - 09-13-2022, 02:52 AM - Forum: General Discussion - Replies (35)

Print this item

  Cool Line Input feature
Posted by: bert22306 - 09-13-2022, 02:18 AM - Forum: General Discussion - Replies (2)

Well, okay, this might also be one of those situations where I'm the only guy who didn't get the memo.

If we create a text file with multiple lines, each line ending with a <return>, and we use Line Input to read each line as one long string, the Line Input command only reads the top line in the file.

Okay, I thought, I can deal with that. I can always copy-paste the other lines to the top, to input each line.

No need!

All you have to do is go back to that Line Input statement, and it will automatically read the next line down, in the text file. How cool is that?

Code: (Select All)
Dim Shared a$
Open "..\Textfile_with_many_lines_each_ending_with_carriage_return.ini" For Input As #1
1 Line Input #1, a$
Call sub_to_do_whatever
Print
Input "More sentences (y/n)"; cont$
If cont$ = "y" Then
    Print
    GoTo 1
End If
Close
End

Sub sub_to_do_whatever
    Print a$
End Sub

I add one line at the bottom of the text file, which says "stop," to end the process. For this demo program, the subroutine only prints the line input from the text file.

Print this item