Author Topic: Questions over `n  (Read 3456 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Questions over `n
« on: January 06, 2019, 01:14:53 am »
Using the wiki for reference: http://qb64.org/wiki/Variable_Types

QB64 allows an odd offset to be attached to our numbers, so we can define them as a series of bits of certain length:  `n

The wiki doesn't give much information on what the limits to the size of n might be, so I've did a little experimenting:

Code: QB64: [Select]
  1. PRINT 3`56

The above works perfectly fine, whereas once we increase the value, as below, the IDE stubbornly tosses an error:

Code: QB64: [Select]
  1. PRINT 3`57

Anyone have any idea why 56 seems to be the magic cutoff value here?



Second, unrelated issue:

Code: QB64: [Select]
  1. PRINT 3`1

I would expect the above to be defined as a single bit number (much like true or false), so printing it should print -1 (0 or -1 for a single bit), in my opinion.

Instead, it prints a value of 3...

How can we have a value of 3, if it's simply using a single bit to store values??



And, to add to the confusion, if we assign it to a variable with the extension, it works as one would expect:

Code: QB64: [Select]
  1. x`1 = 3
  2. PRINT x`1

The above *does* print us a value of -1. 



HOWEVER, if we make it a CONST instead of a variable, we see the same prior behavior:

Code: QB64: [Select]
  1. CONST x`1 = 3
  2. PRINT x`1

In this case, the value is once again... 3.



Something seems off somewhere with these results.  Anyone know what the intended behavior is supposed to be?  Exactly what should the limit on n be for `n?  And how should it behave in regards to numbers/variables/constants?

I know it's a seldom used part of the language, but we should try to make its usage consistent -- or at least document its weird particularities -- if it's going to be allowed in the language.  And, at the moment, I don't have a clue as to what it's actually supposed to be doing for us, with results as varied and odd as these.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Questions over `n
« Reply #1 on: January 06, 2019, 01:25:12 am »
The bit type, especially the n bit type, was never fully implemented. Don't expect there to be any rhyme or reason to some of it.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Questions over `n
« Reply #2 on: January 06, 2019, 01:30:45 am »
The bit type, especially the n bit type, was never fully implemented. Don't expect there to be any rhyme or reason to some of it.

Perhaps a warning to that effect would be warranted for the wiki page, so folks will know not to make use of it anytime soon.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Questions over `n
« Reply #3 on: January 06, 2019, 01:31:38 pm »
I had always assumed that n was limited to 1 to 7, so that a user could have a variable type between the _BIT and the _BYTE, but who would want such a thing?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Questions over `n
« Reply #4 on: January 06, 2019, 01:40:12 pm »
I had always assumed that n was limited to 1 to 7, so that a user could have a variable type between the _BIT and the _BYTE, but who would want such a thing?

It could be useful if all you needed was to track a limited number of on/off states...

Say a game has a lot of terrain with “walk, swim, fly” type tiles across it.

DIM TileMovement (Xlimit, Y limit) AS _BIT * 3

For a 300 x 300 tile map (90000 tiles), you’d only use 270,000 bits to store that information in memory — compared to 720,000 bits, if you stored the info in _BYTE instead.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: Questions over `n
« Reply #5 on: January 06, 2019, 01:56:42 pm »
However, there's no way to store a single bit in memory and a byte will be taken up anyway. So I've been told.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Questions over `n
« Reply #6 on: January 06, 2019, 02:07:32 pm »
However, there's no way to store a single bit in memory and a byte will be taken up anyway. So I've been told.

Aye, for a single bit, but you can pack an array of them.

A _BIT has to be stored in a _BYTE, but you can put up to 8 of them in that same byte.

DIM x(1 TO 80) AS _BIT uses 10 bytes of storage, for example.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: Questions over `n
« Reply #7 on: January 06, 2019, 02:25:59 pm »
After Luke:

Quote
The bit type, especially the n bit type, was never fully implemented. Don't expect there to be any rhyme or reason to some of it.

I wonder how that's handled internally.

FellippeHeitor

  • Guest
Re: Questions over `n
« Reply #8 on: January 06, 2019, 03:01:52 pm »
I wonder how that's handled internally.

A variable defined using DIM AS _BIT is internally stored as int32:
Code: QB64: [Select]
  1. int32 *__BIT1_A=NULL;

then when you assign it any value (in this example I had DIM a as _BIT in my program and I made a = 1), there's this check internally:
Code: QB64: [Select]
  1. if ((*__BIT1_A= 1 )&1){
  2. *__BIT1_A|=-2;
  3. *__BIT1_A&=1;
  4. }

When an array of _BITs is used, as in DIM x(1 TO 80) AS _BIT, this is the code that's run to set x(1) = 1:

Code: QB64: [Select]
  1. tmp_long=array_check(( 1 )-__ARRAY_BIT1_X[4],__ARRAY_BIT1_X[5]);
  2. if (!new_error) setbits(1,(uint8*)(__ARRAY_BIT1_X[0]),tmp_long, 1 );

Then setbits() does this:

Code: QB64: [Select]
  1. void setbits(uint32 bsize,uint8 *base,ptrszint i,int64 val){
  2.     int64 bmask;
  3.     uint64 *bptr64;
  4.     bmask=(((uint64)1)<<bsize)-1;
  5.     i*=bsize;
  6.     bptr64=(uint64*)(base+(i>>3));
  7.     *bptr64=(*bptr64&( ( (bmask<<(i&7)) ^-1)  )) | ((val&bmask)<<(i&7));
  8. }

