Rect_t - optimized type definition

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Rect_t - optimized type definition

Post by MrSwiss »

dodicat wrote:Mr Swiss. If the comment was pointed at me.
features like new and delete introduce unnecessary complications.
As are pointers in general when they are not needed.
Well, I haven't come across any of them, so far ...
I'd probably be the first one to complain, if there where complications.
Btw: some of the ByRef stuff, still suffers from complications (as far, as I'm aware of).
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Rect_t - optimized type definition

Post by MrSwiss »

Just as with other likes/dislikes (or preferences):

- I dislike properties, because they only allow a single parameter (a lot of work, with little gain)

- naming them is 'difficult' because it being the same, for getter/setter (unintuitive, IMO)
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Rect_t - optimized type definition

Post by fxm »

Not agree.
At the opposite, more intuitive for a beginner:
- 2 attributes: width and height
- easy access as if they were 2 variables.

Code: Select all

Type box
  Private:
    Dim As Ushort w, h
  Public:
    Declare Property width () As Ushort
    Declare Property width (Byval w As Ushort)
    Declare Property height () As Ushort
    Declare Property height (Byval h As Ushort)
End Type

Property box.width () As Ushort
  Return This.w
End Property
Property box.width (Byval w As Ushort)
  This.w = w
End Property

Property box.height () As Ushort
  Return This.h
End Property
Property box.height (Byval h As Ushort)
  This.h = h
End Property


' User code
Dim As box b
b.width = 640
b.height = 480
Print b.width & "x" & b.height

Sleep
Imortis
Moderator
Posts: 1923
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: Rect_t - optimized type definition

Post by Imortis »

I can see the benefit in both ways of doing this. It really does depend on the purpose of the code. If it is for YOUR USE ONLY, then do it however you are most comfortable. If you need something for others, like in a group programming situation, then it might be better to work with what would be simpler for everyone.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Rect_t - optimized type definition

Post by dodicat »

Names are also a problem for functions.

Code: Select all

 Type box
    Private:
    Dim As Ushort x, y 'co-ordinates
    Public:
    Declare Function Width (As Short=0) Byref As Ushort
    Declare Function height (As Short=0) Byref As Ushort
    Declare Sub Draw(As Ulong=Rgb(255,255,255))
End Type

Function box.width (x_ As Short) Byref As Ushort
    If x_ Then x=x_
    Static As Ushort horizontal
    Return horizontal
End Function

Function box.height (y_ As Short) Byref As Ushort
    If y_ Then y=y_
    Static As Ushort vertical
    Return vertical
End Function

Sub box.draw(clr As Ulong)
    Line(x,y)-(x+Width,y+height),clr,b  
End Sub

Screen 19,32

Dim As box b

For n As Long=1 To 100
    b.width  =640-n 'true width
    b.height =480-n 'true height
    b.width(80+n\2)   'x co-ordinate of top left corner
    b.height(60+n\2)  'y co-ordinate       "
    b.draw(Rgb(255-n*2.55,n*2.55,n))
Next


Sleep 
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Rect_t - optimized type definition

Post by badidea »

dodicat wrote:Names are also a problem for functions...
That is some confusing code. Note, you can also use this.x so that x_ can be x.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Rect_t - optimized type definition

Post by dodicat »

Further compacting.
And thus confusion.

Code: Select all

Type box
    Declare Function c(As Short=0,As Short=0) Byref As Long  ' c for coordinate and shape data
    Declare Function Draw(As Ulong=0) Byref As Any Ptr       'graphics + image
    Private:
    As Long h                                                'concatenate x,y
    #define mk(a,b) a Or b Shl 16                            ' make long from 2 shorts
End Type

Function box.c(x As Short,y As Short) Byref As Long
    If x Or y Then h=mk(x,y)
    Static As Long p
    Return p
End Function

Function box.draw(clr As Ulong) Byref As Any Ptr
    Line(Loword(h),Hiword(h))-(Loword(h)+Loword(c),Hiword(h)+Hiword(c)),clr,b  
    Static As Any Ptr i
    Return i
End Function

Screen 19,32

Dim As box b
b.draw() =Imagecreate(640,480,Rgb(0,100,255))
Put(80,60),b.draw,Pset
For n As Long=1 To 100
    b.c=mk((640-n),(480-n))'width/height
    b.c(80+n\2,60+n\2)     'x,y
    b.draw(Rgb(255-n*2.55,n*2.55,n))
Next
Imagedestroy b.draw


Sleep   
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Rect_t - optimized type definition

Post by fxm »

But why define a class Type "box" if it is not compatible with several objects simultaneously (due to the 2 static variables inside member functions)?

Rather:

Code: Select all

Type box
    Declare Function c(As Short=0,As Short=0) Byref As Long  ' c for coordinate and shape data
    Declare Function Draw(As Ulong=0) Byref As Any Ptr       'graphics + image
    Private:
    As Long h                                                'concatenate x,y
    As Long p
    As Any Ptr i
    #define mk(a,b) a Or b Shl 16                            ' make long from 2 shorts
End Type

Function box.c(x As Short,y As Short) Byref As Long
    If x Or y Then This.h=mk(x,y)
    Return p
End Function

Function box.draw(clr As Ulong) Byref As Any Ptr
    Line(Loword(This.h),Hiword(This.h))-(Loword(This.h)+Loword(This.c()),Hiword(This.h)+Hiword(This.c())),clr,b 
    Return i
End Function

Screen 19,32

Dim As box b
b.draw() =Imagecreate(640,480,Rgb(0,100,255))
Put(80,60),b.draw,Pset
For n As Long=1 To 100
    b.c()=mk((640-n),(480-n))'width/height
    b.c(80+n\2,60+n\2)     'x,y
    b.draw(Rgb(255-n*2.55,n*2.55,n))
Next
Imagedestroy b.draw


Sleep
[edit]
For dodicat, replace "class" with "Type".
Last edited by fxm on Aug 14, 2018 16:16, edited 2 times in total.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Rect_t - optimized type definition

Post by dodicat »

Better to keep the number of fields/methods of box to a minimum.(For this optimised Rect_t thread)
The most concise way would be only have one any ptr as a field.
Then any methods are already in fb : put,get,imagecreate ,...

My box is a type.
Does fbc 1.06.0 have classes?
I haven't tried it out yet.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Rect_t - optimized type definition

Post by fxm »

fxm wrote:But why define a class Type "box" if it is not compatible with several objects simultaneously (due to the 2 static variables inside member functions)?
I updated my previous post.
But you don't answer my question about your Type "box" that we must only use as a singleton (on single instance simultaneously).
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Rect_t - optimized type definition

Post by coderJeff »

1) In the first example, a nit-pick. From the compiler's point of view, alignment will be a power of 2. Like 1, 2, 4, 8, ... etc. The compiler will add internal padding or trailing padding to the structure to satisfy the alignment. i.e. a structure size of 40 bytes satisfies an alignment of 8.

