Squares

General FreeBASIC programming questions.
Locked
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

You can hold more then one character in an index of a pointer to the string.
But you only can hold some characters to the Right of the string.

I suppose you could create a function to get the middle values:

Code: Select all

dim as string num1 = "1234567890"
dim as zstring ptr p=strptr(num1)
print num1
print p[1]
print p[4]

print 


function Middle(byval s as string,n1 as long,n2 as long) as string
    dim as long lens,L=len(s)
    if n2>L then n2=L
    if n1<1 then n1=1
    if n1>n2 then swap n1,n2
    #macro reverse(s)
    lens=len(s)
     for n as integer=0 to int((lens-1)/2):swap s[n],s[lens-1-n]:next
    #endmacro
dim as zstring ptr p=strptr(s)
s=p[n1-1]
reverse(s)
p=strptr(s)
s= p[L-n2]
reverse(s)
 return s
end function


print Middle(num1,2,4)

sleep
 
But is it worth the effort?
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Squares

Post by dafhi »

I think Albert is visualizing a new syntax

current method:

Code: Select all

clip = mid(mystr, 2, 3) ''start, len (i forget)
Albert's suggestion:

Code: Select all

clip = mystr[2 to 4]
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

No!

They need to make it so the index can return multiple values..

dim as string num = "123456789"
dim as longint part = num[ 2 to 4 ]

The index would return "050 051 052" so , part would equal 050051052

Then to get the decimal values you could subtract 048048048
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Squares

Post by dafhi »

If you're looking for ease of prototyping, I recommend OOP

that way you could

Code: Select all

part = udt.myfunction(2, 4, -48) ''3rd parameter optional
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

Hi Dafhi.
I notice that you have taken down your videos.
What was that bang anyway, your neighbour's shotgun? -- a drive by shooting?

What is your aim Albert with this index thing?
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Dodicat

I was wanting to replace:

'ans+= valulng( mid( values(b) , a , 10 ) )

ans+= (values(b)[a+0]-48)* 1e9
ans+= (values(b)[a+1]-48)* 1e8
ans+= (values(b)[a+2]-48)* 1e7
ans+= (values(b)[a+3]-48)* 1e6
ans+= (values(b)[a+4]-48)* 1e5
ans+= (values(b)[a+5]-48)* 1e4
ans+= (values(b)[a+6]-48)* 1e3
ans+= (values(b)[a+7]-48)* 1e2
ans+= (values(b)[a+8]-48)* 1e1
ans+= (values(b)[a+9]-48)* 1

with:
ans = values(b) [ a to a+9 ]
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Squares

Post by dafhi »

@dodicat - oh you saw that one :D no it was 4th of July, Independence Day here in the U.S.

Albert I'll whip up a UDT when I get some time
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Squares

Post by dafhi »

made a funct instead of udt

Code: Select all

function myfunc(byref st as string, s as long=1, e as long = 0, add as long = 0) as longint
  if e < s then e = len(st)
  dim as longint  decim = 1, ans
  var bas = e+s-1
  for i as long = s to e
    ans += (st[bas-i]+add)*decim
    decim *= 10
  next
  return ans
end function

var b = 1
dim as string values(b)

values(b) = "12345"

? myfunc( values(b), 2, 4, -48 )

sleep
Last edited by dafhi on Jul 23, 2017 2:00, edited 1 time in total.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

Hi Dafhi.
Where s2="12345"
If I put myfunc(s2,1,4,-48) I get 2345.
Shouldn't it be 1234.
I have tweaked your function to get 1234.

Code: Select all

 
'dafhi's function adjusted.
function myfunc2(byref st as string, s as long=1, e as long = 0, add as byte = 0) as ulongint
    s=iif(s<=0,1,s)
    #define  L  *Cast(integer Ptr,Cast(integer,@st)+sizeof(integer))' same as len(st)
     if e < s orelse e > L then e = L
  dim as ulongint  decim = 1, ans
  for i as long = e-1 to s-1 step -1
    ans += (st[i]+add)*decim
    decim = (decim ) Shl 3 +(decim ) Shl 1 ' same as decim*=10
  next
  return ans
end function

dim as string s2="12345"

dim as double t
dim as ulongint g
t=timer
for n as long=1 to 1000000
    g=myfunc2(s2,1,4,-48)
    'g=valulng(mid(s2,1,4))
next
print timer-t,g
sleep
 
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Dodicat

I'm working on a new multiplier using addition... so far it just does half the answer...

When i get it returning the whole answer i'll convert it to pointers to make it fast..

Code: Select all


DECLARE FUNCTION multiplier_7(byref num1 as string, byref num2 as string) as string

screen 19

