Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 16:59 02 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : CM2: DIM bit

     Page 3 of 4    
Author Message
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 10:19pm 18 Sep 2020
Copy link to clipboard 
Print this post

  CaptainBoing said  ...for CMM2 (don't have)

oppps! I didn't expect that!
  CaptainBoing said  Michael, could you write me an equivalent function and I'll put it in the wiki as an alternative for CMM2 (don't have)

With pleasure!

Bit Manipulation Functions for CMM2
'New
SUB FlagSet(bit AS INTEGER)
   FLAGS=FLAGS or (1<<63)
END SUB

'New
SUB FlagRes(bit AS INTEGER)
   FLAGS=FLAGS AND inv (1<<63)
END SUB
 
 
SUB FlagEq(bit As Integer,v as integer)
 IF v=0 THEN
   FlagRes(bit)
 ELSE
   FlagSet(bit)
 ENDIF
END SUB

'New
FUNCTION FlagTest(bit AS INTEGER) AS INTEGER
   FlagTest=(FLAGS AND(1<<bit))<>0
END FUNCTION

Demo:
bittest.zip
causality ≠ correlation ≠ coincidence
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 10:26pm 18 Sep 2020
Copy link to clipboard 
Print this post

  bar1010 said  
  JohnS said  
  bar1010 said  If the Color Maximite 2 is used for business, this inefficiency is causing us to lose money that we could have had if we were more efficient.


No, it isn't.  That is just plain wrong.

John


If we are talking about a few Boolean variables, then it is likely not worth the trouble of adding the functionality, but if we are talking about huge bit arrays then it is certainly worth it.  That is what I have in mind - huge bit arrays.


Well, a minute ago you were off on an irrelevant tangent about Walmart.

You can just use integers or strings and some simple functions to do huge bit arrays instead of fouling up the core interpreter.

John
 
bar1010
Senior Member

Joined: 10/08/2020
Location: United States
Posts: 197
Posted: 10:31pm 18 Sep 2020
Copy link to clipboard 
Print this post

  matherp said  [rant]
MMBasic has three datatypes: strings, 64-bit integers, and double precision floats - end of discussion. It is extremely frustrating when people who know nothing of the history of MMBasic and how long it took Geoff to integrate integers and how many bugs and difficulties that caused blithely suggest, bytes, booleans or whatever. If MMBasic as-is doesn't work for you feel free to use something else. The core basic interpreter isn't going to change. Please also understand the licencing of the source. You can do what you like with it for your own personal use but you may not incorporate any of my or Geoff's code in anything to be released in any way without our permission which in my case will not be forthcoming.

I haven't got the time or energy to answer every new forum user who wants to modify the concept in his or her own image so please lets stop these endless requests for changes or a different version.

I will always try and help new users who have problems with understanding and my greatest pleasure is to see new users like epsilon today whose first posts have been to contribute great new code using the firmware as-is rather than immediately wanting changes
[/rant]


Are there any future plans for a Color Maximite 3?  If so, would like to see a Boolean datatype available for it.
Edited 2020-09-19 10:13 by bar1010
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1642
Posted: 10:34pm 18 Sep 2020
Copy link to clipboard 
Print this post

The bit manipulation functions would be also useful for adventure games and the like in keeping collectable items in one word for locations and inventory.

Invert function for Micromite 170. Inv64 function is obvious.

  Quote  function inv32 (a as integer)
 inv32 = a
xor &hFFFFFFFF
end function



Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 12:53am 19 Sep 2020
Copy link to clipboard 
Print this post

  Quote  Oracle PL/SQL has a BOOLEAN datatype.  The CM2 should as well.

I bow to your superior knowledge of programming languages but I understand that with SQL, internally, the BOOLEAN type is stored as a single-byte integer that can take only the values 0 and 1. So no saving of memory there.
Other languages I do have some limited knowledge of also use a full byte for their BOOL types.

You seems to have an application which requires 40+Mbits. I suggest that the CMM2 is not the platform to use.

If your requirements were more realistic, bit manipulation of string arrays using PEEK and POKE is trivial with the existing commands.

