### Author Topic: Array concatenation  (Read 927 times)

0 Members and 1 Guest are viewing this topic.

#### Arnold

• Hero Member
• Posts: 882
##### Array concatenation
« on: June 30, 2019, 11:21:10 PM »
Hi Charles,

at Rosettacode I found an example dealing with array concatentation. The OxygenBasic solution seems not to work any more with the latest version. I also experimented a little bit and noticed this difference:

Code: [Select]
`'Array concatenationuses consolestring s1[4] = {"The", "quick", "brown", "fox"}string s2[5] = {"jumped", "over", "the", "lazy", "dog"}int n1=countof(s1)int n2=countof(s2)int n=n1+n2sys a=getmemory n * sizeof(string)        'ok'sys a=getmemory(countof(s1)+countof(s2)) * sizeof(string)  'not ok'sys a=getmemory (n1+n2) * sizeof(string)   'not okstring s3 at aint xfor x=1 to n1  s3[x]=s1[x]nextfor x=1 to n2  s3[x+n1]=s2[x]nextprintl s3[1] " " s3[2] " "s3[3] " "s3[4] " "s3[5] " "s3[6] " "s3[6] " "s3[7] " "s3[8] " " s3[9]freememory a ===================================================string t1[4] = {"The", "quick", "brown", "fox"}string t2[5] = {"jumped", "over", "the", "lazy", "dog"}int nn=countof(t1)+countof(t2)sys addr=getmemory nn * sizeof(string)string t3 at addrint xfor x=1 to countof(t1)  t3[x]=t1[x]  nextfor x=1 to countof(t2)  t3[x+countof(t1)]=t2[x]nextprintl t3[1] " " t3[2] " "t3[3] " "t3[4] " "t3[5] " "t3[6] " "t3[6] " "t3[7] " "t3[8] " " t3[9]freememory addr printl "Enter ..."waitkey()`
getmemory using an expression in parantheses seems not to work? It is not a big problem, but I feel obliged to report the behaviour, because O2 terminates without an error message. (though the issue can be spotted quickly)

Roland

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #1 on: July 01, 2019, 01:08:46 AM »
Hi Roland,

getmemory is a normal function (with optional enclosing brackets), so this won't work:

sys a=getmemory(countof(s1)+countof(s2)) * sizeof(string)

but this will:

sys a=getmemory( (countof(s1)+countof(s2)) * sizeof(string)   )

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #2 on: July 01, 2019, 02:00:33 AM »
Concatenating with redim is very efficient, but strings in the new array will remain cross-linked to the originals. This could be a useful feature to be exploited

s3_buffer = s1_buffer + s2_buffer

Code: [Select]
`uses consoleredim string s1(4)s1={"The", "quick", "brown", "fox"}redim string s2(5)s2={"jumped", "over", "the", "lazy", "dog"}''FAST CONCATENATION BUT STRINGS REMAIN LINKEDredim string s3(0)s3_buffer = s1_buffer + s2_buffer@s3 = strptr s3_buffer'int ifor i=1 to 9  print s3[i] " "nextprintls1[4]="bear" 'ALSO AFFECTS S3for i=1 to 9  print s3[i] " "nextprintlprintl "Enter ..." : waitkey()`

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #3 on: July 01, 2019, 02:07:34 AM »
Thank you Charles. I knew that I missed something. Pay attention to the brackets. (Shame on me).

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #4 on: July 02, 2019, 05:50:58 AM »
Hi Charles,

is it possible to apply the s3_buffer approach in a similar way with e.g. floats? This is the task of Rosetta Code solved with a previous version of O2, which does not work this way any more:

Code: [Select]
`'CREATE DYNAMIC ARRAY SPACES USING STRINGSstring sa=nuls 5* sizeof floatstring sb=sa'MAP ARRAY VARIABLES ONTO STRINGSfloat a at *safloat b at *sb'ASSIGN SOME VALUESa<=10,20,30,40,50b<=60,70,80,90,00'ADD ARRAY B TO A BY STRING CONCATENATIONsa+=sb'TESTprint a[7] 'result should be 70`
This is what I have achieved so far (shameful little):

