Author Topic: Array concatenation  (Read 381 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Hero Member
  • *****
  • Posts: 837
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 concatenation

uses console

string 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+n2

sys 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 ok

string s3 at a

int x
for x=1 to n1
  s3[x]=s1[x]
next

for x=1 to n2
  s3[x+n1]=s2[x]
next

printl 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 addr

int x
for x=1 to countof(t1)
  t3[x]=t1[x] 
next

for x=1 to countof(t2)
  t3[x+countof(t1)]=t2[x]
next

printl 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

  • Admin Support Member
  • *****
  • Posts: 4128
    • Oxygen Basic
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

  • Admin Support Member
  • *****
  • Posts: 4128
    • Oxygen Basic
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 console

redim string s1(4)
s1={"The", "quick", "brown", "fox"}
redim string s2(5)
s2={"jumped", "over", "the", "lazy", "dog"}
'
'FAST CONCATENATION BUT STRINGS REMAIN LINKED
redim string s3(0)
s3_buffer = s1_buffer + s2_buffer
@s3 = strptr s3_buffer
'
int i
for i=1 to 9
  print s3[i] " "
next
printl
s1[4]="bear" 'ALSO AFFECTS S3
for i=1 to 9
  print s3[i] " "
next
printl
printl "Enter ..." : waitkey()

Arnold

  • Hero Member
  • *****
  • Posts: 837
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: 837
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 STRINGS

string sa=nuls 5* sizeof float
string sb=sa

'MAP ARRAY VARIABLES ONTO STRINGS

float a at *sa
float b at *sb

'ASSIGN SOME VALUES

a<=10,20,30,40,50
b<=60,70,80,90,00

'ADD ARRAY B TO A BY STRING CONCATENATION

sa+=sb

'TEST

print 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

  • Admin Support Member
  • *****
  • Posts: 4128
    • Oxygen Basic
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: 837
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              'strptr

print 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: 837
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 STRINGS

string sa=nuls 5* sizeof float
string sb=nuls 5* sizeof float

'MAP ARRAY VARIABLES ONTO STRINGS

float a at *sa
float b at *sb

'ASSIGN SOME VALUES

a = {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 CONCATENATION

string sc
sc=sa+sb
float c at *sc

'TEST

print 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

  • Admin Support Member
  • *****
  • Posts: 4128
    • Oxygen Basic
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 scope
end 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: 837
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 »