2) Wasted space actually may be more since alignment rules may be different depending on if it is an array or not. For example, if I allocate 2 separate variables, fbc-win-64bit, even though sizeof(Rect_t) is 40, I get 48 bytes between allocations for this structure because data alignment is 16. +1 for promoting thoughtful use of datatypes!

Code: Select all

'' default data alignment for types in arrays
'' is next power of 2 greater than or equal 
'' than largest element.
  
Type Rect_t
	As Integer  _x, _y, _w, _h
	As ULong    _c
End Type

'' on 64-bit, alignment is 8 bytes due to
'' sizeof(integer) = 8, and results in structure size
'' of 40 bytes, which satisfies alignment = 8 

dim a(0 to 1) as Rect_t
print "Rect_t(): " & cint(@a(1)) - cint(@a(0)) '' 40

'' if not in an array, alignment might be larger,
'' like 16 bytes, resulting in 48 bytes between
'' allocations 

dim as Rect_t b1, b2 
print "Rect_t: " & cint(@b2) - cint(@b1) '' 48 

3) Sorry, your optimized example is lost on me. For each small structure, a pointer is allocated, plus are at the mercy of alignment of the memory allocator (NEW). On fbc-win-64bit 8 bytes per pointer plus 32 bytes per NEW, so 40 bytes per total per "small" structure. On fbc-win-32bit, 4 bytes per pointer plus 16 bytes per "NEW Rect_t", Results will vary by platform. Plus, no ability to store x,y,colour in the structure. ??

Code: Select all

'' using new/delete and pointers
Type Small_Rect_t
    As ushort _w, _h
End Type   

dim c1 as Small_Rect_t ptr = new Small_Rect_t  
dim c2 as Small_Rect_t ptr = new Small_Rect_t
dim c3 as Small_Rect_t ptr = new Small_Rect_t
dim c4 as Small_Rect_t ptr = new Small_Rect_t
print "Small_Rect_t: " & cint(c2) - cint(c1) '' 112
print "Small_Rect_t: " & cint(c3) - cint(c2) '' 32
print "Small_Rect_t: " & cint(c4) - cint(c3) '' 32
delete c4
delete c3
delete c2
delete c1
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Rect_t - optimized type definition

Post by MrSwiss »