Jim
VK7JH
MMedit
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1134
Posted: 02:42am 19 Sep 2020
Copy link to clipboard 
Print this post

  TassyJim said  If your requirements were more realistic, bit manipulation of string arrays using PEEK and POKE is trivial with the existing commands.

Or use a display page as the buffer, and peek and poke in that. Offers the advantage of blit commands for bulk copying, cls for filling values and maybe other graphics commands could be useful too.
Visit Vegipete's *Mite Library for cool programs.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 02:59am 19 Sep 2020
Copy link to clipboard 
Print this post

CLS
DIM test$(137,137,136) LENGTH 1
PRINT "Remaining Heap using 'test$(137,137,136)': ";MM.INFO(heap)
MEMORY
PRINT
ERASE test$()
DIM test$(137,137*137) LENGTH 1
PRINT "Remaining Heap using 'test$(137,137*137)': ";MM.INFO(heap)
MEMORY
PRINT
ERASE test$()
DIM test$(137*137*137) LENGTH 1
PRINT "Remaining Heap using 'test$(137*137*137)': ";MM.INFO(heap)
MEMORY
PRINT
ERASE test$()
DIM test$(137*137*137/255)
PRINT "Remaining Heap using 'test$(137*137*137/255)': ";MM.INFO(heap)
MEMORY
PRINT
ERASE test$()
DIM test%(137*137*137/8)
PRINT "Remaining Heap using 'test%(137*137*137/8)': ";MM.INFO(heap)
MEMORY

Output:
Remaining Heap using 'test$(137,137,136)':  24064
Program:
  1K ( 0%) Program (25 lines)
515K (100%) Free

Data:
5096K (98%) 1 Variable
  0K ( 0%) General
 88K ( 2%) Free

Remaining Heap using 'test$(137,137*137)':  61696
Program:
  1K ( 0%) Program (25 lines)
515K (100%) Free

Data:
5059K (97%) 1 Variable
  0K ( 0%) General
125K ( 3%) Free

Remaining Heap using 'test$(137*137*137)':  99584
Program:
  1K ( 0%) Program (25 lines)
515K (100%) Free

Data:
5022K (96%) 1 Variable
  0K ( 0%) General
162K ( 4%) Free

Remaining Heap using 'test$(137*137*137/255)':  2660608
Program:
  1K ( 0%) Program (25 lines)
515K (100%) Free

Data:
2521K (48%) 1 Variable
  0K ( 0%) General
2663K (52%) Free

Remaining Heap using 'test%(137*137*137/8)':  2670848
Program:
  1K ( 0%) Program (25 lines)
515K (100%) Free

Data:
2511K (48%) 1 Variable
  0K ( 0%) General
2673K (52%) Free
>


Moral of the story:
Single dimension arrays save a small amount of memory but not enough to be worthwhile for normal use.
Using normal length strings give a dramatic improvement due to the overheads with single length strings.
Using arrays of integers saves a bit more memory by getting rid of the length bytes.

Jim
VK7JH
MMedit
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1134
Posted: 04:05am 19 Sep 2020
Copy link to clipboard 
Print this post

Weird windows thing - ignore this post.
Edited 2020-09-19 14:06 by vegipete
Visit Vegipete's *Mite Library for cool programs.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10315
Posted: 07:03am 19 Sep 2020
Copy link to clipboard 
Print this post

  Quote  Are there any future plans for a Color Maximite 3?  If so, would like to see a Boolean datatype available for it.


No: but in any case you misunderstand how an interpreter works. When you create a variable it results in a data structure being created that includes the name (32 bytes), data-type, array of dimensions, and level. One 8 byte field is then overloaded as either the data itself or a pointer to the memory location for a string or an array. This structure is 64-bytes long. A byte or boolean datatype would use the same structure and so be the same size - saving NOTHING. Interpreters are not compilers

