[comp.lang.pascal] re Real Arrays

kirsch@braggvax.arpa (David Kirschbaum) (11/14/87)

PROGRAM ToadPtr;

(*  The Problem Statement:

From: "Owen L. Astrachan" <ola@duke.cs.duke.EDU>
Subject: Turbo data segments
Message-Id: <10591@duke.cs.duke.edu>
Date: 11 Nov 87 18:26:50 GMT
To: info-pascal@brl-vim.arpa

Is there a way of allocating space for an array of 20,000 reals
in Turbo (on an IBM-PC)?  For example, I'd like to implement
what is logically expressed as

  type
    LargeArrayType = array[1..100,1..200] of real;

and then allocate variables of this type.

In order to allocate space from the heap using GetMem an integer argument
must be used.  Since the above declaration needs 120,000 bytes this option
is precluded.

This is not in an application I am writing so I don't know, for example, if
the matrix in question is sparse and would thus lend itself to other
options.

Please email responses, if anyone is interested I'll summarize results.

Thankyou.
---------------------------------------------------------------------
Owen L. Astrachan               CSNET: ola@duke
Dept.of Computer Science        ARPA:  ola@cs.duke.edu
Duke University                 UUCP: {ihnp4!decvax}!duke!ola
Durham NC 27706                 Phone (919)684-5110 Ext. 229
---------------------------------------------------------------------

 ... and the Toad Hall Hack, for Turbo Pascal v3.0 (or whatever):

*)

CONST
  MAX = 200;                            {play with this to see just how big
                                         you CAN make one of these things}

TYPE
  real100ptr = ^real100type;            {pointer to an array ..}
  real100type = ARRAY[1..MAX] OF real;  {.. of reals}

VAR
  HeapTop : ^Integer;                     {to remember our heap}
  real100  : real100ptr;                  {pointer to an array}
  realbuff : ARRAY[1..100] OF real100ptr; {a data segment array of pointers}

  origmem,
  x,y : INTEGER;                        {global array counters}
  r : REAL;                             {global real to play with}

BEGIN
  WRITELN('Demo for dynamic allocation of memory for a real number array.');

  origmem := MemAvail;            {remember how much free memory to start with}

  Mark(HeapTop);                  {make it easy to free dynamic memory later}

  Writeln('Filling Cells 1..1 thru 100..', MAX, ' with 9999.999');

  FOR x := 1 TO 100 DO BEGIN      {these will be dynamic reals}
    Write('.');                   {let the user know we're alive}
    New(real100);                 {allocate the array memory}
    realbuff[x] := real100;       {remember the array's location in our
                                   data segment array}
    FOR y := 1 TO MAX DO          {assign the dynamic real cell's value}
      real100^[y] := 99999.999;
  END;
  Writeln;

  Writeln('Filling Cells 1..1 thru 100..', MAX, ' with computed values.');

  FOR x := 1 TO 100 DO BEGIN      {get each of our dynamic array vectors ..}
    real100 := realbuff[x];       {.. from our data segment array}
    Write('.');                   {let the user know we're alive}
    FOR y := 1 TO MAX DO          {now assign some more real cell values}
      real100^[y] := (x *1.0) + (0.001 * y);
  END;
  Writeln;

  r := origmem;                   {memory remaining at the start}
  IF r < 0 THEN r := r + 65536.0; {in case it was negative}
  real100 := realbuff[100];       {high up in the array}
  real100^[MAX-1] := r;           {store the value}

  r := MemAvail;                  {just to see how much memory we used}
  IF r < 0 THEN r := r + 65536.0; {in case it was negative}
  real100 := realbuff[100];       {get our highest dynamic array vector ..}
  real100^[MAX] := r;             {.. and stuff in the highest cell value}

{ Now read the dynamic reals back (just a few of them) }

  Writeln('Reading back some sample values:');
  Writeln('Cells 1..1 thru 4..4:');
  FOR x := 1 to 4 DO BEGIN       {get our dynamic array vector ..}
    real100 := realbuff[x];      {.. from our data segment array}
    FOR y := 1 TO 4 DO     {now reach out in the dynamic array ..}
      Write(real100^[y]:8:3);    {.. and snarf a real cell value}
    Writeln;
  END;
  Writeln('Cells 97..', MAX-5, ' thru 100..', MAX-2, ':');
  FOR x := 97 TO 100 DO BEGIN
    real100 := realbuff[x];
    FOR y := MAX-5 TO MAX-2 DO
      Write(real100^[y]:8:3);
    Writeln;
  END;

{ Now pick up that very extreme corner of the matrix ... }

  real100 := realbuff[100];        {point to the right dynamic array}
  Writeln('Free memory at program start: ',
          real100^[MAX-1]:10:0, ' paras');
  Writeln('Free memory at program end  : ',
          real100^[MAX]:10:0  , ' paras');
  Writeln('Heap required for a 100x',MAX,' real array: ',
          ( (real100^[MAX-1] - real100^[MAX]) * 16.0):10:0, ' bytes');
  Writeln('Data segment memory requirements: ',
          Ofs(origmem) - Ofs(HeapTop), ' bytes' );
  Release(HeapTop);                {free our heap, just to be neat}
END.

Horrible, ain't it?  Don't let any naive undergrad Computer Sci students
see stuff like this .. it might disillusion them!

David Kirschbaum
Toad Hall
kirsch@braggvax.ARPA

taylorj@byuvax.bitnet (11/18/87)

Here is a slightly different solution to "The Case of the Really Big Real
Array"

type
  secondhalf = array[1..200] of real;
  secondhalfptr = ^secondhalf;

var
  realarray :array[1..100] of secondhalfptr;
     

Allocate space for the array on the heap like this:

  for x := 1 to 100 do begin
    new(realarry[x]);
  end;

Access the array like this :

  r := realarray[20]^[150];
  r := realarray[x]^[y];     {you get the idea}
     
This is off the top of my head, so there may be a few syntactical errors,
but I've done this type of thing before, so I know it works.

Jim Taylor
Microcomputer Support for Curriculum, Brigham Young University
taylorj@byuvax.bitnet

mccaugh@uiucdcsb.UUCP (11/21/87)

 why not just allocate 4 arrays of 2^15-1 reals each, which would more than
 satisfy your needs? Otherwise, use Turbo-C!

 (mccaugh@uiucmsl)