@coderJeff & dodicat,

it took about 10 Min. incl. testing, to remove all ptr's and, correct test/demo code.
Copy-Constructor in .bi, replaced with: Sub init() ... doing exactly the same.
The Types size, as shown with SizeOf(rec(lba)) is still 4 Bytes, with FBC 1.05.0 x64.

The new Rect_t2.bi:

Code: Select all

' Rect_t2.bi -- 2018-08-14, MrSwiss
'
#Pragma Once                            ' only loaded once (include guard)
' ----- start type -----
Type Rect_t                             ' a very basic rectangle type (only: width/height, held internally)
  Private:                              ' no direct user access (to variables)
    As UShort   w, h                    ' variables (unsigned 16 bit integer)
  Public:                               ' interface (gives some rights, to user)
    Declare Sub init(ByVal w1 As UShort, ByVal h1 As UShort)        ' instead of copy-constructor
    ' actor: put rectangle to screen at: x/y, with color: clr and fill: fll (default=FALSE=NOT filled)
    Declare Sub show(ByVal x As Short, ByVal y As Short, ByVal clr As ULong=&hFF7F007F, ByVal fll As Boolean=FALSE)
    Declare Sub setn(ByVal nw As UShort=0, ByVal nh As UShort=0)    ' setter: change current values
    Declare Sub getv(ByRef wt As UShort=0, ByRef ht As UShort=0)    ' getter: returns stored values
    ' no need for a Destructor (default by compiler, does 'the trick')
End Type
'
Sub Rect_t.init( _
    ByVal w1 As UShort, _
    ByVal h1 As UShort _
    )
    This.w = w1 - 1 : This.h = h1 - 1 
End Sub
'
Sub Rect_t.show( _                      ' actor: put rectangle to screen
    ByVal x     As Short, _             ' x position, mandatory (signed 16 bit integer)
    ByVal y     As Short, _             ' y position, mandatory (signed 16 bit integer)
    ByVal clr   As ULong=&hFF7F007F, _  ' 32 bit color (default = purple), optional 
    ByVal fll   As Boolean=FALSE _      ' default, not filled Box, optional
    )
    If fll Then                         ' if fll=TRUE then, show Box filled
        Line (x, y)-Step(This.w, This.h), clr, BF   ' Step = width/height are relative to x/y
        'Line (x, y)-(x + This.w, y + This.h), clr, BF   ' absolute positioning
    Else                                ' otherwise, show Box NOT filled (default)
        Line (x, y)-Step(This.w, This.h), clr, B
    End If
End Sub

Sub Rect_t.setn( _                      ' set new value(s), default: do nothing
    ByVal nw    As UShort=0, _          ' optional new width
    ByVal nh    As UShort=0 _           ' optional new height
    )
    If nw > 0 Then THis.w = nw - 1      ' correction for: relative sizing of RECT
    If nh > 0 Then THis.h = nh - 1
End Sub

Sub Rect_t.getv( _                      ' get currently set value(s)
    ByRef wt    As UShort=0, _          ' optional width (if var. provided)
    ByRef ht    As UShort=0 _           ' optional height (if var. provided)
    )
    wt = This.w + 1 : ht = This.h + 1   ' correction for: real size
End Sub
' ----- end type -----
And, the new test/demo code:

Code: Select all

' simplest_RECTANGLE_type1.bas -- 2018-08-14, MrSwiss
'
' compile: -s gui
'
#Include "Rect_t2.bi"                    ' load the rectangle type

' macros ...
#Define RndARGB         ( CULng(Rnd * &hFFFFFFFFul) )       ' all color32 random, incl. alpha
#Define RngShrt(l, h)   ( CShort(Rnd * ((h) - (l)) + (l)) ) ' random number from a defined range

Const As UShort     scr_w = 1280, scr_h = 768, _            ' this two can be adjusted, by user
                    cd = 32, pg = 2, fg = 64                ' this stuff must remain unchanged!

' ===== start main =====
ScreenRes(scr_w, scr_h, cd, pg, fg)     ' window sizes | 32 bit color | 2 pages | using alpha
Var sp1 = 1, sp2 = 0                    ' screen pages (for buffer swapping)
ScreenSet(sp1, sp2)                     ' pre-set first buffer (to be drawn/shown)

Dim As Rect_t       rec(1 To 30)        ' array of rect_t (number of rectangles)
Dim As Short        lba = LBound(rec), uba = UBound(rec)    ' store current array definitions
Dim As short        tl_offs = -(scr_h Shr 4)    ' top/left offset (based on assumed smaller size)
Dim As Boolean      flg1 = TRUE         ' process control (fill, no fill)

