• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Help Optimize This Binary Division Algorithm (fully commented)

Status
Not open for further replies.
Right now I have a feeling that this is extremely extremely extremely slow and filled with TONS of operations... hell, the shifting of the array to cut out 0s looks totally awful ;o. Be a pal and help optimize it ^)^. I'm thinking of introducing things like a shifting buffer (displacement thing) so that you don't have to shift it around but rather add the displacement on : ). This'll remove some of the evil evil loops. That's my only idea so far, so you guys come up with some others please : ).


Numbers get smaller towards the end of the divisor and remainder arrays. They are smaller towards the beginning of the dividend array.

The final answer is stored in binaryDividendBuffer with size binaryDividendBufferSize (quotient) and remainder with size remainderSize (remainder). This thing works with 0 bugs, but I have a feeling that it is just really bad :eek:.


Oh yes, the reason I am using a binary division algorithm here is because it is handling really big numbers that are in a base that's a power of 2, meaning that I can quickly and efficiently convert to and from binary : D.

JASS:
    globals
    
        private static integer array binaryDividendBuffer          //division binary buffer #1 (to be divided)
        private static integer binaryDividendBufferSize                //division binary count #1
    
        private static integer array binaryBufferDivisor         //division binary buffer #2 (to divide)
        private static integer binaryBufferDivisorSize               //division binary count #2

    endglobals

Code:
JASS:
    local integer currentDividendDigit = binaryDividendBufferSize       //to be divided int digit count
    local integer tempDigit2                                            //temp digit 2
    local integer tempDigit3                                            //temp digit 3
    local integer array remainder                                       //remainder
    local integer remainderSize = 0                                     //remainder count
    local boolean remainderLessThanDividend                             //is the remainder < divisor?
    local integer binaryBufferDividendDigitOffset                       //subtract -1 or 0 (shift the divisor by 1 bit for extra digit)
    local boolean gatheredDigits                                        //were bits gatheredDigits?
    
    loop
        //gather bits equal to the length of the divisor only if the current remainder isn't equal to length of divisor and there are bits remaining
        set gatheredDigits = false
        set gatheredDigits = remainderSize != binaryBufferDivisorSize and 0 != currentDividendDigit
        if (gatheredDigits) then
            loop
                exitwhen remainderSize == binaryBufferDivisorSize or 0 == currentDividendDigit
                
                set currentDividendDigit = currentDividendDigit - 1
                set remainder[remainderSize] = binaryDividendBuffer[currentDividendDigit]
                set remainderSize = remainderSize + 1
                
                set binaryDividendBuffer[currentDividendDigit] = 0
            endloop
        endif
        
        //if the remainder is smaller than the divisor and there are no bits left to gather, exit
        if (remainderSize < binaryBufferDivisorSize and 0 == currentDividendDigit) then
            set binaryDividendBuffer[currentDividendDigit] = 0
            exitwhen true
        endif
        
        //compare the remainder and the divisor to see which one is greater
        set tempDigit2 = 0
        set remainderLessThanDividend = false
        loop
            set remainderLessThanDividend = remainder[tempDigit2] < binaryBufferDivisor[tempDigit2]
            set tempDigit2 = tempDigit2 + 1
            exitwhen tempDigit2 == binaryBufferDivisorSize or remainderLessThanDividend or remainder[tempDigit2] > binaryBufferDivisor[tempDigit2]
        endloop
        
        //if remainderLessThanDividend and there are bits remaining, add an additional bit
        //set the dividend's current bit to 0 IF bits were gatheredDigits (division taking place)
        //if bits weren't gatheredDigits, then setting it to 0 will set an already divided bit
        if (remainderLessThanDividend) then
            exitwhen 0 == currentDividendDigit
            
            if (gatheredDigits) then
                set binaryDividendBuffer[currentDividendDigit] = 0
            endif
            set currentDividendDigit = currentDividendDigit - 1
            set remainder[remainderSize] = binaryDividendBuffer[currentDividendDigit]
            set remainderSize = remainderSize + 1
            set binaryBufferDividendDigitOffset = -1        //shift divisor's bits by 1 to account for extra digit in remainder
        else
            set binaryBufferDividendDigitOffset = 0         //don't shift as there is no extra digit in remainder
        endif
        
        //subtract
        set binaryDividendBuffer[currentDividendDigit] = 1
        set tempDigit2 = remainderSize
        loop
            set tempDigit2 = tempDigit2 - 1
            
            //if only subtract if the divisor actually has a bit to do subtracting (remainder might have 1 more bit than divisor)
            if (tempDigit2 + binaryBufferDividendDigitOffset > -1) then
                //if the remainder's current bit is remainderLessThanDividend than the divisor's bit, borrow
                if (remainder[tempDigit2] < binaryBufferDivisor[tempDigit2 + binaryBufferDividendDigitOffset]) then
                    set remainder[tempDigit2 - 1] = remainder[tempDigit2 - 1] - 1
                    set remainder[tempDigit2] = remainder[tempDigit2] + 2
                endif
                
                //subtract them
                set remainder[tempDigit2] = remainder[tempDigit2] - binaryBufferDivisor[tempDigit2 + binaryBufferDividendDigitOffset]
            endif
            exitwhen 0 == tempDigit2
        endloop
        
        //cut out all of the 0s in front of the remainder and shift it over
        //000033 -> 33
        //this first loop goes through all of the 0s
        loop
            exitwhen 0 != remainder[tempDigit2] or tempDigit2 == remainderSize
            set tempDigit2 = tempDigit2 + 1
        endloop
        
        //this loop removes the 0s by shifting over
        if (0 < tempDigit2) then
            if (tempDigit2 == remainderSize) then
                set remainderSize = 0
                set remainder[0] = 0
            else
                set tempDigit3 = 0
                set remainderSize = remainderSize-tempDigit2
                loop
                    set remainder[tempDigit3] = remainder[tempDigit3+tempDigit2]
                    set remainder[tempDigit3+tempDigit2] = 0
                    set tempDigit3 = tempDigit3 + 1
                    exitwhen tempDigit3 == remainderSize
                endloop
            endif
        endif
        
        exitwhen 0 == currentDividendDigit
    endloop
    
    //cut out all of the 0s in front of dividend
    loop
        exitwhen 0 != binaryDividendBuffer[binaryDividendBufferSize]
        set binaryDividendBufferSize = binaryDividendBufferSize - 1
    endloop
 
Last edited:
JASS:
    set gatheredDigits = false
    set gatheredDigits = remainderSize != binaryBufferDivisorSize and 0 != currentDividendDigit

Really now? :p

Code:
    27 /     3 =    9
 11011 /    11 = 1001

     4 /     2 =    2
   100 /    10 =   10

    54 /    18 =    3
110110 / 10010 =   11

