• 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.

[System] Hyper Array

Level 7
Joined
Apr 30, 2011
Messages
359
JASS:
//========================================================================================
//      
//      Hyper Array
//      -*- overcold_ice -*-
//      
//     -[*] Requirements:
//          - JNGP
//          - latest version of JassHelper
//      
//          Provides storages with extremely dynamic array
//      Uses a hashtable, converting arrays into a key for it, then storing values
//      within
//      
//     -[*] Features:
//          - Limitations:
//              - 8192 HyperArray instance
//              - 2147483647 total dimension
//              - 2147483647 storage per instance
//          
//          - Supports instances with extreme dimension amount (ex: 10D, 99D)
//          - Supports up to 2147483647 storage limit per HyperArray instance
//            for each variable types
//          - Values inserted to HyperArray instances' arrays can be any value
//            (they'll be converted to indexes for the system)
//          - Adjustable default array size (default array size is inserted to any
//            'null' arrays during .create operator)
//      
//     -[*] API:
//      
//      struct HyperArray extends array
//          static method operator [] takes integer Dimension returns 'childtype'
//          ->  method operator [] takes integer DimensionSize returns 'thistype'
//          ->  method operator create takes nothing returns HyperArray
//              allocator for the struct
//          
//          method destroy takes nothing returns nothing
//              deallocator for the struct
//          
//          method operator [] takes integer Key returns 'childtype'
//          ->  method operator [] takes integer Key returns 'thistype'
//          ->  method operator $TYPE$= takes $TYPE$ Value returns nothing
//          ->  method operator $TYPE$ takes nothing returns $TYPE$
//              storage operators
//              $TYPE$ == type of variable to store
//              (see textmacros below)
//      
//     -[*] Examples:
/*
    // . . .
    local HyperArray HA1 = HyperArray [2] [100] [100]   // 2D, storage 100 and 100
                                                        // Total -> 10000
    local HyperArray HA2 = HyperArray [5].create        // 5D, all of them has
                                                        // Default Storage (configurable)
    set HA1 [50] [50].integer = 100
    set HA1 [50] [50].unit    = GetTriggerUnit()    // works
    set HA2 [Pow(2, 5)] [Pow(2, 10)] [Pow(2, 15)] [Pow(2, 20)] [Pow(2, 25)].boolean = true
    set HA2 [HA1 [50] [50].integer] [0] [0] [0] [HA1 [50] [50].integer].integer /*
    */     = HA1 [50] [50].integer
    
    call HA2.destroy()
    // . . .
