ARRAY over 4096 elements

ARRAY over 4096 elements

Postby avista » Fri Jun 01, 2007 11:08 am

I need to use array longer than 4096 elements (multidimensional if possible), and it is verry important to be used in LISTBOX.

Some sugestions ?[/b]
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Postby Antonio Linares » Fri Jun 01, 2007 11:21 am

Clipper arrays are limited to 4096 elements. There is a workaround that consists on using the latest element to point to another array:

aTest[ 4096 ] = Array( 4096 )

Anyhow we do recommend you to port your Clipper application to Harbour/xHarbour where these limitations no longer exist
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby avista » Fri Jun 01, 2007 12:31 pm

Hi Antonio and thanks for fast answer.

-> aTest[ 4096 ] = Array( 4096 )


I will try to use this ....but how to use it in LISTBOX and view that 9191 elements ?

Best regards,
Pande.
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Postby Enrico Maria Giordano » Fri Jun 01, 2007 12:37 pm

You can use a TWBrowse and calculate the correct position of the item to show for each index. For example (not tested):

Code: Select all  Expand view
FUNCTION GETITEM( aArray, i )

    IF i < 4096; RETURN aArray[ i ]; ENDIF

    RETURN aArray[ 4096, i - 4095 ]


EMG
User avatar
Enrico Maria Giordano
 
Posts: 8715
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Re: ARRAY over 4096 elements

Postby FiveWiDi » Sat Jun 02, 2007 10:33 pm

avista wrote:I need to use array longer than 4096 elements (multidimensional if possible), and it is verry important to be used in LISTBOX.

Some sugestions ?[/b]


Firts, Antonio is right.

Second, try something like this with your code:

ArPrgElem[6] = TArray():New( your length array )

@ 1,1 LISTBOX ArPrgElem[3] ;
FIELDS "" ;
UPDATE ;
OF IdeArra4[5][NumPrg][1] ;
ON LEFT DBLCLICK TeclaFWD( VK_RETURN, nFlags, IdeArra)

// ArPrgElem[6] es el objeto de las array de arrays
//
ArPrgElem[3]:nAt = 1
ArPrgElem[3]:bLine = { || { ArPrgElem[6]:xGet(ArPrgElem[3]:nAt) } }
ArPrgElem[3]:bGoTop = { || ArPrgElem[3]:nAt := 1 }
ArPrgElem[3]:bGoBottom = { || ArPrgElem[3]:nAt := Eval( ArPrgElem[3]:bLogicLen ) }
ArPrgElem[3]:bSkip = { | nWant, nOld | nOld := ArPrgElem[3]:nAt, ArPrgElem[3]:nAt += nWant, ;
ArPrgElem[3]:nAt := Max( 1, Min( ArPrgElem[3]:nAt, ;
Eval(ArPrgElem[3]:bLogicLen) ) ), ArPrgElem[3]:nAt - nOld }
ArPrgElem[3]:bLogicLen = { || ArPrgElem[6]:nIndMax }
ArPrgElem[3]:cAlias = "ARRAY"

ArPrgElem[3]:GoTop()
ArPrgElem[3]:nClrText := {|| ColorBloqueo( ArPrgElem[6]:xGet(ArPrgElem[3]:nAt) )}
ArPrgElem[3]:bRClicked := { |nRow,nCol,nKeyFlags| PasaMenu(nRow, nCol, nKeyFlags, IdeArra ) }
ArPrgElem[3]:nLineStyle := 0

...


The class TARRAY:

*****************************************************************************
********************** Funciones £tiles s¢lo en FiveWin *********************
********************** 66¦ parte ********************************************
/* A tener en cuenta:
-Se trata de una matriz de 4096 * 4096 elementos.
-Se van a¤adiendo o borrando ROW's de 4096 a la vez y en esos
casos de realiza un RESIZE() de la matriz.

Se trata de un clase muy interesante a la hora de tratar array's de
grandes dimensiones (superiores a 4096 elementos).
*/