Hmm.. Let's see what algorithm I can devise just by looking at this...
Holy shit! Those Binary versions work in base10 as well :O
I can't believe I never realized this before ...

edit

Ok, here's one algorithm: (I just came up with it)

Take the integer in binary that has the most number of digits.
Count the number of digits that the second divisor has.

You start finding the digits of the quotient like this:


Code:
nevermind.

Nevermind. It works for any integer, but there shouldn't be a remainder.
 
The algorithm I posted at first worked like this:

Base2:

Code:
Base 2:

101001001 / 1010


101001001
1010
____
   1

101001001
 1010
 ____
    0

101001001
  1010
  ____
     0

101001001
   1010
   ____
      0

101001001
    1010
    ____
       0

101001001
     1010
     ____
        0

=> 100000 (32 in base 10)

Base 10:

329 / 10

32 r9

The only thing I'm having a problem with is finding the remainder...

edit
How could I have been so stupid?
You get the remainder by multiplying the quotient by the divisor and subtracting that from the original number.
Done! :D
 
Ugh- After reading a bit more on it (I decided it was best at first after looking at graphs of it's performance versus other algorithms), I realized that it would be horrible for Jass:
Code:
INPUT: positive integers
  x = (x2k-1 … x1x0)b,
  m = (mk-1 …m1m0)b (with mk-1 !=0), and u = b2k/m.
OUTPUT: r = x mod m.
 1. q1 ← x/bk-1, q2 ← q1 * u, q3 ← q2=bk+1.
 2. r1 ← x mod bk+1, r2 ← q3 * m mod bk+1, r ← r1 - r2.
 3. if r < 0 then r ← r + bk+1.
 4. while r >= m do: r ← r-m.
 5. Return(r).

Pseudo code: (where μ = b2k div m)
  q = ((x div b k+1) μ ) div b k+1 ;
  x = x mod b k+1– (qm) mod b k+1 ;
  if (x < 0) then
      x = x + b k+1 ;
  while (x ≥ m) do
      x = x – m;

I guess Montgomery's will work best:

Code:
for (i=0; i < k; i++) do {
    ti = (xi • m’0) mod b;
    x = x + timbi;
}
if (x ≥ m) then
    x = x – m;

ti is the new digit, b is the dividend, x is the quotient, I don't know about the rest though.
I'm getting this information from http://teal.gmu.edu/courses/ECE646/project/reports_2002/IP-1_report.pdf
 
And what is this?

xi • m’0

x initial dot derivative of m0?


If you're going to put it up, please put it up in like JASS format so that I can read it. Well, that one small part is the only part I can't read actually ^^.



Ok, this algorithm seems good : )
4405940540/2539

44/25 = 1.76*100 = 176
176*10000 = 1760000
1760000 * 2539 = 4468640000
4468640000 - 4405940540 = 62699460

62/25 = 2.48 * 100 = 248
248*100 = 24800
1760000 - 24800 = 1735200
1735200 * 2539 = 4405672800
4405672800 - 4405940540 = -267740

26/25 = 1.04 * 100 = 104
1735200 + 104 = 1735304
1735304 * 2539 = 4405936856
4405936856 - 4405940540 = -3684

36/25 = 1
it is 1, so
3684 - 2539 = r1145
1735304 + 1 = 1735305

1735305 r1145


4 iterations, estimated 300 operations

Current BigInt 2 takes about 2539 operations for the above, so we're looking at an 846.33% speed increase ;D.
 
Last edited:
Hey, that looks awesome :D

In school today, I had some free time, so I started finding ways to use binary for multiplication, division, addition and subtraction. I succeeded, but my algorithms were extremely slow :p

I guess doing the math in Base 32768 should be way more efficient :p