struct s_vartbl {                               // structure of the variable table
char name[MAXVARLEN];                       // variable's name
   char type;                                  // its type (T_NUM, T_INT or T_STR)
   char level;                                 // its subroutine or function level (used to track local variables)
   unsigned char size;                         // the number of chars to allocate for each element in a string array
   char dummy;
   int __attribute__ ((aligned (4))) dims[MAXDIM];                     // the dimensions. it is an array if the first dimension is NOT zero
   union u_val{
       MMFLOAT f;                              // the value if it is a float
       long long int i;                        // the value if it is an integer
       MMFLOAT *fa;                            // pointer to the allocated memory if it is an array of floats
       long long int *ia;                      // pointer to the allocated memory if it is an array of integers
       char *s;                                // pointer to the allocated memory if it is a string
   }  __attribute__ ((aligned (8))) val;
} __attribute__ ((aligned (8))) val;

Edited 2020-09-19 17:17 by matherp
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7938
Posted: 08:14am 20 Sep 2020
Copy link to clipboard 
Print this post

How do these work?

  Quote  
'New
SUB FlagSet(bit AS INTEGER)
  FLAGS=FLAGS or (1<<63)
END SUB

'New
SUB FlagRes(bit AS INTEGER)
  FLAGS=FLAGS AND inv (1<<63)
END SUB


