home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / pascal / 4861 < prev    next >
Encoding:
Internet Message Format  |  1992-08-14  |  11.2 KB

  1. Path: sparky!uunet!munnari.oz.au!ariel!ucsvc.ucs.unimelb.edu.au!lugb!lux!9125113g
  2. From: 9125113g@lux.latrobe.edu.au (Mitch Davis)
  3. Newsgroups: comp.lang.pascal
  4. Subject: Re: Arrays > 64K
  5. Message-ID: <1992Aug15.040311.3468@lugb.latrobe.edu.au>
  6. Date: 15 Aug 92 04:03:11 GMT
  7. References: <1992Aug3.102558.21254@newstand.syr.edu> <1992Aug02.170808.2053@crash> <1992Aug13.003031.19643@usenet.ins.cwru.edu>
  8. Sender: news@lugb.latrobe.edu.au (USENET News System)
  9. Organization: La Trobe University
  10. Lines: 322
  11.  
  12. In article <1992Aug13.003031.19643@usenet.ins.cwru.edu> wct@po.CWRU.Edu (William C. Thompson) writes:
  13.  
  14. >Here is a file you can include with your source code.  You need to
  15. >define a type before you {$I} it.
  16. >
  17. >  HugeDataType is.  It follows that another restriction would
  18. >  be you can only have one type of huge array. }
  19.  
  20. Heap big code deleted.  Here's my offering.  Note that because it uses
  21. objects, you can have more than one array of whatever type you want.
  22.  
  23. Note this code was written by me for the International Pascal
  24. Newsletter.  I'd suggest you study the supporting documentation in that
  25. if you want to know more.
  26.  
  27. The file you want is PNL010.ZIP and is widely available.  Check archie.
  28.  
  29. [DOSMEM.PAS]
  30.  
  31. unit DOSMem;
  32.  
  33. interface
  34.  
  35. function Alloc (paras:word):word;
  36.  
  37. procedure Free (p:word);
  38.  
  39. function Largest:word;
  40.  
  41. implementation
  42.  
  43. function Alloc; assembler;
  44.  
  45. asm
  46.   mov  ah, $48
  47.   mov  bx, paras
  48.   int  $21
  49.   jnc  @1
  50.   xor  ax, ax
  51.   @1:
  52. end;
  53.  
  54. procedure Free; assembler;
  55.  
  56. asm
  57.   mov  ah, $49
  58.   mov  es, p
  59.   int  $21
  60. end;
  61.  
  62. function Largest; assembler;
  63.  
  64. asm
  65.   mov  ah, $48
  66.   mov  bx, -1
  67.   int  $21
  68.   mov  ax, bx
  69. end;
  70.  
  71. end.
  72.  
  73. [BIGARRAY.PAS]
  74.  
  75. unit BigArray;
  76.  
  77. {Program to accompany article in issue #10 of the Pascal NewsLetter.     }
  78. {Author: Mitch Davis, 9125113g@lux.latrobe.edu.au                        }
  79. {                     Mitch.Davis@p6.f384.n634.z3.fidonet.org            }
  80. {                     Fidonet: 3:634/384.6                               }
  81. {                     +61-3-890-2062.                                    }
  82.  
  83. { from public domain ideas by Trevor J. Carlsen, 3:690/644 }
  84.  
  85. {This unit lets you implement whopping great big arrays, larger than the }
  86. {64k offered by Turbo Pascal.  It does this by offering a large array    }
  87. {object.                                                                 }
  88. {The array can have elements of any size, and the array can take all free}
  89. {DOS memory.  Thus, you could conceiveably have an array of reals taking }
  90. {some 400k or more.  Each array can take a subscript in the range of 1 to}
  91. {the parameter you hand the Init method - ie, the array is one-based.    }
  92.  
  93. {Note this code has NOT been optimised - it needs it very badly!         }
  94. {A future version of this unit (to be published in the PNL) will be      }
  95. {heavily optimised, will offer multidimensional arrays, and will offer   }
  96. {arrays that spill over onto disk, as well as specific support for sparse}
  97. {arrays.  Keep your eyes out for it!                                     }
  98.  
  99. {This program has NOT been proven correct.  I know it works when used as }
  100. {part of the MDP programs published in PNL #10, but I can't vouch for its}
  101. {operation if and when used in different situations.                     }
  102.  
  103. {I suggest compiling this in 286 mode, at least until I can get around to}
  104. {optimising it!                                                          }
  105.  
  106. {$R-,S-,N+}
  107.  
  108. {$DEFINE OnA286} {Remove this line if you're not on a 186 or higher.}
  109.  
  110. {$IFDEF OnA286} {$G+} {$ELSE} {$G-} {$ENDIF}
  111.  
  112. interface
  113.  
  114. {$IFDEF OnA286}
  115. uses Test186;
  116. {$ENDIF}
  117.  
  118. type BigDOSArray = object
  119.                      procedure SetElemSize (newsize:word);
  120.                      function GetMaxSize:longint;
  121.                      procedure Init (Elems:longint);
  122.                      function Elem (elemnum:longint):pointer;
  123.                      procedure Done;
  124.                    private
  125.                      base:word; {paragraph of base}
  126.                      linear:longint;
  127.                      size:word; {size of each element}
  128.                    end;
  129.  
  130. implementation
  131.  
  132. uses DosMem;
  133.  
  134. procedure BigDOSArray.SetElemSize;
  135.  
  136. begin
  137.   size := newsize;
  138. end;
  139.  
  140. function BigDOSArray.GetMaxSize;
  141.  
  142. var paras:word;
  143.     bytes:longint;
  144.     elemss:longint;
  145.  
  146. begin
  147.   GetMaxSize := pred ((longint (DosMem.Largest) shl 4) div size);
  148. end;
  149.  
  150. procedure BigDOSArray.Init;
  151.  
  152. var bytes:longint;
  153.     paras:word;
  154.  
  155. begin
  156.   base := DosMem.Alloc (succ((longint(Elems) * size) shr 4));
  157.   linear := longint (base) shl 4;
  158. end;
  159.  
  160. function BigDOSArray.Elem;
  161.  
  162. var offset:longint;
  163.  
  164. begin
  165.   offset := pred(elemnum) * size + linear;
  166.   Elem := ptr (offset shr 4,offset and $f);
  167. end;
  168.  
  169. procedure BigDOSArray.Done;
  170.  
  171. begin
  172.   DosMem.Free (base);
  173. end;
  174.  
  175. end.
  176.  
  177. [Here's the article, and a sample (for "sample" read "silly"!) program
  178. which shows you how to use it.]
  179.  
  180. BigArray - you've never seen arrays this BIG!  by Mitch Davis, (3:634/384.6)
  181. ============================================================================
  182.  
  183.  *** Error 22: Structure too large.
  184.  
  185.  *** Error 49: Data segment too large.
  186.  
  187.  *** Error 96: Too many variables.
  188.  
  189.  *** Runtime error 201 at XXXX:YYYY. {Range check}
  190.  
  191.  *** Runtime error 203 at XXXX:YYYY. {Heap full}
  192.  
  193. How many times have you been frustrated by these little beauties?  How many
  194. times has it been because you had an array that just wouldn't stay down?
  195. There are two ways to fix this - you could put your thinking on a diet and
  196. work out some other way that doesn't consume quite so much memory
  197. (recommended!) or you could do it the lazy way, and slot in a unit called
  198. the (drum roll!) *** BigArray ***.
  199.  
  200. BigArray will give you arrays which can be as big as will fit in
  201. conventional memory, ie, they aren't limited to 64k.  The arrays can be of
  202. any type, and are of a single dimension.  (A version being written now lets
  203. you have arrays that spill over to disk or EMS, as well as multi
  204. dimensionals.)
  205.  
  206. The large arrays are implemented as objects.  You use the .SetElemSize
  207. method to tell it how big your elements are, and you can subsequently find
  208. out via .GetMaxSize how many elements the largest array can be.  Then you
  209. call the Init method with the number of elements you'd like, and voila,
  210. your array is done!  When you're finished with the array, call the .Done
  211. method.
  212.  
  213. How are elements accessed?  You pass the element subscript to the .Elem
  214. function, and it returns a pointer to that element.  The idea is that you
  215. then assign that pointer to a pointer variable of the type you're storing.
  216. Then by deferencing the pointer (following it by a caret [^]) you can then
  217. access any fields, bits, WHATEVER that you would with a plain-jane
  218. variable.
  219.  
  220. Let's look at a sample of how you'd use them:
  221.  
  222. program BigArrayTest;
  223.  
  224. {Program to accompany article in issue #10 of the Pascal NewsLetter.     }
  225. {Author: Mitch Davis, (3:634/384.6) +61-3-890-2062.                      }
  226.  
  227. {$G+,M 16384,0,0} {Make SURE you tell TP not to steal all the DOS memory }
  228.                   {for a heap!  If you're not using dynamic variables,   }
  229.                   {set both numbers to 0.                                }
  230.  
  231. {This program provides a nonsense demonstration of how you use the tools }
  232. {in the BigArray unit.                                                   }
  233.  
  234. uses Test186, BigArray; {I run my programs on a i286.  If you have an XT,}
  235.                         {Remove the "G+," from above and the "Test186"   }
  236.                         {from the uses section.                          }
  237.  
  238. type PigeonType = record
  239.                     value:real;
  240.                     changed:boolean;
  241.                   end;
  242.  
  243. var PigeonHole:BigDosArray;
  244.     PigeonPtr:^PigeonType;
  245.     PHnum, MaxSize:longint;
  246.     GlobalChanged:boolean;
  247.  
  248. begin
  249.   writeln ('Welcome to the pigeon-hole.');
  250.   with PigeonHole do begin {This sets up the big array.}
  251.     SetElemSize (sizeof (PigeonType)); {Tells it how big each element will be}
  252.     MaxSize := GetMaxSize;
  253.     Init (MaxSize); {Make it as big as possible.  This is not compulsory.    }
  254.   end;
  255.   writeln ('There are ',MaxSize,' pigeon-holes, numbered from 1 to ',MaxSize,'.');
  256.   write ('Please wait while I clear them... ');
  257.   for PHnum := 1 to MaxSize do begin
  258.     PigeonPtr := PigeonHole.Elem (PHnum); {Get the address of the element}
  259.     PigeonPtr^.Changed := false; {Reference the changed field within that}
  260.   end;                           {element.                               }
  261.   writeln ('Done.');
  262.   GlobalChanged := false; {This will save us search time later if no changes}
  263.   repeat
  264.     write ('Which pigeon hole? (1-',MaxSize,', 0 to quit): ');
  265.     readln (PHnum);
  266.     if (PHnum > 0) and (PHnum <= MaxSize) then begin
  267.       PigeonPtr := PigeonHole.Elem (PHnum);
  268.       with PigeonPtr^ do begin
  269.         case Changed of
  270.           true :writeln ('That pigeon-hole has the value of ',Value:3:2);
  271.           false:writeln ('That is a new pigeon hole.');
  272.         end;
  273.         write ('Change it to? ');
  274.         readln (Value);
  275.         Changed := true; {means this ph will be shown in the end summary}
  276.       end;
  277.       writeln ('Pigeon-hole changed.');
  278.       GlobalChanged := true;
  279.     end;
  280.   until PHnum = 0;
  281.   writeln ('-------------------------------------------------');
  282.   case GlobalChanged of
  283.     false:writeln ('You didn''t change any pigeon holes.');
  284.     true :begin
  285.             writeln ('The pigeon holes you changed were:');
  286.             write ('Wait..',#13);
  287.             for PHnum := 1 to MaxSize do begin {scan thru the ph's}
  288.               PigeonPtr := PigeonHole.Elem (PHnum);
  289.               with PigeonPtr^ do if changed then writeln (PHnum,': ',value:3:5);
  290.             end;
  291.           end;
  292.   end;
  293.   writeln ('Thanks for using the pigeon-holes!');
  294.   PigeonHole.Done;
  295. end.
  296.  
  297. If you understand this (in conjunction with the "interface" section of the
  298. BigArray unit), then you should have no problem working out how to use it.
  299.  
  300. A few usage notes:
  301.  
  302.   o The Big Arrays are 1-based, that is if you call BigDOSArray.Init(10),
  303.     then the element subscripts run from 1 up to 10.
  304.   o There is NO checking to ensure that the element you pass to
  305.     BigDOSArray.Elem is within the defined range.  If it isn't, then you'll
  306.     get garbage results for the pointer result.  Beware!
  307.   o The code for BigDOSArray hasn't been extensively tested.  Caveat
  308.     Emptor!
  309.   o BigDOSArray needs optimising BADLY!  I plan to write it in optimised
  310.     assembler throughout; in the meantime, you'll have to sacrifice speed
  311.     for convenience.
  312.   o I am aware that Turbo Power markets code which implements large
  313.     arrays (and probably MUCH better than I've managed here!).  I haven't
  314.     looked at their code.  Trevor Carlsen's OverSize unit also performs a
  315.     similar function.  I looked at his code, and couldn't understand it.
  316.     That's not meant as a slur on Trevor (3:690/644), who writes code so
  317.     good it should be framed.  I just thought I'd take a different
  318.     approach. Upshot:  If any of the other large-array products fit your
  319.     bill better, use them!
  320.   o The BigDOSArray unit currently compiles in i286 mode.  If you have an
  321.     XT or similar, chop out the G+ and Test186 bits, in the same way as the
  322.     comments in the demo program mention.
  323.  
  324. Well that about wraps it up.  I'd be more than happy to answer any queries
  325. you have about the unit.  Next issue, time and space permitting, I'm
  326. planning on having a followup article which goes into optimisation,
  327. multi-dimensional arrays, etc.  Till then?  Make merry with your Pascal!
  328.  
  329. [End of article]
  330.  
  331. I hope this helps.
  332.  
  333. Mitch. 
  334.