When you said 2539 operations, were you doing them in Base 32768? Because that sounds like a lot :O (Still, it's about 10% of the Op limit)

Random fact: I recently learned that TriggerAddCondition resets the op limit as well.
 
Ok, division is just becoming a pain to debug.


Here is division code
JASS:
library BigInt2 uses Base
    globals
        //BigInt
        private integer ic              //instance count
        private integer array n         //next
        private integer array p         //prev
        private boolean array h         //head
        private integer array v         //value
        
        private boolean mbc
        private integer mbp
        
        //convert string
        private string toBigInt
        private Base strBase
        
        //trigger methods
        private trigger cont
        private trigger divt
        private trigger divt0
        
        private constant integer BASE = 10
    endglobals
    
    private function prn takes string msg returns nothing
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,msg)
    endfunction
    
    //! textmacro BIG_INT_INIT_TRIG takes TRIGGER, FUNCTION
        set $TRIGGER$ = CreateTrigger()
        call TriggerAddCondition($TRIGGER$, Condition(function thistype.$FUNCTION$))
    //! endtextmacro
    //! textmacro BIG_INT_ALLOCATE takes THIS
        if (0 == n[0]) then
            set $THIS$ = ic + 1
            set ic = $THIS$
        else
            set $THIS$ = n[0]
            set n[0] = n[$THIS$]
            set v[$THIS$] = 0
        endif
    //! endtextmacro
    //! textmacro BIG_INT_INIT_HEAD takes THIS
        set n[$THIS$] = $THIS$      //next
        set p[$THIS$] = $THIS$      //prev
        set h[$THIS$] = true        //head
    //! endtextmacro
    //! textmacro BIG_INT_ENQ takes THIS, PREV, NEXT
        set p[$THIS$] = $PREV$
        set n[$THIS$] = $NEXT$
        set p[n[$THIS$]] = $THIS$
        set n[p[$THIS$]] = $THIS$
    //! endtextmacro
    
    //when looking at these macros, consider numbers as stacks. Each node in the stack has size of BASE
    //to go to the next node in the stack, divide by BASE (get remaining digits)
    //to retrieve the current node out of the stack, take the modulos (get current digit)
    //! textmacro BIG_INT_GET_REMAINING_DIGITS takes THIS, TO_POP, BASE
        set $THIS$ = $TO_POP$/$BASE$
    //! endtextmacro
    //! textmacro BIG_INT_ADD_REMAINING_DIGITS takes THIS, TO_POP, BASE
        set $THIS$ = $THIS$ + $TO_POP$/$BASE$
    //! endtextmacro
    //! textmacro BIG_INT_GET_CURRENT_DIGIT takes THIS, DIGITS, BASE
        set $THIS$ = $DIGITS$ - $DIGITS$/$BASE$*$BASE$
    //! endtextmacro
    //! textmacro BIG_INT_ADD_CURRENT_DIGIT takes THIS, DIGITS, BASE
        set $THIS$ = $THIS$ + ($DIGITS$ - $DIGITS$/$BASE$*$BASE$)
    //! endtextmacro
    //! textmacro BIG_INT_STRING_DIGIT_TO_VALUE takes THIS, STRING, POSITION, BASE
        set $THIS$ = $THIS$ + $BASE$.ord(SubString($STRING$, $POSITION$, $POSITION$+1))
    //! endtextmacro
    //! textmacro BIG_INT_REMOVE takes THIS
        set n[p[$THIS$]] = n[$THIS$]
        set p[n[$THIS$]] = p[$THIS$]
    //! endtextmacro
    //! textmacro BIG_INT_DEALLOCATE takes THIS
        set n[$THIS$] = n[0]
        set n[0] = $THIS$
    //! endtextmacro
    private module Init
        private static method onInit takes nothing returns nothing
            set ic = 0
            
            //divide trigger
            //! runtextmacro BIG_INT_INIT_TRIG("divt", "divide2")
            //! runtextmacro BIG_INT_INIT_TRIG("divt0", "divide0")
            
            //string -> BigInt trigger
            //! runtextmacro BIG_INT_INIT_TRIG("cont", "convertString2")
        endmethod
    endmodule
    struct BigInt2 extends array
        static method create takes nothing returns thistype
            local thistype this
            
            //! runtextmacro BIG_INT_ALLOCATE("this")
            //! runtextmacro BIG_INT_INIT_HEAD("this")
            
            return this
        endmethod
        
        private static integer cscd
        private static integer csd
        private static integer cssl
        private static method convertString2 takes nothing returns boolean
            local string str = toBigInt
            local Base base = strBase                   //base that string is in
            local integer i = cssl                      //length of the string
            local integer cd = cscd                     //current digit of string
            
            local integer d = csd                       //current digit of BigInt
            local integer d2                            //temporary to allocate digit of BigInt
            local integer d3
            
            local integer cc = 0
            
            set mbc = false
            
            //loop through the string and convert each of its digits into BASE and put into BigInt
            if (0 == mbp) then
                loop
                    set cc = cc + 9
                    if (cc > 20000) then
                        set mbc = true
                        set cscd = cd
                        return false
                    endif
                    
                    //multiply the entire number by the base
                    loop
                        set d = p[d]
                        exitwhen h[d]
                        
                        set v[d] = v[d]*base.size
                        
                        set cc = cc + 5
                        
                        //format current digit to fit base
                        set d2 = d
                        loop
                            //exitwhen current digit fits base
                            exitwhen v[d2] < BASE
                            
                            //if next doesn't exist, add a new digit
                            set d3 = n[d2]
                            if (h[d3]) then
                                //! runtextmacro BIG_INT_ALLOCATE("d3")
                                //! runtextmacro BIG_INT_ENQ("d3", "d2", "n[d2]")
                                //! runtextmacro BIG_INT_GET_REMAINING_DIGITS("v[d3]", "v[d2]", "BASE")
                                
                                set cc = cc + 9
                            else
                                //! runtextmacro BIG_INT_ADD_REMAINING_DIGITS("v[d3]", "v[d2]", "BASE")
                            endif
                            //! runtextmacro BIG_INT_GET_CURRENT_DIGIT("v[d2]", "v[d2]", "BASE")
                            
                            set d2 = d3
                            
                            set cc = cc + 8
                        endloop
                    endloop
                    
                    //go to next digit (to load next value from string)
                    //if empty, allocate it
                    
                    //load value from string into digit (add it if it exists)
                    //! runtextmacro BIG_INT_STRING_DIGIT_TO_VALUE("v[n[d]]", "str", "cd", "base")
                    set cd = cd + 1
                    
                    //current digit == string length
                    if (cd == i) then
                        set mbp = 1
                        set cc = cc + 3
                        exitwhen true
                    endif
                endloop
            endif
            
            if (cc > 19250 and (v[d] >= BASE or 0 == v[p[d]])) then
                set mbc = true
                return false
            endif
            loop
                set d = n[d]
                exitwhen v[d] < BASE
                
                set d2 = n[d]
                if (h[d2]) then
                    //! runtextmacro BIG_INT_ALLOCATE("d2")
                    //! runtextmacro BIG_INT_ENQ("d2", "d", "n[d]")
                    
                    //! runtextmacro BIG_INT_GET_REMAINING_DIGITS("v[d2]", "v[d]", "BASE")
                else
                    //! runtextmacro BIG_INT_ADD_REMAINING_DIGITS("v[d2]", "v[d]", "BASE")
                endif
                
                //! runtextmacro BIG_INT_GET_CURRENT_DIGIT("v[d2]", "v[d2]", "BASE")
                
                set d = d2
            endloop
            
            set d = p[csd]
            if (0 == v[d]) then
                call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"Zero BigInt")
            
                //! runtextmacro BIG_INT_DEALLOCATE("d")
                //! runtextmacro BIG_INT_INIT_HEAD("csd")
            endif
            
            return true
        endmethod
        static method convertString takes string str, Base base returns thistype
            local string hh = ""
            
            local integer d
        
            set cssl = StringLength(str)
            
            //! runtextmacro BIG_INT_ALLOCATE("csd")
            //! runtextmacro BIG_INT_INIT_HEAD("csd")
            
            if (0 < cssl) then
                set mbp = 0
                set cscd = 1
                set toBigInt = str
                set strBase = base
                
                //! runtextmacro BIG_INT_ALLOCATE("d")
                //! runtextmacro BIG_INT_ENQ("d", "csd", "csd")
                
                //! runtextmacro BIG_INT_STRING_DIGIT_TO_VALUE("v[d]", "str", "0", "base")
                
                if (cscd < cssl) then
                    loop
                        exitwhen TriggerEvaluate(cont)
                        
                        if (not mbc) then
                            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"CRASH")
                            return 0
                        endif
                    endloop
                elseif (0 == v[d]) then
                    //! runtextmacro BIG_INT_DEALLOCATE("d")
                    //! runtextmacro BIG_INT_INIT_HEAD("csd")
                endif
                
                loop
                    set csd = n[csd]
                    exitwhen h[csd]
                    set hh = I2S(v[csd]) + "," + hh
                endloop
                call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,hh)
            endif
            
            return csd
        endmethod
        method destroy takes nothing returns nothing
            set n[p[this]] = n[0]
            set n[0] = this
            set h[this] = false
        endmethod
        private static integer bdnum                //dividend
        private static integer array bddiv          //divisor buffer
        private static integer bdc                  //divisor size
        private static integer bdd                  //divisor
        private static integer bdrem                //remainder
        private static integer bdnumc               //dividend size
        private static integer array bdq            //quotient
        private static integer array bdgr           //guessed remainder
        private static integer bdgrs = 0            //guessed remainder size
        private static integer bdqc                 //quotient size
        private static integer bddol                //divisor large 2 digits
        private static boolean bda                  //do add
        private static method divide2 takes nothing returns boolean
            local integer this = bdnum      //dividend
            local integer d = bddol         //divisor largest 2 digits
            local integer r = bdrem         //remainder
            local integer m = bdc           //divisor size
            local integer dc = bdnumc       //dividend size
            local integer array bgp         //guess product
            local integer bgc = 0           //guess product length
            local integer td                //to divide
            local integer qc = bdqc         //quotient size
            local integer rti
            local real rt
            local integer dif               //difference in digit size between guessed and actual
            local integer i
            local integer i2
            local integer i3
            local integer grs = bdgrs       //guessed remainder size
            
            local string hh = ""
            
            if (0 == qc) then
                set td = v[p[this]]
                if (1 < dc) then
                    set td = td*BASE + v[p[p[this]]]
                endif
                call prn("First 2 Digits of Dividend: "+I2S(td))
                
                //calculate first estimate
                set rti = td/d
                set rt = (td + 0.)/d - rti
                call prn("rt = (" + I2S(td) + " + 0.)/" + I2S(d) + " -> "+R2S(rti+rt))
                
                //get difference in size
                if (td > d*2) then
                    set dif = 1
                else
                    set dif = 0
                endif
                set dif = dif + (dc - m)
                
                call prn("Difference: "+I2S(dif))
                
                set bdq[0] = rti
                loop
                    exitwhen bdq[qc] < BASE
                    set bdq[qc + 1] = bdq[qc]/BASE
                    set bdq[qc] = bdq[qc] - bdq[qc]/BASE*BASE
                    set qc = qc + 1
                endloop
                
                loop
                    set rti = R2I(rt*10)
                    exitwhen 0 == rti
                    
                    set rt = rt*10 - rti
                    
                    //multiply digit by 10
                    set i = qc
                    loop
                        set bdq[i] = bdq[i]*10
                        set i2 = i
                        
                        //format digits to fit
                        loop
                            exitwhen bdq[i2] < BASE
                            set bdq[i2 + 1] = bdq[i2 + 1] + bdq[i2]/BASE
                            set bdq[i2] = bdq[i2] - bdq[i2]/BASE*BASE
                            set i2 = i2 + 1
                        endloop
                        if (i2 > qc) then
                            set qc = i2
                        endif
                        
                        exitwhen 0 == i
                        set i = i - 1
                    endloop
                    
                    //add next decimal
                    set bdq[0] = bdq[0] + rti
                    
                    //format digits to fit
                    set i = 0
                    loop
                        exitwhen bdq[i] < BASE
                        set bdq[i + 1] = bdq[i + 1] + bdq[i]/BASE
                        set bdq[i] = bdq[i] - bdq[i]/BASE*BASE
                        set i = i + 1
                    endloop
                    if (i > qc) then
                        set qc = i
                    endif
                endloop
                
                set i = dif
                loop
                    set bdq[dif] = bdq[qc]
                    set bdq[qc] = 0
                    exitwhen 0 == qc
                    set qc = qc - 1
                    set dif = dif - 1
                endloop
                set qc = i
                
                set hh = ""
                set rti = qc
                loop
                    set hh = hh + I2S(bdq[rti])
                    exitwhen 0 == rti
                    set rti = rti - 1
                endloop
                call prn("First Quotient Guess: "+hh)
                
                //multiply
                set bgc = qc + m - 1
                set i = qc
                loop                                                            //first number
                    set i2 = m
                    if (0 != bdq[i]) then
                        loop                                                    //second number
                            set i2 = i2 - 1
                            if (0 != bddiv[i2]) then
                                set i3 = i+i2
                                set bgp[i3] = bgp[i3] + bdq[i]*bddiv[i2]
                                loop                                            //remainder
                                    exitwhen bgp[i3] < BASE
                                    set bgp[i3 + 1] = bgp[i3 + 1] + bgp[i3]/BASE
                                    set bgp[i3] = bgp[i3] - bgp[i3]/BASE*BASE
                                    set i3 = i3 + 1
                                endloop
                                if (i3 > bgc) then
                                    set bgc = i3
                                endif
                            endif
                            
                            exitwhen 0 == i2
                        endloop
                    endif
                    exitwhen 0 == i
                    set i = i - 1
                endloop
                
                set hh = ""
                set i = bgc
                loop
                    set hh = hh + I2S(bgp[i])
                    exitwhen 0 == i
                    set i = i - 1
                endloop
                call prn("First Product: "+hh)
                
                /*
                //compare guessed quotient with quotient
                if (bdnumc == bdc) then
                    set i = bdc
                    set d = this
                    loop
                        set i = i - 1
                        set d = p[d]
                        set less = v[d] < bddiv[i]
                        exitwhen 0 == i or v[d] != bddiv[i]
                    endloop
                    set equal = 0 == i and v[d] == bddiv[i]
                else
                    set less = bdnumc <= bdc
                    set equal = false
                endif
                */
                
                //get guessed remainder
                set i = 0
                //set bgp[bgc] = 0      //test!
                set grs = bgc
                loop
                    set this = n[this]
                    if (bgp[i] < v[this]) then
                        set bgp[i + 1] = bgp[i + 1] - 1
                        set bgp[i] = bgp[i] + BASE
                    endif
                    set bdgr[i] = bgp[i] - v[this]
                    exitwhen i == bgc
                    set i = i + 1
                endloop
                loop
                    exitwhen 0 != bdgr[grs]
                    set grs = grs - 1
                endloop
                
                set hh = ""
                set i = grs
                loop
                    set hh = hh + I2S(bdgr[i])
                    exitwhen 0 == i
                    set i = i - 1
                endloop
                call prn("First Remainder Guess: "+hh)
                
                return false
            endif
            
            /*
                44/25 = 1.76*100 = 176
                 176*10000 = 1760000
                 1760000 * 2539 = 4468640000
                 4468640000 - 4405940540 = 62699460
            */
        
            return false
        endmethod
        private static method divide0 takes nothing returns boolean
            local integer divisor = bdd
            local integer this = bdnum
            local boolean less
            local boolean equal
            local integer i
            local integer d
            
            local string hh = ""
            
            //store divisor in buffer in base 32768
            set bdc = 0
            loop
                exitwhen 0 == divisor
                set bddiv[bdc] = divisor - divisor/BASE*BASE
                set hh = I2S(bddiv[bdc]) + hh
                set bdc = bdc + 1
                set divisor = divisor/BASE
            endloop
            call prn("Divisor: "+hh)
            set bddol = bddiv[bdc - 1]
            if (1 < bdc) then
                set bddol = bddol*BASE + bddiv[bdc - 2]
            endif
            call prn("First 2 Digits: "+I2S(bddol))
            
            //retrieve dividend size
            set bdnumc = 0
            set hh = ""
            loop
                set this = n[this]
                exitwhen h[this]
                set hh = I2S(v[this])+hh
                set bdnumc = bdnumc + 1
            endloop
            call prn("Dividend: "+hh)
            call prn("Dividend Size: "+I2S(bdnumc))
            
            //compare dividend with divisor
            if (bdnumc == bdc) then
                set i = bdc
                set d = this
                loop
                    set i = i - 1
                    set d = p[d]
                    set less = v[d] < bddiv[i]
                    exitwhen 0 == i or v[d] != bddiv[i]
                endloop
                set equal = 0 == i and v[d] == bddiv[i]
            else
                set less = bdnumc <= bdc
                set equal = false
            endif
            
            //initialize remainder
            //! runtextmacro BIG_INT_ALLOCATE("bdrem")
            //! runtextmacro BIG_INT_INIT_HEAD("bdrem")
            
            if (equal) then
                call prn("Dividend Equal to Divisor")
                
                if (not h[n[n[this]]]) then
                    call prn("Dividend Greater than 1 Digit")
                    set n[p[this]] = n[0]
                    set n[0] = n[n[this]]
                    set p[this] = n[this]
                    set n[n[this]] = this
                endif
                
                set v[n[this]] = 1
                
                set hh = ""
                set d = n[0]
                loop
                    exitwhen 0 == d
                    set hh = hh + "," + I2S(d)
                    set d = n[d]
                endloop
                call prn("Deallocated: " + hh)
                
                set hh = ""
                set d = bdrem
                loop
                    set d = n[d]
                    exitwhen h[d]
                    set hh = I2S(v[d])+hh
                endloop
                if ("" == hh) then
                    call prn("Remainder: 0")
                else
                    call prn("Remainder: " + hh)
                endif
                
                set hh = ""
                loop
                    set this = n[this]
                    exitwhen h[this]
                    set hh = I2S(v[this]) + hh
                endloop
                if ("" == hh) then
                    call prn("Quotient: 0")
                else
                    call prn("Quotient: " + hh)
                endif
                
                return false
            endif
            if (less) then
                call prn("Dividend Less Than Divisor")
            
                set d = bdrem
                
                set p[d] = p[this]
                set n[d] = n[this]
                set p[n[d]] = d
                set n[p[d]] = d
                
                set n[this] = this
                set p[this] = this
                
                set hh = ""
                set d = n[0]
                loop
                    exitwhen 0 == d
                    set hh = hh + "," + I2S(d)
                    set d = n[d]
                endloop
                call prn("Deallocated: " + hh)
                
                set hh = ""
                set d = bdrem
                loop
                    set d = n[d]
                    exitwhen h[d]
                    set hh = I2S(v[d])+hh
                endloop
                if ("" == hh) then
                    call prn("Remainder: 0")
                else
                    call prn("Remainder: " + hh)
                endif
                
                set hh = ""
                loop
                    set this = n[this]
                    exitwhen h[this]
                    set hh = I2S(v[this]) + hh
                endloop
                if ("" == hh) then
                    call prn("Quotient: 0")
                else
                    call prn("Quotient: " + hh)
                endif
                
                return false
            endif
            
            call prn("Dividend Greater Than Divisor")
            
            set bdqc = 0
            set bdgrs = 0
            set bdgr[0] = 0
            set bdq[0] = 0
            set bda = true
            
            return true
        endmethod
        method divide takes integer divisor returns integer
            if (1 < divisor and not h[n[this]]) then
                //pass dividend
                set bdnum = this
                
                //pass divisor
                set bdd = divisor
            
                if (TriggerEvaluate(divt0)) then
                    call TriggerEvaluate(divt)
                endif
                
                return bdrem
            endif
            
            return 0 
        endmethod
        implement Init
    endstruct
