Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Large 3D array
#1
Hello

I want to make a three dimensional array with a large number of indicies. I am using the following code:

DIM a(100,100,100)

I keep getting an error message (error code 9) stating, I think, that the array is too large.

I tried to change the array indicies from static to variable, but this did not work.

Does anyone know what I can do?

tk
Reply
#2
Your array is 100*100*100*2 bytes (assuming it's an integer array), or 2 megabytes. That's way too big for real mode memory. With dos you usually have somewhere between 550k and 605k free, and after QB it's more like 300k.

You'll have to either switch languages, or think of a diffrent way to represent your data that doesn't use as much memory.
Reply
#3
*STAB*

Or use UGL.
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."

Visit www.neobasic.net to see rubbish in all its finest.
Reply
#4
Or a small simple EMS lib. UGL is probably overkill for what he needs.
Reply
#5
Remeber, I'm a newbie. I have no idea what UGL or an EMS lib are...?

tk

I've actually had some success using the ERASE command...will keep you posted.
Reply
#6
UGL is a full features game programming library. It lets your program have sound and high resolution graphics.

A EMS library lets you use EMS memory. UGL can do this too, but UGL may be more than you need.

Does anybody know of a good EMS tutorial for this guy?
Reply
#7
Here's some code I wrote a while ago for somebody else having a similar problem:

Code:
DEFINT A-Z
'$DYNAMIC

TYPE ArrayEMS
  Handle AS INTEGER
  ElementLen AS INTEGER
  NumElements AS LONG
END TYPE

DECLARE SUB EMS.Array.Dim (Array AS ArrayEMS)
DECLARE SUB EMS.Array.Set (Array AS ArrayEMS, Element&, SrcSegment, SrcOffset)
DECLARE SUB EMS.Array.Get (Array AS ArrayEMS, Element&, DstSegment, DstOffset)
DECLARE SUB EMS.Array.Erase (Array AS ArrayEMS)

CLS

IF NOT EMS.Init THEN             'make sure EMS is available
  PRINT "No EMM detected."
  END
END IF

DIM TestArray AS ArrayEMS         'set up an EMS array called TestArray
TestArray.ElementLen = 2          '2 = integer, 4 = long integer
TestArray.NumElements = 1000000   'element range = 1 to 1,000,000
EMS.Array.Dim TestArray           'allocate EMS memory for the array

a = 12345  'just some random numbers
b = 3210

'put the value of 'a' into element #1 of the EMS array TestArray
EMS.Array.Set TestArray, 1, VARSEG(a), VARPTR(a)

'put the value of 'b' into element #1,000,000 of the EMS array TestArray
EMS.Array.Set TestArray, 1000000, VARSEG(b), VARPTR(b)

a = 0    'now clear 'a' and 'b' so we can test if it worked
b = 0

'get the value element #1 of the EMS array TestArray and store it in 'a'
EMS.Array.Get TestArray, 1, VARSEG(a), VARPTR(a)

'get the value element #1,000,000 of the EMS array TestArray and store it in 'b'
EMS.Array.Get TestArray, 1000000, VARSEG(b), VARPTR(b)

PRINT a  'check 'em
PRINT b

EMS.Array.Erase TestArray  'deallocate the array (you *must* do this before
                           'your program ends, or the EMS memory will not be
                           'released!)

END

SUB EMS.Array.Dim (Array AS ArrayEMS)

  IF EMS.FreeHandles = 0 THEN
    PRINT "EMS.Array.Dim: No free handles!"
    EXIT SUB
  END IF

  BytesNeeded& = Array.NumElements * Array.ElementLen
  PagesNeeded = BytesNeeded& / 16384 + .5

  IF EMS.FreePages < PagesNeeded THEN
    PRINT "EMS.Array.Dim: Not enough free pages! ("; EMS.FreePages; "available,"; PagesNeeded; "needed)"
    EXIT SUB
  END IF

  Handle = EMS.AllocPages(PagesNeeded)
  Array.Handle = Handle

END SUB

SUB EMS.Array.Set (Array AS ArrayEMS, Element&, SrcSegment, SrcOffset)

  IF Element& < 1 OR Element& > Array.NumElements THEN
    PRINT "EMS.Array.Set: Subscript out of range ("; Element&; "given; must be between 1 and"; Array.NumElements; ")"
    EXIT SUB
  END IF

  Offset& = (Element& - 1) * Array.ElementLen
  Page = Offset& \ 16384
  PageOffset = Offset& - (Page * 16384&)
  EMS.CopyMem CLNG(Array.ElementLen), 0, SrcSegment, SrcOffset, Array.Handle, Page, PageOffset

END SUB

SUB EMS.Array.Get (Array AS ArrayEMS, Element&, DstSegment, DstOffset)

  IF Element& < 1 OR Element& > Array.NumElements THEN
    PRINT "EMS.Array.Get: Subscript out of range ("; Element&; "given; must be between 1 and"; Array.NumElements; ")"
    EXIT SUB
  END IF

  Offset& = (Element& - 1) * Array.ElementLen
  Page = Offset& \ 16384
  PageOffset = Offset& - (Page * 16384&)
  EMS.CopyMem CLNG(Array.ElementLen), Array.Handle, Page, PageOffset, 0, DstSegment, DstOffset

END SUB

SUB EMS.Array.Erase (Array AS ArrayEMS)

  EMS.DeallocPages Array.Handle

END SUB


Needs EMS.BAS (you can probably remove some functionsSmile
Code:
DEFINT A-Z
'$DYNAMIC
'$INCLUDE: 'QB.BI'

DIM SHARED Regs AS RegTypeX
DIM SHARED EMS.Error            'Holds the error code of the last operation

DECLARE FUNCTION EMS.ErrorMsg$ ()
DECLARE FUNCTION EMS.Init ()
DECLARE FUNCTION EMS.Version$ ()
DECLARE FUNCTION EMS.PageFrame ()
DECLARE FUNCTION EMS.FreeHandles ()
DECLARE FUNCTION EMS.FreePages ()
DECLARE FUNCTION EMS.TotalPages ()
DECLARE FUNCTION EMS.AllocPages (NumPages)
DECLARE SUB EMS.DeallocPages (Handle)
DECLARE SUB EMS.MapPage (Physical, Logical, Handle)
DECLARE SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)
DECLARE SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)
DECLARE SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)