*/
//========================================================================================
library HyperArray
    
    //====================================================================================
    //  C A L I B R A T I O N  S E C T I O N
    //====================================================================================
    globals
        private constant integer DEFAULT_ARRAY_SIZE = 8192
    endglobals
    //====================================================================================
    
    globals
        private hashtable Hashtable = InitHashtable()
        
        // Hashtable's keys
        private constant integer DimensionSize  = 0
        private constant integer IdCount        = 8192
        private constant integer ValueStorage   = 16384
        
        // Struct's values
        private integer array StructId
        private integer array MaxDimension
        
        // Temp variables
        private integer CurrentDimension
        private integer CurrentKey
        
        // Used for StructId's usage
        private integer       StructId_Count    = -1
        private integer array StructId_Recycle
        private integer array StructId_Dimension
    endglobals
    
    private function GetArrayCount takes integer this, integer d returns integer
        //arg integer d                         // dimension number
        local integer l = MaxDimension [this]   // used in loop
        local integer a = 1                     // number of arrays
        
        loop
            exitwhen l == d
            
            set a = a * LoadInteger(Hashtable, DimensionSize + this, l)
            
            set l = l - 1
        endloop
        
        return a
    endfunction
    
    private function RegId takes integer this returns nothing
        local integer sid = StructId_Recycle [0]    // struct id
        
        if sid == 0 and StructId_Dimension [sid] != MaxDimension [this] then
            set StructId_Count = StructId_Count - MaxDimension [this]
            set sid = StructId_Count
            set StructId_Dimension [sid] = MaxDimension [this]
        else
            set StructId_Recycle [0] = StructId_Recycle [sid]
        endif
        
        set StructId [this] = sid
    endfunction
    
    private function UnregId takes integer this returns nothing
        local integer sid = StructId [this]     // struct id
        
        set StructId_Recycle [sid] = StructId_Recycle [0]
        set StructId_Recycle [0]   = sid
    endfunction
    
    private function GetArrayId takes integer this, integer d, integer a returns integer
        //arg integer d     // what dimension
        //arg integer a     // what array/key
        
        if HaveSavedInteger(Hashtable, StructId [this] + d, a) then
            return LoadInteger(Hashtable, StructId [this] + d, a)
        endif
        
        call SaveInteger(Hashtable, IdCount + this, d, LoadInteger(Hashtable, IdCount + this, d) + 1)
        call SaveInteger(Hashtable, StructId [this] + d, a, LoadInteger(Hashtable, IdCount + this, d))
        
        return LoadInteger(Hashtable, StructId [this] + d, a)
    endfunction
    
    private struct CreateArray extends array
        method operator [] takes integer s returns thistype
            //arg integer s     // this dimension maximum size
            
            set CurrentDimension = CurrentDimension + 1
            
            if CurrentDimension > MaxDimension [this] then
                return this
            endif
            
            call SaveInteger(Hashtable, DimensionSize + this, CurrentDimension, s)
            
            return this
        endmethod
        
        method operator create takes nothing returns HyperArray
            loop
                exitwhen CurrentDimension == MaxDimension [this]
                set CurrentDimension = CurrentDimension + 1
                
                if not HaveSavedInteger(Hashtable, DimensionSize + this, CurrentDimension) then
                    call SaveInteger(Hashtable, DimensionSize + this, CurrentDimension, DEFAULT_ARRAY_SIZE)
                endif
            endloop
            
            return this
        endmethod
    endstruct
    
    private struct GetArray extends array
        method operator [] takes integer k returns thistype
            //arg integer k     // what key
            //loc integer aid   // k's id
            //loc integer sds   // this' dimension size
            local integer aid = GetArrayId(this, CurrentDimension + 1, k)
            local integer sds = LoadInteger(Hashtable, DimensionSize + this, CurrentDimension + 1)
            
            if aid > sds then
                return this
            endif
            
            set CurrentDimension = CurrentDimension + 1
            
            if CurrentDimension > MaxDimension [this] then
                return this
            elseif CurrentDimension == MaxDimension [this] then
                set CurrentKey = CurrentKey + aid
            else
                set CurrentKey = CurrentKey + (aid - 1) * GetArrayCount(this, CurrentDimension)
            endif
            
            return this
        endmethod
        
        //! textmacro HyperArray___MakeStorage takes TYPE, FUNC
            method operator $TYPE$ takes nothing returns $TYPE$
                return Load$FUNC$(Hashtable, ValueStorage + this, CurrentKey)
            endmethod
            
            method operator $TYPE$= takes $TYPE$ v returns nothing
                //arg $TYPE$ v      // value to store
                call Save$FUNC$(Hashtable, ValueStorage + this, CurrentKey, v)
            endmethod
        //! endtextmacro
        
        //! runtextmacro HyperArray___MakeStorage("boolean", "Boolean")
        //! runtextmacro HyperArray___MakeStorage("integer", "Integer")
        //! runtextmacro HyperArray___MakeStorage("real", "Real")
        //! runtextmacro HyperArray___MakeStorage("string", "Str")
        
        //! runtextmacro HyperArray___MakeStorage("ability", "AbilityHandle")
        //! runtextmacro HyperArray___MakeStorage("boolexpr", "BooleanExprHandle")
        //! runtextmacro HyperArray___MakeStorage("button", "ButtonHandle")
        //! runtextmacro HyperArray___MakeStorage("defeatcondition", "DefeatConditionHandle")
        //! runtextmacro HyperArray___MakeStorage("destructable", "DestructableHandle")
        //! runtextmacro HyperArray___MakeStorage("dialog", "DialogHandle")
        //! runtextmacro HyperArray___MakeStorage("effect", "EffectHandle")
        //! runtextmacro HyperArray___MakeStorage("event", "TriggerEventHandle")
        //! runtextmacro HyperArray___MakeStorage("fogmodifier", "FogModifierHandle")
        //! runtextmacro HyperArray___MakeStorage("fogstate", "FogStateHandle")
        //! runtextmacro HyperArray___MakeStorage("force", "ForceHandle")
        //! runtextmacro HyperArray___MakeStorage("group", "GroupHandle")
        //! runtextmacro HyperArray___MakeStorage("hashtable", "HashtableHandle")
        //! runtextmacro HyperArray___MakeStorage("image", "ImageHandle")
        //! runtextmacro HyperArray___MakeStorage("item", "ItemHandle")
        //! runtextmacro HyperArray___MakeStorage("itempool", "ItemPoolHandle")
        //! runtextmacro HyperArray___MakeStorage("leaderboard", "LeaderboardHandle")
        //! runtextmacro HyperArray___MakeStorage("lightning", "LightningHandle")
        //! runtextmacro HyperArray___MakeStorage("location", "LocationHandle")
        //! runtextmacro HyperArray___MakeStorage("multiboard", "MultiboardHandle")
        //! runtextmacro HyperArray___MakeStorage("multiboarditem", "MultiboardItemHandle")
        //! runtextmacro HyperArray___MakeStorage("player", "PlayerHandle")
        //! runtextmacro HyperArray___MakeStorage("quest", "QuestHandle")
        //! runtextmacro HyperArray___MakeStorage("questitem", "QuestItemHandle")
        //! runtextmacro HyperArray___MakeStorage("rect", "RectHandle")
        //! runtextmacro HyperArray___MakeStorage("region", "RegionHandle")
        //! runtextmacro HyperArray___MakeStorage("sound", "SoundHandle")
        //! runtextmacro HyperArray___MakeStorage("texttag", "TextTagHandle")
        //! runtextmacro HyperArray___MakeStorage("timer", "TimerHandle")
        //! runtextmacro HyperArray___MakeStorage("timerdialog", "TimerDialogHandle")
        //! runtextmacro HyperArray___MakeStorage("trackable", "TrackableHandle")
        //! runtextmacro HyperArray___MakeStorage("trigger", "TriggerHandle")
        //! runtextmacro HyperArray___MakeStorage("triggercondition", "TriggerConditionHandle")
        //! runtextmacro HyperArray___MakeStorage("triggeraction", "TriggerActionHandle")
        //! runtextmacro HyperArray___MakeStorage("ubersplat", "UbersplatHandle")
        //! runtextmacro HyperArray___MakeStorage("unit", "UnitHandle")
        //! runtextmacro HyperArray___MakeStorage("unitpool", "UnitPoolHandle")
        //! runtextmacro HyperArray___MakeStorage("widget", "WidgetHandle")
    endstruct
    
    struct HyperArray extends array
        private static integer  Count
        private        thistype Recycle
        
        static method [] takes integer d returns CreateArray
            //arg integer  d        // this' max dimension size
            local thistype this = thistype(0).Recycle
            
            if this == 0 then
                set .Count = .Count + 1
                set this   = .Count
            else
                set thistype(0).Recycle = this.Recycle
            endif
            
            set MaxDimension [this] = d
            set CurrentDimension = 0
            
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            set this.Recycle        = thistype(0).Recycle
            set thistype(0).Recycle = this
            
            set StructId     [this] = 0
            set MaxDimension [this] = 0
            
            call FlushChildHashtable(Hashtable, DimensionSize + this)
            call FlushChildHashtable(Hashtable, IdCount + this)
            call FlushChildHashtable(Hashtable, ValueStorage + this)
        endmethod
        
        method operator [] takes integer k returns GetArray
            //arg integer k     // what key
            //loc integer aid   // k's id
            //loc integer sds   // this' dimension size
            local integer aid = GetArrayId(this, 1, k)
            local integer sds = LoadInteger(Hashtable, DimensionSize + this, 1)
            
            if aid > sds then
                return this
            endif
            
            set CurrentDimension = 1
            
            if CurrentDimension > MaxDimension [this] then
                return this
            elseif CurrentDimension == MaxDimension [this] then
                set CurrentKey = CurrentKey + aid
            else
                set CurrentKey = CurrentKey + (aid - 1) * GetArrayCount(this, CurrentDimension)
            endif
            
            return this
        endmethod
    endstruct