endlibrary

JASS:
struct testers extends array
    private static method init takes nothing returns nothing
        local string n = "4405940540"
        //local string n = "1405940540"
        local string n2 = "2539"
        local Base b10 = Base["0123456789"]
        
        //local string n = "123456"
        //local string n2 = "12345678"
        //local Base b10 = Base["0123456789"]
        
        local BigInt2 i = BigInt2.convertString(n, b10)
        local BigInt2 i2 = BigInt2.convertString(n2, b10)
        
        //local BigInt check = BigInt.convertString("1000006391940908413713847760525667356171079486808715567679633141552105925377922410603427853838264556793163468146196127555", b10)
        
        //set check.base = Base["01"]
        //call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,check.toString())
        
        call i.divide(2539)
        //call i.print(Base["0123456789"])
        
        call DestroyTimer(GetExpiredTimer())
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TimerStart(CreateTimer(),0,false,function thistype.init)
    endmethod
endstruct


It was working all right when the first 2 digits of the first number were larger, but it's not loading the reals up for smaller.


If anyone wants to mess with the division or help improve it, go for it ;p. Right I'm taking a break for a while >.>.



divide0 appears to work flawlessly. There are tons of debug messages, so just try running the map first. Oh, you'll probably need all of these won't you.

JASS:
library Base /* v1.0.4.1
*************************************************************************************
*
*   A script used for base conversion where integers are represented as strings in
*   another base.
*
*************************************************************************************
*
*   */uses/*
*
*       */ Ascii /*         wc3c.net/showthread.php?t=110153
*       */ Table /*         hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
************************************************************************************
*
*   struct Base extends array
*
*       readonly integer size
*           -   number of digits in base
*       readonly string string
*           -   string representing base's character set
*
*       static method operator [] takes string base returns Base
*
*       method convertToString takes integer i returns string
*       method convertToInteger takes string i returns integer
*
*       method ord takes string c returns integer
*       method char takes integer i returns string
*
*       method isValid takes string value returns boolean
*           -   determines if all of the characters in the string are valid base character
*
*************************************************************************************/

