[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]

    {
    From: perivar@ibg.uit.no (Per Ivar Steinsund)

    I've made a unit (Huge) that uses the global-heap to allocate
    memory for arrays. The size of the arrays are only limited by
    hardware memory.
    }
    Unit Huge;

    (***********************************************)
    (* Unit for making dynamic arrays and matrix.  *)
    (* The elementsize has a limit of 64 kB, but   *)
    (* the total size of each array/matrix is only *)
    (* limited by available memory.                *)
    (*                                             *)
    (* Per Ivar Steinsund (1994)                   *)
    (*                                             *)
    (* Example of use:                             *)
    (*                                             *)
    (* var J:longint;                              *)
    (*     Arr:PHugeRealArray;                     *)
    (*                                             *)
    (* begin                                       *)
    (*    Arr:=new(PHugeRealArray,Init(0,200000,   *)
    (*             SizeOf(Real),true));            *)
    (*    if Arr^.Data<>nil then                   *)
    (*       for J:=0 to 200000 do Arr^.I(J)^:=J/5;*)
    (*    Arr^.Done;                               *)
    (* end;                                        *)
    (*                                             *)
    (***********************************************)

    interface

    uses  Objects,WinAPI,OMemory,WinTypes;

    Const
        SegSize=$FFFF;

    Type
        Adr=record
           Off,Seg:Word;
        end;

        PHugeArray=^THugeArray;
        THugeArray=Object(TObject)
           Data:Pointer;
           MinX,MaxX:LongInt;
           ElementSize,ElementsPerSeg:LongInt;
           constructor Init(Min,Max:LongInt; Size:Word; Message:boolean);
           function ChangeSize(Min,Max:LongInt; Message:boolean):boolean;
           function I(X:LongInt):Pointer;
           destructor done; virtual;
           procedure GrabMem(var NewData:Pointer; Range:LongInt;
    Change,Message:boolean);
           function GetPtr(Pos:LongInt):Pointer;
        end;

        PReal=^Real;

        PHugeRealArray=^THugeRealArray;
        THugeRealArray=Object(THugeArray)
           function I(X:LongInt):PReal;
        end;

        PHugeMatrix=^THugeMatrix;
        THugeMatrix=Object(THugeArray)
           MinY,MaxY,RangeY:LongInt;
           constructor Init(Min1,Max1,Min2,Max2:LongInt; Size:Word;
    Message:boolean);
           function ChangeSize(Min1,Max1,Min2,Max2:LongInt;
    Message:boolean):boolean;
           function I(X,Y:LongInt):Pointer;
        end;

        PHugeWordMatrix=^THugeWordMatrix;
        THugeWordMatrix=Object(THugeMatrix)
           function I(X,Y:LongInt):PWord;
        end;

    implementation

        constructor THugeArray.Init(Min,Max:LongInt; Size:Word; Message:boolean);

        begin
           MinX:=Min;
           MaxX:=Max;
           ElementSize:=Size;
           GrabMem(Data,MaxX-MinX+1,false,Message);
        end;

        destructor THugeArray.done;

        begin
           GlobalFreePtr(Data);
        end;

        function THugeArray.I(X:LongInt):Pointer;

        begin
           I:=GetPtr(X-MinX);
    {$IFOPT R+}
           if (X<MinX) or (X>MaxX) then
              if id_No=MessageBox(0,'Error in huge array, continue?','Index out of range!',
                                  mb_YesNo or mb_IconQuestion) then
              begin
                 Done;
                 Halt;
              end;
    {$ENDIF}
        end;

        function THugeArray.ChangeSize(Min,Max:LongInt; Message:boolean):boolean;

        var NewData:Pointer;

        begin
           MinX:=Min;
           MaxX:=Max;
           GrabMem(NewData,MaxX-MinX+1,true,Message);
           if NewData<>nil then
           begin
              ChangeSize:=true;
              Data:=NewData;
           end
           else ChangeSize:=false;
        end;

        procedure THugeArray.GrabMem(var NewData:Pointer; Range:LongInt;
    Change,Message:boolean);

        var MemSize:LongInt;

        begin
           MemSize:=Range*ElementSize;
           if not Change then ElementsPerSeg:=SegSize div ElementSize;
           if (MemSize>SegSize) and (SegSize mod ElementSize<>0) then
              MemSize:=(Range div ElementsPerSeg)*SegSize+ElementSize*(Range mod
    ElementsPerSeg);
           if Change then NewData:=GlobalReAllocPtr(Data,MemSize,Gmem_Moveable or
    Gmem_NoDiscard)
                     else NewData:=GlobalAllocPtr(Gmem_Moveable or
    Gmem_NoDiscard,MemSize);
           if (NewData=nil) and Message then
              MessageBox(0,'It is not possible to allocate enough memory.',
                         'Error',mb_OK or mb_IconInformation);
        end;

        function THugeArray.GetPtr(Pos:LongInt):Pointer;

        begin
           GetPtr:=Ptr(Adr(Data).Seg+(Pos div ElementsPerSeg)*SelectorInc,
                       Adr(Data).Off+(Pos mod ElementsPerSeg)*ElementSize);
        end;

        function THugeRealArray.I(X:LongInt):PReal;

        begin
           I:=inherited I(X);
        end;

        constructor THugeMatrix.Init(Min1,Max1,Min2,Max2:LongInt; Size:Word;
    Message:boolean);

        begin
           MinX:=Min1;
           MaxX:=Max1;
           MinY:=Min2;
           MaxY:=Max2;
           RangeY:=1+MaxY-MinY;
           ElementSize:=Size;
           GrabMem(Data,(MaxX-MinX+1)*(MaxY-MinY+1),false,Message);
        end;

        function THugeMatrix.ChangeSize(Min1,Max1,Min2,Max2:LongInt;
    Message:boolean):boolean;

        var NewData:Pointer;

        begin
           MinX:=Min1;
           MaxX:=Max1;
           MinY:=Min2;
           MaxY:=Max2;
           RangeY:=1+MaxY-MinY;
           GrabMem(NewData,(MaxX-MinX+1)*(MaxY-MinY+1),true,Message);
           if NewData<>nil then
           begin
              ChangeSize:=true;
              Data:=NewData;
           end
           else ChangeSize:=false;
        end;

        function THugeMatrix.I(X,Y:LongInt):Pointer;

        begin
           I:=GetPtr(Y-MinY+RangeY*(X-MinX));
    {$IFOPT R+}
           if (X<MinX) or (X>MaxX) or (Y<MinY) or (Y>MaxY) then
              if id_No=MessageBox(0,'Error in huge matrix, continue?','Index out of range!',
                                  mb_YesNo or mb_IconQuestion) then
              begin
                 Done;
                 Halt;
              end;
    {$ENDIF}
        end;

        function THugeWordMatrix.I(X,Y:LongInt):PWord;

        begin
           I:=inherited I(X,Y);
        end;

    end.

    program TestHuge;

    uses Huge,WinCrt;

    const Max:LongInt=200000;
          MaxMat:LongInt=2500;

    var J:longint;
        Arr:PHugeRealArray;
        Mat:PHugeWordMatrix;

    begin
       Arr:=new(PHugeRealArray,Init(0,Max,
                SizeOf(Real),true));
       if Arr^.Data<>nil then
       begin
          RandSeed:=1;
           for J:=0 to 50 do
             Arr^.I(random(Max))^:=J;
          RandSeed:=1;
          for J:=0 to 50 do
             writeln(Arr^.I(random(Max))^:5:1);
       end;
       Arr^.Done;
       Mat:=new(PHugeWordMatrix,Init(0,MaxMat,0,MaxMat,
                SizeOf(Word),true));
       if Mat^.Data<>nil then
       begin
          RandSeed:=1;
           for J:=0 to 50 do
             Mat^.I(random(MaxMat),random(MaxMat))^:=J;
          RandSeed:=1;
          for J:=0 to 50 do
             writeln(Mat^.I(random(MaxMat),random(MaxMat))^);
       end;
       Mat^.Done;
       writeln('Done');
    end.

[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]