System LongInt

SerraAvenger

Cuz I can
Reaction score
234
What it is
This is my approach to get over the 2^31-1 integer size.
It uses a struct called longinteger that contains a couple of integers - basically it is a base1.000.000.000 integer with SIZE digits.
USES vJASS

How to implement it
If you haven't got JassPack NewGen, get it.
Create a new trigger, name it appropriately, and convert it to custom text.
Copy and paste the code into your newly created trigger. Overwrite anything currently in it.

How to use it
If you are working inside of a library ( the vJASS thing. Not the one with the books ), you will first have to make sure the library knows where to find the functions from this library.
The line in which you create the library needs to look like this:
Code:
library NAME [I]initialiser FUNC_NAME[/I] requires [I]OTHER_STUFF, [/I] LongInt
If you're not working in a library, then it doesn't matter.

An example says more than thousand words, so here is one:

JASS:
library TestingLongInt initializer Init requires LongInt
function Init takes nothing returns nothing
    local longinteger long1 // the type name is longinteger
    local longinteger long2
    set long1 = CreateLong( 0 ) // CreateLong( integer ) creates a new longinteger. The integer argument assings the starting value.
    set long2 = S2L ( "123456789123456789" ) // S2L( string ) is another way to create a longinteger. It basically converts the string argument to the longinteger
    call LongAddInt( long1, 5000 ) // Adds an integer to long1.
    call LongAddLongEx( long1, long2, false ) // LongAddLongEx adds long2 to long1. The parameter specifies whether long2 shall be destroyed during the process or not.
    call LongAddLong( long1, long2 ) // same as above, just that long2 will always be destroyed.
    call BJDebugMsg( L2S( long1 ) ) // L2S converts a long to a string. It is the inverse function of S2L.
    call DestroyLong( long1 ) // Destroys long1. If you don't destroy longs once you no longer need them, you might get a memory leak. "nulling" is not required, as a longinteger is no handle. 
endfunction

endlibrary

What does work:
- Positive longintegers ( negative is on the way )
- Addition
What won't work ( as in never ):
- Multiplication / division
What will come:
- Negative longintegers
- Comparision
The Code
JASS:
library LongInt

// Version 0.5

globals 
    constant integer SIZE = 4 // max numbersize = MAX_PART_SIZE ^ SIZE = 10^(9*SIZE) 
endglobals

struct longinteger
    private integer array part[ SIZE ]
    private integer parts = 1
    
    static constant integer MAX_PART_SIZE = 1000000000 // The base of the number ( 1.000.000.000 )- DON'T CHANGE!
    static constant integer LOG_PART_SIZE = 9          // log( MAX_PART_SIZE ) - DON'T CHANGE!
    
    static method create takes integer base returns longinteger
        local longinteger new = .allocate()
        local integer i = 0
        
        loop
            exitwhen i >= SIZE
            set new.part[ i ] = 0
            set i = i + 1
        endloop
        
        set new.part[0] = base
        call new.partition()
        return new
    endmethod
    
    
    static method from_s takes string s returns longinteger
        local longinteger new = .allocate()
        local integer sLen  = StringLength( s )
        local integer parts = sLen / .LOG_PART_SIZE
        local integer i  = 0
        local integer dI = .LOG_PART_SIZE
        
        if SIZE < parts then
            debug call BJDebugMsg( SCOPE_PREFIX + ": Size is smaller than required ( " + I2S( SIZE ) + " / " + I2S( parts ) + " )!" )
            set parts = SIZE
            set s = SubString( s, sLen - ( parts * .LOG_PART_SIZE ), sLen )
            set sLen = parts * .LOG_PART_SIZE
        endif
        
        set new.parts = parts
            
        loop
            exitwhen i >= parts
            
            set new.part[ i ] = S2I( SubString( s, sLen - (i+1) * dI,  sLen - i*dI ) )
            
            set i = i + 1
        endloop
        return new
    endmethod
    
    private method partitionIndex takes integer index returns nothing
        if IAbsBJ( .part[ index ] ) >= .MAX_PART_SIZE then
            set .part[ index + 1 ] = .part[ index + 1 ] + .part[ index ] / .MAX_PART_SIZE
            set .part[ index ] = .part[ index ] - ( .part[ index ] / .MAX_PART_SIZE ) * .MAX_PART_SIZE
            if .parts <= index then
                set .parts = index + 1
            endif
        endif
    endmethod
    
    private method partition takes nothing returns nothing
        local integer i = 0
        loop    
            exitwhen i >= .parts   
            
            call .partitionIndex( i )
            
            set i = i + 1
        endloop
    endmethod
        
    method addLong takes longinteger other, boolean destroyOther returns longinteger
        local integer partsTotal = IMaxBJ( .parts, other.parts )
        local integer i = 0
        loop
            exitwhen i >= partsTotal
            
            set .part[ i ] = .part[ i ] + other.part[ i ]
            
            call .partitionIndex( i )

            set i = i + 1
        endloop
        set .parts = partsTotal

        if destroyOther then
            call other.destroy()
        endif
        
        return this
    endmethod

    method addInt takes integer other returns longinteger
        return .addLong( .create( other ), true )
    endmethod

    method to_s takes nothing returns string
        local integer i = .parts - 1
        local string  res = ""
        loop
            exitwhen i < 0
            
            set res = res + I2S( .part[ i ] )
            
            set i = i - 1
        endloop
        return res
    endmethod
    