/*************************************************************************************
*
*   Code
*
*************************************************************************************/
    globals
        private Table gt=0          //stacks of strings with same hashes
        private integer array n     //next node pointer for gt stack
        private string array b      //base of string
        private Table array t       //base character table
        private integer c=0         //base instance count
        private integer array s     //base size
    endglobals
    private module Init
        private static method onInit takes nothing returns nothing
            set gt=Table.create()
        endmethod
    endmodule
    struct Base extends array
        debug private static boolean array a        //is allocated
        method operator string takes nothing returns string
            return b[this]
        endmethod
        method operator size takes nothing returns integer
            return s[this]
        endmethod
        static method operator [] takes string base returns thistype
            local integer value     //string hash value
            local string char       //iterated character
            local integer i=0       //this
            local integer v         //stack of hashes
            local integer dv        //copy of v
            local integer hv        //copy of value
            debug if (1<StringLength(base)) then
                set value = StringHash(base)    //first get the hash
                set i = gt[value]               //get first node of hash table
                set v = i                       //copy
                if (0!=i) then                  //if stack exists, then loop through
                    loop
                        exitwhen 0==i or base==b[i]
                        set i=n[i]
                    endloop
                endif
                //if this still doesn't exist, create it
                if (0==i) then
                    //allocate
                    set c=c+1
                    set i=c
                    set dv=v
                    set hv=value
                    debug set a[i]=true
                    set t[i]=Table.create()     //character table
                    set b[i]=base               //base string
                    //value is now used for iterating through the base string
                    set value=StringLength(base)
                    set s[i]=value    
                    loop
                        set value=value-1
                        set char=SubString(base,value,value+1)
                        set v=Char2Ascii(char)
                        //if the character already exists, stop
                        //and deallocate (invalid base)
                        debug if (t[i].has(v)) then
                            debug call t[i].destroy()   //destroy character table
                            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CREATION ERROR: "+char+" MULTIPLY DEFINED")
                            debug set c=c-1
                            debug set a[i]=false
                            debug return 0
                        //character doesn't exist
                        debug else
                            set t[i][v]=value
                            set t[i].string[-value]=char
                        debug endif
                        exitwhen 0==value
                    endloop
                    //if dv is 0, then allocate dv
                    if (0==dv) then
                        set gt[hv]=i
                    //otherwise add i to hash stack
                    else
                        set n[i]=n[dv]
                        set n[dv]=i
                    endif
                endif
                return i
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CREATION ERROR: "+base+" IS INVALID")
            debug return 0
        endmethod
        method convertToString takes integer i returns string
            local integer k=s[this]
            local string n=""
            debug if (a[this]) then
                debug if (0<=i) then
                    loop
                        exitwhen i<k
                        set n=t[this].string[-(i-i/k*k)]+n
                        set i=i/k
                    endloop
                    return t[this].string[-i]+n
                debug endif
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CONVERSION ERROR: "+I2S(i)+" IS OUT OF BOUNDS")
                debug return null
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CONVERSION ERROR: "+I2S(this)+" IS NOT ALLOCATED")
            debug return null
        endmethod
        method convertToInteger takes string i returns integer
            local integer n=0
            local integer p=StringLength(i)
            local integer l=0
            local integer k=s[this]
            local string char
            debug if (a[this]) then
                loop
                    exitwhen 0==p
                    set p=p-1
                    set l=l+1
                    set char=SubString(i,l-1,l)
                    debug if (t[this].has(Char2Ascii(char))) then
                        set n=n+t[this][Char2Ascii(char)]*R2I(Pow(k,p))
                    debug else
                        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CONVERSION ERROR: "+char+" IS OUT OF BOUNDS")
                        debug return 0
                    debug endif
                endloop
                return n
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CONVERSION ERROR: "+I2S(this)+" IS NOT ALLOCATED")
            debug return 0
        endmethod
        method ord takes string c returns integer
            debug if (a[this]) then
                debug if (1<StringLength(c) or ""==c or null==c or not (t[this].has(Char2Ascii(c)))) then
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE ORD ERROR: "+c+" IS OUT OF BOUNDS")
                    debug return 0
                debug endif
                return t[this][Char2Ascii(c)]
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE ORD ERROR: "+I2S(this)+" IS NOT ALLOCATED")
            debug return 0
        endmethod
        method char takes integer i returns string
            debug if (a[this]) then
                debug if (i<s[this] and 0<=i) then
                    return t[this].string[-i]
                debug endif
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CHAR ERROR: "+I2S(i)+" IS OUT OF BOUNDS")
                debug return null
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"BASE CHAR ERROR: "+I2S(this)+" IS NOT ALLOCATED")
            debug return null
        endmethod
        method isValid takes string s returns boolean
            local integer i=StringLength(s)
            local string c
            if (0<i) then
                loop
                    set c=SubString(s,i-1,i)
                    if (not t[this].has(Char2Ascii(c))) then
                        return false
                    endif
                    set i=i-1
                    exitwhen 0==i
                endloop
            else
                return false
            endif
            return true
        endmethod
        implement Init
    endstruct