For i As UInteger = lba To uba          ' initialize the array (copy constructor call)
    rec(i).init(RngShrt(scr_W * .1, scr_w * .4), _  ' min. = 10% | max. 40% (of width)
                RngShrt(scr_h * .05, scr_h * .3))   ' min. = 5% | max. 30% (of height)
Next                                    ' use macros for sizing (fixed min/max aspect ratio's _
                                        ' but, based on current screen sizes used)
Do
    If Len(InKey()) > 0 Then Exit Do    ' on user action --> EXIT LOOP (quit prog.)
    Cls
    For i As UInteger = lba To uba      ' rectangles to screen (using macros for pos. & color)
        rec(i).show(RngShrt(tl_offs, scr_w - tl_offs), _    ' positioning wit offset, based _
                    RngShrt(tl_offs, scr_h - tl_offs), _    ' on the current width/height used
                    RndARGB, flg1)      ' random color | fill/no fill (switches each run!)
    Next
    Draw String (30, 21), "type size: " + Str(SizeOf(rec(lba))) ' show types size (4 bytes)
    Swap sp1, sp2 : ScreenSet(sp1, sp2) ' swap visible/working page (show latest drawn buffer)
    flg1 = Not flg1 : Sleep(500, 1)     ' invert flag | free some CPU (let user see it 0.5 sec.)
Loop
' clean up ...
Erase(rec)
' ===== end main =====  ' ----- EOF -----
1) If you read carefully, I've stated 40 bytes, alligned in x64.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Rect_t - optimized type definition

Post by dodicat »

fxm wrote:
fxm wrote:But why define a class Type "box" if it is not compatible with several objects simultaneously (due to the 2 static variables inside member functions)?
I updated my previous post.
But you don't answer my question about your Type "box" that we must only use as a singleton (on single instance simultaneously).
Yes fxm.
Only one box shown in many ways is allowed.

I agree with coderjeff, the type should contain all the information to create a box.
x,y,width,height,colour.

I am not sure whether my following snippet conforms with the above definition or absolutely does not.
An ecumenical matter as Father Ted might have said.
(Back to pointers Mr Swiss)

Code: Select all

 

type box
    as ulong ptr p               'all the spatial information
    declare sub draw()           'drawing method
end type

sub box.draw()
   if p[5] then line(p[0],p[1])-(p[0]+p[2],p[1]+p[3]),p[4],bf else _
                line(p[0],p[1])-(p[0]+p[2],p[0]+p[3]),p[4],b
end sub

screen 19,32,,64

dim as long lim=20
dim as byte q=1
dim as box b(1 to lim)
 
    do
    cls
    q=-q
    for n as long=1 to lim
        with b(n)
            .p=new ulong[6]
            .p[0]=rnd*600   'x
            .p[1]=rnd*500   'y
            .p[2]=rnd*200   'width
            .p[3]=rnd*200   'height
            .p[4]=rgba(rnd*255,rnd*255,rnd*255,100+rnd*155)
            .p[5]=1+q          'filler
            .draw
            delete [] .p
        end with
    next n
    sleep
    loop until inkey=chr(27)

sleep


  
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Rect_t - optimized type definition

Post by MrSwiss »

(dodicat, no Pointers necessary, I'm afraid)

If you guy's want a type, fully packed with informations ...

Not yet implemented, just the structure, called Tiny_Rect (20 bytes):

Code: Select all

' Tiny_Rect_test1.bas -- 2018-08-15, MrSwiss
'
' compile: -s console
'
' if full rectangle info in a type is required (MrSwiss style)
Type Tiny_Rect              ' rectangle type with full info (20 bytes)
    As Short    x, y        ' x-, y-coordinates
    As UShort   w, h, ls    ' width, height, line style
    As UByte    fll         ' filled? 0 = NO, 1 = border-, 2 = fill color
    As Boolean  vis         ' visible/hidden
    As ULong    cb, cf      ' colors border/fill
End Type

Dim As Tiny_Rect    recf    ' full info rectangle struct

' no test/demo code, just a size output
#Ifdef __FB_64BIT__
Print "FBC x64"
#Else
Print "FBC x32"
#EndIf  ' __FB_64BIT__

Print "type size: " + Str(SizeOf(recf))
Locate 9, 2 : Print "press a key, to EXIT ... ";

Sleep
Btw. struct/type packing in FBC, is done depending on the "lagest sized variable", inside
the struct/type and, doesn't follow any other rules (AFAIR, as in FB-doc stated).
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Rect_t - optimized type definition

Post by fxm »

Finally a friendly Type structure for the data fields.
Post Reply