do 
    
    dim as string num1
    dim as string num2
    for a as longint = 1 to 8 step 1
        num1+=str(int(rnd*10))
    next
    for a as longint = 1 to 8 step 1
        num2+=str(int(rnd*10))
    next
    if num2 < num1 then swap num1 , num2
        
    print
    print num1
    print num2
    print valulng(num1) * valulng(num2)
    
    dim as string short_mul( 0 to 9 )
    for a as ubyte = 0 to 9 step 1
        dim as string value=""
        dim as ubyte mul
        dim as ubyte carry
        dim as string check=""
        for b as longint = len(num1)-1  to 0 step -1
                mul = ( ( num1[ b ] -48 ) * a ) + carry
                carry = 0
                check = right("00" + str(mul) , 2)
                carry = val(left(check,1))
                check = right(check,1)
                value = str(check) + value
        next
        if carry <> 0 then value = str(carry) + value
        short_mul(a) = value
    next
    
    dim as longint max = len(short_mul(9))
    for a as ubyte = 0 to 9 step 1
        if len(short_mul(a)) < max then short_mul(a) = "0" + short_mul(a)
    next
    
    dim as string answer = ""
    dim as longint value = 0 
    dim as ubyte vals = 0
    dim as longint place = 0
    dim as longint hold = 0
    dim as longint locat = 0
    dim as string carry = ""
    do
        carry=""
        for a as longint = hold to 0 step -1
            vals = val( mid( num2 , len(num2) - locat , 1 ) )
            value+= val( mid( short_mul( vals ) , len( short_mul(0) ) - a , 1 ) ) 
            locat+=1
            'print value , locat , a
        next
        locat = 0
        hold+=1
        
        dim as string check = right( string( 16,"0") + str(value) , 16 )
        dim as string rght = right( check , 1 )
        carry = left( check , 15 )
        value = valulng(carry)
        answer= rght + answer
        
    loop until hold = len(num2)
    
    'answer = str( valulng(carry)) + answer
    
    print string( len(str(valulng(num1) * valulng(num2)) ) - len(answer) ,"_") + answer
    
        
    sleep
    
loop until inkey=chr(27)

sleep
end





'===============================================================================
'===============================================================================
function multiplier_7(byref num1 as string, byref num2 as string) as string
    
    dim as string number1,number2
    dim as string answer,outtext
    
    dim as string int1,frac1,int2,frac2
    dim as ulongint dec,dec1,len1,len2
    dim as string str1
    
    dim as string sign1,sign2,outsign
    
    number1 = num1
    number2 = num2
    
    sign1 = left(number1,1)
    if sign1 = "+" or sign1 = "-" then number1 = mid(number1,2) else sign1 = ""
    
    sign2 = left(number2,1)
    if sign2 = "+" or sign2 = "-" then number2 = mid(number2,2) else sign2 = ""
    
    if (sign1 = sign2) then outsign = ""
    if (sign1 <> sign2) then outsign = "-"
    
    dec = instr(1,number1,".")
    if dec > 0 then 
        int1 = left(number1,dec-1)
        frac1 = mid(number1,dec+1)
    else
        int1 = number1
        frac1 = ""
    end if
    
    dec = instr(1,number2,".")
    if dec > 0 then 
        int2 = left(number2,dec-1)
        frac2 = mid(number2,dec+1)
    else
        int2 = number2
        frac2 = ""
    end if

    dec = len(frac1)+len(frac2)
    number1 = int1+frac1
    number2 = int2+frac2

    'swap numbers so that bigger number is number1 and smaller is number2
    if len(number2) > len(number1) then swap number1,number2
    if len(number1) = len(number2) then 
        if val(left(number2,1)) > val(left(number1,1)) then swap number1,number2
    end if

    'make numbers equal multiple of 7 bytes
    do
        str1 = str(len(number1)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number1 = "0" + number1
    loop until dec1 = 0
    do
        str1 = str(len(number2)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number2 = "0" + number2
    loop until dec1 = 0
    
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number1)*8,chr(0))
    dim as ulongint ptr ulp1 
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number1)-1 step 7
        val1 = (number1[a+0]-48)*1000000ull
        val1+= (number1[a+1]-48)*100000ull
        val1+= (number1[a+2]-48)*10000ull
        val1+= (number1[a+3]-48)*1000ull
        val1+= (number1[a+4]-48)*100ull
        val1+= (number1[a+5]-48)*10ull
        val1+= (number1[a+6]-48)*1ull
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number1 = left(n1,len_1)
    n1=""
    
    'convert the numeric strings to use pointers
    'convert number2
    dim as string n2 = string(len(number2)*8,chr(0))
    dim as ulongint ptr ulp2
    ulp2 = cptr(ulongint ptr,strptr(n2))
    dim as longint val2
    dim as longint len_2 = 0
    for a = 0 to len(number2)-1 step 7
        val2 = (number2[a+0]-48)*1000000ull
        val2+= (number2[a+1]-48)*100000ull
        val2+= (number2[a+2]-48)*10000ull
        val2+= (number2[a+3]-48)*1000ull
        val2+= (number2[a+4]-48)*100ull
        val2+= (number2[a+5]-48)*10ull
        val2+= (number2[a+6]-48)*1ull
        *ulp2 = val2
        ulp2+=1
        len_2+=8
    next
    number2 = left(n2,len_2)
    n2=""
    
    'create accumulator
    answer = string( len(number1) + len(number2) + 8 , chr(0) ) 
    'dimension vars for the mul
    dim as longint ptr start1,stop1,start2,stop2 'use longint because the pointers go negative
    dim as longint ptr chk_1 , chk_2
    dim as longint ptr inc1,inc2
    dim as longint ptr outplace
    dim as ulongint carry
    dim as ulongint total
    dim as ulongint blocknumber1 = len(number1)/8
    dim as ulongint blocknumber2 = len(number2)/8
    dim as ulongint outblocks = len(answer)/8
    
    'set initial accumulator place
    outplace = cptr(longint ptr , strptr(answer)) + (outblocks - 1)
    'set initial pointers into number1 
    start1 = cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    stop1 =  cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    'set initial pointers into number2
    start2 = cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    stop2 =  cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    'set comparison to beg of numbers
    chk_1 = cptr( longint ptr , strptr(number1))
    chk_2 = cptr( longint ptr , strptr(number2))
    
    'zero the carry
    carry = 0
    
    'begin looping thru strings multiplying
    do
        'set total to zero
        total = 0
        'we are going to be incrementing thru number2 while decrementing thru number1
        'working in opposite directions from start1 to stop1 and start2 to stop2
        'inc1 works from right to left in the top number1 string
        'inc2 works from start2 to stop 2, in the bottom number2 string, decrementing each loop.
        inc1 = start1
        inc2 = start2
        do
            total += *inc1 * *inc2
            inc1-= 1
            inc2+= 1
        loop until inc2 = stop2+1
    
        total = total + carry
        carry = total \ 1e7
        *outplace = total mod 1e7
        '*outplace = imod(total , 1e7)
        
        outplace -= 1
        
        'each loop we need to decrement stop1
        'if stop1 goes negative we reset it to zero and decrement stop2
        stop1 -= 1
        if stop1 < chk_1 then
            stop1 += 1
            stop2 -=1
            if stop2 < chk_2 then stop2+= 1
        end if
        'each loop we decrement start2 to the left
        start2 -= 1
        'if start2 goes negative we reset it to zero and decrement start1
        'start1 is the rightmost digit of number1 we need to multiply
        if start2 < chk_2 then
            start2 += 1
            start1 -= 1
            if start1 < chk_1 then start1+=1
        end if
    
    loop until outplace = cptr(ulongint ptr,strptr(answer))+1
    
    'put in the carry at the end
    if carry > 0  then *outplace = carry else *outplace = 0
    
    'convert answer back to ascii
    for a as ulongint = 1 to outblocks-1 step 1
        val1 = *outplace
        outplace +=1
        outtext = outtext + right("0000000" + str(val1),7)
    next    

    'put in the decimal point
    outtext = left(outtext,len(outtext)-dec) + "." +  mid(outtext,(len(outtext)-dec)+1)
    'trim leading zeros
    outtext = trim(outtext,"0") 'if multiplying by 1, we have a zero in front.
    outtext = outsign + outtext

    return outtext