#include "FiveWin.ch"

#define CR Chr( 13 )

/*
{ { ::a2[ 1, 1 ], ::a2[ 1, 2 ], ..., ::a2[ 1, Len( ::a2[ 2 ] ) ] }, ;
{ ::a2[ 2, 1 ], ::a2[ 2, 2 ], ..., ::a2[ 2, Len( ::a2[ 2 ] ) ] }, ;
.......
{ ::a2[ 4096, 1 ], ::a2[ 4096, 2 ], ..., ::a2[ 4096, Len( ::a2[ 2 ] ) ] } ;
}
*/

/*
Con oArray:nIndMax = 500000 .-
Para nI = 245741, se produce un "Clipper internal error":
"Error no recuperable 332:
Desbordamiento de la memoria para matrices/cadenas"

He comprobado que funciona con oArray:nIndMax = 300000 .-
*/

CLASS TArray

DATA a2
DATA nIndMax, nIndRow, nIndCol

METHOD New( nIndMax ) CONSTRUCTOR // 0 <= nIndMax <= 4096^2
METHOD End() INLINE ::a2 := nil, ;
Memory( -1 )

METHOD xSet( nInd, xValor )
METHOD xGet( nInd )
METHOD uAdd( xValor ) //incluye resizing
METHOD uIns( nInd, xValor ) //incluye resizing
METHOD uDel( nInd ) //incluye resizing

METHOD uIncrSize() //m‚todo auxiliar
METHOD uDecrSize() //m‚todo auxiliar

ENDCLASS


METHOD New( nIndMax ) CLASS TArray

If nIndMax < 0 .or. nIndMax > 16777216
/*MsgStop( "Clase TArray()" + CR + ;
"nIndMax =" + Str( nIndMax ) + CR + ;
OemToAnsi( "Indice máximo fuera de rango." ),;
"0 <= nIndMax <= 4096^2 (16777216)" ;
)*/
MsgStop( "Clase TArray()" + CR + ;
"nIndMax =" + Str( nIndMax ) + CR + ;
"Indice máximo fuera de rango.", ;
"0 <= nIndMax <= 4096^2 (16777216)" ;
)
End
::nIndMax := nIndMax
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
::a2 := Array( ::nIndRow, ::nIndCol )
Memory( -1 )

RETURN Self


METHOD xSet( nInd, xValor ) CLASS TArray

*No lo pongo, para no retardar...
*If nInd < 1 .or. nInd > ::nIndMax
* MsgStop( "Clase TArray()" + CR + ;
* "::xSet( nInd, xValor )", ;
* "Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
* )
*End
::nIndCol := Int( nInd / 4096 ) // ::nIndCol >= 0
::nIndRow := nInd - ::nIndCol * 4096 // ::nIndRow >= 0
If ::nIndRow = 0
*( ::nIndCol > 0 )
::nIndRow := 4096
Else
::nIndCol++
End
::a2[ ::nIndRow, ::nIndCol ] := xValor

RETURN xValor


METHOD xGet( nInd ) CLASS TArray

*No lo pongo, para no retardar...
*If nInd < 1 .or. nInd > ::nIndMax
* MsgStop( "Clase TArray()" + CR + ;
* "::xGet( nInd )", ;
* "Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
* )
*End
::nIndCol := Int( nInd / 4096 ) // ::nIndCol >= 0
::nIndRow := nInd - ::nIndCol * 4096 // ::nIndRow >= 0
If ::nIndRow = 0
*( ::nIndCol > 0 )
::nIndRow := 4096
Else
::nIndCol++
End

RETURN ::a2[ ::nIndRow, ::nIndCol ]


METHOD uIncrSize() CLASS TArray

local nIndCol, nI

