How a function return can alone provide an array

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How a function return can alone provide an array

Post by fxm »

How 2 dynamic arrays of the same dimension can be swapped

From my second post, we can define a macro to swap 2 dynamic arrays compatible versus their dimensions (same dimension value from 1 up to 8), by only swapping the 2 array descriptors.

See the commented code below:

Code: Select all

' Only for a fbc version >= 1.08

#include once "fbc-int/array.bi"

' Swap 2 arrays of same dimensions (from 1 up to 8):
'   array1, array2: array names (ending with "()") to swap (both dynamic and of same dimension)
'   bool: boolean variable to receive the macro end status
'         True => OK (arrays swapped)
'         False => NOK (arrays not swapped because not dynamic or incompatible versus their dimensions)
#macro arraySwap(array1, array2, bool)
    Scope
        If (FBC.ArrayDescriptorPtr(array1)->flags And FBC.FBARRAY_FLAGS_FIXED_LEN) = 0 _
            And (FBC.ArrayDescriptorPtr(array2)->flags And FBC.FBARRAY_FLAGS_FIXED_LEN) = 0 _
            And FBC.ArrayDescriptorPtr(array1)->dimensions = FBC.ArrayDescriptorPtr(array1)->dimensions Then
                Dim As Integer N = Sizeof(FBC.FBARRAY) - (FBC.FB_MAXDIMENSIONS - FBC.ArrayDescriptorPtr(array1)->dimensions) * Sizeof(FBC.FBARRAYDIM)
                Dim As Byte Ptr p = Allocate(N)
                fb_memcopy(Byval p, *FBC.ArrayDescriptorPtr(array2), N)
                fb_memcopy(*FBC.ArrayDescriptorPtr(array2), *FBC.ArrayDescriptorPtr(array1), N)
                fb_memcopy(*FBC.ArrayDescriptorPtr(array1), *p, N)
                Deallocate(p)
                bool = True   '' compatible arrays
        Else
            bool = False  '' incompatible arrays
        End If
    End Scope
#endmacro

Redim As String array1(1 To 9, 1 To 5)  '' two-dimension var-len array, sized
For I As Integer = Lbound(array1, 1) To Ubound(array1, 1)
    For J As Integer = Lbound(array1, 2) To Ubound(array1, 2)
        array1(I, J) = Str(I * 10 + J)
    Next J
Next I

Dim As String array2(Any, Any)  '' two-dimension var-len array, unsized
Dim As Boolean b
arraySwap(array1(), array2(), b)
If b Then
    Print "compatible arrays for swapping"
    ' printing the returned array
    For I As Integer = Lbound(array2, 1) To Ubound(array2, 1)
        For J As Integer = Lbound(array2, 2) To Ubound(array2, 2)
            Print "'" & array2(I, J) & "'",
        Next J
        Print
    Next I
Else
    Print "Incompatible arrays for swapping"
End If

Sleep
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How a function return can alone provide an array

Post by dodicat »

I think this is similar, without the guards.
Arrays must be dynamic.

Code: Select all


#include once "fbc-int/array.bi"


#macro SwitchToFrom(array1,array2)
scope
    var t=*FBC.ArrayDescriptorPtr(array2())
    *FBC.ArrayDescriptorPtr(array2())=*FBC.ArrayDescriptorPtr(array1())
   *FBC.ArrayDescriptorPtr(array1())=t
   end scope
#endmacro

#macro show2d(a)
if ubound(a,1)=-1 then print "Null"
for n as long=lbound(a,1) to ubound(a,1)
    for m as long =lbound(a,2) to ubound(a,2)
        print a(n,m);" ";
next m
print
next n
print
#endmacro

#macro show1d(a)
if ubound(a,1)=-1 then print "Null"
for n as long=lbound(a,1) to ubound(a,1)
    print a(n);" ";
next
print
#endmacro

redim as long a(3,2) 
a(0,0)=1 :   a(0,1)=0:  a(0,2)=7
a(1,0)=0 :   a(1,1)=1:  a(1,2)=9
a(2,0)=2 :   a(2,1)=3:  a(2,2)=20
a(3,0)=0.75:a(3,1)=-0.5:a(3,2)=-8
'
redim as long M1(3,2)
M1(0,0)= -1 : M1(0,1)=2 :  M1(0,2)= 3 
M1(1,0)= 4  : M1(1,1)=5 :  M1(1,2)= 6
M1(2,0)= 7 :  M1(2,1)=8 :  M1(2,2)= 9
M1(3,0)= -7 : M1(3,1)=-8 : M1(3,2)=9

show2d(a)
show2d(M1)
print "__________________"
print
SwitchToFrom(a,M1)
show2d(a)
show2d(M1)
print"----------------- Done -------------------------"


redim as string  a1(1 to 3)
a1(1)="a"
a1(2)="b"
a1(3)="c"
redim as string    a2()

show1d(a1)
show1d(a2)

print "__________________"
print
SwitchToFrom(a2,a1)
show1d(a1)
show1d(a2)
print 
print"----------------- Done -------------------------"

dim as double d1(2,3)={ {1,2,3,4}, _
                        {5,6,7,8},_
                        {9,10,11,12}}
 redim as double d11(2,3)
 fb_memcopy(d11(0,0),d1(0,0),12*sizeof(double))'get into a dynamic array
 
 
redim as double d2()

show2d(d11)
show2d(d2)
print "__________________"
print
SwitchToFrom(d2,d11)
show2d(d11)
show2d(d2)
print"----------------- Done -------------------------"

sleep

 
A similar job probably could be done via memcopying alone, but I didn't try it.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How a function return can alone provide an array

Post by fxm »

In theory, your code only works for dynamic arrays and arrays declared without dimensions or with the maximum dimension (8).
Otherwise, the size of the allocated data for the descriptor is smaller than the one of the declared descriptor type ('FBC.FBARRAY'). That can induces memory overflows when you copy the arrays versus their declared sizes and not the allocated sizes.
(see FBARRAY (array descriptor structure and access))
Post Reply