endlibrary
library Ascii
///////////////////////////////////////////////////////////////////
//      function Char2Ascii takes string s returns integer
//          integer ascii = Char2Ascii("F")
//
//      function Ascii2Char takes integer a returns string
//          string char = Ascii2Char('F')
//
//      function A2S takes integer a returns string
//          string rawcode = A2S('CODE')
//
//      function S2A takes string s returns integer
//          integer rawcode = S2A("CODE")
//
///////////////////////////////////////////////////////////////////
    globals
        private integer array i //hash
        private string array c  //char
    endglobals
    function Char2Ascii takes string s returns integer
        local integer a
        if ("\\"==s) then
            return 92
        endif
        set a=i[StringHash(s)/0x1F0748+0x3EA]
        if (s!=c[a]) then
            debug if (0==a) then
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"ASCII ERROR: INVALID CHARACTER")
                debug return 0
            debug endif
            return a+32
        endif
        return a
    endfunction
    function Ascii2Char takes integer a returns string
        return c[a]
    endfunction
    function A2S takes integer a returns string
        local string s=""
        loop
            set s=c[a-a/256*256]+s
            set a=a/256
            exitwhen 0==a
        endloop
        return s
    endfunction
    function S2A takes string s returns integer
        local integer a=0
        local integer l=StringLength(s)
        local integer j=0
        local string m
        local integer h
        loop
            exitwhen j==l
            set m=SubString(s,j,j+1)
            if ("\\"==m) then
                set a=a*256+92
            else
                set h=i[StringHash(m)/0x1F0748+0x3EA]
                if (m!=c[h]) then
                    debug if (0==h) then
                        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"ASCII ERROR: INVALID CHARACTER")
                        debug return 0
                    debug endif
                    set a=a*256+h+32
                else
                    set a=a*256+h
                endif
            endif
            set j=j+1
        endloop
        return a
    endfunction
    private module Init
        private static method onInit takes nothing returns nothing
            set i[931]=8
            set i[1075]=9
            set i[1586]=10
            set i[1340]=12
            set i[412]=13
            set i[198]=32
            set i[1979]=33
            set i[1313]=34
            set i[1003]=35
            set i[1264]=36
            set i[983]=37
            set i[1277]=38
            set i[306]=39
            set i[904]=40
            set i[934]=41
            set i[917]=42
            set i[1972]=43
            set i[1380]=44
            set i[1985]=45
            set i[869]=46
            set i[1906]=47
            set i[883]=48
            set i[1558]=49
            set i[684]=50
            set i[582]=51
            set i[668]=52
            set i[538]=53
            set i[672]=54
            set i[1173]=55
            set i[71]=56
            set i[277]=57
            set i[89]=58
            set i[1141]=59
            set i[39]=60
            set i[1171]=61
            set i[51]=62
            set i[305]=63
            set i[0]=64
            set i[222]=65
            set i[178]=66
            set i[236] =67
            set i[184]=68
            set i[1295]=69
            set i[1390]=70
            set i[1276]=71
            set i[203]=72
            set i[1314]=73
            set i[209]=74
            set i[1315]=75
            set i[170]=76
            set i[1357]=77
            set i[1343]=78
            set i[1397]=79
            set i[1420]=80
            set i[1419]=81
            set i[1396]=82
            set i[1374]=83
            set i[1407]=84
            set i[499]=85
            set i[1465]=86
            set i[736]=87
            set i[289]=88
            set i[986]=89
            set i[38]=90
            set i[1230]=91
            set i[1636]=93
            set i[1416]=94
            set i[1917]=95
            set i[217]=96
            set i[833]=123
            set i[1219]=124
            set i[553]=125
            set i[58]=126
            set c[8]="\b"
            set c[9]="\t"
            set c[10]="\n"
            set c[12]="\f"
            set c[13]="\r"
            set c[32]=" "
            set c[33]="!"
            set c[34]="\""
            set c[35]="#"
            set c[36]="$"
            set c[37]="%"
            set c[38]="&"
            set c[39]="'"
            set c[40]="("
            set c[41]=")"
            set c[42]="*"
            set c[43]="+"
            set c[44]=","
            set c[45]="-"
            set c[46]="."
            set c[47]="/"
            set c[48]="0"
            set c[49]="1"
            set c[50]="2"
            set c[51]="3"
            set c[52]="4"
            set c[53]="5"
            set c[54]="6"
            set c[55]="7"
            set c[56]="8"
            set c[57]="9"
            set c[58]=":"
            set c[59]=";"
            set c[60]="<"
            set c[61]="="
            set c[62]=">"
            set c[63]="?"
            set c[64]="@"
            set c[65]="A"
            set c[66]="B"
            set c[67]="C"
            set c[68]="D"
            set c[69]="E"
            set c[70]="F"
            set c[71]="G"
            set c[72]="H"
            set c[73]="I"
            set c[74]="J"
            set c[75]="K"
            set c[76]="L"
            set c[77]="M"
            set c[78]="N"
            set c[79]="O"
            set c[80]="P"
            set c[81]="Q"
            set c[82]="R"
            set c[83]="S"
            set c[84]="T"
            set c[85]="U"
            set c[86]="V"
            set c[87]="W"
            set c[88]="X"
            set c[89]="Y"
            set c[90]="Z"
            set c[92]="\\"
            set c[97]="a"
            set c[98]="b"
            set c[99]="c"
            set c[100]="d"
            set c[101]="e"
            set c[102]="f"
            set c[103]="g"
            set c[104]="h"
            set c[105]="i"
            set c[106]="j"
            set c[107]="k"
            set c[108]="l"
            set c[109]="m"
            set c[110]="n"
            set c[111]="o"
            set c[112]="p"
            set c[113]="q"
            set c[114]="r"
            set c[115]="s"
            set c[116]="t"
            set c[117]="u"
            set c[118]="v"
            set c[119]="w"
            set c[120]="x"
            set c[121]="y"
            set c[122]="z"
            set c[91]="["
            set c[93]="]"
            set c[94]="^"
            set c[95]="_"
            set c[96]="`"
            set c[123]="{"
            set c[124]="|"
            set c[125]="}"
            set c[126]="~"
        endmethod
    endmodule
    private struct Inits extends array
        implement Init
    endstruct