FUNCTION EMS.AllocPages (NumPages)

  'Allocates the number of pages in [NumPages] and
  'returns the EMS handle the memory is allocated to.

  Regs.ax = &H4300                           'Allocate [NumPages] pages of EMS
  Regs.bx = NumPages
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

  EMS.AllocPages = Regs.dx                   'Return the handle

END FUNCTION

SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)

  'Copies memory from EMS or base memory to EMS or base memory, where:
  '
  'Length&    = Length of memory to copy in bytes
  'SrcHandle  = EMS handle of source memory (use 0 if source is base memory)
  'SrcSegment = Segment of source memory (or page number if source is EMS)
  'SrcOffset  = Offset of source memory
  'DstHandle  = EMS handle of destination memory (use 0 if destination is base memory)
  'DstSegment = Segment of destination memory (or page number if destination is EMS)
  'DstOffset  = Offset of destination memory

  'Determine the source and destination memory types by checking the handles
  IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1)
  IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1)

  'Create a buffer containing the copy information
  CopyInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment)

  Regs.ax = &H5700                           'Copy the memory region
  Regs.ds = VARSEG(CopyInfo$)                'described in the buffer
  Regs.si = SADD(CopyInfo$)
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

END SUB

SUB EMS.DeallocPages (Handle)

  'Deallocates the EMS pages allocated the EMS handle [Handle].
  'You MUST remember to call the sub before your program ends
  'if you allocate any memory!

  Regs.ax = &H4500                           'Release the pages allocated to [Handle]
  Regs.dx = Handle
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

