Huge #'s

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Thanks for all ideas - I updated my VNF code so far and the next point will be a DIV and MOD routine (but I found no fast method for now)...

Changes:
- EQ-Check added
- GT-Check regards sign
- Mul (0,a) and Sub(a,b) removes leading 0s and correct sign, when result=0

Michael

:idea: everyone who like to optimize the code is welcome
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

:shock:
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Post by jack »

Michael Vogel, here's a document that may be of interest to you; Modern Computer Arithmetic, Richard Brent and Paul Zimmermann, version 0.1.1, November 2006, http://www.loria.fr/~zimmerma/mca/mca-0.1.1.pdf
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

jack wrote:Michael Vogel, here's a document that may be of interest to you; Modern Computer Arithmetic, Richard Brent and Paul Zimmermann, version 0.1.1, November 2006, http://www.loria.fr/~zimmerma/mca/mca-0.1.1.pdf
Hi Jack,
quite interesting document - thanks you!

Now I will try to use it to get a DIV function implemented, then I'll have all base functions for big integer numbers :)

Michael
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Huge #'s

Post by Little John »

Hallo Michael,

your code for calculating with big numbers is interesting. However, my first test of multiplication failed:

Code: Select all

zahl1$ = "-123"
zahl2$ = "456"

PutNumber(@zahl1$, num1)
PutNumber(@zahl2$, num2)

VNFMul(num1, num2, num3)

Debug Number(num3)
returns 56088, but should of course return -56088.

BTW: The procedure PutNumber() can be made a little simpler. Just don't pass the first parameter as pointer, but the normal way. Then you can do without a subsequent PeekS():

Code: Select all

Procedure PutNumber (t.s, *num.VNF)
   Protected n, p
;   Protected t.s

   *num\sign = 0

;   t = PeekS(@*s)
   n = Len(t) - #VNFLen
Regards, Little John
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Huge #'s

Post by Michael Vogel »

Hi,

I got -56088, so I'm not sure which version you were testing – here is the latest (I found on my notebook):

Code: Select all

; Version 0.5.0