endlibrary
library Table // made by Bribe, special thanks to Nestharus, version 3.0.0.0
/*
    API
    
    ------------
    struct Table
    | static method create takes nothing returns Table
    |     create a new Table
    |    
    | method destroy takes nothing returns nothing
    |     destroy it
    |    
    | method flush takes nothing returns nothing
    |     flush all stored values inside of it
    |    
    | method remove takes integer key returns nothing
    |     remove the value at index "key"
    |    
    | method operator []= takes integer key, $TYPE$ value returns nothing
    |     assign "value" to index "key"
    |    
    | method operator [] takes integer key returns $TYPE$
    |     load the value at index "key"
    |    
    | method has takes integer key returns boolean
    |     whether or not the key was assigned
    |
    ----------------
    struct TableArray
    | static method operator [] takes integer array_size returns TableArray
    |     create a new array of Tables of size "array_size"
    |
    | method destroy takes nothing returns nothing
    |     destroy it
    |
    | method flush takes nothing returns nothing
    |     flush and destroy it
    |
    | method operator size takes nothing returns integer
    |     returns the size of the TableArray
    |
    | method operator [] takes integer key returns Table
    |     returns a Table accessible exclusively to index "key"
*/
    
globals
    private hashtable ht = InitHashtable() //The last hashtable you need
    private integer more = 2 //Index generation for Tables (above 2)
    private integer less = 0 //Index generation for TableArrays (below 0)
endglobals
    
private struct dex extends array
    static method operator size takes nothing returns Table
        return 1
    endmethod
    static method operator list takes nothing returns Table
        return 2
    endmethod
endstruct
    