end function
'===============================================================================
'===============================================================================

albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Dodicat

I got it returning the whole answer and it's 100% accurate... takes 3.57 seconds to do 1000 x1000 digits..

Code: Select all


DECLARE FUNCTION multiplier_7(byref num1 as string, byref num2 as string) as string

screen 19

do 
    
    dim as string num1
    dim as string num2
    for a as longint = 1 to 100 step 1
        num1+=str(int(rnd*10))
    next
    for a as longint = 1 to 100 step 1
        num2+=str(int(rnd*10))
    next
    if len(num2) < len(num1)  then swap num1 , num2
        
    print
    print num1
    print num2
    
    dim as double t1 , t2 , t3 , t4
    
    t1 = timer
    
    dim as string short_mul( 0 to 9 )
    for a as ubyte = 0 to 9 step 1
        dim as string value=""
        dim as ubyte mul
        dim as ubyte carry
        dim as string check=""
        for b as longint = len(num1)-1  to 0 step -1
                mul = ( ( num1[ b ] -48 ) * a ) + carry
                carry = 0
                check = right("00" + str(mul) , 2)
                carry = val(left(check,1))
                check = right(check,1)
                value = str(check) + value
        next
        if carry <> 0 then value = str(carry) + value
        short_mul(a) = value
    next
    
    dim as longint max = len(short_mul(9))
    for a as ubyte = 0 to 9 step 1
        if len(short_mul(a)) < max then short_mul(a) = "0" + short_mul(a)
    next
    
    dim as string answer = ""
    dim as longint value = 0 
    dim as ubyte vals = 0
    dim as longint place = 0
    dim as longint hold = 0
    dim as longint locat = 0
    dim as string carry = ""
    dim as longint start = 0
    dim as longint ends = 0
    dim as longint steps = -1
    dim as byte toggle = 0
    do
        carry=""
        for a as longint = hold to 0 step -1
            if len(num2)-1-locat >-1 and len(num2)-1-locat <= len(num2)-1 then 
                'vals = val( mid( num2 , len(num2) - locat , 1 ) )
                vals = num2[ len(num2)-1-locat ] - 48
                'value+= val( mid( short_mul( vals ) , len( short_mul(0) ) - a , 1 ) ) 
                if a >=0 and a <= len(short_mul(vals))-1 then value+= short_mul( vals )[ len( short_mul(0) ) - 1- a] -48
            end if
            locat+= 1
         '  print value , locat , a
        next
        locat=0
        hold+= 1
        dim as string check = right( string( 16,"0") + str(value) , 16 )
        dim as string rght = right( check , 1 )
        carry = left( check , 15 )
        value = valulng(carry)
        answer= rght + answer
    loop until hold = len(num2)+len(num1)
    
    answer = ltrim(answer,"0")
    
    t2 = timer
    
    print answer
    
    t3 = timer
        dim as string real_answer = multiplier_7( num1 , num2 )
        real_answer = rtrim( real_answer,".")
    t4 = timer
    
    print real_answer
    print
    print "Time = " ; t2 - t1
    print "Time = " ; t4 - t3
        
    sleep
    