Code: [Select]
`redim float aa[5]redim float bb[5] aa = {10,20,30,40,50}bb = {60,70,80,90,00}print aa[4] + ", " + bb[2]`
Adding two arrays like cc=aa+bb would be a tempting option, but it is also ok to assign the values individually.

Roland

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #5 on: July 02, 2019, 06:31:21 AM »
Yes, it will work more cleanly with floats and integers,since we are no longer dealing with string pointers.

cc_buffer = aa_buffer + bb_buffer

This is more efficient than transferring elements individually

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #6 on: July 02, 2019, 11:58:16 PM »
Hi Charles,

it took some time until I found my mistake: despite the type float of cc I must apply strptr for cc_buffer. So this code will show the correct results:

Code: [Select]
`redim float aa(5)redim float bb(5) aa = {10,20,30,40.5,50}bb = {60,70.5,80,90,00}'print aa[4] + ", " + bb[2]redim float cc(0)cc_buffer = aa_buffer + bb_buffer@cc = strptr cc_buffer              'strptrprint cc[4]  + ", " + cc[7]`
Redim makes concatenation very effective.

I would like to ask two questions. Can the code of the RosettaCode example above be solved with the latest version of Oxygen too? And could redim be used with type any or with structs? FBSL offers a solution for concatenation of mixed arrays (int, string, single). If this is possible with O2 in some way then this will offer a lot of interesting aspects.

Roland

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #7 on: July 03, 2019, 11:04:06 PM »
I found this solution for the task of RosettaCode:

Code: [Select]
`'CREATE DYNAMIC ARRAY SPACES USING STRINGSstring sa=nuls 5* sizeof floatstring sb=nuls 5* sizeof float'MAP ARRAY VARIABLES ONTO STRINGSfloat a at *safloat b at *sb'ASSIGN SOME VALUESa = {10,20,30,40,50}b = {60,70,80,90,00}'print a[5] ", " b[4]'ADD ARRAY B and A to C BY STRING CONCATENATIONstring scsc=sa+sbfloat c at *sc'TESTprint c[7] 'result 70`
Most probably there are more and better ways to do concatenation (besides using redim). But I think it is nice that there are alternatives to solve a task.

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #8 on: July 04, 2019, 01:07:06 AM »
Hi Roland,

That is how redim works in o2.

The current redim macro (from oxsc\lang.inc):
Code: [Select]
`def redim  #ifndef %2_buffer    dim string %2_buffer = ""    dim %1 byref %2  #endif  scope    int _qb_ = %3    int _le_ = len %2_buffer    int _qn_ = _le_ / sizeof(%1)    #if match "%4","clear"      int _i_      for _i_=1 to _qn_        #if typecodeof(%2)>=0x200          #ifdef %1.destructor            %2[_i_].destructor          #endif        #elseif typecodeof(%2)>=0xa0          %2[_i_]=""        #else          %2[_i_]=0        #endif      next    #endif    #if typecodeof(%2)>=0xa0      if _qb_<_qn_        _qb_=_qn_ 'disallow reduction      endif    #endif    if _qb_ > _qn_      %2_buffer += nuls( sizeof(%1) * (_qb_ - _qn_))    elseif _qb_ <  _qn_      %2_buffer = left( %2_buffer, sizeof(%1) * _qb_ )    endif    @%2=strptr(%2_buffer)  end scopeend def`
Redim will support both primitives and UDTs.

Concatenation the buffers works well for direct types, but for strings and other pointered types, it requires that the underlying data is non-volatile, and the data is used as read-only.

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #9 on: July 04, 2019, 11:49:33 PM »
Thank you, Charles, for the code of redim.  In any case, it is worthwhile to learn more about the possible use of this macro.
« Last Edit: July 09, 2019, 06:36:07 AM by Arnold »

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #10 on: August 30, 2019, 08:07:48 AM »
Hi Charles,