END SUB

FUNCTION EMS.ErrorMsg$

  'Returns a text string describing the error code in EMS.Error.

  SELECT CASE EMS.Error
    CASE &H0: Msg$ = "successful"
    CASE &H80: Msg$ = "internal error"
    CASE &H81: Msg$ = "hardware malfunction"
    CASE &H82: Msg$ = "busy -- retry later"
    CASE &H83: Msg$ = "invalid handle"
    CASE &H84: Msg$ = "undefined function requested by application"
    CASE &H85: Msg$ = "no more handles available"
    CASE &H86: Msg$ = "error in save or restore of mapping context"
    CASE &H87: Msg$ = "insufficient memory pages in system"
    CASE &H88: Msg$ = "insufficient memory pages available"
    CASE &H89: Msg$ = "zero pages requested"
    CASE &H8A: Msg$ = "invalid logical page number encountered"
    CASE &H8B: Msg$ = "invalid physical page number encountered"
    CASE &H8C: Msg$ = "page-mapping hardware state save area is full"
    CASE &H8D: Msg$ = "save of mapping context failed"
    CASE &H8E: Msg$ = "restore of mapping context failed"
    CASE &H8F: Msg$ = "undefined subfunction"
    CASE &H90: Msg$ = "undefined attribute type"
    CASE &H91: Msg$ = "feature not supported"
    CASE &H92: Msg$ = "successful, but a portion of the source region has been overwritten"
    CASE &H93: Msg$ = "length of source or destination region exceeds length of region allocated to either source or destination handle"
    CASE &H94: Msg$ = "conventional and expanded memory regions overlap"
    CASE &H95: Msg$ = "offset within logical page exceeds size of logical page"
    CASE &H96: Msg$ = "region length exceeds 1 MB"
    CASE &H97: Msg$ = "source and destination EMS regions have same handle and overlap"
    CASE &H98: Msg$ = "memory source or destination type undefined"
    CASE &H9A: Msg$ = "specified alternate map register or DMA register set not supported"
    CASE &H9B: Msg$ = "all alternate map register or DMA register sets currently allocated"
    CASE &H9C: Msg$ = "alternate map register or DMA register sets not supported"
    CASE &H9D: Msg$ = "undefined or unallocated alternate map register or DMA register set"
    CASE &H9E: Msg$ = "dedicated DMA channels not supported"
    CASE &H9F: Msg$ = "specified dedicated DMA channel not supported"
    CASE &HA0: Msg$ = "no such handle name"
    CASE &HA1: Msg$ = "a handle found had no name, or duplicate handle name"
    CASE &HA2: Msg$ = "attempted to wrap around 1M conventional address space"
    CASE &HA3: Msg$ = "source array corrupted"
    CASE &HA4: Msg$ = "operating system denied access"
    CASE ELSE: Msg$ = HEX$(EMS.Error) '"undefined error"
  END SELECT

  EMS.ErrorMsg$ = Msg$

END FUNCTION

SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)

  'Exhanges memory from EMS or base memory to EMS or base memory, where:
  '
  'Length&    = Length of memory to exchange in bytes
  'SrcHandle  = EMS handle of source memory (use 0 if source is base memory)
  'SrcSegment = Segment of source memory (or page number if source is EMS)
  'SrcOffset  = Offset of source memory
  'DstHandle  = EMS handle of destination memory (use 0 if destination is base memory)
  'DstSegment = Segment of destination memory (or page number if destination is EMS)
  'DstOffset  = Offset of destination memory

  'Determine the source and destination memory types by checking the handles
  IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1)
  IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1)

  'Create a buffer containing the copy information
  ExchInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment)

  Regs.ax = &H5701                           'Exchange the memory region
  Regs.ds = VARSEG(ExchInfo$)                'described in the buffer
  Regs.si = SADD(ExchInfo$)
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

END SUB

