Big Square root by long division

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Big Square root by long division

Post by dodicat »

This is a digit by digit method for square roots.
I have a question to testers, at the end of the code I use an example from the help file for COMMAND.
No matter how I define compiler options, whether by code (as here) or by command line, I cannot see my options from COMMAND()
If no options, then it takes about a second, with speed optimizations (02 or O3) it takes less than half a second for 5000 decimal places, so the optimizations will be noticed.

Code: Select all

#cmdline "-v -gen gcc -Wc -O2"
#include "crt/stdio.bi" 'for printf for those using win 11 terminal


Function plus(Byval _num1 As String,Byval _num2 As String) As String
    Static As Const Ubyte addQmod(0 To 19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}
    Static As Const Ubyte addbool(0 To 19)={0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1}
    Var n_=0
    Dim As Ubyte addup=Any,addcarry=Any
    #macro finish()
    answer=Ltrim(answer,"0")
    Return answer
    #endmacro
    If Len(_num2)>Len(_num1) Then 
        Swap _num2,_num1
    End If
    Var diff=Len(_num1)-Len(_num2)
    Dim as string answer="0"+_num1
    addcarry=0
    For n_=Len(_num1)-1 To diff Step -1 
        addup=_num2[n_-diff]+_num1[n_]-96
        answer[n_+1]=ADDQmod(addup+addcarry)
        addcarry=ADDbool(addup+addcarry)
    Next n_ 
    If addcarry=0 Then 
        finish()
    End If
    If n_=-1 Then 
        answer[0]=addcarry+48
        finish()
        Endif
        For n_=n_ To 0 Step -1 
            addup=_num1[n_]-48
            answer[n_+1]=ADDQmod(addup+addcarry)
            addcarry=ADDbool(addup+addcarry)
            If addcarry=0 Then Exit For
        Next n_
        answer[0]=addcarry+48
        finish()
    End Function
    
    Function minus(Byval num1 As String,Byval num2 As String) As String
        Static As Const  Ubyte subQmod(0 To 19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}
        Static As Const Ubyte subBool(0 To 19)={1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}
        Dim As Integer bigger  =Any      
        Dim sign As String 
        Var lenf=Len(NUM1)
        Var lens=Len(NUM2)
        #macro finishup()
        answer=Ltrim(answer,"0")
        If answer="" Then Return "0"
        Return sign+answer
        #endmacro
        #macro compare()
        Do
            If Lens>lenf Then bigger= -1:Exit Do
            If Lens<lenf Then bigger =0:Exit Do
            If NUM2>NUM1 Then 
                bigger=-1
            Else
                bigger= 0
            End If
            Exit Do
        Loop
        #endmacro
        compare()
        If bigger Then 
            sign="-"
            Swap NUM2,NUM1
            Swap lens,lenf
        End If
        Var diff=lenf-lens
        Dim As String answer=NUM1
        Dim As Integer n=Any
        Dim As Ubyte takeaway=Any,subtractcarry=Any
        subtractcarry=0
        For n=lenf-1 To diff Step -1 
            takeaway= num1[n]-num2[n-diff]+10-subtractcarry
            answer[n]=Subqmod(takeaway)
            subtractcarry=Subbool(takeaway)
        Next n 
        
        If subtractcarry=0 Then:finishup():End If
        If n=-1 Then:finishup():End If
        For n=n To 0 Step -1 
            takeaway= num1[n]-38-subtractcarry 
            answer[n]=Subqmod(takeaway)
            subtractcarry=Subbool(takeaway)
            If subtractcarry=0 Then Exit For
        Next n
        finishup()
    End Function 
    
    Function smult(n As String,d As Long) As String 'multiply n by a single digit
        Static As Ubyte _mod(99)= _  
        {48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57}
        Static As Ubyte _div(99)= _
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3, _
        3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,6, _
        6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,9, _
        9,9,9,9,9,9,9,9,9}
        Dim As String ans=String(Len(n)+1,0)
        Dim As Ubyte carry,main,temp
        For z As Integer=Len(n)-1 To 0 Step -1
            temp=(d)*(n[z]-48)+carry
            main=_mod(temp)
            carry=temp\10
            'carry=_div(temp)'temp\10 'alternate
            ans[z+1]=main
        Next z
        ans[0]=carry+48
        Return Iif(Len(Ltrim(ans,"0")),Ltrim(ans,"0"),"0")
    End Function
    
    Function isbigger(n1 As String,n2 As String) As Long 'is n1>n2
        Dim As Long lenn1=Len(n1),lenn2=Len(n2)
        #macro hide
        If Len(n1)>Len(n2) Then Return -1
        If Len(n1)<Len(n2) Then Return 0
        #endmacro
        'hide
        If Lenn1>Lenn2 Then Return -1
        If Lenn1<Lenn2 Then Return 0
        
        If n1>n2 Then 
            Return -1
        Else
            Return 0
        End If
    End Function 
    
    Function bmult(Byval a As String,Byval b As String,flag As Long=0) As String
        Static As Ubyte _mod(99)= _  
        {48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48, _
        49,50,51,52,53,54,55,56,57}
        Static As Ubyte _div(99)= _
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3, _
        3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,6, _
        6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,9, _
        9,9,9,9,9,9,9,9,9}
        Var la = Len(a),lb = Len(b)
        If Len(b)>Len(a) Then Swap a,b:Swap la,lb
        Dim As Ubyte n=Any,carry=Any,ai=Any
        Dim as string c =String(la+lb,"0")
        For i As Integer =la-1 To 0 Step -1
            carry=0:ai=a[i]-48
            For j As Integer =lb-1 To 0 Step -1
                n = ai * (b[j]-48) + (c[i+j+1]-48) + carry
                carry =_Div(n):c[i+j+1]=_Mod(n)
            Next j
            c[i]+=carry
        Next i
        If Ltrim(c,"0")="" Then Return "0"
        If flag=1 Then Return c  Else  Return Ltrim(c,"0")
    End Function
    
    Sub _Remove(Text As String,Char As String)
        Var index = 0,asci=Asc(char)
        For i As Integer = 0 To Len(Text) - 1
            If Text[i] <> asci Then Text[index] = Text[i] : index =index+ 1
        Next : Text = Left(Text,index)
    End Sub
    
    Sub _split(stri As String,char As String,var1 As String,var2 As String)
        Dim As Integer pst=Instr(stri,char)
        var1="":var2=""
        If pst<>0 Then
            var1=Mid(stri,1,pst-1)
            var2=Mid(stri,pst+1)
        Else
            var1=stri
        End If
    End Sub 
    
    Sub insert(s As String,char As String=".",position As Long)
        If position>0 And position<=Len(s) Then
            Dim As String part1=Mid(s,1,position-1)
            Dim As String part2=Mid(s,position)
            s=part1+char+part2
        End If
    End Sub  
    Function fmult(Byval a As String,Byval b As String) As String
        Dim As String sign
        If Instr(a,"-") xor Instr(b,"-") Then
            _remove(a,"-")
            _remove(b,"-")
            sign="-"
        End If
        If Instr(a,"-") And Instr(b,"-") Then
            _remove(a,"-")
            _remove(b,"-")
            sign=""
        End If
        
        Dim As String var1,var2
        _split(a,".",var1,var2)
        Dim As Integer lendec1=Len(var2)
        _split(b,".",var1,var2)
        Dim As Integer lendec2=Len(var2)
        _remove(a,".")
        _remove(b,".")
        Dim As String ans=bmult(a,b,1)
        insert(ans,".",Len(ans)-(lendec1+lendec2)+1)
        
        Return sign+Ltrim(ans,"0")
    End Function
    
    Function bigSQR(st As String,pl As Integer) As String
        Dim As String var1,var2,p1',p2
        Dim  As Integer j=Any,tr
        #macro split(stri,var1)
        For j=0 To Len(stri)-1
            If tr=0 And stri[j]<>46 Then 
                var1=var1+Chr(stri[j])
            End If
            If stri[j]=46 Then tr=1
        Next j
        tr=0
        #endmacro
        If Instr(st,"-")<>0 Then Return " 1.#QNAN"
        Dim s As String=st
        Dim cp1 As String
        split(s,p1)  'p1=number part
        Dim As Integer lenp1=Len(p1)
        Dim As String pair,div,num,mult,diff,temp,olddiv,digit
        Static As String cd(0 To 10)
        Dim As Integer d=Any,count,divflag=Any,k=Any,p,endrun=Any,index,c=1
        
        For i As Integer = 0 To Len(s) - 1 'remove decimal .
            If s[i] <> 46 Then s[index] = s[i] : index =index+ 1
        Next : s = Left(s,index)
        
        If (Lenp1+1+1) Mod 2 =0 Then p=2 Else p=1
        s=s+String(2*pl,"0")
        Dim decflag As Integer
        If p1="" Then
            decflag=1
            temp=temp+"."
        End If
        endrun=Lenp1+2*pl
        Dim As Long bg
        Do 
            pair=Mid(s,c,p)
            num=Ltrim(num+pair,"0")
            divflag=0
            Dim As String sd
            For d=0 To 9
                sd=Str(d)
                digit=sd:k=1
                count=count+1
                If divflag=0 Then div=olddiv+sd
                mult=smult(div,d)
                bg=isbigger(num,mult)
                diff=minus((num),mult): cd(count)=diff
                If diff[0]=48   Then 
                    digit=sd
                    k=1
                    Exit For
                End If
                If diff[0]=45 Then  
                    divflag=1
                    digit=Str(d-1)
                    div=olddiv+digit
                    k=0
                    Exit For
                End If
            Next d
            div=plus(div,digit)
            olddiv=div
            num=cd(count-1+k)
            temp=temp+digit
            If decflag=0 Then
                cp1=cp1+pair
                If cp1=p1 Then
                    temp=temp+"."
                End If
            End If
            count=0
            k=1
            c=c+p
            p=2
        Loop Until c>=endrun
        Return temp
    End Function
    
    Dim As Double t=Timer
    Dim As String number=".000000000000000000000000000000123456789"'some positive number
    Dim As String sq= bigSQR(number,5000)
    Dim As Double t2=Timer
    Color 15
    Printf( sq+!"\n") 'incase you are using win 11 terminal
    Color 3
    Print t2-t,"seconds",Len(Mid(sq,1+Instr(sq,".")));" decimal places"
    Color 15
    Print "check original and sqr*sqr"
    Print number
    printf(Left(fmult(sq,sq),200)+"  . . ."+!"\n")
    Print
    
    'FROM HELPFILE FOR COMMAND
    Print "program launched via: " & Command(0)
    
    Dim As Long i = 1
    Do
        Dim As String arg = Command(i)
        If Len(arg) = 0 Then
            Exit Do
        End If
        
        Print "command line argument " & i & " = """ & arg & """"
        i += 1
    Loop
    
    If i = 1 Then
        Print "(no command line arguments)"
    End If
    Print "Done . . ."
    
    Sleep
    
    
     
Last edited by dodicat on Jul 07, 2025 8:22, edited 1 time in total.
RetardedAndProud
Posts: 42
Joined: Jun 09, 2024 18:26

Re: Big Sqare root by long division

Post by RetardedAndProud »

RE: Your code example,
Command line arguments work fine under Linux.


Sorry, I miss understood your problem until srvaldez posted.

Under GCC you can specify -frecord-gcc-switches to embedd the options.

Code: Select all

gcc -O2 -Wall <more options, blah blah> -frecord-gcc-switches file.c
readelf -p .GCC.command.line a.out
Last edited by RetardedAndProud on Jul 03, 2025 12:41, edited 1 time in total.
srvaldez
Posts: 3662
Joined: Sep 25, 2005 21:54

Re: Big Sqare root by long division

Post by srvaldez »

Hi dodicat :D
I don't think that you are going to get the FB compile command, only the command used to launch the compiled program, or am I completely missing the point?
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Big Sqare root by long division

Post by dodicat »

The example in __FB_ARGC__ doesn't show any arguments either, whether written in code or passed via commandline.
There probably is a way, maybe in win32 api, I'll investigate further.
The compile command is written to stdout, or stderr for gcc, so the arguments (options) are thereabouts somewhere.
Last edited by dodicat on Jul 03, 2025 14:15, edited 1 time in total.
SARG
Posts: 1892
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Big Sqare root by long division

Post by SARG »

I agree with srvaldez.
You can't get the parameters used for compilation when executing the resulting executable.
However using -v you can see them even if in code.

Using #cmdline "-v -gen gcc -Wc -O2" we get -O2 at the end of the compil line

Code: Select all

compiling C:  D:\compiler108\freebasic64bit\bin\win64\gcc.exe -m64 -march=x86-64 -S -nostdlib -nostdinc -Wall -Wno-unused -Wno-main -Werror-implicit-function-declaration -O0 -fno-strict-aliasing -fno-ident -frounding-math -fno-math-errno -fwrapv -fno-exceptions -fno-asynchronous-unwind-tables -funwind-tables -Wno-format -masm=intel "D:\compiler108\tests compiler\test.c" -o "D:\compiler108\tests compiler\test.asm" -O2
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Big Sqare root by long division

Post by dodicat »

Thanks SARG.
But what about the examples in command and __FB_ARGC__ in the help file, what are they all about?
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Big Sqare root by long division

Post by dodicat »

I think the arguments are not command line options, but passed arguments, like a drag and drop say.

Code: Select all

dim as string s=command(1)
 Sub displayCommandLineArguments( ByVal argc As Integer, ByVal argv As ZString Ptr Ptr )
    Dim i As Integer
    For i = 0 To argc - 1
        Print "arg "; i; " = '"; *argv[i]; "'"
    Next i
End Sub

displayCommandLineArguments( __FB_ARGC__, __FB_ARGV__ )
sleep 
compile this and drag a file into the ewxecutable.
SARG
Posts: 1892
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Big Sqare root by long division

Post by SARG »

I can't understand where is the problem.
Command line when compiling defines arguments for fbc.exe as for any other exes.
They are extracted and used by the compiler. In case of command line in code they are replaced by the new ones and compilation is restarted.
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Big Sqare root by long division

Post by dodicat »

There is no problem now.
commnd() or __FB_ARGC__, __FB_ARGV__ cannot pick up compiler switches, only arguments.
An example of picking up the switches:

Code: Select all

#include "file.bi"

Declare Function compile(compiler As String) As String 
Declare Function optionsstring(s As String) As String

Dim As String PathToCompiler="C:\Users\wlhut\Desktop\fb\fb10.1\FreeBASIC-1.10.1-winlibs-gcc-9.3.0\FreeBASIC-1.10.1-winlibs-gcc-9.3.0\fbc64.exe"
Dim As String pathtofile="C:\Users\wlhut\Desktop\fb\code\arctan.pp.bas"
Dim As String options="-w all -fpmode fast -fpu sse -gen gcc -Wc -Ofast"



Dim As String s= (compile(Chr(34,34)+PathToCompiler+Chr(34)+" "+options+Chr(32,34)+pathtofile+Chr(34,32,34)))

If Instr(s,"Fail")=0 Then
    Print optionsstring(s)
Else
    Print "Fail"
End If
Sleep


Function optionsstring(s As String) As String
    Dim As String g= Mid(s,Instr(s,"exe")+3,100)
    Dim As Long i=Instr(g,"\")
    Return Mid(g,2,i-5)
End Function

Function compile(compiler As String) As String 
    Dim As String File = "temporary_text.abc"
    Dim As Double t=Timer
    Var e = Shell(compiler+" "+" >>"+file+" 2>&1")
    t=Timer-t
    Var f=Freefile,txt="",L=0
    Open file For Binary As #f
    L=Lof(f)
    If L>0 Then 
        txt = String(L,0)
        Get #f, , txt
    End If
    Close #f
    txt=compiler+Chr(13,10)+txt
    txt=" "+txt
    If Instr(txt,"Invalid command-line option") Then e=1:txt+=" Invalid command-line option "+Chr(13,10)
    If Fileexists(File) Then Kill File
    If Len(L)=0 Then Return "Error"
    If e=0 Then txt+="compiled in " & t & " seconds" Else txt+=Chr(13,10)+"Fail!"
    Return txt
End Function
  
It is only academic really, I set the switches, I don't need reminded of what they were!
Anyway, thank you all for your patience.
dodicat
Posts: 8289
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Big Sqare root by long division

Post by dodicat »

Thanks srvaldez, I did CATch your contribution, only just.
Post Reply