I am looking for a way to reset some structures in an array. At the moment I do this by resetting the values in the fields of the corresponding structures. Is there a more general way to achieve this without specifying the fields? I assume the solution is included in the redim macro, but it seems I am not able to find it.

Roland

Code: [Select]
`string cr=chr(13,10)string prtype info  char name[40]  int  ageend type'print hex(typecodeof info)int countof_staff=6redim info staff[countof_staff]int ifor i = 1 to 5   staff[i].name = "Officer " + str(i)   staff[i].age = 40-i   pr += i ": " + staff[i].name + ": " + staff[i].age +crnextpr += i ": " + staff[countof_staff].name + ": " + staff[countof_staff].age +crint used_mem = countof_staff*sizeof(info)pr += "Used memory: " + used_mem +cr +cr   'print sizeof(info) + cr   staff[4].name = "" : staff[4].age = 0   staff[5].name = "" : staff[5].age = 0for i = 1 to countof_staff   pr += i ": " + staff[i].name + ": " + staff[i].age +crnextused_mem = countof_staff*sizeof(info)pr += "Used memory: " + used_mem +crprint pr`

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #11 on: August 30, 2019, 02:01:17 PM »
Hi Roland,

Resetting individual fields is good enough, and safe for non-flat structures. You can make the UDT into a class with a destructor, for clearing individual members.

The current redim clear option looks for a destructor and, it it exists,  invokes it for each member of the dynamic array.

redim typ v(10) clear

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #12 on: August 31, 2019, 02:00:45 AM »
Thank you, Charles. I wondered about the clear option, but I have not found an example of it yet, and I am not brave enough to test this.

I tried another approach and added an additional member dta in type info. Would this be applicable? If there are side-effects I will delete the values individually, although using a type with e.g. 10 members it would be interesting to do this with a single statement.

Roland

Code: [Select]
`\$ filename "test.exe"'uses rtl32'uses rtl64string cr=chr(13,10)string prtype info  char name[40]  sys  age               'test for 64-bit  =  char dta[sizeof(info)]  end type'print sizeof info'print hex(typecodeof info)int countof_staff=6redim info staff[countof_staff]int ifor i = 1 to 5   staff[i].name = "Officer " + str(i)   staff[i].age = 40-i   pr += i ": " + staff[i].name + ": " + staff[i].age +crnextpr += i ": " + staff[countof_staff].name + ": " + staff[countof_staff].age +crint used_mem = countof_staff*sizeof(info)pr += "Used memory: " + used_mem +cr +cr   staff[4].dta=nuls sizeof(info)   staff[5].dta=nuls sizeof(info)      'staff[4].name = "New Officer" : staff[4].age = 22   for i = 1 to countof_staff   pr += i ": " + staff[i].name + ": " + staff[i].age +crnextused_mem = countof_staff*sizeof(info)pr += "Used memory: " + used_mem +crprint pr`

#### Charles Pegge

• Posts: 4222
##### Re: Array concatenation
« Reply #13 on: August 31, 2019, 03:19:25 AM »

staff[4].dta=nuls sizeof(info)

this code avoids the string intermediary, and could be applied to any flat structure:

Code: [Select]
`sub clear(sys p, int n)  byte b at (p)  while n>0    b=0 : @b++ : n--  wendend sub`
in assembler:

Code: [Select]
`sub clear(sys p, int n)mov ecx,nmov rsi,p( dec ecx : jl exit mov byte [rsi],0 inc rsi repeat)end sub`
clear @staff[4], sizeof(info)
« Last Edit: August 31, 2019, 03:36:12 AM by Charles Pegge »

#### Arnold

• Hero Member
• Posts: 882
##### Re: Array concatenation
« Reply #14 on: August 31, 2019, 04:13:56 AM »
Wow! This is impressive. I will not need an extra dta member and will get the expected result. Thank you again for this little helpful routine.