Author Topic: array in type  (Read 6004 times)

0 Members and 1 Guest are viewing this topic.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
array in type
« on: June 11, 2021, 07:04:18 pm »
apparently arrays are not allowed in a type, that's a pity
is there a work-around for this limitation?

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: array in type
« Reply #1 on: June 11, 2021, 07:18:16 pm »
Use MEM and then store the array in the MEM
Shuwatch!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: array in type
« Reply #2 on: June 11, 2021, 07:21:29 pm »
yes, but mem requires a lot of house keeping, not user friendly
I thinking of faking an array using a string*size

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: array in type
« Reply #3 on: June 11, 2021, 07:27:36 pm »
Do it however you wish
Shuwatch!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: array in type
« Reply #4 on: June 11, 2021, 07:50:21 pm »
here's my attempt at a fake array
Code: QB64: [Select]
  1. Type dec
  2.     m As String * 50
  3.  
  4. Dim As dec d
  5.  
  6. j = 1
  7. For i = 1 To 12
  8.     v = MKL$(i)
  9.     Mid$(d.m, j, 4) = v
  10.     j = j + 4
  11.  
  12. j = 1
  13. For i = 1 To 12
  14.     n = CVL(Mid$(d.m, j, 4))
  15.     j = j + 4
  16.     Print i, n
  17.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: array in type
« Reply #5 on: June 11, 2021, 08:06:21 pm »
I've been talking about String arrays like forever!
So has Luke: https://www.qb64.org/forum/index.php?topic=1511.msg129084#msg129084

Right after that reply there is one for variable length strings.
« Last Edit: June 11, 2021, 08:07:38 pm by bplus »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: array in type
« Reply #6 on: June 11, 2021, 08:58:15 pm »
I fail to see how that is more elegant than MEM.
Shuwatch!

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: array in type
« Reply #7 on: June 11, 2021, 09:22:55 pm »
It doesn't require initialising the men block, and (more importantly) is automatically collected by the garbage collector when it goes out of scope.

FellippeHeitor

  • Guest
Re: array in type
« Reply #8 on: June 11, 2021, 09:57:02 pm »
I've used string arrays quite often too.

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: array in type
« Reply #9 on: June 11, 2021, 10:22:45 pm »

from https://stackoverflow.com/questions/53410020/use-an-array-in-a-user-defined-type-in-qbasic

Quote
Although you CANNOT do this in QB1.1, QB4.5, or QB64, you CAN do this in supersets of the BASIC dialect known as QB7.1(BC7/PDS), and VBDOS(v1.00):

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: array in type
« Reply #10 on: June 11, 2021, 10:24:58 pm »
It must be time for my YEARLY or MULTI-YEARLY petition for ARRAYs in UDT!

ARRAYs IN UDTs PLEASE!
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: array in type
« Reply #11 on: June 12, 2021, 10:09:15 am »
It must be time for my YEARLY or MULTI-YEARLY petition for ARRAYs in UDT!

ARRAYs IN UDTs PLEASE!

What! and waste all these great work-arounds? ;-))


Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: array in type
« Reply #12 on: June 12, 2021, 11:08:39 am »
thanks bplus, my example above can be simplified a bit if our simulated array index starts at 0
Code: QB64: [Select]
  1. For i = 0 To 12-1
  2.     v = MKL$(i)
  3.     Mid$(d.m, 4 * i + 1, 4) = v
  4.  
no need for a dedicated variable for the index
« Last Edit: June 12, 2021, 11:21:44 am by jack »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: array in type
« Reply #13 on: June 12, 2021, 12:47:00 pm »
here's the start of my project, a decimal floating-point package and hence the need for array in type
I chose unsigned long for the elements because the result of multiplying two longs fits in a 64-bit integer
the code here is only the foundation, as a test it converts strings to decfloat and back, I also did a proof of concept addition
Quote
3.14159265 358979323 846264338 327950288 419716939 937510582E+00000
 3.14159265 358979323 846264338 327950288 419716939 937510582E+00000
 6.28318530 717958647 692528676 655900576 839433879 875021164E+00000