endlibrary
 
Last edited:
If you use TableArray arrays, you can go up to 3D with practical sizes like:
3DArray[8192][262144][2147483647]

You can even make a 6DArray ;)

6DArray[90][90][512][512][32768][32768]

You would mask a 3DArray and do this:
3DArray[index1 * 90 + index2][index3 * 512 + index4][index5 * 32768 + index6]

And using that, you could make a 12D Array ^.^
It would be really crazy though :p

To make up for the small size of the first 2 indices:
5DArray[8192][512][512][32768][32768]

And just to increase the space allocated for the others, you could give users the ability to define sizes with a maximum of 8192.

This method works 100%.

It's pretty hard to read your code in it's current form :p

Here are some tips to increase readability:
- No spaces in between arrays:
t [xxx] [xxxx] [xxx].boolean = true
>>
t[xxx][xxxx][xxx].boolean = true

- Better variable names in some places so we can understand what you're doing :p

etc..
 
Yeah, but those HyperArrays supported by Table don't work as intended :3

JASS:
struct Demo extends array

    static method onInit takes nothing returns nothing
        local Table tb = Table.create()
        
        set tb[100][12][22] = 1
        set tb[90][1][22] = 0
        
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, I2S(tb[100][12][22]))
    endmethod
    
endstruct

This should display 1.
It displays 0 instead.

Only the last index actually works :/

tb[1101][1337][5] is the same as tb[9001][11][5]
 
Level 7
Joined
Apr 30, 2011
Messages
359
the optimizer is fixed ?_?
any links ? (please~)
---
updated !!!
can someone change the title to "[System] Hyper Array" (no Ext)
because this won't use NewTable anymore
and this is basically a replica to our NewTable, but specially designed for Array uses

edit:
thanks mod :D
 
Last edited:
I've never needed a resource like this. And from my experience with your resources, you don't submit them because you have a need for them either, you submit them simply because you wrote them for one reason or another.

I see... no demo map, no test script, nothing that this resource supports that isn't supported by either (New)Table, LinkedListStruct or even that new thing that Nestharus submitted.
 
Top