private struct handles extends array
    method has takes integer key returns boolean
        return HaveSavedHandle(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSavedHandle(ht, this, key)
    endmethod
endstruct
    
private struct agents extends array
    method operator []= takes integer key, agent value returns nothing
        call SaveAgentHandle(ht, this, key, value)
    endmethod
endstruct
    
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
    method operator [] takes integer key returns $TYPE$
        return Load$FUNC$(ht, this, key)
    endmethod
    method operator []= takes integer key, $TYPE$ value returns nothing
        call Save$FUNC$(ht, this, key, value)
    endmethod
    method has takes integer key returns boolean
        return HaveSaved$SUPER$(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSaved$SUPER$(ht, this, key)
    endmethod
endstruct
private module $TYPE$m
    method operator $TYPE$ takes nothing returns $TYPE$s
        return this
    endmethod
endmodule
//! endtextmacro
    
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
    method operator [] takes integer key returns $TYPE$
        return Load$FUNC$Handle(ht, this, key)
    endmethod
    method operator []= takes integer key, $TYPE$ value returns nothing
        call Save$FUNC$Handle(ht, this, key, value)
    endmethod
endstruct
private module $TYPE$m
    method operator $TYPE$ takes nothing returns $TYPE$s
        return this
    endmethod
endmodule
//! endtextmacro
    
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
    
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
    
struct Table extends array
    
    // Implement modules for intuitive type-syntax
    implement realm
    implement booleanm
    implement stringm
    implement playerm
    implement widgetm
    implement destructablem
    implement itemm
    implement unitm
    implement abilitym
    implement timerm
    implement triggerm
    implement triggerconditionm
    implement triggeractionm
    implement eventm
    implement forcem
    implement groupm
    implement locationm
    implement rectm
    implement boolexprm
    implement soundm
    implement effectm
    implement unitpoolm
    implement itempoolm
    implement questm
    implement questitemm
    implement defeatconditionm
    implement timerdialogm
    implement leaderboardm
    implement multiboardm
    implement multiboarditemm
    implement trackablem
    implement dialogm
    implement buttonm
    implement texttagm
    implement lightningm
    implement imagem
    implement ubersplatm
    implement regionm
    implement fogstatem
    implement fogmodifierm
    implement hashtablem
    
    method operator handle takes nothing returns handles
        return this
    endmethod
    
    method operator agent takes nothing returns agents
        return this
    endmethod
    
    // set this = a[GetSpellAbilityId()]
    method operator [] takes integer key returns Table
        return LoadInteger(ht, this, key)
    endmethod
    
    // set a[389034] = 8192
    method operator []= takes integer key, Table a returns nothing
        call SaveInteger(ht, this, key, a)
    endmethod
    
    // set b = a.has(2493223)
    method has takes integer key returns boolean
        return HaveSavedInteger(ht, this, key)
    endmethod
    
    // call a.remove(294080)
    method remove takes integer key returns nothing
        call RemoveSavedInteger(ht, this, key)
    endmethod
    
    // Remove all data from a Table instance
    method flush takes nothing returns nothing
        call FlushChildHashtable(ht, this)
    endmethod
    
    // local Table a = Table.create()
    static method create takes nothing returns Table
        local Table this = dex.list[0]
        
        if this == 0 then
            set more = more + 1
            set this = more
        else
            set dex.list[0] = dex.list[this]
            call dex.list.remove(this)
        endif
        
        debug set dex.list[this] = -1
        return this
    endmethod
    
    // Removes all data from a Table instance and recycles its index.
    //
    //     call a.destroy()
    //
    method destroy takes nothing returns nothing
        debug if dex.list[this] != -1 then
            debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
            debug return
        debug endif
        
        call this.flush()
        
        set dex.list[this] = dex.list[0]
        set dex.list[0] = this
    endmethod
    
endstruct
    
struct TableArray extends array
    
    //Returns a new TableArray to do your bidding. Simply use:
    //
    //    local TableArray ta = TableArray[array_size]
    //
    static method operator [] takes integer array_size returns TableArray
        local Table a = dex.size[array_size] //Get the unique recycle list for this array size
        local TableArray this = a[0]         //The last-destroyed TableArray that had this array size
        
        debug if array_size <= 0 then
            debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
            debug return 0
        debug endif
        
        if this == 0 then
            set less = less - array_size
            set this = less
        else
            set a[0] = a[this]  //Set the last destroyed to the last-last destroyed
            call a.remove(this) //Clear hash memory
        endif
        
        set dex.size[this] = array_size //This remembers the array size
        return this
    endmethod
    
    //Returns the size of the TableArray
    method operator size takes nothing returns integer
        return dex.size[this]
    endmethod
    
    //da[integer a].unit[integer b] = unit u
    //da[integer a][integer c] = integer d
    //
    //Inline-friendly when not running in debug mode
    //
    method operator [] takes integer key returns Table
        static if DEBUG_MODE then
            local integer i = this.size
            if i == 0 then
                call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
                return 0
            elseif key < 0 or key >= i then
                call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
                return 0
            endif
        endif
        return this + key
    endmethod
    
    //Destroys a TableArray without flushing it; assumed you'd call .flush()
    //if you want it flushed too. This is public so that if you are flushing
    //instances the whole time you don't waste efficiency when disposing the
    //TableArray.
    //
    method destroy takes nothing returns nothing
        local Table a = dex.size[this.size]
        
        debug if this.size <= 0 then
            debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
            debug return
        debug endif
        
        if a == 0 then
            //Create an array to index recycled instances with their array size
            set a = Table.create()
            set dex.size[this.size] = a
        endif
        
        call dex.size.remove(this) //Clear the array size from hash memory
        
        set a[this] = a[0]
        set a[0] = this
    endmethod
    
    //All you need to know about this one is that it won't hit the op limit.
    private static method clean takes Table a, integer end returns nothing
        local integer i = a + 5000
        if i < end then
            call clean.evaluate(i, end)
            set end = i
        endif
        loop
            call a.flush()
            set a = a + 1
            exitwhen a == end
        endloop
    endmethod
    
    //Flushes the TableArray and also destroys it. Doesn't get any more
    //similar to the FlushParentHashtable native than this.
    //
    method flush takes nothing returns nothing
        local integer end = this.size + this
        debug if this == end then
            debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
            debug return
        debug endif
        call clean.evaluate(this, end)
        call this.destroy()
    endmethod
    
endstruct
    
endlibrary


And yea... divide2 is the method you'll be looking at. I haven't coded all of it yet, I just decided to take a break after I realized that the quotient guesser part was broken : P.
JASS:
                set bdq[0] = rti
                loop
                    exitwhen bdq[qc] < BASE
                    set bdq[qc + 1] = bdq[qc]/BASE
                    set bdq[qc] = bdq[qc] - bdq[qc]/BASE*BASE
                    set qc = qc + 1
                endloop
                
                loop
                    set rti = R2I(rt*10)
                    exitwhen 0 == rti
                    
                    set rt = rt*10 - rti
                    
                    //multiply digit by 10
                    set i = qc
                    loop
                        set bdq[i] = bdq[i]*10
                        set i2 = i
                        
                        //format digits to fit
                        loop
                            exitwhen bdq[i2] < BASE
                            set bdq[i2 + 1] = bdq[i2 + 1] + bdq[i2]/BASE
                            set bdq[i2] = bdq[i2] - bdq[i2]/BASE*BASE
                            set i2 = i2 + 1
                        endloop
                        if (i2 > qc) then
                            set qc = i2
                        endif
                        
                        exitwhen 0 == i
                        set i = i - 1
                    endloop
                    
                    //add next decimal
                    set bdq[0] = bdq[0] + rti
                    
                    //format digits to fit
                    set i = 0
                    loop
                        exitwhen bdq[i] < BASE
                        set bdq[i + 1] = bdq[i + 1] + bdq[i]/BASE
                        set bdq[i] = bdq[i] - bdq[i]/BASE*BASE
                        set i = i + 1
                    endloop
                    if (i > qc) then
                        set qc = i
                    endif
                endloop
                
                set i = dif
                loop
                    set bdq[dif] = bdq[qc]
                    set bdq[qc] = 0
                    exitwhen 0 == qc
                    set qc = qc - 1
                    set dif = dif - 1
                endloop
                set qc = i

And this may appear to be way slower than the binary division, but it is a lot less iterations of these massive operations. Also the operations aren't as massive as you'd think ^)^, it's just a ton of small loops ;o. Well, multiplication is slightly massive >: P.
 
Status
Not open for further replies.
Top