loop until inkey=chr(27)

sleep
end





'===============================================================================
'===============================================================================
function multiplier_7(byref num1 as string, byref num2 as string) as string
    
    dim as string number1,number2
    dim as string answer,outtext
    
    dim as string int1,frac1,int2,frac2
    dim as ulongint dec,dec1,len1,len2
    dim as string str1
    dim as string sign1,sign2,outsign
    
    number1 = num1
    number2 = num2
    
    sign1 = left(number1,1)
    if sign1 = "+" or sign1 = "-" then number1 = mid(number1,2) else sign1 = ""
    
    sign2 = left(number2,1)
    if sign2 = "+" or sign2 = "-" then number2 = mid(number2,2) else sign2 = ""
    
    if (sign1 = sign2) then outsign = ""
    if (sign1 <> sign2) then outsign = "-"
    
    dec = instr(1,number1,".")
    if dec > 0 then 
        int1 = left(number1,dec-1)
        frac1 = mid(number1,dec+1)
    else
        int1 = number1
        frac1 = ""
    end if
    
    dec = instr(1,number2,".")
    if dec > 0 then 
        int2 = left(number2,dec-1)
        frac2 = mid(number2,dec+1)
    else
        int2 = number2
        frac2 = ""
    end if

    dec = len(frac1)+len(frac2)
    number1 = int1+frac1
    number2 = int2+frac2

    'swap numbers so that bigger number is number1 and smaller is number2
    if len(number2) > len(number1) then swap number1,number2
    if len(number1) = len(number2) then 
        if val(left(number2,1)) > val(left(number1,1)) then swap number1,number2
    end if

    'make numbers equal multiple of 7 bytes
    do
        str1 = str(len(number1)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number1 = "0" + number1
    loop until dec1 = 0
    do
        str1 = str(len(number2)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number2 = "0" + number2
    loop until dec1 = 0
    
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number1)*8,chr(0))
    dim as ulongint ptr ulp1 
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number1)-1 step 7
        val1 = (number1[a+0]-48)*1000000ull
        val1+= (number1[a+1]-48)*100000ull
        val1+= (number1[a+2]-48)*10000ull
        val1+= (number1[a+3]-48)*1000ull
        val1+= (number1[a+4]-48)*100ull
        val1+= (number1[a+5]-48)*10ull
        val1+= (number1[a+6]-48)*1ull
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number1 = left(n1,len_1)
    n1=""
    
    'convert the numeric strings to use pointers
    'convert number2
    dim as string n2 = string(len(number2)*8,chr(0))
    dim as ulongint ptr ulp2
    ulp2 = cptr(ulongint ptr,strptr(n2))
    dim as longint val2
    dim as longint len_2 = 0
    for a = 0 to len(number2)-1 step 7
        val2 = (number2[a+0]-48)*1000000ull
        val2+= (number2[a+1]-48)*100000ull
        val2+= (number2[a+2]-48)*10000ull
        val2+= (number2[a+3]-48)*1000ull
        val2+= (number2[a+4]-48)*100ull
        val2+= (number2[a+5]-48)*10ull
        val2+= (number2[a+6]-48)*1ull
        *ulp2 = val2
        ulp2+=1
        len_2+=8
    next
    number2 = left(n2,len_2)
    n2=""
    
    'create accumulator
    answer = string( len(number1) + len(number2) + 8 , chr(0) ) 
    'dimension vars for the mul
    dim as longint ptr start1,stop1,start2,stop2 'use longint because the pointers go negative
    dim as longint ptr chk_1 , chk_2
    dim as longint ptr inc1,inc2
    dim as longint ptr outplace
    dim as ulongint carry
    dim as ulongint total
    dim as ulongint blocknumber1 = len(number1)/8
    dim as ulongint blocknumber2 = len(number2)/8
    dim as ulongint outblocks = len(answer)/8
    
    'set initial accumulator place
    outplace = cptr(longint ptr , strptr(answer)) + (outblocks - 1)
    'set initial pointers into number1 
    start1 = cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    stop1 =  cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    'set initial pointers into number2
    start2 = cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    stop2 =  cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    'set comparison to beg of numbers
    chk_1 = cptr( longint ptr , strptr(number1))
    chk_2 = cptr( longint ptr , strptr(number2))
    
    'zero the carry
    carry = 0
    
    'begin looping thru strings multiplying
    do
        'set total to zero
        total = 0
        'we are going to be incrementing thru number2 while decrementing thru number1
        'working in opposite directions from start1 to stop1 and start2 to stop2
        'inc1 works from right to left in the top number1 string
        'inc2 works from start2 to stop 2, in the bottom number2 string, decrementing each loop.
        inc1 = start1
        inc2 = start2
        do
            total += *inc1 * *inc2
            inc1-= 1
            inc2+= 1
        loop until inc2 = stop2+1
    
        total = total + carry
        carry = total \ 1e7
        *outplace = total mod 1e7
        '*outplace = imod(total , 1e7)
        
        outplace -= 1
        
        'each loop we need to decrement stop1
        'if stop1 goes negative we reset it to zero and decrement stop2
        stop1 -= 1
        if stop1 < chk_1 then
            stop1 += 1
            stop2 -=1
            if stop2 < chk_2 then stop2+= 1
        end if
        'each loop we decrement start2 to the left
        start2 -= 1
        'if start2 goes negative we reset it to zero and decrement start1
        'start1 is the rightmost digit of number1 we need to multiply
        if start2 < chk_2 then
            start2 += 1
            start1 -= 1
            if start1 < chk_1 then start1+=1
        end if
    
    loop until outplace = cptr(ulongint ptr,strptr(answer))+1
    
    'put in the carry at the end
    if carry > 0  then *outplace = carry else *outplace = 0
    
    'convert answer back to ascii
    for a as ulongint = 1 to outblocks-1 step 1
        val1 = *outplace
        outplace +=1
        outtext = outtext + right("0000000" + str(val1),7)
    next    

    'put in the decimal point
    outtext = left(outtext,len(outtext)-dec) + "." +  mid(outtext,(len(outtext)-dec)+1)
    'trim leading zeros
    outtext = trim(outtext,"0") 'if multiplying by 1, we have a zero in front.
    outtext = outsign + outtext

    return outtext