If ::nIndMax > 4096
nIndCol := 1 + Int( ::nIndMax / 4096 ) // nIndCol >= 2
Else
nIndCol := 1
End
::nIndMax++ ///////
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
If nIndCol != ::nIndCol
*Resizeado de las columnas.-
For nI := 1 To 4096
aSize( ::a2[ nI ], ::nIndCol )
Next
Memory( -1 )
End
SysRefresh() //necesario para que funcione la pr¢xima ejecuci¢n
// de funciones del tipo Msg...()

RETURN nil


METHOD uDecrSize() CLASS TArray

local nIndCol, nI

IF ::nIndMax = 1
::nIndMax-- // ::nIndMax := 0
::nIndRow := 4096
::nIndCol := 1
::a2 := Array( 4096, 1 )
Memory( -1 )
ELSE
If ::nIndMax > 4096
nIndCol := 1 + Int( ::nIndMax / 4096 ) // nIndCol >= 2
Else
nIndCol := 1
End
::nIndMax-- ///////
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
If nIndCol != ::nIndCol
*Resizeado de las columnas.-
For nI := 1 To 4096
aSize( ::a2[ nI ], ::nIndCol )
Next
Memory( -1 )
End
END
SysRefresh() //necesario para que funcione la pr¢xima ejecuci¢n
// de funciones del tipo Msg...()

RETURN nil


METHOD uAdd( xValor ) CLASS TArray

::uIncrSize()
::xSet( ::nIndMax, xValor )

RETURN nil


METHOD uIns( nInd, xValor ) CLASS TArray

local x
local nI

IF ::nIndMax = 0
::uIncrSize()
nInd := 1 //"pasamos de" lo que valga nInd
ELSE
If nInd > ::nIndMax
MsgStop( "Clase TArray()" + CR + ;
"::uIns( nInd, xValor )", ;
"Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
)
End
::uIncrSize()
*Desplazamiento hacia abajo.-
For nI := ::nIndMax To nInd + 1 Step -1
x := ::xGet( nI - 1 )
::xSet( nI, x )
Next
END
::xSet( nInd, xValor )

RETURN nil


METHOD uDel( nInd ) CLASS TArray

local x
local nI

IF ::nIndMax = 0
MsgStop( "Clase TArray()" + CR + ;
"Intento de borrar siendo ::nIndMax = 0",;
"::uDel( " + LTrim( Str( nInd ) ) + " )" ;
)
ELSE
If nInd > ::nIndMax
MsgStop( "Clase TArray()" + CR +;
"::uDel( nInd )", ;
"Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
)
End
If ::nIndMax > 1 //de lo contrario, ::nIndMax = 1
if nInd < ::nIndMax //de lo contrario, nInd = ::nIndMax
*Desplazamiento hacia arriba.-
For nI := nInd To ::nIndMax - 1
x := ::xGet( nI + 1 )
::xSet( nI, x )
Next
end
End
*(Despreciamos el actual elemento ::nIndMax -‚simo)
::uDecrSize()
END

RETURN nil


Regards
Carlos G.

Note: Que alguién le traduzca mi mal ingles.
FiveWiDi
 
Posts: 1189
Joined: Mon Oct 10, 2005 2:38 pm

Postby avista » Wed Jun 06, 2007 12:24 pm

I solved the problem thanaks to your sugestions ....
not using the classes but this working great.

Best regards

p.s

Here is the program
=============



#include "FiveWin.ch"

static oWnd

//----------------------------------------------------------------------------//

function Main()

LOCAL oDlg

// Put in aSample array 40963
aSample={}
for i=1 to 10
aSampleTemp = {}
for j=1 to 4096
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{"1","2","3"})


DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"

// aSample = {{"",""}}
@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL

oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"

oList:GoTop()

ACTIVATE DIALOG oDlg CENTERED

return NIL

//--------------------------------------------------//

FUNCTION MyArrItem( aArray, nPozicija )
nRow = INT(nPozicija/4096) + 1
nCol = nPozicija - (nRow - 1) * 4096

IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF

RETURN aArray[nRow, nCol]

//--------------------------------------------------//

FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])

RETURN nLen
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Postby Antonio Linares » Wed Jun 06, 2007 3:58 pm

Very good :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby avista » Tue Jun 12, 2007 2:10 pm

Better sample ...
If someone have better solution about sorting please reply

Best regards,
Pande.

Program ...
//---------------------------------//


#include "FiveWin.ch"

static oWnd

//----------------------------------------------------------------------------//

function Main()

LOCAL oDlg
LOCAL oBtn

// Put in aSample array 12291 elements
aSample={}
for i=1 to 3
aSampleTemp = {}
for j=4096 to 1 step -1
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{str(1),str(2),str(3)})

DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"

@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL

oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"

oList:GoTop()
oList:Refresh()

// Sort aSample array if need
@ 20, 5 BUTTON oBtn PROMPT "&Sort Array" OF oDlg SIZE 130,10 PIXEL ;
ACTION ( oBtn:Disable() ,;
aSample := MyArrSort( aSample ) ,;
oBtn:Enable() ,;
oList:GoTop() ,;
oList:Refresh() ;
)

ACTIVATE DIALOG oDlg CENTERED

return NIL

//--------------------------------------------------//
// cData = aArray[ nPosition ]
// solution for big array: cData = MyArrItem( aArray, nPosition )

FUNCTION MyArrItem( aArray, nPosition )
nRow = INT(nPosition/4096) + 1
nCol = nPosition - (nRow - 1) * 4096

IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF

RETURN aArray[nRow, nCol]

//--------------------------------------------------//
// nLen = LEN( aArray )
// solution for big array: nLen = MyArrLen( aArray )

FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])

RETURN nLen

//--------------------------------------------------//
// AADD( aArray, cData )
// solution for big array: MyArrAdd( aArray, cData )

FUNCTION MyArrAdd( aArray, cData )

nLen = LEN(aArray)

if nLen = 0 .or. LEN( aArray[nLen] ) = 4096
aadd( aArray, {} )
nLen = nLen +1
endif

aadd( aArray[nLen], cData )

RETURN NIL

//--------------------------------------------------//
// ASORT( aArray )
// solution for big array: MyArrSort( aArray )
// May be someone know better way to sort ?

FUNCTION MyArrSort( aArray )

for i=1 to len(aArray) // Sorting ARRAY in every element
asort(aArray[i])
next

if len(aArray) > 1 // MERGE sorted ARRAYS in every element in one big array
aNewArray = {aArray[1]}

for i=2 to len(aArray)
aTempArr1 = aNewArray
aTempArr2 = aArray[i]
aNewArray = {}
nBrojac1 = 1
nBrojac2 = 1
lIzlez = .f.
do while !lIzlez

cPodatok1 = MyArrItem( aTempArr1, nBrojac1 ) // Item from bigarray
cPodatok2 = aTempArr2[ nBrojac2 ] // Item from onedimensional array

if cPodatok1 <= cPodatok2
MyArrAdd( aNewArray, cPodatok1 )
nBrojac1 = nBrojac1 +1
else
MyArrAdd( aNewArray, cPodatok2 )
nBrojac2 = nBrojac2 +1
endif

if nBrojac1 > MyArrLen( aTempArr1 )
for j = nBrojac2 to LEN( aTempArr2 )
MyArrAdd( aNewArray, aTempArr2[j] )
next
lIzlez = .t.
elseif nBrojac2 > LEN( aTempArr2 )
for j = nBrojac1 to MyArrLen( aTempArr1 )
MyArrAdd( aNewArray, MyArrItem( aTempArr1, j ) )
next
lIzlez = .t.
endif

enddo

next

endif

RETURN aNewArray
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia


Return to FiveWin for CA-Clipper

Who is online

Users browsing this forum: No registered users and 3 guests