; Define VNF - Vogels Number Format


    #VNFDim=10000; ~90000 Ciphers ;)

    Structure VNF
        len.w
        sign.w
        num.l[#VNFDim]
    EndStructure

    ; Signs
    #VNFNegative=1
    #VNFPositive=0

    ; Errortypes (len-field)
    #VNFUndefined=-1
    #VNFInfinitive=-2
    #VNFOverflow=-3
    #VNFNotImplemented=-4

    ; Dimensions
    #VNFLen=9
    #VNFMod=1000000000

    Declare.s Number(*num.VNF);                    String
    Declare GetNumber(*s.s,*num.VNF);            s <- num
    Declare PutNumber(*s.s,*num.VNF);            s -> num

    Declare VNFNormalize(*a.VNF);                    a = (a)
    Declare VNFError(type,stype,*a.VNF);          c    =    Err
    Declare VNFCopy(*a.VNF,*b.VNF);                b = a
    Declare VNFZero(*a.VNF);                            a = 0
    Declare VNFAbs(*a.VNF);                            a = |a|

    Declare VNFMuW(*a.VNF,b.l,*c.VNF);            c = a*b, |b|<10^10
    Declare VNFMul(*a.VNF,*b.VNF,*c.VNF);      c = a*b
    Declare VNFDiv(*a.VNF,*b.VNF,*c.VNF);      c = a/b
    Declare VNFDiW(*a.VNF,b.l,*c.VNF);            c = a/b, |b|<10^10
    Declare VNFAdd(*a.VNF,*b.VNF,*c.VNF);      c = a+b
    Declare VNFSub(*a.VNF,*b.VNF,*c.VNF);      c = a-b
    Declare VNFSqr(*a.VNF);                              a = a*a
    Declare VNFPow(*a.VNF,b.l,*c.VNF);            c = a^b

    Declare.l VNFGt(*a.VNF,*b.VNF,abs=0);       a>b? or |a|>|b|?
    Declare.l VNFEq(*a.VNF,*b.VNF,abs=0);       a=b? or |a|=|b|?
    Declare.l VNFPositive(*a.VNF);                       a>=0?

    Global VNF_Cache_A.VNF
    Global VNF_Cache_B.VNF
    Global VNF_Cache_C.VNF

; EndDefine

Procedure.s Number(*num.VNF)

    Protected n
    Protected t.s

    If *num\len<0

        Select *num\len
        Case #VNFUndefined
            t="Undefined"
        Case #VNFInfinitive
            t="Infinitive"
            If *num\sign
                t="Minus "+t
            EndIf
        Case #VNFOverflow
            t="Overflow"
        Case #VNFNotImplemented
            t="Not Implemented"
        EndSelect

    Else

        If *num\sign
            t="-"
        EndIf

        n=*num\len
        t+Str(*num\num[n])

        While n>0
            n-1
            t+RSet(Str(*num\num[n]),#VNFLen,"0")
        Wend

    EndIf

    ProcedureReturn t

EndProcedure
Procedure GetNumber(*s.String,*num.VNF)

    ; ACHTUNG! s ist bei dieser Routine vom Typ String!
    ; (bei x.string bedeutet dies den Aufruf "GetNumber(x,number)" und die Ausgabe "Debug x\s")

    Protected n
    Protected t.s

    If *num\sign
        t="-"
    EndIf

    n=*num\len
    t+Str(*num\num[n])

    While n>0
        n-1
        t+RSet(Str(*num\num[n]),#VNFLen,"0")
    Wend

    *s\s=t

EndProcedure
Procedure PutNumber(*s.s,*num.VNF)

    Protected n,p
    Protected t.s

    *num\sign=#VNFPositive

    t=PeekS(@*s)
    n=Len(t)-#VNFLen

    While n>0
        *num\num[p]=Val(PeekS(@t+n,#VNFLen))
        p+1
        n-#VNFLen
    Wend

    n=Val(PeekS(@t,9+n))
    If n<0
        *num\sign=#VNFNegative
        n=-n
    EndIf

    *num\num[p]=n

    *num\len=p

EndProcedure

Procedure VNFNormalize(*a.VNF)
    ; Strap leading zeros (000.000.000)
    If *a\len>=0
        While (*a\len>=0) And (*a\num[*a\len]=0)
            *a\len-1
        Wend
        ; Value equal Zero? Positiv sign
        If *a\len<0
            *a\len=0
            *a\sign=#VNFPositive
        EndIf
    EndIf
EndProcedure
Procedure VNFError(type,stype,*a.VNF)

    If type>=0
        type=stype
    EndIf

    Debug "ERROR "+Str(type)
    *a\len=type

EndProcedure
Procedure VNFCopy(*a.VNF,*b.VNF)
    Protected n

    n=*a\len
    *b\len=n
    *b\sign=*a\sign

    While n>=0
        *b\num[n]=*a\num[n]
        n-1
    Wend

EndProcedure
Procedure VNFZero(*a.VNF)
    *a\len=0
    *a\sign=#VNFPositive
    *a\num[0]=0
EndProcedure
Procedure VNFAbs(*a.VNF)
    *a\sign=#VNFPositive
EndProcedure

Procedure.l VNFEq(*a.VNF,*b.VNF,abs=0)

    Protected n,d

    If n<>*b\len
        ProcedureReturn #False
    ElseIf (abs=0) And (*a\sign<>*b\sign)
        ProcedureReturn #False
    Else
        While n>=0
            If *a\num[n]<>*b\num[n]
                ProcedureReturn #False
            EndIf
            n-1
        Wend
        ProcedureReturn #True;    a=b
    EndIf

EndProcedure
Procedure.l VNFGt(*a.VNF,*b.VNF,abs=0)

    Protected n,d

    If abs=0

        If *a\sign<>*b\sign
            If *a\sign=#VNFPositive
                ProcedureReturn #True
            Else
                ProcedureReturn #False
            EndIf
        EndIf

    Else

        n=*a\len
        If n>*b\len
            ProcedureReturn #True
        ElseIf n<*b\len
            ProcedureReturn #False
        Else
            While n>=0
                d=*a\num[n]-*b\num[n]
                If d>0
                    ProcedureReturn #True
                ElseIf d<0
                    ProcedureReturn #False
                EndIf
                n-1
            Wend
            ProcedureReturn #False;    a=b
        EndIf

    EndIf

EndProcedure
Procedure.l VNFPositive(*a.VNF)

    If *a\sign=#VNFPositive
        ProcedureReturn #True
    Else
        ProcedureReturn #False
    EndIf

EndProcedure

Procedure VNFMuW(*a.VNF,b.l,*c.VNF)

    Protected n
    Protected m.q

    n=*a\len

    If n<0
        VNFError(n,0,*c.VNF)
    Else

        If b=0
            *c\len=0
            *c\sign=#VNFPositive
            *c\num[0]=0
        Else

            If b<0
                b=-b
                *c\sign=#VNFNegative-*a\sign
            Else
                *c\sign=*a\sign
            EndIf

            n=0
            Repeat
                m+*a\num[n] * b
                *c\num[n]=m%#VNFMod
                m/#VNFMod

                n+1
            Until n>*a\len

            If m
                *c\num[n]=m
            Else
                n-1
            EndIf
            *c\len=n

        EndIf
    EndIf

EndProcedure
Procedure VNFMul(*a.VNF,*b.VNF,*c.VNF)

    Protected la
    Protected lb
    Protected n

    Protected s.q
    Protected z.q

    If (*a\len<0) Or (*b\len<0)
        VNFError(*a\len,*b\len,*c.VNF)
    Else
        *c\sign=(*a\sign + *b\sign)&1;    because #VNFNegative=1
        *c\len=*a\len+*b\len+1
        For n=0 To *c\len
            *c\num[n]=0
        Next n

        la=0
        Repeat
            lb=0
            z=*b\num[lb]
            Repeat
                s=*a\num[la] * *b\num[lb] + *c\num[la+lb]
                ;Debug Str(*a\num[la])+" * "+Str(*b\num[lb])+" + "+Str(*c\num[la+lb+1])
                ;Debug " = "+StrQ(s)+"  -> "+Str(s/#VNFMod)+" | "+Str(s%#VNFMod)
                *c\num[la+lb]=s%#VNFMod
                *c\num[la+lb+1]+s/#VNFMod
                lb+1
            Until lb>*b\len
            la+1
        Until la>*a\len

        VNFNormalize(*c)

    EndIf
EndProcedure
Procedure VNFDiW(*a.VNF,b.l,*c.VNF)

    Protected n
    Protected d.q,q.q

    n=*a\len

    If n<0
        VNFError(n,0,*c.VNF)
    Else

        If b=0
            *c\len=#VNFUndefined
        Else

            If b<0
                b=-b
                *c\sign=#VNFNegative-*a\sign
            Else
                *c\sign=*a\sign
            EndIf

            Repeat
                d=d*#VNFMod+*a\num[n]
                q=d/b
                *c\num[n]=q
                d-q*b
                n-1
            Until n<0

            VNFNormalize(*c)

        EndIf
    EndIf

EndProcedure
Procedure VNFDiv(*a.VNF,*b.VNF,*c.VNF)

    Protected n

    If (*a\len<0) Or (*b\len<0)
        VNFError(*a\len,*b\len,*c.VNF)
    Else

        n=*b\len
        If n=0
            If *b\num[0]=0
                *c\len=#VNFUndefined
            Else
                ;Debug "diw"
                VNFDiW(*a.VNF,*b\num[0],*c.VNF)
                *c\sign=-(1&(*a\sign+*b\sign))
            EndIf

        Else

            If VNFGt(*b,*a,#True)
                VNFZero(*c)
            Else

                ; Hmmm...

            EndIf
        EndIf
    EndIf

EndProcedure
Procedure VNFAdd(*a.VNF,*b.VNF,*c.VNF)

    Protected n
    Protected s

    If (*a\len<0) Or (*b\len<0)
        VNFError(*a\len,*b\len,*c.VNF)
    Else

        If *a\sign<>*b\sign
            ;Debug "sub"
            *b\sign=*a\sign
            VNFSub(*a.VNF,*b.VNF,*c.VNF)
        Else

            *c\sign=*a\sign

            If *a\len<*b\len
                Swap *a,*b
            EndIf

            While n<=*a\len
                s+*a\num[n]
                If n<=*b\len
                    s+*b\num[n]
                EndIf
                *c\num[n]=s%#VNFMod
                s/#VNFMod
                n+1
            Wend
            If s
                *c\num[n]=s
            Else
                n-1
            EndIf

            *c\len=n
        EndIf

    EndIf
EndProcedure
Procedure VNFSub(*a.VNF,*b.VNF,*c.VNF)

    Protected n
    Protected s

    If (*a\len<0) Or (*b\len<0)
        VNFError(*a\len,*b\len,*c.VNF)
    Else

        If *a\sign<>*b\sign
            ;Debug "add"
            *b\sign=*a\sign
            VNFAdd(*a.VNF,*b.VNF,*c.VNF)
        Else

            If VNFGt(*a.VNF,*b.VNF,#True)
                *c\sign=*a\sign
            Else
                ;Debug "swp"
                Swap *a,*b
                *c\sign=#VNFNegative-*a\sign
            EndIf


            While n<=*a\len
                s+*a\num[n]
                If n<=*b\len
                    s-*b\num[n]
                EndIf
                If s<0
                    *c\num[n]=s+#VNFMod
                    s=-1
                Else
                    *c\num[n]=s
                    s=0
                EndIf
                n+1
            Wend

            *c\len=n-1

            VNFNormalize(*c)

        EndIf
    EndIf

EndProcedure
Procedure VNFSqr(*a.VNF)
    If *a\len>=0
        VNFMul(*a,*a,VNF_Cache_C)
        VNFCopy(VNF_Cache_C,*a)
    EndIf
EndProcedure
Procedure VNFPow(*a.VNF,b.l,*c.VNF)

    Protected z=0,s,sign

    If b<0

        ; a^b | b<0 not implemented for now...
        VNFError(#VNFNotImplemented,0,*c.VNF)

    ElseIf *a\len>=0

        VNFCopy(*a,VNF_Cache_A)
        PutNumber(@"1",VNF_Cache_B)

        If VNFPositive(*a)=#False
            VNFAbs(VNF_Cache_A)
            If b&1 : VNF_Cache_B\Sign=#VNFNegative : EndIf
        EndIf

        While b>0
            s=1<<z
            If b&s
                VNFMul(VNF_Cache_A,VNF_Cache_B,VNF_Cache_C)
                VNFCopy(VNF_Cache_C,VNF_Cache_B)
                b-s
            EndIf

            If b
                VNFSqr(VNF_Cache_A)
                z+1
            EndIf

        Wend

        VNFCopy(VNF_Cache_B,*c)

    EndIf
EndProcedure

x.VNF
y.VNF
z.VNF

;DisableDebugger
time=-GetTickCount_()

Select 44

Case 44
    zahl1$ = "-123"
    zahl2$ = "456"

    PutNumber(@zahl1$, x)
    PutNumber(@zahl2$, y)

    VNFMul(x,y,z)

    Debug Number(z)

EndSelect

time+GetTickCount_()

EnableDebugger
Debug ""
Debug "Calculation time was "+Str(time)+" ms"

Every optimizations (and enhancements) are welcome :wink:

Michael
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Huge #'s

Post by Little John »

Michael Vogel wrote:I got -56088, so I'm not sure which version you were testing
I tested the version, that you see after clicking at the link that I provided in my post. ;-)
Michael Vogel wrote:– here is the latest (I found on my notebook):
With this version, I get -56088, too. Thanks!

Regards, Little John
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Huge #'s

Post by Guimauve »

Hello everyone,

Sorry to re-open a two years old topic but I have little bit modified the Micheal Vogel original code so I return it back to community.
By the way, apparently the conversion from string to VogelNumberFormat work only if the program is compiled in Ascii mode. I get strange result with Unicode program.

Edit #1 : PeekS() replaced by equivalent Mid() inside String_To_VogelsNumberFormat(), now the command the command work well whatever if the program is Ascii or Unicode
Edit #2 : Read/WritePreference command added + Random modification for stripping leading 0 manually

Best regards
Guimauve

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V4.0.0
; Project name : Vogels Number Format
; File name : Vogels Number Format.pb
; File Version : 1.0.2
; Programmation : OK
; Programmed by : Guimauve
; Creation Date : 06-07-2012
; Last update : 01-11-2012
; Coded for : PureBasic 5.00 Beta 8
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Programming notes
;
; This code is a re-work of Vogels Number Format orginally 
; created by Michel Vogel (PureBasic English Forum).
;
; List of changes :
;
; - VNF structure name : Renamed to "VogelsNumberFormat"
; - Number() ---> Removed : Use VogelsNumberFormat_To_String() instead
; - GetNumber() ---> Removed : Use VogelsNumberFormat_To_String() instead
; - PutNumber() ---> Removed : Use String_To_VogelsNumberFormat() instead
; 
; Commands added :
; 
; - VogelsNumberFormat_To_String()
; - String_To_VogelsNumberFormat()
; - ReadVogelsNumberFormat()
; - WriteVogelsNumberFormat()
; - VogelsNumberFormat_Factorial() --> Work upto 999!
; - VogelsNumberFormat_Random()
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Size Array Constants <<<<<

#VOGELS_NUMBER_FORMAT_NUM_MAX = 100000

#VOGELS_NUMBER_FORMAT_NEGATIVE = 1
#VOGELS_NUMBER_FORMAT_POSITIVE = 0
#VOGELS_NUMBER_FORMAT_UNDEFINED = -1
#VOGELS_NUMBER_FORMAT_INFINITIVE = -2
#VOGELS_NUMBER_FORMAT_OVERFLOW = -3
#VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED = -4
#VOGELS_NUMBER_FORMAT_LEN = 9
#VOGELS_NUMBER_FORMAT_MOD = 1000000000

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<

Structure VogelsNumberFormat

  Len.w
  Sign.w
  Num.l[#VOGELS_NUMBER_FORMAT_NUM_MAX]

EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<

Macro GetVogelsNumberFormatLen(VogelsNumberFormatA)
  
  VogelsNumberFormatA\Len
  
EndMacro

Macro GetVogelsNumberFormatSign(VogelsNumberFormatA)
  
  VogelsNumberFormatA\Sign
  
EndMacro

Macro GetVogelsNumberFormatNum(VogelsNumberFormatA, NumID)
  
  VogelsNumberFormatA\Num[NumID]
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<

Macro SetVogelsNumberFormatLen(VogelsNumberFormatA, P_Len)
  
  GetVogelsNumberFormatLen(VogelsNumberFormatA) = P_Len
  
EndMacro

Macro SetVogelsNumberFormatSign(VogelsNumberFormatA, P_Sign)
  
  GetVogelsNumberFormatSign(VogelsNumberFormatA) = P_Sign
  
EndMacro

Macro SetVogelsNumberFormatNum(VogelsNumberFormatA, NumID, P_Num)
  
  GetVogelsNumberFormatNum(VogelsNumberFormatA, NumID) = P_Num
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<

Macro ResetVogelsNumberFormat(VogelsNumberFormatA)
 
  ClearStructure(VogelsNumberFormatA, VogelsNumberFormat)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read in Binary file <<<<<

Procedure ReadVogelsNumberFormat(FileID.l, *VogelsNumberFormatA.VogelsNumberFormat)
 
  SetVogelsNumberFormatLen(*VogelsNumberFormatA, ReadWord(FileID))
  SetVogelsNumberFormatSign(*VogelsNumberFormatA, ReadWord(FileID))
 
  For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
    SetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID, ReadLong(FileID))
  Next
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Write in Binary file <<<<<

Procedure WriteVogelsNumberFormat(FileID.l, *VogelsNumberFormatA.VogelsNumberFormat)
 
  WriteWord(FileID, GetVogelsNumberFormatLen(*VogelsNumberFormatA))
  WriteWord(FileID, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
 
  For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
    WriteLong(FileID, GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
  Next
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.005 seconds (25600.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Declare VogelsNumberFormat_Add(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
Declare VogelsNumberFormat_Sub(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)

Procedure.s VogelsNumberFormat_To_String(*VogelsNumberFormatA.VogelsNumberFormat)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
    
    Select GetVogelsNumberFormatLen(*VogelsNumberFormatA)
        
      Case #VOGELS_NUMBER_FORMAT_UNDEFINED
        VFN_2_String.s = "Undefined"
        
      Case #VOGELS_NUMBER_FORMAT_INFINITIVE
        VFN_2_String = "Infinitive"
        If GetVogelsNumberFormatSign(*VogelsNumberFormatA)
          VFN_2_String = "Minus " + VFN_2_String
        EndIf
        
      Case #VOGELS_NUMBER_FORMAT_OVERFLOW
        VFN_2_String = "Overflow"
        
      Case #VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED
        VFN_2_String = "Not Implemented"
        
    EndSelect
    
  Else
    
    If GetVogelsNumberFormatSign(*VogelsNumberFormatA)
      VFN_2_String = "-"
    EndIf
    
    NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA)
    VFN_2_String + Str(GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
    
    While NumID > 0
      NumID - 1
      VFN_2_String + RSet(Str(GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)), #VOGELS_NUMBER_FORMAT_LEN, "0")
    Wend
    
  EndIf
  
  ProcedureReturn VFN_2_String
EndProcedure

Procedure String_To_VogelsNumberFormat(*VogelsNumberFormatA.VogelsNumberFormat, String.s)
  
  SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
  
  NumID = Len(String) - #VOGELS_NUMBER_FORMAT_LEN
  
  While NumID > 0
    SetVogelsNumberFormatNum(*VogelsNumberFormatA, p, Val(Mid(String, NumID+1, #VOGELS_NUMBER_FORMAT_LEN)))
    p + 1
    NumID - #VOGELS_NUMBER_FORMAT_LEN
    
  Wend
  
  NumID = Val(Mid(String, 1, 9 + NumID))
  
  If NumID < 0
    SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_NEGATIVE)
    NumID = -NumID
  EndIf
  
  SetVogelsNumberFormatNum(*VogelsNumberFormatA, p, NumID)
  SetVogelsNumberFormatLen(*VogelsNumberFormatA, p)
  
EndProcedure

Procedure VogelsNumberFormat_Normalize(*VogelsNumberFormatA.VogelsNumberFormat)
  
  ; Strap leading zeros (000.000.000)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
    
    While (GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0) And (GetVogelsNumberFormatNum(*VogelsNumberFormatA, GetVogelsNumberFormatLen(*VogelsNumberFormatA)) = 0)
      SetVogelsNumberFormatLen(*VogelsNumberFormatA, GetVogelsNumberFormatLen(*VogelsNumberFormatA) - 1)
    Wend
    
    ; Value equal Zero? Positiv sign
    
    If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
      SetVogelsNumberFormatLen(*VogelsNumberFormatA, 0)
      SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
    EndIf
    
  EndIf
  
EndProcedure

Procedure VogelsNumberFormat_Error(type, stype, *VogelsNumberFormatA.VogelsNumberFormat)
  
  If type >= 0
    type = stype
  EndIf
  
  SetVogelsNumberFormatLen(*VogelsNumberFormatA, type)
  Debug "ERROR " + Str(type)
  
  ProcedureReturn Type
EndProcedure

Procedure VogelsNumberFormat_Copy(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat)
  
  SetVogelsNumberFormatLen(*VogelsNumberFormatB, GetVogelsNumberFormatLen(*VogelsNumberFormatA))
  SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
  
  For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
    SetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID, GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
  Next
  
EndProcedure

Procedure VogelsNumberFormat_Zero(*VogelsNumberFormatA.VogelsNumberFormat)
  
  SetVogelsNumberFormatLen(*VogelsNumberFormatA, 0)
  SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
  
  For NumID = 0 To #VOGELS_NUMBER_FORMAT_NUM_MAX - 1
    SetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID, 0)
  Next
  
EndProcedure

Procedure VogelsNumberFormat_Abs(*VogelsNumberFormatA.VogelsNumberFormat)
  
  SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
  
EndProcedure

Procedure VogelsNumberFormat_Equal(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, Abs = 0)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) <> GetVogelsNumberFormatLen(*VogelsNumberFormatB)
    
    ProcedureReturn #False
    
  ElseIf (Abs = 0) And (GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB))
    
    ProcedureReturn #False
    
  Else
    
    For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
      If GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) <> GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
        ProcedureReturn #False
      EndIf
      
    Next
    
    ProcedureReturn #True
    
  EndIf
  
EndProcedure

Procedure VogelsNumberFormat_GreaterThan(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, Abs = 0)
  
  If Abs = 0
    
    If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
      If GetVogelsNumberFormatSign(*VogelsNumberFormatA) = #VOGELS_NUMBER_FORMAT_POSITIVE
        ProcedureReturn #True
      Else
        ProcedureReturn #False
      EndIf
    EndIf
    
  Else
    
    If GetVogelsNumberFormatLen(*VogelsNumberFormatA) > GetVogelsNumberFormatLen(*VogelsNumberFormatB) 
      
      ProcedureReturn #True
      
    ElseIf GetVogelsNumberFormatLen(*VogelsNumberFormatA) < GetVogelsNumberFormatLen(*VogelsNumberFormatB) 
      
      ProcedureReturn #False
      
    Else
      
      
      For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
        
        d = GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) - GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
        
        If d > 0
          ProcedureReturn #True
        ElseIf d < 0
          ProcedureReturn #False
        EndIf
        
      Next 
      
      ProcedureReturn #False;    a=b
      
    EndIf
    
  EndIf
  
EndProcedure

Procedure VogelsNumberFormat_Positive(*VogelsNumberFormatA.VogelsNumberFormat)
  
  If GetVogelsNumberFormatSign(*VogelsNumberFormatA) = #VOGELS_NUMBER_FORMAT_POSITIVE
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

Procedure VogelsNumberFormat_Mul(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
  
  Protected la, lb
  Protected s.q, z.q
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
  Else
    
    SetVogelsNumberFormatSign(*VogelsNumberFormatC, (GetVogelsNumberFormatSign(*VogelsNumberFormatA) + GetVogelsNumberFormatSign(*VogelsNumberFormatB)) & 1)
    SetVogelsNumberFormatLen(*VogelsNumberFormatC, GetVogelsNumberFormatLen(*VogelsNumberFormatA) + GetVogelsNumberFormatLen(*VogelsNumberFormatB) + 1)
    
    For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatC)
      SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, 0)
    Next 
    
    la = 0
    
    Repeat
      
      lb = 0
      
      Repeat
        
        s.q = GetVogelsNumberFormatNum(*VogelsNumberFormatA, la) * GetVogelsNumberFormatNum(*VogelsNumberFormatB, lb) + GetVogelsNumberFormatNum(*VogelsNumberFormatC, la+lb)
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb, s % #VOGELS_NUMBER_FORMAT_MOD)
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb + 1, GetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb + 1) + s / #VOGELS_NUMBER_FORMAT_MOD)
        lb + 1
        
      Until lb > GetVogelsNumberFormatLen(*VogelsNumberFormatB)
      
      la + 1
      
    Until la > GetVogelsNumberFormatLen(*VogelsNumberFormatA)
    
    VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure Private_VogelsNumberFormat_MuW(*VogelsNumberFormatA.VogelsNumberFormat, b.l, *VogelsNumberFormatC.VogelsNumberFormat)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), 0, *VogelsNumberFormatC)
  Else
    
    If b = 0
      VogelsNumberFormat_Zero(*VogelsNumberFormatC)
    Else
      
      If b < 0
        b = -b
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      Else
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      EndIf
      
      NumID = 0
      
      For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
        m.q + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) * b
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, m % #VOGELS_NUMBER_FORMAT_MOD)
        m / #VOGELS_NUMBER_FORMAT_MOD
      Next
      
      If m
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, m)
      Else
        NumID - 1
      EndIf
      
      SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
      
    EndIf
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure Private_VogelsNumberFormat_DiW(*VogelsNumberFormatA.VogelsNumberFormat, b.l, *VogelsNumberFormatC.VogelsNumberFormat)
  
  Protected NumID
  Protected d.q, q.q
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), 0, *VogelsNumberFormatC)
  Else
    
    If b = 0
      SetVogelsNumberFormatLen(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_UNDEFINED)
    Else
      
      If b < 0
        b = -b
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      Else
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      EndIf
      
      For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
        
        d = d * #VOGELS_NUMBER_FORMAT_MOD + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
        q = d / b
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, q)
        d - q * b
        
      Next
      
      VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
      
    EndIf
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Div(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
  Else

    If GetVogelsNumberFormatLen(*VogelsNumberFormatB) = 0
      If GetVogelsNumberFormatNum(*VogelsNumberFormatB, 0) = 0
        SetVogelsNumberFormatLen(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_UNDEFINED)
      Else
        Private_VogelsNumberFormat_DiW(*VogelsNumberFormatA, GetVogelsNumberFormatNum(*VogelsNumberFormatB, 0), *VogelsNumberFormatC)
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, -(1 & (GetVogelsNumberFormatSign(*VogelsNumberFormatA) + GetVogelsNumberFormatSign(*VogelsNumberFormatB))))
      EndIf
      
    Else

      If VogelsNumberFormat_GreaterThan(*VogelsNumberFormatB, *VogelsNumberFormatA, #True)
        VogelsNumberFormat_Zero(*VogelsNumberFormatC)
      Else

        ; Hmmm...
        
      EndIf
      
    EndIf
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Add(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
  
  Protected n
  Protected s
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
  Else
    
    If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
      SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      VogelsNumberFormat_Sub(*VogelsNumberFormatA, *VogelsNumberFormatB, *VogelsNumberFormatC)
    Else
      
      SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      
      If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < GetVogelsNumberFormatLen(*VogelsNumberFormatB)
        Swap *VogelsNumberFormatA, *VogelsNumberFormatB
      EndIf
      
      For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
        
        s + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
        
        If NumID <= GetVogelsNumberFormatLen(*VogelsNumberFormatB)
          s + GetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID)
        EndIf
        
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s % #VOGELS_NUMBER_FORMAT_MOD)
        s / #VOGELS_NUMBER_FORMAT_MOD
        
      Next
      
      NumID + 1
      
      If s
        SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s)
      Else
        NumID - 1
      EndIf
      
      SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
      VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
      
    EndIf
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Sub(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
  
  Protected n
  Protected s
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
    Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
  Else
    
    If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
      
      SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      VogelsNumberFormat_Add(*VogelsNumberFormatA, *VogelsNumberFormatB, *VogelsNumberFormatC)
    Else
      
      If VogelsNumberFormat_GreaterThan(*VogelsNumberFormatA, *VogelsNumberFormatB, #True)
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      Else
        Swap *VogelsNumberFormatA, *VogelsNumberFormatB
        SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
      EndIf
      
      For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
        
        s + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
        
        If NumID <= GetVogelsNumberFormatLen(*VogelsNumberFormatB)
          s - GetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID)
        EndIf
        
        
        If s < 0
          SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s + #VOGELS_NUMBER_FORMAT_MOD)
          s = -1
        Else
          SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s)
          s = 0
        EndIf
        
      Next
      
      SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
      VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
      
    EndIf
    
  EndIf
  
  ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Square(*VogelsNumberFormatA.VogelsNumberFormat)
  
  If GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
    Error = VogelsNumberFormat_Mul(*VogelsNumberFormatA, *VogelsNumberFormatA, VNF_Cache_C.VogelsNumberFormat)
    VogelsNumberFormat_Copy(VNF_Cache_C, *VogelsNumberFormatA)
    ResetVogelsNumberFormat(VNF_Cache_C)
  EndIf  
  
  ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Pow(*VogelsNumberFormatA.VogelsNumberFormat, Exponent.l, *VogelsNumberFormatC.VogelsNumberFormat)
  
  Protected z = 0, s, sign
  
  If Exponent < 0
    
    ; a^b | b<0 not implemented for now...
    VogelsNumberFormat_Error(#VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED, 0, *VogelsNumberFormatC)
    
  ElseIf GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
    
    VogelsNumberFormat_Copy(*VogelsNumberFormatA, VNF_Cache_A.VogelsNumberFormat)
    String_To_VogelsNumberFormat(VNF_Cache_B.VogelsNumberFormat, "1")
    
    If VogelsNumberFormat_Positive(*VogelsNumberFormatA) = #False
      VogelsNumberFormat_Abs(VNF_Cache_A)
      If Exponent & 1 
        SetVogelsNumberFormatSign(VNF_Cache_B, #VOGELS_NUMBER_FORMAT_NEGATIVE)
      EndIf
    EndIf
    
    While Exponent > 0
      
      s = 1 << z
      
      If Exponent & s
        VogelsNumberFormat_Mul(VNF_Cache_A, VNF_Cache_B, VNF_Cache_C.VogelsNumberFormat)
        VogelsNumberFormat_Copy(VNF_Cache_C, VNF_Cache_B)
        Exponent = Exponent - s
      EndIf
      
      If Exponent
        VogelsNumberFormat_Square(VNF_Cache_A)
        z = z + 1
      EndIf
      
    Wend
    
    VogelsNumberFormat_Copy(VNF_Cache_B, *VogelsNumberFormatC)
    
  EndIf
  
  ResetVogelsNumberFormat(VNF_Cache_A)
  ResetVogelsNumberFormat(VNF_Cache_B)
  ResetVogelsNumberFormat(VNF_Cache_C)
  
EndProcedure

Procedure VogelsNumberFormat_Factorial(Value.l, *VogelsNumberFormatC.VogelsNumberFormat)
  
  String_To_VogelsNumberFormat(VNF_Cache_B.VogelsNumberFormat, "1")
  
  For Index = 2 To Value
    String_To_VogelsNumberFormat(VNF_Cache_C.VogelsNumberFormat, Str(Index))
    VogelsNumberFormat_Mul(VNF_Cache_B, VNF_Cache_C, VNF_Cache_R.VogelsNumberFormat)
    VogelsNumberFormat_Copy(VNF_Cache_R, VNF_Cache_B)
  Next
  
  VogelsNumberFormat_Copy(VNF_Cache_B, *VogelsNumberFormatC)
  
  ResetVogelsNumberFormat(VNF_Cache_B)
  ResetVogelsNumberFormat(VNF_Cache_C)
  ResetVogelsNumberFormat(VNF_Cache_R)
  
EndProcedure
Procedure VogelsNumberFormat_Random(*VogelsNumberFormatA.VogelsNumberFormat, MaximumDigitCount.l)
  
  Max = Random(MaximumDigitCount)
  
  For Index = 1 To Max
    RandomNumber.s = RandomNumber + Str(Random(9))
  Next
  
  If Left(RandomNumber, 1)  = "0"
    RandomNumber = Right(RandomNumber, Len(RandomNumber) - 1)
  EndIf
  
  String_To_VogelsNumberFormat(*VogelsNumberFormatA, RandomNumber)

EndProcedure

Procedure ReadPreferenceVogelsNumberFormat(GroupName.s, *VogelsNumberFormatA.VogelsNumberFormat)
   
  String_To_VogelsNumberFormat(*VogelsNumberFormatA, ReadPreferenceString(GroupName, VogelsNumberFormat_To_String(*VogelsNumberFormatA)))
  
EndProcedure

Procedure WritePreferenceVogelsNumberFormat(GroupName.s, *VogelsNumberFormatA.VogelsNumberFormat)
  
  WritePreferenceString(GroupName, VogelsNumberFormat_To_String(*VogelsNumberFormatA))
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<< 
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<< 
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<< 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

Procedure.s FormatInteger(Number.s)
  
  ; Format Integer created by Gnozal
  
  NumberLen = Len(Number)
  Start = NumberLen % 3
  FormatedNumber.s = Left(Number, Start)
  
  For i = Start + 1 To NumberLen - Start Step 3
    FormatedNumber + " " + Mid(Number, i, 3)
  Next
  
  ProcedureReturn LTrim(FormatedNumber)
EndProcedure

Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(MyNumber.VogelsNumberFormat, "00000000000000000000123456789987654321123456789987654321")
Debug VogelsNumberFormat_To_String(MyNumber)
VogelsNumberFormat_Normalize(MyNumber)
Debug VogelsNumberFormat_To_String(MyNumber)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(X.VogelsNumberFormat, "23456")
String_To_VogelsNumberFormat(Y.VogelsNumberFormat, "98765")
VogelsNumberFormat_Add(X, Y, Z.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Z)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(Number1.VogelsNumberFormat, "12345678999999994012121212155454789921999")
String_To_VogelsNumberFormat(Number2.VogelsNumberFormat, "15906045674")
VogelsNumberFormat_Mul(Number1, Number2, Number3.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Number1) + " * " + VogelsNumberFormat_To_String(Number2) + " = " + VogelsNumberFormat_To_String(Number3)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(Number.VogelsNumberFormat, "100")
VogelsNumberFormat_Pow(Number, 100, Result.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Result)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

For Factorial = 50 To 100
  VogelsNumberFormat_Factorial(Factorial, TestFactorial.VogelsNumberFormat)
  Debug Str(Factorial) + "! = " + FormatInteger(VogelsNumberFormat_To_String(TestFactorial))
Next

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

For RandomID = 0 To 5
  VogelsNumberFormat_Random(TestRandom.VogelsNumberFormat, 25)
  Debug FormatInteger(VogelsNumberFormat_To_String(TestRandom))
Next

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Dear Optimist, Pessimist,
and Realist,

While you guys were
busy arguing about the
glass of water, I DRANK IT !

Sincerely,
the Opportunist
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Re: Huge #'s

Post by jack »

hello Guimauve
I get a stack overflow at line 769 (Windows 7-32 PB 5 b8), but works OK on my Mac PB x64
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Huge #'s

Post by Guimauve »

jack wrote:hello Guimauve
I get a stack overflow at line 769 (Windows 7-32 PB 5 b8), but works OK on my Mac PB x64
Just be sure, it's on the "VogelsNumberFormat_Pow(Number, 100, Result.VogelsNumberFormat)" you get this error ?
If so can you try this code and tell if the same error happen ?

Best regards
Guimauve

Code: Select all

; Version 0.5.0

; Define VNF - Vogels Number Format

#VNFDim = 10000; ~90000 Ciphers ;)

Structure VNF
  len.w
  sign.w
  num.l[#VNFDim]
EndStructure

; Signs
#VNFNegative=1
#VNFPositive=0

; Errortypes (len-field)
#VNFUndefined=-1
#VNFInfinitive=-2
#VNFOverflow=-3
#VNFNotImplemented=-4

; Dimensions
#VNFLen=9
#VNFMod=1000000000

Declare.s Number(*num.VNF)          ; String
Declare GetNumber(*s.s,*num.VNF)    ; s <- num
Declare PutNumber(s.s,*num.VNF)     ; s -> num

Declare VNFNormalize(*a.VNF)        ; a = (a)
Declare VNFError(type,stype,*a.VNF) ; c = Err
Declare VNFCopy(*a.VNF,*b.VNF)      ; b = a
Declare VNFZero(*a.VNF)             ; a = 0
Declare VNFAbs(*a.VNF)              ; a = |a|

Declare VNFMuW(*a.VNF,b.l,*c.VNF)   ; c = a*b, |b|<10^10
Declare VNFMul(*a.VNF,*b.VNF,*c.VNF); c = a*b
Declare VNFDiv(*a.VNF,*b.VNF,*c.VNF); c = a/b
Declare VNFDiW(*a.VNF,b.l,*c.VNF)   ; c = a/b, |b|<10^10
Declare VNFAdd(*a.VNF,*b.VNF,*c.VNF); c = a+b
Declare VNFSub(*a.VNF,*b.VNF,*c.VNF); c = a-b
Declare VNFSqr(*a.VNF)              ; a = a*a
Declare VNFPow(*a.VNF,b.l,*c.VNF)   ; c = a^b

Declare.l VNFGt(*a.VNF,*b.VNF,abs=0); a > b? or |a| > |b|?
Declare.l VNFEq(*a.VNF,*b.VNF,abs=0); a = b? or |a| = |b|?
Declare.l VNFPositive(*a.VNF)       ; a >= 0?

; EndDefine

Procedure.s Number(*num.VNF)
  
  Protected n
  Protected t.s
  
  If *num\len<0
    
    Select *num\len
        
      Case #VNFUndefined
        t="Undefined"
        
      Case #VNFInfinitive
        t="Infinitive"
        If *num\sign
          t="Minus "+t
        EndIf
        
      Case #VNFOverflow
        t="Overflow"
        
      Case #VNFNotImplemented
        t="Not Implemented"
        
    EndSelect
    
  Else
    
    If *num\sign
      t="-"
    EndIf
    
    n=*num\len
    t+Str(*num\num[n])
    
    While n>0
      n-1
      t+RSet(Str(*num\num[n]),#VNFLen,"0")
    Wend
    
  EndIf
  
  ProcedureReturn t
EndProcedure

Procedure GetNumber(*s.String,*num.VNF)
  
  ; ACHTUNG! s ist bei dieser Routine vom Typ String!
  ; (bei x.string bedeutet dies den Aufruf "GetNumber(x,number)" und die Ausgabe "Debug x\s")
  
  Protected n
  Protected t.s
  
  If *num\sign
    t = "-"
  EndIf
  
  n=*num\len
  t+Str(*num\num[n])
  
  While n>0
    n-1
    t+RSet(Str(*num\num[n]),#VNFLen,"0")
  Wend
  
  *s\s=t
  
EndProcedure

Procedure PutNumber(s.s,*num.VNF)
  
  Protected n,p
  Protected t.s
  
  *num\sign=#VNFPositive
  
  t=PeekS(@s)
  n=Len(t)-#VNFLen
  
  While n>0
    *num\num[p]=Val(PeekS(@t+n,#VNFLen))
    p+1
    n-#VNFLen
  Wend
  
  n=Val(PeekS(@t,9+n))
  If n<0
    *num\sign=#VNFNegative
    n=-n
  EndIf
  
  *num\num[p]=n
  
  *num\len=p
  
EndProcedure

Procedure VNFNormalize(*a.VNF)
  ; Strap leading zeros (000.000.000)
  If *a\len>=0
    While (*a\len>=0) And (*a\num[*a\len]=0)
      *a\len-1
    Wend
    ; Value equal Zero? Positiv sign
    If *a\len<0
      *a\len=0
      *a\sign=#VNFPositive
    EndIf
  EndIf
EndProcedure

Procedure VNFError(type,stype,*a.VNF)
  
  If type>=0
    type=stype
  EndIf
  
  Debug "ERROR "+Str(type)
  *a\len=type
  
EndProcedure

Procedure VNFCopy(*a.VNF,*b.VNF)
  Protected n
  
  n=*a\len
  *b\len=n
  *b\sign=*a\sign
  
  While n>=0
    *b\num[n]=*a\num[n]
    n-1
  Wend
  
EndProcedure

Procedure VNFZero(*a.VNF)
  *a\len=0
  *a\sign=#VNFPositive
  *a\num[0]=0
EndProcedure

Procedure VNFAbs(*a.VNF)
  *a\sign=#VNFPositive
EndProcedure

Procedure.l VNFEq(*a.VNF,*b.VNF,abs=0)
  
  Protected n,d
  
  If n<>*b\len
    ProcedureReturn #False
  ElseIf (abs=0) And (*a\sign<>*b\sign)
    ProcedureReturn #False
  Else
    While n>=0
      If *a\num[n]<>*b\num[n]
        ProcedureReturn #False
      EndIf
      n-1
    Wend
    ProcedureReturn #True;    a=b
  EndIf
  
EndProcedure

Procedure.l VNFGt(*a.VNF,*b.VNF,abs=0)
  
  Protected n,d
  
  If abs=0
    
    If *a\sign<>*b\sign
      If *a\sign=#VNFPositive
        ProcedureReturn #True
      Else
        ProcedureReturn #False
      EndIf
    EndIf
    
  Else
    
    n=*a\len
    If n>*b\len
      ProcedureReturn #True
    ElseIf n<*b\len
      ProcedureReturn #False
    Else
      While n>=0
        d=*a\num[n]-*b\num[n]
        If d>0
          ProcedureReturn #True
        ElseIf d<0
          ProcedureReturn #False
        EndIf
        n-1
      Wend
      ProcedureReturn #False;    a=b
    EndIf
    
  EndIf
  
EndProcedure

Procedure.l VNFPositive(*a.VNF)
  
  If *a\sign=#VNFPositive
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

Procedure VNFMuW(*a.VNF,b.l,*c.VNF)
  
  Protected n
  Protected m.q
  
  n=*a\len
  
  If n<0
    VNFError(n,0,*c.VNF)
  Else
    
    If b=0
      *c\len=0
      *c\sign=#VNFPositive
      *c\num[0]=0
    Else
      
      If b<0
        b=-b
        *c\sign=#VNFNegative-*a\sign
      Else
        *c\sign=*a\sign
      EndIf
      
      n=0
      Repeat
        m+*a\num[n] * b
        *c\num[n]=m%#VNFMod
        m/#VNFMod
        
        n+1
      Until n>*a\len
      
      If m
        *c\num[n]=m
      Else
        n-1
      EndIf
      *c\len=n
      
    EndIf
  EndIf
  
EndProcedure

Procedure VNFMul(*a.VNF,*b.VNF,*c.VNF)
  
  Protected la
  Protected lb
  Protected n
  
  Protected s.q
  Protected z.q
  
  If (*a\len<0) Or (*b\len<0)
    VNFError(*a\len,*b\len,*c.VNF)
  Else
    *c\sign=(*a\sign + *b\sign)&1;    because #VNFNegative=1
    *c\len=*a\len+*b\len+1
    For n=0 To *c\len
      *c\num[n]=0
    Next n
    
    la=0
    Repeat
      lb=0
      z=*b\num[lb]
      Repeat
        s=*a\num[la] * *b\num[lb] + *c\num[la+lb]
        ;Debug Str(*a\num[la])+" * "+Str(*b\num[lb])+" + "+Str(*c\num[la+lb+1])
        ;Debug " = "+StrQ(s)+"  -> "+Str(s/#VNFMod)+" | "+Str(s%#VNFMod)
        *c\num[la+lb]=s%#VNFMod
        *c\num[la+lb+1]+s/#VNFMod
        lb+1
      Until lb>*b\len
      la+1
    Until la>*a\len
    
    VNFNormalize(*c)
    
  EndIf
  
EndProcedure

Procedure VNFDiW(*a.VNF,b.l,*c.VNF)
  
  Protected n
  Protected d.q,q.q
  
  n=*a\len
  
  If n<0
    VNFError(n,0,*c.VNF)
  Else
    
    If b=0
      *c\len=#VNFUndefined
    Else
      
      If b<0
        b=-b
        *c\sign=#VNFNegative-*a\sign
      Else
        *c\sign=*a\sign
      EndIf
      
      Repeat
        d=d*#VNFMod+*a\num[n]
        q=d/b
        *c\num[n]=q
        d-q*b
        n-1
      Until n<0
      
      VNFNormalize(*c)
      
    EndIf
  EndIf
  
EndProcedure

Procedure VNFDiv(*a.VNF,*b.VNF,*c.VNF)
  
  Protected n
  
  If (*a\len<0) Or (*b\len<0)
    VNFError(*a\len,*b\len,*c.VNF)
  Else
    
    n=*b\len
    If n=0
      If *b\num[0]=0
        *c\len=#VNFUndefined
      Else
        ;Debug "diw"
        VNFDiW(*a.VNF,*b\num[0],*c.VNF)
        *c\sign=-(1&(*a\sign+*b\sign))
      EndIf
      
    Else
      
      If VNFGt(*b,*a,#True)
        VNFZero(*c)
      Else
        
        ; Hmmm...
        
      EndIf
    EndIf
  EndIf
  
EndProcedure

Procedure VNFAdd(*a.VNF,*b.VNF,*c.VNF)
  
  Protected n
  Protected s
  
  If (*a\len<0) Or (*b\len<0)
    VNFError(*a\len,*b\len,*c.VNF)
  Else
    
    If *a\sign<>*b\sign
      ;Debug "sub"
      *b\sign=*a\sign
      VNFSub(*a.VNF,*b.VNF,*c.VNF)
    Else
      
      *c\sign=*a\sign
      
      If *a\len<*b\len
        Swap *a,*b
      EndIf
      
      While n<=*a\len
        s+*a\num[n]
        If n<=*b\len
          s+*b\num[n]
        EndIf
        *c\num[n]=s%#VNFMod
        s/#VNFMod
        n+1
      Wend
      If s
        *c\num[n]=s
      Else
        n-1
      EndIf
      
      *c\len=n
    EndIf
    
  EndIf
EndProcedure

Procedure VNFSub(*a.VNF,*b.VNF,*c.VNF)
  
  Protected n
  Protected s
  
  If (*a\len<0) Or (*b\len<0)
    VNFError(*a\len,*b\len,*c.VNF)
  Else
    
    If *a\sign<>*b\sign
      ;Debug "add"
      *b\sign=*a\sign
      VNFAdd(*a.VNF,*b.VNF,*c.VNF)
    Else
      
      If VNFGt(*a.VNF,*b.VNF,#True)
        *c\sign=*a\sign
      Else
        ;Debug "swp"
        Swap *a,*b
        *c\sign=#VNFNegative-*a\sign
      EndIf
      
      
      While n<=*a\len
        s+*a\num[n]
        If n<=*b\len
          s-*b\num[n]
        EndIf
        If s<0
          *c\num[n]=s+#VNFMod
          s=-1
        Else
          *c\num[n]=s
          s=0
        EndIf
        n+1
      Wend
      
      *c\len=n-1
      
      VNFNormalize(*c)
      
    EndIf
  EndIf
  
EndProcedure

Procedure VNFSqr(*a.VNF)
  If *a\len>=0
    VNFMul(*a,*a,VNF_Cache_C.VNF)
    VNFCopy(VNF_Cache_C,*a)
  EndIf  
EndProcedure

Procedure VNFPow(*a.VNF,b.l,*c.VNF)
  
  Protected z=0,s,sign
  
  If b<0
    
    ; a^b | b<0 not implemented for now...
    VNFError(#VNFNotImplemented,0,*c.VNF)
    
  ElseIf *a\len>=0
    
    VNFCopy(*a,VNF_Cache_A.VNF)
    PutNumber("1",VNF_Cache_B.VNF)
    
    If VNFPositive(*a)=#False
      VNFAbs(VNF_Cache_A)
      If b & 1 
        VNF_Cache_B\Sign=#VNFNegative 
      EndIf
    EndIf
    
    While b > 0
      s = 1 << z
      If b & s
        VNFMul(VNF_Cache_A,VNF_Cache_B,VNF_Cache_C.VNF)
        VNFCopy(VNF_Cache_C,VNF_Cache_B)
        b = b - s
      EndIf
      
      If b
        VNFSqr(VNF_Cache_A)
        z + 1
      EndIf
      
    Wend
    
    VNFCopy(VNF_Cache_B,*c)
    
  EndIf
  
EndProcedure

Procedure VNFRandom(*a.VNF, MaximumDigitCount.l)
  
  Max = Random(MaximumDigitCount)
  
  For Index = 0 To Max
    RandomNumber.s = RandomNumber + Str(Random(9))
  Next

  PutNumber(RandomNumber, *a)
  
EndProcedure

;// Zone de test

; ;Une addition
; Debug "Demo Addition"
; 
; x.VNF
; y.VNF
; z.VNF
; 
; A$="12345678999999994012121212155454789921999"
; B$="-1"
; 
; DisableDebugger
; time=-ElapsedMilliseconds()
; 
; PutNumber(A$,x)
; PutNumber(B$,y)
; 
; VNFAdd(x,y,z)
; time+ElapsedMilliseconds()
; 
; EnableDebugger
; Debug Number(z)
; Debug "Durée "+Str(time)+" ms"
; Debug ""
; 
; ;Une multiplication
; Debug "Demo Multiplication"
; Number1.VNF
; Number2.VNF
; Result.VNF
; 
; Number1$="12345678999999994012121212155454789921999"
; Number2$="15906045674"
; 
; DisableDebugger
; time = -ElapsedMilliseconds()
; 
; PutNumber(Number1$, Number1)
; PutNumber(Number2$, Number2)
; 
; VNFMul(Number1, Number2, Result)
; time + ElapsedMilliseconds()
; 
; EnableDebugger
; 
; Debug Number(Number1) + " * " + Number(Number2) + " = " + Number(Result)
; Debug "Durée "+Str(time)+" ms"
; Debug ""
; ;Puissance
; Debug "Demo Multiplication"
; Number.VNF
; Exponent.l
; Result.VNF
; 
; Number$="1000" 
; Exponent.l=1000
; 
; DisableDebugger
; time=-ElapsedMilliseconds()
; 
; PutNumber(Number$,Number)
; VNFPow(Number,Exponent,Result)
; time+ElapsedMilliseconds()
; 
; EnableDebugger
; Debug Number(Result)
; 
; Debug "Durée "+Str(time)+" ms"
; Debug ""

; For TestID = 0 To 5
;  VNFRandom(RandomVNF.VNF, 25)
;  Debug Number(RandomVNF)
; Next

; Debug ""

PutNumber("1000", Number.VNF)
VNFPow(Number, 1000,Result.VNF)
Debug Number(Result)
Dear Optimist, Pessimist,
and Realist,

While you guys were
busy arguing about the
glass of water, I DRANK IT !

Sincerely,
the Opportunist
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Huge #'s

Post by electrochrisso »

That is where I get the error too Guimauve, your last code works ok. :)
For reference I am on PB 461.
PureBasic! Purely the best 8)
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Huge #'s

Post by Guimauve »

Hello everyone,

It's very strange because the difference between these codes can't justify why the original don't crash and my version crash.
Furthermore, it work on Mac x64 and Linux x64 and not Windows 7 32 bits

I will run my code on Window XP 32 Bits to figure what is going on. I hope the problem will happen so will be able to investigate.

Edit #1 : Under Windows XP SP 3 (32 bits) + PB 4.61 I don't get any error. The code execute as expected.

Best regards
Guimauve
Dear Optimist, Pessimist,
and Realist,

While you guys were
busy arguing about the
glass of water, I DRANK IT !

Sincerely,
the Opportunist
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Huge #'s

Post by electrochrisso »

Perhaps I should have mentioned I was using Win7 sp1 starter, 32bit.
I will give it a try on Vista sp2 32bit later on today.
PureBasic! Purely the best 8)
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Huge #'s

Post by Guimauve »

Hello everyone,

OK Windows 7 X64 but with PureBasic x86 on virtual machine, I get the Stack overflow error. So now I can do something.

Edit : I think I got it. Can some one try this code and tell me if the error is still happen :

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V4.0.0
; Project name : Vogels Number Format
; File name : Vogels Number Format.pb
; File Version : 1.0.2
; Programmation : OK
; Programmed by : Guimauve
; Creation Date : 06-07-2012
; Last update : 01-11-2012
; Coded for : PureBasic 5.00 Beta 8
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Programming notes
;
; This code is a re-work of Vogels Number Format orginally 
; created by Michel Vogel (PureBasic English Forum).
;
; List of changes :
;
; - VNF structure name : Renamed to "VogelsNumberFormat"
; - Number() ---> Removed : Use VogelsNumberFormat_To_String() instead
; - GetNumber() ---> Removed : Use VogelsNumberFormat_To_String() instead
; - PutNumber() ---> Removed : Use String_To_VogelsNumberFormat() instead
; 
; Commands added :
; 
; - VogelsNumberFormat_To_String()
; - String_To_VogelsNumberFormat()
; - ReadVogelsNumberFormat()
; - WriteVogelsNumberFormat()
; - VogelsNumberFormat_Factorial() --> Work upto 999!
; - VogelsNumberFormat_Random()
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Size Array Constants <<<<<

#VOGELS_NUMBER_FORMAT_NUM_MAX = 10000

#VOGELS_NUMBER_FORMAT_NEGATIVE = 1
#VOGELS_NUMBER_FORMAT_POSITIVE = 0
#VOGELS_NUMBER_FORMAT_UNDEFINED = -1
#VOGELS_NUMBER_FORMAT_INFINITIVE = -2
#VOGELS_NUMBER_FORMAT_OVERFLOW = -3
#VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED = -4
#VOGELS_NUMBER_FORMAT_LEN = 9
#VOGELS_NUMBER_FORMAT_MOD = 1000000000

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<

Structure VogelsNumberFormat

	Len.w
	Sign.w
	Num.l[#VOGELS_NUMBER_FORMAT_NUM_MAX]

EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<

Macro GetVogelsNumberFormatLen(VogelsNumberFormatA)
	
	VogelsNumberFormatA\Len
	
EndMacro

Macro GetVogelsNumberFormatSign(VogelsNumberFormatA)
	
	VogelsNumberFormatA\Sign
	
EndMacro

Macro GetVogelsNumberFormatNum(VogelsNumberFormatA, NumID)
	
	VogelsNumberFormatA\Num[NumID]
	
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<

Macro SetVogelsNumberFormatLen(VogelsNumberFormatA, P_Len)
	
	GetVogelsNumberFormatLen(VogelsNumberFormatA) = P_Len
	
EndMacro

Macro SetVogelsNumberFormatSign(VogelsNumberFormatA, P_Sign)
	
	GetVogelsNumberFormatSign(VogelsNumberFormatA) = P_Sign
	
EndMacro

Macro SetVogelsNumberFormatNum(VogelsNumberFormatA, NumID, P_Num)
	
	GetVogelsNumberFormatNum(VogelsNumberFormatA, NumID) = P_Num
	
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<

Macro ResetVogelsNumberFormat(VogelsNumberFormatA)
	
	ClearStructure(VogelsNumberFormatA, VogelsNumberFormat)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read in Binary file <<<<<

Procedure ReadVogelsNumberFormat(FileID.l, *VogelsNumberFormatA.VogelsNumberFormat)
	
	SetVogelsNumberFormatLen(*VogelsNumberFormatA, ReadWord(FileID))
	SetVogelsNumberFormatSign(*VogelsNumberFormatA, ReadWord(FileID))
	
	For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
		SetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID, ReadLong(FileID))
	Next
	
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Write in Binary file <<<<<

Procedure WriteVogelsNumberFormat(FileID.l, *VogelsNumberFormatA.VogelsNumberFormat)
	
	WriteWord(FileID, GetVogelsNumberFormatLen(*VogelsNumberFormatA))
	WriteWord(FileID, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
	
	For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
		WriteLong(FileID, GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
	Next
	
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.005 seconds (25600.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Declare VogelsNumberFormat_Add(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
Declare VogelsNumberFormat_Sub(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)

Procedure.s VogelsNumberFormat_To_String(*VogelsNumberFormatA.VogelsNumberFormat)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
		
		Select GetVogelsNumberFormatLen(*VogelsNumberFormatA)
				
			Case #VOGELS_NUMBER_FORMAT_UNDEFINED
				VFN_2_String.s = "Undefined"
				
			Case #VOGELS_NUMBER_FORMAT_INFINITIVE
				VFN_2_String = "Infinitive"
				If GetVogelsNumberFormatSign(*VogelsNumberFormatA)
					VFN_2_String = "Minus " + VFN_2_String
				EndIf
				
			Case #VOGELS_NUMBER_FORMAT_OVERFLOW
				VFN_2_String = "Overflow"
				
			Case #VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED
				VFN_2_String = "Not Implemented"
				
		EndSelect
		
	Else
		
		If GetVogelsNumberFormatSign(*VogelsNumberFormatA)
			VFN_2_String = "-"
		EndIf
		
		NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA)
		VFN_2_String + Str(GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
		
		While NumID > 0
			NumID - 1
			VFN_2_String + RSet(Str(GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)), #VOGELS_NUMBER_FORMAT_LEN, "0")
		Wend
		
	EndIf
	
	ProcedureReturn VFN_2_String
EndProcedure

Procedure String_To_VogelsNumberFormat(*VogelsNumberFormatA.VogelsNumberFormat, String.s)
	
	SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
	
	NumID = Len(String) - #VOGELS_NUMBER_FORMAT_LEN
	
	While NumID > 0
		SetVogelsNumberFormatNum(*VogelsNumberFormatA, p, Val(Mid(String, NumID+1, #VOGELS_NUMBER_FORMAT_LEN)))
		p + 1
		NumID - #VOGELS_NUMBER_FORMAT_LEN
		
	Wend
	
	NumID = Val(Mid(String, 1, 9 + NumID))
	
	If NumID < 0
		SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_NEGATIVE)
		NumID = -NumID
	EndIf
	
	SetVogelsNumberFormatNum(*VogelsNumberFormatA, p, NumID)
	SetVogelsNumberFormatLen(*VogelsNumberFormatA, p)
	
EndProcedure

Procedure VogelsNumberFormat_Normalize(*VogelsNumberFormatA.VogelsNumberFormat)
	
	; Strap leading zeros (000.000.000)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
		
		While (GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0) And (GetVogelsNumberFormatNum(*VogelsNumberFormatA, GetVogelsNumberFormatLen(*VogelsNumberFormatA)) = 0)
			SetVogelsNumberFormatLen(*VogelsNumberFormatA, GetVogelsNumberFormatLen(*VogelsNumberFormatA) - 1)
		Wend
		
		; Value equal Zero? Positiv sign
		
		If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
			SetVogelsNumberFormatLen(*VogelsNumberFormatA, 0)
			SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
		EndIf
		
	EndIf
	
EndProcedure

Procedure VogelsNumberFormat_Error(type, stype, *VogelsNumberFormatA.VogelsNumberFormat)
	
	If type >= 0
		type = stype
	EndIf
	
	SetVogelsNumberFormatLen(*VogelsNumberFormatA, type)
	Debug "ERROR " + Str(type)
	
	ProcedureReturn Type
EndProcedure

Procedure VogelsNumberFormat_Copy(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat)
	
	SetVogelsNumberFormatLen(*VogelsNumberFormatB, GetVogelsNumberFormatLen(*VogelsNumberFormatA))
	SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
	
	For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
		SetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID, GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID))
	Next
	
EndProcedure

Procedure VogelsNumberFormat_Zero(*VogelsNumberFormatA.VogelsNumberFormat)
	
	SetVogelsNumberFormatLen(*VogelsNumberFormatA, 0)
	SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
	
	For NumID = 0 To #VOGELS_NUMBER_FORMAT_NUM_MAX - 1
		SetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID, 0)
	Next
	
EndProcedure

Procedure VogelsNumberFormat_Abs(*VogelsNumberFormatA.VogelsNumberFormat)
	
	SetVogelsNumberFormatSign(*VogelsNumberFormatA, #VOGELS_NUMBER_FORMAT_POSITIVE)
	
EndProcedure

Procedure VogelsNumberFormat_Equal(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, Abs = 0)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) <> GetVogelsNumberFormatLen(*VogelsNumberFormatB)
		
		ProcedureReturn #False
		
	ElseIf (Abs = 0) And (GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB))
		
		ProcedureReturn #False
		
	Else
		
		For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
			If GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) <> GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
				ProcedureReturn #False
			EndIf
			
		Next
		
		ProcedureReturn #True
		
	EndIf
	
EndProcedure

Procedure VogelsNumberFormat_GreaterThan(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, Abs = 0)
	
	If Abs = 0
		
		If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
			If GetVogelsNumberFormatSign(*VogelsNumberFormatA) = #VOGELS_NUMBER_FORMAT_POSITIVE
				ProcedureReturn #True
			Else
				ProcedureReturn #False
			EndIf
		EndIf
		
	Else
		
		If GetVogelsNumberFormatLen(*VogelsNumberFormatA) > GetVogelsNumberFormatLen(*VogelsNumberFormatB) 
			
			ProcedureReturn #True
			
		ElseIf GetVogelsNumberFormatLen(*VogelsNumberFormatA) < GetVogelsNumberFormatLen(*VogelsNumberFormatB) 
			
			ProcedureReturn #False
			
		Else
			
			
			For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
				
				d = GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) - GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
				
				If d > 0
					ProcedureReturn #True
				ElseIf d < 0
					ProcedureReturn #False
				EndIf
				
			Next 
			
			ProcedureReturn #False;    a=b
			
		EndIf
		
	EndIf
	
EndProcedure

Procedure VogelsNumberFormat_Positive(*VogelsNumberFormatA.VogelsNumberFormat)
	
	If GetVogelsNumberFormatSign(*VogelsNumberFormatA) = #VOGELS_NUMBER_FORMAT_POSITIVE
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf
	
EndProcedure

Procedure VogelsNumberFormat_Mul(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
	
	Protected la, lb
	Protected s.q, z.q
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
	Else
		
		SetVogelsNumberFormatSign(*VogelsNumberFormatC, (GetVogelsNumberFormatSign(*VogelsNumberFormatA) + GetVogelsNumberFormatSign(*VogelsNumberFormatB)) & 1)
		SetVogelsNumberFormatLen(*VogelsNumberFormatC, GetVogelsNumberFormatLen(*VogelsNumberFormatA) + GetVogelsNumberFormatLen(*VogelsNumberFormatB) + 1)
		
		For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatC)
			SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, 0)
		Next 
		
		la = 0
		
		Repeat
			
			lb = 0
			
			Repeat
				
				s.q = GetVogelsNumberFormatNum(*VogelsNumberFormatA, la) * GetVogelsNumberFormatNum(*VogelsNumberFormatB, lb) + GetVogelsNumberFormatNum(*VogelsNumberFormatC, la+lb)
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb, s % #VOGELS_NUMBER_FORMAT_MOD)
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb + 1, GetVogelsNumberFormatNum(*VogelsNumberFormatC, la + lb + 1) + s / #VOGELS_NUMBER_FORMAT_MOD)
				lb + 1
				
			Until lb > GetVogelsNumberFormatLen(*VogelsNumberFormatB)
			
			la + 1
			
		Until la > GetVogelsNumberFormatLen(*VogelsNumberFormatA)
		
		VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure Private_VogelsNumberFormat_MuW(*VogelsNumberFormatA.VogelsNumberFormat, b.l, *VogelsNumberFormatC.VogelsNumberFormat)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), 0, *VogelsNumberFormatC)
	Else
		
		If b = 0
			VogelsNumberFormat_Zero(*VogelsNumberFormatC)
		Else
			
			If b < 0
				b = -b
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			Else
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			EndIf
			
			NumID = 0
			
			For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
				m.q + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID) * b
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, m % #VOGELS_NUMBER_FORMAT_MOD)
				m / #VOGELS_NUMBER_FORMAT_MOD
			Next
			
			If m
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, m)
			Else
				NumID - 1
			EndIf
			
			SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
			
		EndIf
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure Private_VogelsNumberFormat_DiW(*VogelsNumberFormatA.VogelsNumberFormat, b.l, *VogelsNumberFormatC.VogelsNumberFormat)
	
	Protected NumID
	Protected d.q, q.q
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), 0, *VogelsNumberFormatC)
	Else
		
		If b = 0
			SetVogelsNumberFormatLen(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_UNDEFINED)
		Else
			
			If b < 0
				b = -b
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			Else
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			EndIf
			
			For NumID = GetVogelsNumberFormatLen(*VogelsNumberFormatA) To 0 Step -1
				
				d = d * #VOGELS_NUMBER_FORMAT_MOD + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
				q = d / b
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, q)
				d - q * b
				
			Next
			
			VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
			
		EndIf
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Div(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
	Else

		If GetVogelsNumberFormatLen(*VogelsNumberFormatB) = 0
			If GetVogelsNumberFormatNum(*VogelsNumberFormatB, 0) = 0
				SetVogelsNumberFormatLen(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_UNDEFINED)
			Else
				Private_VogelsNumberFormat_DiW(*VogelsNumberFormatA, GetVogelsNumberFormatNum(*VogelsNumberFormatB, 0), *VogelsNumberFormatC)
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, -(1 & (GetVogelsNumberFormatSign(*VogelsNumberFormatA) + GetVogelsNumberFormatSign(*VogelsNumberFormatB))))
			EndIf
			
		Else

			If VogelsNumberFormat_GreaterThan(*VogelsNumberFormatB, *VogelsNumberFormatA, #True)
				VogelsNumberFormat_Zero(*VogelsNumberFormatC)
			Else

				; Hmmm...
				
			EndIf
			
		EndIf
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Add(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
	
	Protected n
	Protected s
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
	Else
		
		If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
			SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			VogelsNumberFormat_Sub(*VogelsNumberFormatA, *VogelsNumberFormatB, *VogelsNumberFormatC)
		Else
			
			SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			
			If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < GetVogelsNumberFormatLen(*VogelsNumberFormatB)
				Swap *VogelsNumberFormatA, *VogelsNumberFormatB
			EndIf
			
			For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
				
				s + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
				
				If NumID <= GetVogelsNumberFormatLen(*VogelsNumberFormatB)
					s + GetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID)
				EndIf
				
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s % #VOGELS_NUMBER_FORMAT_MOD)
				s / #VOGELS_NUMBER_FORMAT_MOD
				
			Next
			
			NumID + 1
			
			If s
				SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s)
			Else
				NumID - 1
			EndIf
			
			SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
			VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
			
		EndIf
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Sub(*VogelsNumberFormatA.VogelsNumberFormat, *VogelsNumberFormatB.VogelsNumberFormat, *VogelsNumberFormatC.VogelsNumberFormat)
	
	Protected n
	Protected s
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) < 0 Or GetVogelsNumberFormatLen(*VogelsNumberFormatB) < 0
		Error = VogelsNumberFormat_Error(GetVogelsNumberFormatLen(*VogelsNumberFormatA), GetVogelsNumberFormatLen(*VogelsNumberFormatB), *VogelsNumberFormatC)
	Else
		
		If GetVogelsNumberFormatSign(*VogelsNumberFormatA) <> GetVogelsNumberFormatSign(*VogelsNumberFormatB)
			
			SetVogelsNumberFormatSign(*VogelsNumberFormatB, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			VogelsNumberFormat_Add(*VogelsNumberFormatA, *VogelsNumberFormatB, *VogelsNumberFormatC)
		Else
			
			If VogelsNumberFormat_GreaterThan(*VogelsNumberFormatA, *VogelsNumberFormatB, #True)
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			Else
				Swap *VogelsNumberFormatA, *VogelsNumberFormatB
				SetVogelsNumberFormatSign(*VogelsNumberFormatC, #VOGELS_NUMBER_FORMAT_NEGATIVE - GetVogelsNumberFormatSign(*VogelsNumberFormatA))
			EndIf
			
			For NumID = 0 To GetVogelsNumberFormatLen(*VogelsNumberFormatA)
				
				s + GetVogelsNumberFormatNum(*VogelsNumberFormatA, NumID)
				
				If NumID <= GetVogelsNumberFormatLen(*VogelsNumberFormatB)
					s - GetVogelsNumberFormatNum(*VogelsNumberFormatB, NumID)
				EndIf
				
				
				If s < 0
					SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s + #VOGELS_NUMBER_FORMAT_MOD)
					s = -1
				Else
					SetVogelsNumberFormatNum(*VogelsNumberFormatC, NumID, s)
					s = 0
				EndIf
				
			Next
			
			SetVogelsNumberFormatLen(*VogelsNumberFormatC, NumID)
			VogelsNumberFormat_Normalize(*VogelsNumberFormatC)
			
		EndIf
		
	EndIf
	
	ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Square(*VogelsNumberFormatA.VogelsNumberFormat)
	
	If GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
		Error = VogelsNumberFormat_Mul(*VogelsNumberFormatA, *VogelsNumberFormatA, VNF_Cache_C.VogelsNumberFormat)
		VogelsNumberFormat_Copy(VNF_Cache_C, *VogelsNumberFormatA)
		ResetVogelsNumberFormat(VNF_Cache_C)
	EndIf  
	
	ProcedureReturn Error
EndProcedure

Procedure VogelsNumberFormat_Pow(*VogelsNumberFormatA.VogelsNumberFormat, Exponent.l, *VogelsNumberFormatC.VogelsNumberFormat)
	
	Protected z = 0, s, sign
	
	If Exponent < 0
		
		; a^b | b<0 not implemented for now...
		VogelsNumberFormat_Error(#VOGELS_NUMBER_FORMAT_NOT_IMPLEMENTED, 0, *VogelsNumberFormatC)
		
	ElseIf GetVogelsNumberFormatLen(*VogelsNumberFormatA) >= 0
		
		VogelsNumberFormat_Copy(*VogelsNumberFormatA, VNF_Cache_A.VogelsNumberFormat)
		String_To_VogelsNumberFormat(VNF_Cache_B.VogelsNumberFormat, "1")
		
		If VogelsNumberFormat_Positive(*VogelsNumberFormatA) = #False
			VogelsNumberFormat_Abs(VNF_Cache_A)
			If Exponent & 1 
				SetVogelsNumberFormatSign(VNF_Cache_B, #VOGELS_NUMBER_FORMAT_NEGATIVE)
			EndIf
		EndIf
		
		While Exponent > 0
			
			s = 1 << z
			
			If Exponent & s
				VogelsNumberFormat_Mul(VNF_Cache_A, VNF_Cache_B, VNF_Cache_C.VogelsNumberFormat)
				VogelsNumberFormat_Copy(VNF_Cache_C, VNF_Cache_B)
				Exponent = Exponent - s
			EndIf
			
			If Exponent
				VogelsNumberFormat_Square(VNF_Cache_A)
				z = z + 1
			EndIf
			
		Wend
		
		VogelsNumberFormat_Copy(VNF_Cache_B, *VogelsNumberFormatC)
		
	EndIf
	
	ResetVogelsNumberFormat(VNF_Cache_A)
	ResetVogelsNumberFormat(VNF_Cache_B)
	ResetVogelsNumberFormat(VNF_Cache_C)
	
EndProcedure

Procedure VogelsNumberFormat_Factorial(Value.l, *VogelsNumberFormatC.VogelsNumberFormat)
	
	String_To_VogelsNumberFormat(VNF_Cache_B.VogelsNumberFormat, "1")
	
	For Index = 2 To Value
		String_To_VogelsNumberFormat(VNF_Cache_C.VogelsNumberFormat, Str(Index))
		VogelsNumberFormat_Mul(VNF_Cache_B, VNF_Cache_C, VNF_Cache_R.VogelsNumberFormat)
		VogelsNumberFormat_Copy(VNF_Cache_R, VNF_Cache_B)
	Next
	
	VogelsNumberFormat_Copy(VNF_Cache_B, *VogelsNumberFormatC)
	
	ResetVogelsNumberFormat(VNF_Cache_B)
	ResetVogelsNumberFormat(VNF_Cache_C)
	ResetVogelsNumberFormat(VNF_Cache_R)
	
EndProcedure
Procedure VogelsNumberFormat_Random(*VogelsNumberFormatA.VogelsNumberFormat, MaximumDigitCount.l)
	
	Max = Random(MaximumDigitCount)
	
	For Index = 1 To Max
		RandomNumber.s = RandomNumber + Str(Random(9))
	Next
	
	If Left(RandomNumber, 1)  = "0"
		RandomNumber = Right(RandomNumber, Len(RandomNumber) - 1)
	EndIf
	
	String_To_VogelsNumberFormat(*VogelsNumberFormatA, RandomNumber)

EndProcedure

Procedure ReadPreferenceVogelsNumberFormat(GroupName.s, *VogelsNumberFormatA.VogelsNumberFormat)
		
	String_To_VogelsNumberFormat(*VogelsNumberFormatA, ReadPreferenceString(GroupName, VogelsNumberFormat_To_String(*VogelsNumberFormatA)))
	
EndProcedure

Procedure WritePreferenceVogelsNumberFormat(GroupName.s, *VogelsNumberFormatA.VogelsNumberFormat)
	
	WritePreferenceString(GroupName, VogelsNumberFormat_To_String(*VogelsNumberFormatA))
	
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<< 
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<< 
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<< 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

Procedure.s FormatInteger(Number.s)
	
	; Format Integer created by Gnozal
	
	NumberLen = Len(Number)
	Start = NumberLen % 3
	FormatedNumber.s = Left(Number, Start)
	
	For i = Start + 1 To NumberLen - Start Step 3
		FormatedNumber + " " + Mid(Number, i, 3)
	Next
	
	ProcedureReturn LTrim(FormatedNumber)
EndProcedure

Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(MyNumber.VogelsNumberFormat, "00000000000000000000123456789987654321123456789987654321")
Debug VogelsNumberFormat_To_String(MyNumber)
VogelsNumberFormat_Normalize(MyNumber)
Debug VogelsNumberFormat_To_String(MyNumber)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(X.VogelsNumberFormat, "23456")
String_To_VogelsNumberFormat(Y.VogelsNumberFormat, "98765")
VogelsNumberFormat_Add(X, Y, Z.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Z)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(Number1.VogelsNumberFormat, "12345678999999994012121212155454789921999")
String_To_VogelsNumberFormat(Number2.VogelsNumberFormat, "15906045674")
VogelsNumberFormat_Mul(Number1, Number2, Number3.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Number1) + " * " + VogelsNumberFormat_To_String(Number2) + " = " + VogelsNumberFormat_To_String(Number3)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

String_To_VogelsNumberFormat(Number.VogelsNumberFormat, "100")
VogelsNumberFormat_Pow(Number, 100, Result.VogelsNumberFormat)
Debug VogelsNumberFormat_To_String(Result)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

For Factorial = 50 To 100
	VogelsNumberFormat_Factorial(Factorial, TestFactorial.VogelsNumberFormat)
	Debug Str(Factorial) + "! = " + FormatInteger(VogelsNumberFormat_To_String(TestFactorial))
Next

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

For RandomID = 0 To 5
	VogelsNumberFormat_Random(TestRandom.VogelsNumberFormat, 25)
	Debug FormatInteger(VogelsNumberFormat_To_String(TestRandom))
Next

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Best regards
Guimauve
Dear Optimist, Pessimist,
and Realist,

While you guys were
busy arguing about the
glass of water, I DRANK IT !

Sincerely,
the Opportunist
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Huge #'s

Post by Michael Vogel »

Nice to see, that you're tuning my code, thanks for all your efforts :wink:

PS: who knows, maybe I will be able to implement the missing div routine sometime in the future...

PSS: what about this small modification for your FormatInteger procedure?

Code: Select all

Procedure.s FormatInteger(Number.s,Group.i=3)

	; Format Integer created by Gnozal

	NumberLen = Len(Number)
	Start = NumberLen % Group
	FormatedNumber.s = Left(Number, Start)
	
	i=Start + 1 
	While i<=NumberLen - Start
		FormatedNumber + " " + Mid(Number, i,Group)
		i+Group
	Wend

	ProcedureReturn LTrim(FormatedNumber)
	
EndProcedure
Post Reply