endstruct

function CreateLong takes integer base returns longinteger
    return longinteger.create( base )
endfunction

function LongAddLongEx takes longinteger l1, longinteger l2, boolean destroyOther returns longinteger
    return l1.addLong( l2, destroyOther )
endfunction

function LongAddLong takes longinteger l1, longinteger l2 returns longinteger
    return l1.addLong( l2, true )
endfunction

function LongAddInt takes longinteger l, integer int returns longinteger
    return l.addInt( int )
endfunction

function L2S takes longinteger l returns string
    return l.to_s()
endfunction

function S2L takes string s returns longinteger
    return longinteger.from_s( s )
endfunction

function DestroyLong takes longinteger toDestroy returns nothing
    call toDestroy.destroy()
endfunction
endlibrary
 

SerraAvenger

Cuz I can
Reaction score
234
What made you come up with this? What might it be useful for?

Phew... That are a couple of good questions : )
Actually, I thought about doing something like this a couple of years ago...
Back then, I had a need for it.

Now I had a discussion with a young lad named Dekar who posted on the Battleships Advanced homepage, asking how high "Rank" ( a value that should represent your playing power. Can be saved via save load codes ) can go in that map. I told him approx. 2³¹ - 1, as that is the maximum integer size.

So he asked me why I can't just use two integers... And I told him that Trollkopp (the maker of Bs Adv) doesn't use JASS (because it contains the german word for yes, ja, and the acronym for a Nazi-Regime Terror Unit (the SS) :D), and that It would be incredibly difficult to do without JASS.

Then I just asked my self: How difficult would it be exactly?
Hence I tried... And shortly after came up with a system that knows unsigned longintegers only and can't multiply.

I'm currently working on signed longintegers (While they do currently work, it seems that there is too much function calling with them - I'm trying to fix that).

What it might be useful for?
Dunno. I never had a use for them. But as it is nice to have them as an option, and I haven't found a system that implements them yet, I just uploaded it.
Perhaps some strange counting... I really don't know.
Samael88 (Trollkopp would hate that name :D) has requested such thing, it seems.

OffTopic: I knew you would comment on this thread :D
 

SerraAvenger

Cuz I can
Reaction score
234
I'm currently working on signed longintegers (While they do currently work, it seems that there is too much function calling with them - I'm trying to fix that).

Oh my god. I feel so dumb now. It worked perfectly all the time, I just forgot to remove the calculation out of the second struct...
I tried to do everything by hand there, while the same thing was allready done in another operation >_>

Hence I had a couple of extra calculations xD
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
We should create a new tag [ScriptForFun].
However i should use this tag for mines also :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top