Code: QB64: [Select]
  1.  
  2. Const NUM_DIGITS = 9 * 10
  3. Const NUM_DWORDS = NUM_DIGITS \ 9
  4. Const NUM_BYTES = 2 + 4 * NUM_DWORDS
  5. Const BIAS = 1073741824 '2 ^ 30
  6.  
  7. ' Error definitions
  8.  
  9. Const DIVZ_ERR = 1 'Divide by zero
  10. Const EXPO_ERR = 2 'Exponent overflow error
  11. Const EXPU_ERR = 3 'Exponent underflow error
  12.  
  13. Type decfloat
  14.     sign As _Unsigned Integer
  15.     exponent As _Unsigned Long
  16.     mantissa As String * Num_bytes
  17.  
  18. Dim As decfloat x, y
  19.  
  20. pi = "3.14159265358979323846264338327950288419716939937510582097494459"
  21. pi = pi + "230781640628620899862803482534211706798214808651328230664709384"
  22.  
  23. Call str2dec(pi, x)
  24. Call str2dec(pi, y)
  25.  
  26. Print dec2str(x)
  27. Print dec2str(y)
  28.  
  29. ' =====================================================
  30. ' add x + y = 2 * Pi
  31.  
  32. c = 0
  33. For i = NUM_DWORDS - 1 To 0 Step -1
  34.     v = CVL(Mid$(x.mantissa, 4 * i + 1, 4)) + CVL(Mid$(y.mantissa, 4 * i + 1, 4)) + c
  35.     If v > 999999999 Then
  36.         v = v - 1000000000
  37.         c = 1
  38.     Else
  39.         c = 0
  40.     End If
  41.     Mid$(y.mantissa, 4 * i + 1, 4) = MKL$(v)
  42.  
  43. Print dec2str(y)
  44. Call RSHIFT_1(y)
  45. Call LSHIFT_1(y)
  46. Print "the last digit before E should be 0 due to right-shift"
  47. Print dec2str(y)
  48.  
  49. Sub str2dec (value As String, n As decfloat)
  50.     Dim As Integer j, s, d, e, ep, ex, es, i, f, fp, fln
  51.     Dim As String c, f1, f2, f3, ts
  52.     Dim As _Unsigned Long ulng
  53.  
  54.     j = 1
  55.     s = 1
  56.     d = 0
  57.     e = 0
  58.     ep = 0
  59.     ex = 0
  60.     es = 1
  61.     i = 0
  62.     f = 0
  63.     fp = 0
  64.     f1 = ""
  65.     f2 = ""
  66.     f3 = ""
  67.     value = UCase$(value)
  68.     fln = Len(value)
  69.  
  70.     While j <= fln
  71.         c = Mid$(value, j, 1)
  72.         If ep = 1 Then
  73.             If c = " " Then
  74.                 j = j + 1
  75.                 GoTo skip_while
  76.             End If
  77.             If c = "-" Then
  78.                 es = -es
  79.                 c = ""
  80.             End If
  81.             If c = "+" Then
  82.                 j = j + 1
  83.                 GoTo skip_while
  84.             End If
  85.             If (c = "0") And (f3 = "") Then
  86.                 j = j + 1
  87.                 GoTo skip_while
  88.             End If
  89.             If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  90.                 f3 = f3 + c
  91.                 ex = 10 * ex + (Asc(c) - 48)
  92.                 j = j + 1
  93.                 GoTo skip_while
  94.             End If
  95.         End If
  96.  
  97.         If c = " " Then
  98.             j = j + 1
  99.             GoTo skip_while
  100.         End If
  101.         If c = "-" Then
  102.             s = -s
  103.             j = j + 1
  104.             GoTo skip_while
  105.         End If
  106.         If c = "+" Then
  107.             j = j + 1
  108.             GoTo skip_while
  109.         End If
  110.         If c = "." Then
  111.             If d = 1 Then
  112.                 j = j + 1
  113.                 GoTo skip_while
  114.             End If
  115.             d = 1
  116.         End If
  117.         If (c > "/") And (c < ":") Then 'c is digit between 0 and 9
  118.             If ((c = "0") And (i = 0)) Then
  119.                 If d = 0 Then
  120.                     j = j + 1
  121.                     GoTo skip_while
  122.                 End If
  123.                 If (d = 1) And (f = 0) Then
  124.                     e = e - 1
  125.                     j = j + 1
  126.                     GoTo skip_while
  127.                 End If
  128.             End If
  129.             If d = 0 Then
  130.                 f1 = f1 + c
  131.                 i = i + 1
  132.             Else
  133.                 If (c > "0") Then
  134.                     fp = 1
  135.                 End If
  136.                 f2 = f2 + c
  137.                 f = f + 1
  138.             End If
  139.         End If
  140.         If c = "E" Then
  141.             ep = 1
  142.         End If
  143.         j = j + 1
  144.         skip_while:
  145.     Wend
  146.     If fp = 0 Then
  147.         f = 0
  148.         f2 = ""
  149.     End If
  150.  
  151.     If s = -1 Then s = &H8000 Else s = 0
  152.     n.sign = s
  153.     ex = es * ex - 1 + i + e
  154.     f1 = f1 + f2
  155.     f1 = Mid$(f1, 1, 1) + Right$(f1, Len(f1) - 1)
  156.     fln = Len(f1)
  157.     If Len(f1) > ((NUM_DWORDS * 9) + 1) Then
  158.         f1 = Mid$(f1, 1, ((NUM_DWORDS * 9) + 1))
  159.     End If
  160.     While Len(f1) < ((NUM_DWORDS * 9) + 1)
  161.         f1 = f1 + "0"
  162.     Wend
  163.     j = 1
  164.     For i = 0 To NUM_DWORDS - 1
  165.         ts = Mid$(f1, j, 9)
  166.         ulng = Val(ts)
  167.         Mid$(n.mantissa, 4 * i + 1, 4) = MKL$(ulng)
  168.         If ulng <> 0 Then fp = 1
  169.         j = j + 9
  170.     Next
  171.     If fp Then n.exponent = (ex + BIAS + 1) Else n.exponent = 0
  172.  
  173. Function dec2str$ (n As decfloat)
  174.     Dim As Integer i, ex
  175.     Dim As String v, f, ts
  176.     If n.exponent > 0 Then
  177.         ex = (n.exponent And &H7FFFFFFF) - BIAS - 1
  178.     Else
  179.         ex = 0
  180.     End If
  181.     If n.sign Then v = "-" Else v = " "
  182.     ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * 0 + 1, 4))))
  183.     If Len(ts) < 9 Then
  184.         ts = ts + String$(9 - Len(ts), "0")
  185.     End If
  186.     v = v + Left$(ts, 1) + "." + Mid$(ts, 2)
  187.     For i = 1 To NUM_DWORDS - 1
  188.         ts = _Trim$(Str$(CVL(Mid$(n.mantissa, 4 * i + 1, 4))))
  189.         If Len(ts) < 9 Then
  190.             ts = String$(9 - Len(ts), "0") + ts
  191.         End If
  192.         v = v + ts
  193.     Next
  194.     f = _Trim$(Str$(Abs(ex)))
  195.     f = String$(5 - Len(f), "0") + f
  196.     If ex < 0 Then v = v + "E-" Else v = v + "E+"
  197.     v = v + f
  198.     dec2str = v
  199.  
  200. Sub RSHIFT_1 (mantissa As decfloat)
  201.     Dim As _Unsigned Long v1, v2
  202.     Dim As Long i
  203.     For i = NUM_DWORDS - 1 To 1 Step -1
  204.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) \ 10
  205.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i - 1) + 1, 4)) Mod 10
  206.         v2 = v2 * 100000000 + v1
  207.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v2)
  208.     Next
  209.     Mid$(mantissa.mantissa, 4 * 0 + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * 0 + 1, 4)) \ 10)
  210.  
  211. Sub LSHIFT_1 (mantissa As decfloat)
  212.     Dim As _Unsigned Long v1, v2
  213.     Dim As Long i
  214.     For i = 0 To NUM_DWORDS - 2
  215.         v1 = CVL(Mid$(mantissa.mantissa, 4 * i + 1, 4)) Mod 100000000
  216.         v2 = CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) \ 100000000
  217.         Mid$(mantissa.mantissa, 4 * i + 1, 4) = MKL$(v1 * 10 + v2)
  218.         Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4) = MKL$(CVL(Mid$(mantissa.mantissa, 4 * (i + 1) + 1, 4)) Mod 100000000)
  219.     Next
  220.     Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4) = MKL$(10 * CVL(Mid$(mantissa.mantissa, 4 * (NUM_DWORDS - 1) + 1, 4)) Mod 100000000)
  221.  
« Last Edit: June 12, 2021, 08:43:07 pm by jack »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: array in type
« Reply #14 on: June 12, 2021, 03:21:35 pm »
instead of using the convoluted CVL, Mkl$ and Mid$ to access the memory I think using a temporary array would be far better
proof of concept
<edit> not reliable
Code: QB64: [Select]
  1.     Sub memcpy (ByVal dest As _Offset, Byval source As _Offset, Byval bytes As Long)
  2.  
  3. Type dec
  4.     m As String * 46
  5.  
  6. Dim As Long i, m
  7. Dim As Long a(0 To 10), b(0 To 10)
  8. Dim x As dec
  9.  
  10. For i = 0 To 10
  11.     a(i) = i * i
  12.  
  13. memcpy _Offset(x.m), _Offset(a()), Len(a())
  14.  
  15. For i = 0 To 10
  16.     m = CVL(Mid$(x.m, 4 * i + 1, 4))
  17.     Print i, m
  18.  
  19. memcpy _Offset(b()), _Offset(x.m), Len(b())
  20.  
  21. For i = 0 To 10
  22.     Print i, b(i)
  23.  
« Last Edit: June 12, 2021, 08:44:08 pm by jack »