It really is an illusion to use _BIT with memory economy in mind.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Questions over `n
« Reply #9 on: January 07, 2019, 05:18:03 am »
The bit type, especially the n bit type, was never fully implemented.

I have reported previously that _BIT variables are not handled correctly into/out of FUNCTIONs and subroutines

Code: QB64: [Select]
  1. CONST True = -1`, False = 0`
  2. BooleanBit` = True
  3. BooleanByte%% = BooleanBit`
  4.  
  5. 'PRINT B1%%(BooleanBit`)
  6. 'CALL Routine1((BooleanBit`), Result1`)
  7. 'PRINT Result1`
  8.  
  9. PRINT B2%%(BooleanBit`)
  10. CALL Routine2((BooleanByte%%), Result2%%)
  11. PRINT Result2%%
  12.  
  13.  
  14. 'FUNCTION B1%% (C`)
  15. '    IF C` THEN
  16. '        B1%% = True
  17. '    ELSE
  18. '        B1%% = False
  19. '    END IF
  20. 'END FUNCTION
  21.  
  22. FUNCTION B2%% (C%%)
  23.     IF C%% THEN
  24.         B2%% = True
  25.     ELSE
  26.         B2%% = False
  27.     END IF
  28.  
  29. 'SUB Routine1 (D`, E`)
  30. '    IF D` THEN
  31. '        E` = True
  32. '    ELSE
  33. '        E` = False
  34. '    END IF
  35. 'END SUB
  36.  
  37. SUB Routine2 (D%%, E%%)
  38.     IF D%% THEN
  39.         E%% = True
  40.     ELSE
  41.         E%% = False
  42.     END IF
  43.  

If lines 5-7, 15-21 and 31-35 are not commented out the program fails (usually C++ compilation).  As programmers, we love the _BIT type variable (Boolean logic everywhere) and I always use this type wherever possible.  It's a pity that I have to copy them to a _BYTE when transferring to a subroutine or function.  But no worries, just remember to do this and all works fine.  Steve, if you now tell me that I've been doing something else stupid I shall slink off into a corner somewhere!


Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Questions over `n
« Reply #10 on: January 07, 2019, 06:14:28 am »
Quote
Steve, if you now tell me that I've been doing something else stupid I shall slink off into a corner somewhere!

The only thing wrong which I can see is how you use _BIT. 

As Fell said, “There’s no way to store a single bit in memory and a byte will be taken up anyway.”

Think of a computer as a highway.  Cars drive up and down the road, carrying information from one place to another...

In this analogy, a _BYTE would basically be a car, and a _BIT would be a person...

To drive down the interstate, you have to pack the person (_BIT) into a car (_BYTE).  A person just can’t walk down the highway (it’s actually illegal here in Virginia; probably illegal across *all* US interstates); they HAVE to be inside a car.

Individually, it makes no sense to use _BIT; when they’re just going to be packed up and shoved into a _BYTE anyway.



So, if a _BIT *has* to be in a _BYTE, what’s the point to them??

Just like that car going down the highway can hold multiple people, a _BYTE can hold multiple _BITs.

A single person has to get in a car to use the interstate.  A single _BIT has to be packed into a _BYTE to be stored in memory.

Multiple people can cram into the same car.  Multiple _BITs can fit into the same _BYTE.



Honestly, the only time a programmer should use _BIT is when they’re going to pack an array with them.

DIM True AS _BIT <— This line is actually doing your program HARM.  The computer has to shove that bit into a byte, store it in memory, then unpack it again from that stored byte, every time you call it.

_BIT usage, by its very nature, is slow and inefficient.  Another way to think of them is as an egg.  You *have* to keep your eggs in a carton to put them in your fridge.  When you need them, you open the fridge, get the carton, open it, and THEN pull out the egg to use.  It’s much more efficient and quicker, if all you have to deal with is the egg cartons themselves.

_BITs purpose is to reduce speed and efficiency, in return for lower memory usage. 

The only time it makes sense to use _BIT is with arrays of information.

DIM variable AS _BIT <— this uses a _BYTE of memory, and is packed and unpacked before use.

DIM array(7) AS _BIT <— this packs 8 bits of infomation into a _BYTE of memory, and is packed and unpacked before use.



The *only* thing you accomplish by making a single variable a _BIT, is you slow down your program and make it less efficient.  No memory savings.  No advantage at all.  Just a drag on performance.

_BIT is only useful, if you’re going to be packing multiple ones of it into _BYTE — and the *ONLY* way we do that is with arrays.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Questions over `n
« Reply #11 on: January 07, 2019, 06:36:18 am »
Steve, regrettably I shall continue to walk down that highway!  I know that when those very clever people created the _BIT type they were thinkng "if we have millions of these small variables, it'll be efficient for the processor to pack them into a _BYTE, rather than have them all individually _BYTEs".  But because that variable type _BIT is allowed to be used, the dumb programmer will think "I have these variables which are only allowed to be True (-1 by convention) or False (0 by convention), so the best variable type to use is _BIT".  The traffic will have to slow down for the idiot who continues to walk down the centre of the highway.*

(* my programs don't generally use a lot of processor power: for any that do need real processing power, perhaps I'll bear your cautionary remarks in mind).

« Last Edit: January 07, 2019, 07:33:45 am by Qwerkey »

FellippeHeitor

  • Guest
Re: Questions over `n
« Reply #12 on: January 07, 2019, 07:13:26 am »
Quote
DIM variable AS _BIT <— this uses a _BYTE of memory, and is packed and unpacked before use.

4 bytes, as I've mentioned above.