end function
'===============================================================================
'===============================================================================

dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

Nice Albert.
Here is an adaptation of dafhi's function.
ValMid
It replaced your val(mid( ...

I have set 1000 X 1000

Code: Select all

DECLARE FUNCTION multiplier_7(byref num1 as string, byref num2 as string) as string


'From Dafhi's idea
function ValMid(byref st as string, s as long, e as long ) as ulongint
    's=iif(s<=0,1,s)
   if s<=0 then  return 0
    var L=*Cast(integer Ptr,Cast(integer,@st)+sizeof(integer))' same as len(st)
  if  e > L then e = L-1
  dim as longint  decim = 1, ans
  for i as long = e-1 + s-1 to s-1 step -1
    ans += (st[i]-48)*decim
    decim = (decim ) Shl 3 +(decim ) Shl 1 ' same as decim*=10
  next
  return (ans)
end function

'screen 19

do 
    
    dim as string num1
    dim as string num2
    for a as longint = 1 to 1000 step 1
        num1+=str(int(rnd*10))
    next
    for a as longint = 1 to 1000 step 1
        num2+=str(int(rnd*10))
    next
    if len(num2) < len(num1)  then swap num1 , num2
        
    print
    print num1
    print num2
    print
    dim as double t1 , t2
    
    t1 = timer
    
    dim as string short_mul( 0 to 9 )
    for a as ubyte = 0 to 9 step 1
        dim as string value=""
        dim as ubyte mul
        dim as ubyte carry
        dim as string check=""
        for b as longint = len(num1)-1  to 0 step -1
                mul = ( ( num1[ b ] -48 ) * a ) + carry
                carry = 0
                check = right("00" + str(mul) , 2)
                carry = val(left(check,1))
                check = right(check,1)
                value = str(check) + value
        next
        if carry <> 0 then value = str(carry) + value
        short_mul(a) = value
    next
    
    dim as longint max = len(short_mul(9))
    for a as ubyte = 0 to 9 step 1
        if len(short_mul(a)) < max then short_mul(a) = "0" + short_mul(a)
    next
    
    dim as string answer = ""
    dim as longint value = 0 
    dim as ubyte vals = 0
    dim as longint place = 0
    dim as longint hold = 0
    dim as longint locat = 0
    dim as string carry = ""
    dim as longint start = 0
    dim as longint ends = 0
    dim as longint steps = -1
    dim as byte toggle = 0
    do
        carry=""
        for a as longint = hold to 0 step -1
            vals = valmid( num2 , len(num2) - locat , 1 )                     '**************
            
            value+= valmid( short_mul( vals ) , len( short_mul(0) ) - a , 1 ) '************* 
            locat+= 1
        '    print value , locat , a
        next
        locat=0
        hold+= 1
        dim as string check = right( string( 16,"0") + str(value) , 16 )
        dim as string rght = right( check , 1 )
        carry = left( check , 15 )
        value = valulng(carry)
        answer= rght + answer
    loop until hold = len(num2)+len(num1)
    
    answer = ltrim(answer,"0")
    
    t2 = timer
    
    print answer
    print
    dim as string real_answer = multiplier_7( num1 , num2 )
    real_answer = rtrim( real_answer,".")
    print real_answer
    
    print
    print "Time = " ; t2 - t1
        
    sleep
    
loop until inkey=chr(27)

sleep
end





'===============================================================================
'===============================================================================
function multiplier_7(byref num1 as string, byref num2 as string) as string
    
    dim as string number1,number2
    dim as string answer,outtext
    
    dim as string int1,frac1,int2,frac2
    dim as ulongint dec,dec1,len1,len2
    dim as string str1
    dim as string sign1,sign2,outsign
    
    number1 = num1
    number2 = num2
    
    sign1 = left(number1,1)
    if sign1 = "+" or sign1 = "-" then number1 = mid(number1,2) else sign1 = ""
    
    sign2 = left(number2,1)
    if sign2 = "+" or sign2 = "-" then number2 = mid(number2,2) else sign2 = ""
    
    if (sign1 = sign2) then outsign = ""
    if (sign1 <> sign2) then outsign = "-"
    
    dec = instr(1,number1,".")
    if dec > 0 then 
        int1 = left(number1,dec-1)
        frac1 = mid(number1,dec+1)
    else
        int1 = number1
        frac1 = ""
    end if
    
    dec = instr(1,number2,".")
    if dec > 0 then 
        int2 = left(number2,dec-1)
        frac2 = mid(number2,dec+1)
    else
        int2 = number2
        frac2 = ""
    end if

    dec = len(frac1)+len(frac2)
    number1 = int1+frac1
    number2 = int2+frac2

    'swap numbers so that bigger number is number1 and smaller is number2
    if len(number2) > len(number1) then swap number1,number2
    if len(number1) = len(number2) then 
        if val(left(number2,1)) > val(left(number1,1)) then swap number1,number2
    end if

    'make numbers equal multiple of 7 bytes
    do
        str1 = str(len(number1)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number1 = "0" + number1
    loop until dec1 = 0
    do
        str1 = str(len(number2)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number2 = "0" + number2
    loop until dec1 = 0
    
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number1)*8,chr(0))
    dim as ulongint ptr ulp1 
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number1)-1 step 7
        val1 = (number1[a+0]-48)*1000000ull
        val1+= (number1[a+1]-48)*100000ull
        val1+= (number1[a+2]-48)*10000ull
        val1+= (number1[a+3]-48)*1000ull
        val1+= (number1[a+4]-48)*100ull
        val1+= (number1[a+5]-48)*10ull
        val1+= (number1[a+6]-48)*1ull
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number1 = left(n1,len_1)
    n1=""
    
    'convert the numeric strings to use pointers
    'convert number2
    dim as string n2 = string(len(number2)*8,chr(0))
    dim as ulongint ptr ulp2
    ulp2 = cptr(ulongint ptr,strptr(n2))
    dim as longint val2
    dim as longint len_2 = 0
    for a = 0 to len(number2)-1 step 7
        val2 = (number2[a+0]-48)*1000000ull
        val2+= (number2[a+1]-48)*100000ull
        val2+= (number2[a+2]-48)*10000ull
        val2+= (number2[a+3]-48)*1000ull
        val2+= (number2[a+4]-48)*100ull
        val2+= (number2[a+5]-48)*10ull
        val2+= (number2[a+6]-48)*1ull
        *ulp2 = val2
        ulp2+=1
        len_2+=8
    next
    number2 = left(n2,len_2)
    n2=""
    
    'create accumulator
    answer = string( len(number1) + len(number2) + 8 , chr(0) ) 
    'dimension vars for the mul
    dim as longint ptr start1,stop1,start2,stop2 'use longint because the pointers go negative
    dim as longint ptr chk_1 , chk_2
    dim as longint ptr inc1,inc2
    dim as longint ptr outplace
    dim as ulongint carry
    dim as ulongint total
    dim as ulongint blocknumber1 = len(number1)/8
    dim as ulongint blocknumber2 = len(number2)/8
    dim as ulongint outblocks = len(answer)/8
    
    'set initial accumulator place
    outplace = cptr(longint ptr , strptr(answer)) + (outblocks - 1)
    'set initial pointers into number1 
    start1 = cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    stop1 =  cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    'set initial pointers into number2
    start2 = cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    stop2 =  cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    'set comparison to beg of numbers
    chk_1 = cptr( longint ptr , strptr(number1))
    chk_2 = cptr( longint ptr , strptr(number2))
    
    'zero the carry
    carry = 0
    
    'begin looping thru strings multiplying
    do
        'set total to zero
        total = 0
        'we are going to be incrementing thru number2 while decrementing thru number1
        'working in opposite directions from start1 to stop1 and start2 to stop2
        'inc1 works from right to left in the top number1 string
        'inc2 works from start2 to stop 2, in the bottom number2 string, decrementing each loop.
        inc1 = start1
        inc2 = start2
        do
            total += *inc1 * *inc2
            inc1-= 1
            inc2+= 1
        loop until inc2 = stop2+1
    
        total = total + carry
        carry = total \ 1e7
        *outplace = total mod 1e7
        '*outplace = imod(total , 1e7)
        
        outplace -= 1
        
        'each loop we need to decrement stop1
        'if stop1 goes negative we reset it to zero and decrement stop2
        stop1 -= 1
        if stop1 < chk_1 then
            stop1 += 1
            stop2 -=1
            if stop2 < chk_2 then stop2+= 1
        end if
        'each loop we decrement start2 to the left
        start2 -= 1
        'if start2 goes negative we reset it to zero and decrement start1
        'start1 is the rightmost digit of number1 we need to multiply
        if start2 < chk_2 then
            start2 += 1
            start1 -= 1
            if start1 < chk_1 then start1+=1
        end if
    
    loop until outplace = cptr(ulongint ptr,strptr(answer))+1
    
    'put in the carry at the end
    if carry > 0  then *outplace = carry else *outplace = 0
    
    'convert answer back to ascii
    for a as ulongint = 1 to outblocks-1 step 1
        val1 = *outplace
        outplace +=1
        outtext = outtext + right("0000000" + str(val1),7)
    next    

    'put in the decimal point
    outtext = left(outtext,len(outtext)-dec) + "." +  mid(outtext,(len(outtext)-dec)+1)
    'trim leading zeros
    outtext = trim(outtext,"0") 'if multiplying by 1, we have a zero in front.
    outtext = outsign + outtext

    return outtext

end function
'===============================================================================
'===============================================================================
 
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: Squares

Post by srvaldez »

hi dodicat, that's a 18x speed boost.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

Another speed boost:

Code: Select all

DECLARE FUNCTION multiplier_7(byref num1 as string, byref num2 as string) as string



#define strlen(st) *Cast(integer Ptr,Cast(integer,@st)+sizeof(integer))
'screen 19

do 
    
    dim as string num1
    dim as string num2
    for a as longint = 1 to 1000 step 1
        num1+=str(int(rnd*10))
    next
    for a as longint = 1 to 1000 step 1
        num2+=str(int(rnd*10))
    next
    if len(num2) < len(num1)  then swap num1 , num2
        
    print
    print num1
    print num2
    print
    dim as double t1 , t2
    
    t1 = timer
    
    dim as string short_mul( 0 to 9 )
    for a as ubyte = 0 to 9 step 1
        dim as string value=""
        dim as ubyte mul
        dim as ubyte carry
        dim as string check=""
        for b as longint = len(num1)-1  to 0 step -1
                mul = ( ( num1[ b ] -48 ) * a ) + carry
                carry = 0
                check = right("00" + str(mul) , 2)
                carry = val(left(check,1))
                check = right(check,1)
                value = str(check) + value
        next
        if carry <> 0 then value = str(carry) + value
        short_mul(a) = value
    next
    
    dim as longint max = len(short_mul(9))
    for a as ubyte = 0 to 9 step 1
        if len(short_mul(a)) < max then short_mul(a) = "0" + short_mul(a)
    next
    
    dim as string answer = ""
    dim as longint value = 0 
    dim as ubyte vals = 0
    dim as longint place = 0
    dim as longint hold = 0
    dim as longint locat = 0
    dim as string carry = ""
    dim as longint start = 0
    dim as longint ends = 0
    dim as longint steps = -1
    dim as byte toggle = 0
    do
        carry=""
        for a as longint = hold to 0 step -1
           var tmp= strlen(num2) - locat
           if tmp<=0 then vals=0 else vals=num2[tmp-1]-48
           tmp= strlen( short_mul(0) ) - a
           if tmp<=0 then tmp=0 else tmp= short_mul( vals )[tmp-1]-48
            value+= tmp
            locat+= 1
        '    print value , locat , a
        next
        locat=0
        hold+= 1
        dim as string check = right( string( 16,"0") + str(value) , 16 )
        dim as string rght = right( check , 1 )
        carry = left( check , 15 )
        value = valulng(carry)
        answer= rght + answer
    loop until hold = len(num2)+len(num1)
    
    answer = ltrim(answer,"0")
    
    t2 = timer
    
    print answer
    print
    dim as string real_answer = multiplier_7( num1 , num2 )
    real_answer = rtrim( real_answer,".")
    print real_answer
    
    print
    print "Time = " ; t2 - t1
        
    sleep
    
loop until inkey=chr(27)

sleep
end





'===============================================================================
'===============================================================================
function multiplier_7(byref num1 as string, byref num2 as string) as string
    
    dim as string number1,number2
    dim as string answer,outtext
    
    dim as string int1,frac1,int2,frac2
    dim as ulongint dec,dec1,len1,len2
    dim as string str1
    dim as string sign1,sign2,outsign
    
    number1 = num1
    number2 = num2
    
    sign1 = left(number1,1)
    if sign1 = "+" or sign1 = "-" then number1 = mid(number1,2) else sign1 = ""
    
    sign2 = left(number2,1)
    if sign2 = "+" or sign2 = "-" then number2 = mid(number2,2) else sign2 = ""
    
    if (sign1 = sign2) then outsign = ""
    if (sign1 <> sign2) then outsign = "-"
    
    dec = instr(1,number1,".")
    if dec > 0 then 
        int1 = left(number1,dec-1)
        frac1 = mid(number1,dec+1)
    else
        int1 = number1
        frac1 = ""
    end if
    
    dec = instr(1,number2,".")
    if dec > 0 then 
        int2 = left(number2,dec-1)
        frac2 = mid(number2,dec+1)
    else
        int2 = number2
        frac2 = ""
    end if

    dec = len(frac1)+len(frac2)
    number1 = int1+frac1
    number2 = int2+frac2

    'swap numbers so that bigger number is number1 and smaller is number2
    if len(number2) > len(number1) then swap number1,number2
    if len(number1) = len(number2) then 
        if val(left(number2,1)) > val(left(number1,1)) then swap number1,number2
    end if

    'make numbers equal multiple of 7 bytes
    do
        str1 = str(len(number1)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number1 = "0" + number1
    loop until dec1 = 0
    do
        str1 = str(len(number2)/7)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number2 = "0" + number2
    loop until dec1 = 0
    
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number1)*8,chr(0))
    dim as ulongint ptr ulp1 
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number1)-1 step 7
        val1 = (number1[a+0]-48)*1000000ull
        val1+= (number1[a+1]-48)*100000ull
        val1+= (number1[a+2]-48)*10000ull
        val1+= (number1[a+3]-48)*1000ull
        val1+= (number1[a+4]-48)*100ull
        val1+= (number1[a+5]-48)*10ull
        val1+= (number1[a+6]-48)*1ull
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number1 = left(n1,len_1)
    n1=""
    
    'convert the numeric strings to use pointers
    'convert number2
    dim as string n2 = string(len(number2)*8,chr(0))
    dim as ulongint ptr ulp2
    ulp2 = cptr(ulongint ptr,strptr(n2))
    dim as longint val2
    dim as longint len_2 = 0
    for a = 0 to len(number2)-1 step 7
        val2 = (number2[a+0]-48)*1000000ull
        val2+= (number2[a+1]-48)*100000ull
        val2+= (number2[a+2]-48)*10000ull
        val2+= (number2[a+3]-48)*1000ull
        val2+= (number2[a+4]-48)*100ull
        val2+= (number2[a+5]-48)*10ull
        val2+= (number2[a+6]-48)*1ull
        *ulp2 = val2
        ulp2+=1
        len_2+=8
    next
    number2 = left(n2,len_2)
    n2=""
    
    'create accumulator
    answer = string( len(number1) + len(number2) + 8 , chr(0) ) 
    'dimension vars for the mul
    dim as longint ptr start1,stop1,start2,stop2 'use longint because the pointers go negative
    dim as longint ptr chk_1 , chk_2
    dim as longint ptr inc1,inc2
    dim as longint ptr outplace
    dim as ulongint carry
    dim as ulongint total
    dim as ulongint blocknumber1 = len(number1)/8
    dim as ulongint blocknumber2 = len(number2)/8
    dim as ulongint outblocks = len(answer)/8
    
    'set initial accumulator place
    outplace = cptr(longint ptr , strptr(answer)) + (outblocks - 1)
    'set initial pointers into number1 
    start1 = cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    stop1 =  cptr(longint ptr , strptr(number1))+(blocknumber1-1)
    'set initial pointers into number2
    start2 = cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    stop2 =  cptr(longint ptr , strptr(number2))+(blocknumber2-1)
    'set comparison to beg of numbers
    chk_1 = cptr( longint ptr , strptr(number1))
    chk_2 = cptr( longint ptr , strptr(number2))
    
    'zero the carry
    carry = 0
    
    'begin looping thru strings multiplying
    do
        'set total to zero
        total = 0
        'we are going to be incrementing thru number2 while decrementing thru number1
        'working in opposite directions from start1 to stop1 and start2 to stop2
        'inc1 works from right to left in the top number1 string
        'inc2 works from start2 to stop 2, in the bottom number2 string, decrementing each loop.
        inc1 = start1
        inc2 = start2
        do
            total += *inc1 * *inc2
            inc1-= 1
            inc2+= 1
        loop until inc2 = stop2+1
    
        total = total + carry
        carry = total \ 1e7
        *outplace = total mod 1e7
        '*outplace = imod(total , 1e7)
        
        outplace -= 1
        
        'each loop we need to decrement stop1
        'if stop1 goes negative we reset it to zero and decrement stop2
        stop1 -= 1
        if stop1 < chk_1 then
            stop1 += 1
            stop2 -=1
            if stop2 < chk_2 then stop2+= 1
        end if
        'each loop we decrement start2 to the left
        start2 -= 1
        'if start2 goes negative we reset it to zero and decrement start1
        'start1 is the rightmost digit of number1 we need to multiply
        if start2 < chk_2 then
            start2 += 1
            start1 -= 1
            if start1 < chk_1 then start1+=1
        end if
    
    loop until outplace = cptr(ulongint ptr,strptr(answer))+1
    
    'put in the carry at the end
    if carry > 0  then *outplace = carry else *outplace = 0
    
    'convert answer back to ascii
    for a as ulongint = 1 to outblocks-1 step 1
        val1 = *outplace
        outplace +=1
        outtext = outtext + right("0000000" + str(val1),7)
    next    

    'put in the decimal point
    outtext = left(outtext,len(outtext)-dec) + "." +  mid(outtext,(len(outtext)-dec)+1)
    'trim leading zeros
    outtext = trim(outtext,"0") 'if multiplying by 1, we have a zero in front.
    outtext = outsign + outtext

    return outtext

end function
'===============================================================================
'===============================================================================
  
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: Squares

Post by srvaldez »

hello dodicat :-) that's a 46x boost from the the original.
Locked