PDA

View Full Version : Passing an array (name) as return parameter



Johannes
01-04-2011, 13:28
I've defined a sub BigInt_FactPrime(a As String, ByRef pf() As String) where a is the number that is to be factorised and pf() is the array which will contain the prime factors. I've got the function working but I have to dimension the array beforehand for it to work, even though I do a ReDim (see code).


SUB BigInt_FactPrime()
LOCAL a,b,c,q,r AS STRING
LOCAL i,n AS DWORD
DIM pf() AS LOCAL STRING
DIM p(7) AS LOCAL INTEGER

' Variables for thinBasic_ParseVariableInfo.
LOCAL sVpt,sMtp,sStp,sFix,sElm,sEsz,sDpt,sPos AS LONG
' Parse parameters.
IF thinBasic_CheckOpenParens THEN
thinBasic_ParseString a
IF thinBasic_CheckComma THEN
thinBasic_ParseVariableInfo(sVpt,sMtp,sStp,sFix,sElm,sEsz,sDpt,sPos)
IF NOT thinBasic_ErrorFlag THEN
IF thinBasic_CheckCloseParens THEN
' Variabele moet een dynamische string zijn.
IF sMtp<>%MainType_IsString OR sFix THEN RTError("Return variable for factors must be a dynamic string array") : EXIT SUB

' processing code deleted
' pf() is properly REDIMed here as pf(1 TO n)

' Transfer internal array to thinBasic.
thinBasic_VariableRedim(sVpt, %TRUE, n, 0, 0)
FOR i=1 TO n
thinBasic_ChangeVariableStringDirect(sVpt, i, pf(i))
NEXT i

END IF
END IF
END IF
END IF
END SUB
The little test script I have is the following.


Uses "Console"
Module "BigInt"
Alias String As BigInt
BigInt a,b,n,p
DWord i,j
Quad t
Boolean c
PrintL "FactPrime..."
Dim pf(1) As BigInt
a=BigInt_Dec(BigInt_Pow(2,64))
Print BigInt_ToString(a)+" = "
BigInt_SetForcePlus(FALSE)
HiResTimer_Get
BigInt_FactPrime(a,pf())
t=HiResTimer_Delta
j=UBound(pf)
Print BigInt_ToString(pf(1))+$SPC
If j>1 Then
For i=2 To j
Print "* "+BigInt_ToString(pf(i))+$SPC
Next i
EndIf
BigInt_SetForcePlus(TRUE)
PrintL " ("+TStr$(t/1000000)+")"
PrintL
WaitKey

If I do the DIM of pf as pf() (line 9) I get a runtime error in thinBasic_ParseVariableInfo. Should I use another function from the SDK than thinBasic_ParseVariableInfo? Should I do something else so that I can supply an undimensioned array? I know it's possible because ListDir does it.

Any help is greatly appreciated.

ErosOlmi
01-04-2011, 15:58
Hi Johannes,

I'm at work at the moment so little time but try this way:


'---Used to have a pointer to a parsed variable
LOCAL pVariable AS LONG

'---Use the following SDK thinBasic_VariableParsePtr
'---Parse a variable and if ok pVariable will have a ptr to it (ptr is an internal thinBasic ptr so do not use directly)
thinBasic_VariableParsePtr(pVariable)

'---You can use the following to get variable pVariable info:
DIM MainType As Long
DIM SubType As Long
DIM IsArray As Long
thinBasic_VariableGetInfoPtr(pVariable, MainType, SubType , IsArray )
if MainType = %MainType_IsString then
if IsArray then
...
'---When ready redim your parsed variable
thinBasic_VariableRedim(pVar, %FALSE, 1, 0, 0)
...
end if
end if


Let me know.
Eros

Johannes
03-04-2011, 20:42
Eros,

When I use thinBasic_VariableParsePtr() I get a run-time error.

Error code: 252
Description: Invalid delimiter
Token found: pf
Additional info: 1502

The error occurs if I use pf or pf() in line 14, regardless of how I have dimensioned the variable in line 9.

ErosOlmi
03-04-2011, 22:18
Strange, it should work and here it is working fine.

My example was intended to be mixed with your so do not keep my example as is but you need to parse all token like you was doing.
Try something like the following and let me know:



Sub BigInt_FactPrime()

Local MyBigString As String
Local NumberOfItems As Long
Local lCounter As Long

'---Used to have a pointer to a parsed variable
Local pVariable As Long

'Parse parameters.
If thinBasic_CheckOpenParens Then
thinBasic_ParseString MyBigString
If thinBasic_CheckComma Then
'---Use the following SDK thinBasic_VariableParsePtr
'---Parse a variable and if ok pVariable will have a ptr to it (ptr is an internal thinBasic ptr so do not use directly)
thinBasic_VariableParsePtr(pVariable)
'---You can use the following to get variable pVariable info:
Dim MainType As Long
Dim SubType As Long
Dim IsArray As Long
thinBasic_VariableGetInfoPtr(pVariable, MainType, SubType, IsArray )


