• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

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

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Please use some proper variable names now that the optimizer is fixed.

NewTable already supports "HyperArrays". This is valid syntax, for example:

JASS:
set u = tb[100][500].unit['X']

It compiles to something like:

JASS:
set u = LoadUnitHandle(ht, LoadInteger(ht, LoadInteger(ht, tb, 100), 500), 'X')
 
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:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
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