FUNCTION EMS.FreeHandles

  'Returns the number of free (available) EMS handles.

  Regs.ax = &H4B00                             'Get the # of handles in use
  InterruptX &H67, Regs, Regs
  UsedHandles = Regs.bx

  Regs.ax = &H5402                             'Get the total # of handles
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100    'Store the status code
  TotalHandles = Regs.bx

  EMS.FreeHandles = TotalHandles - UsedHandles 'Subtract to get the # of free handles

END FUNCTION

FUNCTION EMS.FreePages

  'Returns the number of free (available) EMS pages
  '(Multiply by 16 to get the amount free EMS in KB.)

  Regs.ax = &H4200                           'Get the # of free pages
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code
  EMS.FreePages = Regs.bx

END FUNCTION

FUNCTION EMS.Init

  'Returns true (-1) if an EMM is installed
  'or false (0) if an EMM is not installed.

  Regs.ax = &H3567                        'Get the interrupt vector for int 67h
  InterruptX &H21, Regs, Regs
  DEF SEG = Regs.es                       'Point to the interrupt segment
  FOR x = 10 TO 17                        'Store the 8 bytes at ES:0A in EMM$
    EMM$ = EMM$ + CHR$(PEEK(x))
  NEXT
  IF EMM$ <> "EMMXXXX0" THEN
    EMS.Init = 0              'EMM not installed
  ELSE
    EMS.Init = -1             'EMM installed
  END IF

END FUNCTION

SUB EMS.MapPage (Physical, Logical, Handle)

  'Maps the logical EMS page [Logical] (allocated to the handle [Handle])
  'to the physical page [Physical] in the EMS page frame.

  Regs.ax = &H4400 + Physical                'Map the logical page [Logical]
  Regs.bx = Logical                          'to the physical page [Physical]
  Regs.dx = Handle
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

END SUB

SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)

  'Maps up to 4 logical EMS pages to physical pages in the page frame, where:
  '
  'PhysicalStart = Physical page first logical page is mapped to
  'LogicalStart  = First logical page to map
  'NumPages      = Number of pages to map (1 to 4)
  'Handle        = EMS handle logical pages are allocated to

  'Create a buffer containing the page information
  FOR x = 0 TO NumPages - 1
    MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)
  NEXT

  Regs.ax = &H5000                           'Map the pages in the buffer
  Regs.cx = NumPages                         'to the pageframe
  Regs.dx = Handle
  Regs.ds = VARSEG(MapInfo$)
  Regs.si = SADD(MapInfo$)
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code

END SUB

FUNCTION EMS.PageFrame

  'Returns the segment of the EMS page frame

  Regs.ax = &H4100                           'Get the segment of the page frame
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Save the status code
  EMS.PageFrame = Regs.bx

END FUNCTION

FUNCTION EMS.TotalPages

  'Returns the total number of EMS pages
  '(Multiply by 16 to get the total amount of EMS in KB.)

  Regs.ax = &H4200                           'Get the # of total pages
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code
  EMS.TotalPages = Regs.dx

END FUNCTION

FUNCTION EMS.Version$

  'Returns a string containing the EMM version.
  '(Must be "4.0" or greater to use our routines.)

  Regs.ax = &H4600                           'Get the EMM version
  InterruptX &H67, Regs, Regs
  EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Save the status code

  Version = Regs.ax AND &HFF                 'Split the version number into
  Major = (Version AND &HF0) \ &H10          'its major and minor counterparts
  Minor = Version AND &HF
  EMS.Version$ = LTRIM$(STR$(Major)) + "." + LTRIM$(STR$(Minor))

END FUNCTION
Reply
#8
Wow!

I really appreciate all the help. I certainly have found a place to go when I am at sticking points.

I think I found a way around my conundrum; now I realize I was using up way too much memory for the computation I was doing (thanks to lots of you who posted).

I will certainly look through the code if I ever REALLY need a 100x100x100 block of data.

Thanks, you guys.

tk
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)