If Not thinBasic_ErrorFlag Then
If thinBasic_CheckCloseParens Then
' Variabele moet een dynamische string zijn.
If MainType = %MainType_IsString Then
If IsArray Then

'---
'...do what you need to do
'---

NumberOfItems = 10 '---<<<Just an example
'---When ready redim your parsed variable
thinBasic_VariableRedim(pVariable, %TRUE, NumberOfItems, 0, 0)

'---Fill with data
For lCounter = 1 To NumberOfItems
thinBasic_ChangeVariableStringDirect(pVariable, lCounter, MyBigString & Str$(lCounter))
Next
End If
Else
'---Error
Exit Sub
End If
End If
End If

End If
End If
End Sub

Johannes
03-04-2011, 23:50
Eros,

I was using the thinBasic_VariableParsePtr as a function within an IF statement, not as a subroutine. That was what caused the error and it's working perfectly now, both with DIM pf(1) and with DIM pf().

Grazie mille,
Giovanni

Johannes
04-04-2011, 00:31
I want to make sure the array is one-dimensional and that the strings are not fixed-size. (BigInts are dynamic strings.) I want to use thinBasic_ArrayGetInfo but the construction below (lines 20-25) doesn't work. (Returned values sDim and sFix are always zero.)


SUB BigInt_FactPrime()
LOCAL a,b,c,q,r AS STRING
LOCAL i,n AS DWORD
DIM pf() AS LOCAL STRING
DIM p(7) AS LOCAL INTEGER
LOCAL sVpt,sMtp,sStp,sArr,sFix,sDim AS LONG
' Parse parameters.
IF thinBasic_CheckOpenParens THEN ' (
thinBasic_ParseString a ' a AS STRING
IF thinBasic_CheckComma THEN ' ,
thinBasic_VariableParsePtr(sVpt) ' BYREF pf AS STRING
IF NOT thinBasic_ErrorFlag THEN
IF thinBasic_CheckCloseParens THEN ' )
' Variable must be a one-dimensional dynamic string array.
thinBasic_VariableGetInfoPtr(sVpt,sMtp,sStp,sArr)
IF sMtp<>%MainType_IsString OR sArr<>%TRUE THEN RTError("Return variable for factors must be a one-dimensional dynamic string array") : EXIT SUB



sFix = thinBasic_ArrayGetInfo(sVpt,%Array_ElementsAreFixed)
sDim = thinBasic_ArrayGetInfo(sVpt,%Array_Dimensions)

MSGBOX STR$(sVpt)+STR$(sFix)+STR$(sDim)

if sFix or sDim<>1 THEN RTError("Return variable for factors must be a one-dimensional dynamic string array") : EXIT SUB



' (Main processing removed)

' Transfer internal array to thinBasic.
thinBasic_VariableRedim(sVpt, %TRUE, n, 0, 0)
FOR i=1 TO n
thinBasic_ChangeVariableStringDirect(sVpt, i, pf(i))
NEXT i

END IF
END IF
END IF
END IF
END SUB
The SDK says I need to use the pointer as returned by thinBasic_ArrayGetPtr but that function uses the name of the array. How do I get from the pointer returned by thinBasic_VariableParsePtr to the name of the variable?

ErosOlmi
04-04-2011, 06:17
It is a little tricky and odd but

using your sVpt (that is a pointer to a high level variable info) you need to get another pointer using something like


dim pArray as long
pArray = thinBasic_VariablePtrToDirectPtr(sVpt)

pArray is a variable pointer of the internal Core representation of the variable.

With this pointer you can use thinBasic_ArrayGetInfo function in this way:

if thinBasic_ArrayGetInfo(pArray, %Array_ElementsAreFixed) =%FALSE then ...
if thinBasic_ArrayGetInfo(pArray, %Array_Dimensions) = 1 then ...

In any case because you will REDIM your array, I do not think you need to care about how many dimensions also because if script array is not dimensioned there are no dimensions to check.
When you redim an array with PRESERVE = %false, the full content of the array is released and a new memory storage is allocated. So even if your array has 3 dimensions, you can REDIM it with 1.

Should work
Let me know

Eros

Johannes
04-04-2011, 12:41
Eros,

I realised the bit about REDIM, so checking for number of dimensions isn't necessary. But I absolutely need to know that the strings are not fixed because the results will be absolute garbage. (Fixed strings append CHR$20 and not CHR$0 which will give disastrous results. A string that is too short is obviously a problem. And the whole principle of Big Integers is based on dynamic strings.)

And it works. Again, grazie mille.

ErosOlmi
04-04-2011, 12:50
Great!

And I'm happy you are using thinBasic SDK. So thanks to you.