Is it something magical about the version of MMBasic for the CMM2 (which I don't have), I wondered? The "bit" argument passed to the sub is only used by telepathy.

I tried them just for giggles on the DOS version:

FlagSet does nothing. May be useful to change it to
FLAGS=bit or (1<<63)
in which case FLAGS is replaced by a zero word with a single bit set on every call.

FlagRes, in its current form, merely zeroes FLAGS on every call.

The correct format is, of course, (1<<bit)

I came up with something else of more concern if you are looking for a lot of bit storage. Using original or new versions of these routines I can't reset bits from bit 53 upwards, even though all variables are integers. They will set and test but not reset.

Here's my little test prog. Input command,bit_number e.g. s,0 will set bit 0

bits01.zip
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 10:50am 20 Sep 2020
Copy link to clipboard 
Print this post

  Mixtel90 said  How do these work?

  Quote  
'New
SUB FlagSet(bit AS INTEGER)
...
SUB FlagRes(bit AS INTEGER)
.


Is it something magical about the version of MMBasic for the CMM2 (which I don't have), I wondered? The "bit" argument passed to the sub is only used by telepathy.


Don't get hung up on the <<63 - it was just to illustrate a method. In anger it should read <<bit

Check here for the complete (correct) code
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 11:03am 20 Sep 2020
Copy link to clipboard 
Print this post

  Mixtel90 said  How do these work?

[...]

FlagSet does nothing. May be useful to change it to
FLAGS=bit or (1<<63)


Hi Mixtel90, you are correct!
This should work:

Bit Manipulation Functions for CMM2 (for CBs Wiki)

'New
SUB FlagSet(bit AS INTEGER)
  FLAGS=FLAGS or (1<<bit)
END SUB

'New
SUB FlagRes(bit AS INTEGER)
  FLAGS=FLAGS AND inv (1<<bit)
END SUB


SUB FlagEq(bit As Integer,v as integer)
IF v=0 THEN
  FlagRes(bit)
ELSE
  FlagSet(bit)
ENDIF
END SUB

'New
FUNCTION FlagTest(bit AS INTEGER) AS INTEGER
  FlagTest=(FLAGS AND(1<<bit))<>0
END FUNCTION


Regards
causality ≠ correlation ≠ coincidence
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 11:06am 20 Sep 2020
Copy link to clipboard 
Print this post

  CaptainBoing said  
Don't get hung up on the <<63 - it was just to illustrate a method. In anger it should read <<bit

Check here for the complete (correct) code


Thanks CB!

Michael
causality ≠ correlation ≠ coincidence
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 11:15am 20 Sep 2020
Copy link to clipboard 
Print this post

actually, this code is now broken. Anyone any ideas why using << breaks the OR function?

Admittedly I am using an old version (5.04.08) on a micromite but I imagine this particular bit of the firmware is old as the hills - take a look at the following.

the original code:

 dim integer flag

 SUB FlagSet(bit AS INTEGER)
   FLAG=FLAG OR (2^bit)
 END SUB  

 SUB FlagRes(bit AS INTEGER)
   FLAG=(FLAG OR (2^bit)) XOR (2^bit)
 END SUB

 FUNCTION FlagTest(bit AS INTEGER) AS INTEGER
   FlagTest=ABS(SGN(FLAG AND (2^bit)))
 END FUNCTION

gives the expected output:
> flagset 2:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000100
> flagset 63:?bin$(flag,64)
1000000000000000000000000000000000000000000000000000000000000100
> flagset 62:?bin$(flag,64)
1100000000000000000000000000000000000000000000000000000000000100
> flagset 31:?bin$(flag,64)
1100000000000000000000000000000010000000000000000000000000000100
>


But the new code using 1<<bit instead of 2^bit,
'Set a Flag
Sub FlagSet(bit As Integer)
 FLAG=FLAG Or 1<<bit
End Sub

gives this.
> flagset 2:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000100
> flagset 63:?bin$(flag,64)
1000000000000000000000000000000000000000000000000000000000000000
> flag=0
> flagset 2:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000100
> flagset 62:?bin$(flag,64)
0100000000000000000000000000000000000000000000000000000000000000
> flagset 2:?bin$(flag,64)
0100000000000000000000000000000000000000000000000000000000000000
> flagres 62:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000000
> flagset 2:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000100
> flagset 0:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000101
> flagset 31:?bin$(flag,64)
0000000000000000000000000000000010000000000000000000000000000000
>


bits get cleared as if ANDed can anyone verify this? (any platform)
Edited 2020-09-20 21:20 by CaptainBoing
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 11:43am 20 Sep 2020
Copy link to clipboard 
Print this post

The new code probably needs brackets around the 1<<bit to make the precedence work the way you want

Jim
VK7JH
MMedit
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 11:44am 20 Sep 2020
Copy link to clipboard 
Print this post

  Mixtel90 said  I came up with something else of more concern if you are looking for a lot of bit storage. Using original or new versions of these routines I can't reset bits from bit 53 upwards, even though all variables are integers. They will set and test but not reset.

Here's my little test prog. Input command,bit_number e.g. s,0 will set bit 0

bits01.zip


This should work:
Function inv64(b As integer) AS INTEGER
inv64 = b Xor &hFFFFFFFFFFFFFFFF
End Function

causality ≠ correlation ≠ coincidence
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 11:52am 20 Sep 2020
Copy link to clipboard 
Print this post

@CB

Sub FlagSet(bit As INTEGER)
flags=flags Or 1<<bit
End Sub

works on my CMM2, even without the brackets.
Strange.
causality ≠ correlation ≠ coincidence
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2442
Posted: 11:55am 20 Sep 2020
Copy link to clipboard 
Print this post

that was a tricky one to figure out!

try this version of the code, only requiring flagset:

Dim integer flag

Sub FlagSet(bit As INTEGER)
  FLAG=FLAG Or (2^bit)
  Print Bin$(FLAG, 64)
  Print FLAG
End Sub


save and RUN with f2

now type the following at the prompt:

> flagset(1)
0000000000000000000000000000000000000000000000000000000000000010
2
> flagset(63)
1000000000000000000000000000000000000000000000000000000000000010
-9223372036854775806
>
> clear
>
> flagset(1)
0000000000000000000000000000000000000000000000000000000000000010
2
> flagset(63)
1000000000000000000000000000000000000000000000000000000000000000
-9.22337e+18
>


not the difference between the behaviour BEFORE and AFTER typing 'clear'?

the first two calls to flagset occur after FLAG has been defined (because of the save and RUN) as a 64-bit integer. but after the 'clear' FLAG reverts to being the default type the first time it is used by a call to flagset, ie, as a 32-bit float. 32-bit floats can only represent EXACTLY a range covering 24 bits. seethe diagram here:
https://en.wikipedia.org/wiki/Single-precision_floating-point_format

while higher numbered bits can be set, doing so causes lower bits to drop off the end.

the moral: implicitly define the type of FLAG by using FLAG%.


cheers,
rob   :-)

addendum: the CMM2 uses 63-bit floats, where the exact range of storing integers is 53 bits. see:
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
Edited 2020-09-20 22:01 by robert.rozee
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2442
Posted: 12:19pm 20 Sep 2020
Copy link to clipboard 
Print this post

try giving this a spin:

Sub flagSET(bit)
  FLAG%=FLAG% Or (1<<bit)
  Print Bin$(FLAG%, 64)
  Print FLAG%
End Sub

Sub flagCLR(bit)
  FLAG%=FLAG% And (-1 Xor (1<<bit))
  Print Bin$(FLAG%, 64)
  Print FLAG%
End Sub

Function flagTST(bit)
  FlagTST=((FLAG% And (1<<bit))<>0)
End Function
End



cheers,
rob   :-)
Edited 2020-09-20 22:28 by robert.rozee
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 12:24pm 20 Sep 2020
Copy link to clipboard 
Print this post

  TassyJim said  The new code probably needs brackets around the 1<<bit to make the precedence work the way you want


