Function returning an array
-
- Posts: 22
- Joined: Sep 01, 2011 15:54
- Location: Madrid-Spain
- Contact:
Function returning an array
Hello to all members,
can be possible Free-Basic returns an array from one custom function? Anyone can write sample sourcecode?
Thanks. ;-)
can be possible Free-Basic returns an array from one custom function? Anyone can write sample sourcecode?
Thanks. ;-)
-
- Posts: 88
- Joined: Apr 03, 2011 3:44
- Location: Inside the bomb
- Contact:
Re: Function returning an array
Code: Select all
type array
a(1000)as byte
end type
declare function arr as array
dim as array a
randomize
cls
a=arr
sleep:end
function arr as array
dim as array a
dim as integer t
for t=0 to 1000
a.a(t)=int(rnd*100)+1
next
return a
end function
Re: Function returning an array
You could make a sub that takes an array and writes to it.
Code: Select all
sub fill (array() as integer)
for i as integer = 0 to ubound(array)
array(i) = i
next
end sub
Re: Function returning an array
Be aware that you are only passing the address of the array, BYREF, not the array itself.
-
- Posts: 22
- Joined: Sep 01, 2011 15:54
- Location: Madrid-Spain
- Contact:
Re: Function returning an array
Thank you for replies. I think Destructosoft's sample is that I need.
Best. :-)
Best. :-)
Re: Function returning an array
Remark: this solution (array encapsulated in a type) can process only static arrays.AlejandroPadrino wrote:Thank you for replies. I think Destructosoft's sample is that I need.
Best. :-)
Re: Function returning an array
- If we use a 'function () As UDT', the object containing the array is entirely passed in the stack, and consequently the available array size is limited by the free stack size.
- If we use a 'function () As UDT Ptr', only the pointer to the object containing the array is passed in the stack, and consequently the available array size is not limited by the free stack size.
(see my previous post: http://www.freebasic.net/forum/viewtopi ... 13#p166413)
- If we use a 'function () As UDT Ptr', only the pointer to the object containing the array is passed in the stack, and consequently the available array size is not limited by the free stack size.
(see my previous post: http://www.freebasic.net/forum/viewtopi ... 13#p166413)
-
- Posts: 22
- Joined: Sep 01, 2011 15:54
- Location: Madrid-Spain
- Contact:
Re: Function returning an array
Very useful information, Fxm.
Thank you. :-)
Thank you. :-)
Re: Function returning an array
I set out to determine how much longer it took to return an array on the stack, compared to returning a pointer, but examining the assembly code it looks like the array is not actually returned on the stack, but copied to an address that is passed in the call. It will end up on the stack only if the receiving array is allocated from the stack.
Code: Select all
type arraytype
array(10000)as integer
end type
function ReturnOnStack() as arraytype
dim as arraytype array
for i as integer = 0 to 100
array.array(i) = i
next
asm nop
return array
asm nop
end function
function ReturnPtr() as arraytype ptr
dim as arraytype array
for i as integer = 0 to 100
array.array(i) = i
next
return @array
end function
dim as arraytype r
dim as arraytype ptr p
dim as double t
sleep 5000
t = timer
r = ReturnOnStack()
print using "##.##ms returning on stack";(timer-t) * 1000
for i as integer = 1 to 100
print r.array(i),
next
print
t = timer
p = ReturnPtr()
print using "##.##ms returning pointer";(timer-t) * 1000
for i as integer = 1 to 100
print p->array(i),
next
print
sleep
Re: Function returning an array
I do not well understand!MichaelW wrote:..., but examining the assembly code it looks like the array is not actually returned on the stack, but copied to an address that is passed in the call. It will end up on the stack only if the receiving array is allocated from the stack.
This following example is issued from a post of me (see my previous post):
- The object containing the array seems to be returned in the system stack memory (1 MB), because it crashes if array is too big, while 'UDT0' is 'Static' and 'UDT1' is 'Shared'!
Code: Select all
Type UDT
' array(1023, 1023) As Byte ' does not work (stack overflow => crash)
array(511, 511) As Byte
End Type
Function Get_Array () As UDT
Static UDT0 AS UDT ' not in stack
For I As Integer = 0 To 9
For J As Integer = 0 To 9
UDT0.array(I, J) = I * 10 + J
Next J
Next I
Function = UDT0 ' a copy of UDT0 is put in the stack,
Erase UDT0.array ' then we can erase array of UDT0
End Function
Dim Shared UDT1 As UDT ' not in stack
UDT1 = Get_Array()
For I As Integer = 0 To 9
For J As Integer = 0 To 9
Print Using "###"; UDT1.array(I, J);
Next J
Print "..."
Next I
Print "..."
Print "array size:"; Sizeof(UDT); " bytes ="; Sizeof(UDT) / 1024 / 1024; " MB"
Sleep
Re: Function returning an array
Here is a partially commented version of the assembly code:
It looks like the returned array is being copied again after the function returns, and it seems to me that this should not be necessary if the correct address was passed to the function. I'm out of time to investigate, for now.
Code: Select all
.intel_syntax noprefix
#test.bas' compilation started at 12:41:59 (FreeBASIC 0.24.0)
.section .text
.balign 16
.globl _RETURNONSTACK@4
_RETURNONSTACK@4:
push ebp
mov ebp, esp
sub esp, 40008 ; allocate stack space for local array
push ebx
push esi
push edi
.Lt_0004:
lea eax, [ebp-40004] ; load ebx with address of local array
push eax
mov edi, eax
xor eax, eax
mov ecx, 10001
rep stosd ; fill local array with zeros
pop eax
mov dword ptr [ebp-40008], 0
.Lt_000A:
lea eax, [ebp-40004]
mov ebx, dword ptr [ebp-40008]
sal ebx, 2
add eax, ebx
mov ebx, dword ptr [ebp-40008]
mov dword ptr [eax], ebx
.Lt_0008:
inc dword ptr [ebp-40008]
.Lt_0007:
cmp dword ptr [ebp-40008], 100
jle .Lt_000A
.Lt_0009:
nop
lea ebx, [ebp-40004] ; load ebx with address of local array
mov edi, dword ptr [ebp+8] ; load edi with passed in address
mov esi, ebx ; load esi with address of local array
mov ecx, 10001 ; set count
rep movsd ; copy from local array to receiving array
jmp .Lt_0005
nop
.Lt_0005:
mov eax, dword ptr [ebp+8] ; set return value to passed in address
pop edi ; the above appears to be discarded on return
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 4
.balign 16
.globl _RETURNPTR@0
_RETURNPTR@0:
push ebp
mov ebp, esp
sub esp, 40012
push ebx
mov dword ptr [ebp-4], 0
.Lt_000B:
lea eax, [ebp-40008]
push eax
push edi
mov edi, eax
xor eax, eax
mov ecx, 10001
rep stosd
pop edi
pop eax
mov dword ptr [ebp-40012], 0
.Lt_0010:
lea eax, [ebp-40008]
mov ebx, dword ptr [ebp-40012]
sal ebx, 2
add eax, ebx
mov ebx, dword ptr [ebp-40012]
mov dword ptr [eax], ebx
.Lt_000E:
inc dword ptr [ebp-40012]
.Lt_000D:
cmp dword ptr [ebp-40012], 100
jle .Lt_0010
.Lt_000F:
lea ebx, [ebp-40008]
mov dword ptr [ebp-4], ebx
.Lt_000C:
mov eax, dword ptr [ebp-4]
pop ebx
mov esp, ebp
pop ebp
ret
.balign 16
.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, 80028 ; allocate stack space for 2 arrays
push ebx
mov dword ptr [ebp-4], 0
call ___main
push 0
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@12
.Lt_0002:
lea eax, [ebp-40008]
push eax
push edi
mov edi, eax
xor eax, eax
mov ecx, 10001
rep stosd
pop edi
pop eax
mov dword ptr [ebp-40012], 0
mov dword ptr [ebp-40020], 0
mov dword ptr [ebp-40016], 0
push 5000
call _fb_Sleep@4
call _fb_Timer@0
fstp qword ptr [ebp-40020]
lea eax, [ebp-40008]
lea ebx, [ebp-80024]
push eax
push edi
mov edi, ebx
xor eax, eax
mov ecx, 10001
rep stosd
pop edi
pop eax
lea ebx, [ebp-80024] ; load ebx with address of receiving array
push ebx ; push address
mov ebx, eax
call _RETURNONSTACK@4 ; call function
lea eax, [ebp-80024]
push edi
push esi
mov edi, ebx
mov esi, eax
mov ecx, 10001
rep movsd
pop esi
pop edi
push 26
push offset _Lt_0012
call _fb_StrAllocTempDescZEx@8
push eax
call _fb_PrintUsingInit@4
push -2147483647
call _fb_Timer@0
fsub qword ptr [ebp-40020]
fmul qword ptr [_Lt_001C]
sub esp,8
fstp qword ptr [esp]
push 0
call _fb_PrintUsingDouble@16
push 0
call _fb_PrintUsingEnd@4
mov dword ptr [ebp-80028], 1
.Lt_0016:
push 2
lea eax, [ebp-40008]
mov ebx, dword ptr [ebp-80028]
sal ebx, 2
add eax, ebx
push dword ptr [eax]
push 0
call _fb_PrintInt@12
.Lt_0014:
inc dword ptr [ebp-80028]
.Lt_0013:
cmp dword ptr [ebp-80028], 100
jle .Lt_0016
.Lt_0015:
push 1
push 0
call _fb_PrintVoid@8
call _fb_Timer@0
fstp qword ptr [ebp-40020]
call _RETURNPTR@0
mov dword ptr [ebp-40012], eax
push 25
push offset _Lt_0017
call _fb_StrAllocTempDescZEx@8
push eax
call _fb_PrintUsingInit@4
push -2147483647
call _fb_Timer@0
fsub qword ptr [ebp-40020]
fmul qword ptr [_Lt_001C]
sub esp,8
fstp qword ptr [esp]
push 0
call _fb_PrintUsingDouble@16
push 0
call _fb_PrintUsingEnd@4
mov dword ptr [ebp-80028], 1
.Lt_001B:
push 2
mov eax, dword ptr [ebp-80028]
sal eax, 2
mov ebx, dword ptr [ebp-40012]
add ebx, eax
push dword ptr [ebx]
push 0
call _fb_PrintInt@12
.Lt_0019:
inc dword ptr [ebp-80028]
.Lt_0018:
cmp dword ptr [ebp-80028], 100
jle .Lt_001B
.Lt_001A:
push 1
push 0
call _fb_PrintVoid@8
push -1
call _fb_Sleep@4
.Lt_0003:
push 0
call _fb_End@4
mov eax, dword ptr [ebp-4]
pop ebx
mov esp, ebp
pop ebp
ret
#test.bas' compilation took 0.005746540420176416 secs
.section .data
.balign 4
_Lt_0012: .ascii "##.##ms returning on stack\0"
.balign 4
_Lt_0017: .ascii "##.##ms returning pointer\0"
.balign 8
_Lt_001C: .double 1000
Re: Function returning an array
I modified my previous program, adding to UDT a 'Let' operator to monitor the assignment:
- '@This:982868 @rhs:4239368' corresponds to 'Function = UDT0' with This=Function and rhs=UDT0,
- '@This:4501512 @rhs:982868' corresponds to 'UDT1 = Get_Array()' with This=UDT1 and rhs=Get_Array() that is well in the stack.
- Besides, @Function = @Get_Array() in the stack => not double copying apparently in the stack.
Code: Select all
Type UDT
' array(1023, 1023) As Byte ' does not work (stack overflow => crash)
array(511, 511) As Byte
Declare Operator Let (Byref rhs As UDT)
End Type
Operator UDT.Let (Byref rhs As UDT)
Dim stack As Integer
Print "(@stack:"; @stack; ") @This:"; @This; " @rhs:"; @rhs
For I As Integer = 0 To Ubound(This.array, 1)
For J As Integer = 0 To Ubound(This.array, 2)
This.array(I, J) = rhs.array(I, J)
Next J
Next I
End Operator
Function Get_Array () As UDT
Static UDT0 AS UDT ' not in stack
For I As Integer = 0 To 9
For J As Integer = 0 To 9
UDT0.array(I, J) = I * 10 + J
Next J
Next I
Function = UDT0 ' a copy of UDT0 is put in the stack,
Erase UDT0.array ' then we can erase array of UDT0
End Function
Dim Shared UDT1 As UDT ' not in stack
UDT1 = Get_Array()
For I As Integer = 0 To 9
For J As Integer = 0 To 9
Print Using "###"; UDT1.array(I, J);
Next J
Print "..."
Next I
Print "..."
Print "array size:"; Sizeof(UDT); " bytes ="; Sizeof(UDT) / 1024 / 1024; " MB"
Sleep
Code: Select all
(@stack:982724) @This:982868 @rhs:4239368
(@stack:982812) @This:4501512 @rhs:982868
0 1 2 3 4 5 6 7 8 9...
10 11 12 13 14 15 16 17 18 19...
20 21 22 23 24 25 26 27 28 29...
30 31 32 33 34 35 36 37 38 39...
40 41 42 43 44 45 46 47 48 49...
50 51 52 53 54 55 56 57 58 59...
60 61 62 63 64 65 66 67 68 69...
70 71 72 73 74 75 76 77 78 79...
80 81 82 83 84 85 86 87 88 89...
90 91 92 93 94 95 96 97 98 99...
...
array size: 262144 bytes = 0.25 MB
- '@This:4501512 @rhs:982868' corresponds to 'UDT1 = Get_Array()' with This=UDT1 and rhs=Get_Array() that is well in the stack.
- Besides, @Function = @Get_Array() in the stack => not double copying apparently in the stack.