Hi Jim,  I did it both ways, still get that weird behaviour where the bit gets cleared.

  robert.rozee said  
the moral: implicitly define the type of FLAG by using FLAG%.


if working from a command prompt yes but as part of the running code, the Dim takes care of this.

something is not right and I can't put my finger on it. In the below test, I progressively set the flags (after a run) and as soon as I get to bit 23, it zeroes all the earlier bits. This is an OR, it absolutely cannot reset bits!  What is going on? 24 bits is 3 bytes - nothing "special" to the maths in MMBasic as far as I can see:


> list all
'preamble
'Dim Integer Flag


'Set a Flag
Sub FlagSet(bit As Integer)
 FLAG=FLAG Or (1<<bit)
End Sub

'Clear a flag
Sub FlagRes(bit As Integer)
 Local Integer x
 x=1<<bit
 FLAG=(FLAG Or x) Xor x
End Sub

'Equate a flag to a value
Sub FlagEq(bit As Integer,v As Integer)
 If v Then
  FlagSet(bit)
 Else
  FlagRes(bit)
 EndIf
End Sub

'Test a flag
Function FlagTest(bit As Integer) As Integer
 FlagTest=Abs(Sgn(FLAG And (1<<bit)))
End Function

'Bitise Invert a value
'For MMBasics without native Inv() Function
Function Inv(a As Integer)
 Inv=a Xor &hFFFFFFFFFFFFFFFF
End Function
>
>run
>
> flagset 0 :?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000001
> flagset 1:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000011
> flagset 2:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000000111
> flagset 3:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000001111
> flagset 4:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000011111
> flagset 5:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000000111111
> flagset 6:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000001111111
> flagset 7:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000011111111
> flagset 8:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000000111111111
> flagset 9:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000001111111111
> flagset 10:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000011111111111
> flagset 11:?bin$(flag,64)
0000000000000000000000000000000000000000000000000000111111111111
> flagset 12:?bin$(flag,64)
0000000000000000000000000000000000000000000000000001111111111111
> flagset 13:?bin$(flag,64)
0000000000000000000000000000000000000000000000000011111111111111
> flagset 14:?bin$(flag,64)
0000000000000000000000000000000000000000000000000111111111111111
> flagset 15:?bin$(flag,64)
0000000000000000000000000000000000000000000000001111111111111111
> flagset 16:?bin$(flag,64)
0000000000000000000000000000000000000000000000011111111111111111
> flagset 17:?bin$(flag,64)
0000000000000000000000000000000000000000000000111111111111111111
> flagset 18:?bin$(flag,64)
0000000000000000000000000000000000000000000001111111111111111111
> flagset 19:?bin$(flag,64)
0000000000000000000000000000000000000000000011111111111111111111
> flagset 20:?bin$(flag,64)
0000000000000000000000000000000000000000000111111111111111111111
> flagset 21:?bin$(flag,64)
0000000000000000000000000000000000000000001111111111111111111111
> flagset 22:?bin$(flag,64)
0000000000000000000000000000000000000000011111111111111111111111
> flagset 23:?bin$(flag,64)
0000000000000000000000000000000000000001000000000000000000000000
>


it skips setting bit 23, sets bit 24 and clears 0-22  

I am going to try this on another MicroMite just to see if there is something freaky with the firmware.
Edited 2020-09-20 22:27 by CaptainBoing
 
     Page 3 of 4    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025