AND or OR which is faster?

Recommended Posts

I am trying to squeeze some performance out of a comparison.

I cannot see much difference between And/Or in XB  Does it make a difference Compiled?

So, if the first element where true the OR would be faster.  If it where false the AND would be faster.

But what is happening in the actual game, the lower elements matter the most.  So, the cls(7) will be true or false most often followed by 8,9 etc.

Next can I replace GCHAR with a PEEK?  Would it matter?  Compiled?

I am getting close to finishing a game, but I want to tighten it up...  I plan on refactoring a little and untangling some of the spaghetti but the key part where the speed is most important is the compare and gchar.

10 DIM CLS(20)

15 FOR X=7 TO 15

20 CLS(X)=32

25 NEXT X
30 FOR X=1 TO 1000
40 IF CLS(7)=32 AND CLS(8)=32 AND CLS(9)=32 AND CLS(10)=32 AND CLS(11)=32 AND CLS(12)=32 AND CLS(13)=32 AND CLS(14)=32 AND CLS(15)=32 THEN 50 ELSE END
50 NEXT X

VS

10 DIM CLS(20)

15 FOR X=7 TO 15

20 CLS(X)=32

25 NEXT X

30 FOR X=1 TO 1000
40 IF CLS(7)>92 OR CLS(8)>92 OR CLS(9)>92 OR CLS(10)>92 OR CLS(11)>92 OR CLS(12)>92 OR CLS(13)>92 OR CLS(14)>92 OR CLS(15)>92 THEN END ELSE 50
50 NEXT X

Share on other sites

In compiled code, OR is slightly faster than AND. But I don't think you would be able to notice.

Using arrays is definitely slower, both compiled and in XB. Wherever possible you should use variables.

Share on other sites
2 minutes ago, senior_falcon said:

In compiled code, OR is slightly faster than AND. But I don't think you would be able to notice.

Using arrays is definitely slower, both compiled and in XB. Wherever possible you should use variables.

Thanks for the reply.  I have changed to the OR version.

I was using this array because I had already been using it in another part of the program.  So, rather then create more variables.

Also, makes looping easy..

Hmm, I will try to use normal vars rather than array and see if that helps.  I think this will take a lot more statements to complete the same task.

But I have another subroutine that I may be able to piggyback on and kill to birds with one stone.

Oh fun!  LOL.

Share on other sites
6 hours ago, 1980gamer said:

40 IF CLS(7)>92 OR CLS(8)>92 OR CLS(9)>92 OR CLS(10)>92 OR CLS(11)>92 OR CLS(12)>92 OR CLS(13)>92 OR CLS(14)>92 OR CLS(15)>92    THEN  END   ELSE 50

When I look at all those logical conditions I find myself wondering if there is one of them that is critical? Maybe there are two that are show-stoppers.

If so those could be part of an IF statement so that you shortcut testing everything IF you don't need to.

Using logical flags with AND  and OR  can save time for two conditions vs IF under the right conditions, but I think you are forcing the machine to compute all of the logical operations,  even if you fail the first one.

That could be a bottle-neck maybe. (?)  But maybe it has to be that way for your program.

Just a thought.

The compiler make fast code but it's not very speedy processor under the hood.

Share on other sites
2 hours ago, TheBF said:

When I look at all those logical conditions I find myself wondering if there is one of them that is critical? Maybe there are two that are show-stoppers.

If so those could be part of an IF statement so that you shortcut testing everything IF you don't need to.

Using logical flags with AND  and OR  can save time for two conditions vs IF under the right conditions, but I think you are forcing the machine to compute all of the logical operations,  even if you fail the first one.

That could be a bottle-neck maybe. (?)  But maybe it has to be that way for your program.

Just a thought.

The compiler make fast code but it's not very speedy processor under the hood.

Unfortunately any one of these conditions could be true.  The lower ones are most probable at least.

I think I can use a constant for the next segment of the program and that "may" help?

The or vs. and was noticeable within the actual game. Complied even more so.

I am doing a block of gchar's into the cls(x) values.  I was calling the GCHARS on each pass.  Dropping the values into the array was a huge increase in speed.

But I still want to squeeze a little more out of it!

Share on other sites
36 minutes ago, 1980gamer said:

I am doing a block of gchar's into the cls(x) values.  I was calling the GCHARS on each pass.  Dropping the values into the array was a huge increase in speed.

But I still want to squeeze a little more out of it!

Depending upon the comparisons necessary, what about taking the value returned by GCHAR and placing it into a string using CHR\$(), then making an en-mass comparison?  For instance

```10 S\$="" :: FOR I=4 TO 13 :: CALL GCHAR(R,I,X) :: S\$=S\$&CHR\$(X) :: NEXT I ! WHERE R IS THE SCREEN ROW
20 IF S\$="          " THEN 100 ! TEN SPACES
30 REM THIS IS THE REST OF THE PROGRAM

100 REM THIS IS WHERE WE WANT TO GO```

If you know CTRL key character codes, you could still use this for un-printable characters.  Though it makes copy and paste text listings impossible.  Honestly not sure if this will make it faster, but it could make it easier to program.

Share on other sites

10 CALL HGET(R,I,S\$) ! WHERE R IS ON THE SCREEN ROW

20 IF S\$=RPT\$(" ",10) THEN 100 ! TEN SPACES

30 REM THIS IS THE REST OF PROGRAM

100 REM THIS IS WHERE WE WANT TO GO

This is how I would do it in RXB. But that is just me?

Edited by RXB
Spelling

Share on other sites
26 minutes ago, RXB said:

This is how I would do it in RXB. But that is just me?

If using RXB, I would not use RPT\$() as you did, because for 10 characters the space savings is minimal (I think only one byte and only targeted toward this example,) but I also do not believe the function is any faster than a literal string.  The latter, of course, would have to be tested.

Otherwise, the HGET subprogram is handy but will not compile.

Share on other sites
8 hours ago, 1980gamer said:

Unfortunately any one of these conditions could be true.  The lower ones are most probable at least.

I think I can use a constant for the next segment of the program and that "may" help?

The or vs. and was noticeable within the actual game. Complied even more so.

I am doing a block of gchar's into the cls(x) values.  I was calling the GCHARS on each pass.  Dropping the values into the array was a huge increase in speed.

But I still want to squeeze a little more out of it!

ok.

This makes me wonder if the compiled code would be smaller (and therefore faster)  if you just summed the contents of the CLS() array in a FOR/NEXT loop.

That would be like an AND on each value but I don't know if the compiler will make faster code than that inline statement. The loop overhead would be not bad in machine code.

Might be worth a try.

You might have to change the initial value in the array . ?

Share on other sites
9 hours ago, TheBF said:

ok.

This makes me wonder if the compiled code would be smaller (and therefore faster)  if you just summed the contents of the CLS() array in a FOR/NEXT loop.

That would be like an AND on each value but I don't know if the compiler will make faster code than that inline statement. The loop overhead would be not bad in machine code.

Might be worth a try.

You might have to change the initial value in the array . ?

10 DIM CLS(20)

15 FOR X=7 TO 15

20 CLS(X)=32

25 NEXT X

30 FOR X=1 TO 1000

35 for ck=7 to 15

40 IF CLS(ck)>92 THEN END ELSE 50

45 next ck

50 NEXT X

So, this seems counter intuitive to me..  Nesting the loop, meaning 9,000 more executions of for and next...

However

.

.

It is significantly faster.   What did I do wrong?  How can this be?  HMMMMMM

Edited by 1980gamer

Share on other sites

You would have to look at the code the compiler generates. Is that easy to see?

Share on other sites
2 hours ago, 1980gamer said:

10 DIM CLS(20)

15 FOR X=7 TO 15

20 CLS(X)=0

25 NEXT X

30 FOR X=1 TO 1000

35 for ck=7 to 15

40 IF CLS(ck) THEN END ELSE 50

45 next ck

50 NEXT X

So you had a huge amount of code inside 1000 iteration loop. I think that was the problem.

I am also wondering if the amount of code in the comparison would be less by just checking for non-zero in CLS(7) ... CLS(15)  as in the BASIC code above.

I just tested BASIC with this so I know the IF statement works this way in the interpreter. Don't about the compiler.

```100 X=0
110 IF X THEN 120 ELSE 130
120 PRINT "TRUE"
130 PRINT "FALSE"
```

Share on other sites

Somehow the nested loop is faster?

I wish I could check for 0.  32 is a space or blank char from GCHAR.

I have to all kinds of offsets etc.

I am hoping some refactoring and some other clever things will speed it up.

I have a series of 11 IF statements.

11580 IF CLS(COL)>92 THEN I=I+1 ELSE 11595
11581 IF CLS(COL)=93 THEN G1=G1+1 :: GOTO 11595
11582 IF CLS(COL)=101 THEN G2=G2+1 :: GOTO 11595
11583 IF CLS(COL)=109 THEN G3=G3+1 :: GOTO 11595
11584 IF CLS(COL)=117 THEN G4=G4+1 :: GOTO 11595
11585 IF CLS(COL)=125 THEN G5=G5+1 :: GOTO 11595
11586 IF CLS(COL)=95 THEN G6=G6+1 :: GOTO 11595
11587 IF CLS(COL)=103 THEN G7=G7+1 :: GOTO 11595
11588 IF CLS(COL)=111 THEN G8=G8+1 :: GOTO 11595
11589 IF CLS(COL)=119 THEN G9=G9+1 :: GOTO 11595
11590 IF CLS(COL)=127 THEN G10=G10+1

I am hoping the goto's will help the logic fall out quicker.  I put them in the order that is most likely true....  At least at the start of the game.

In XB I did not notice any speed change...  But I am going to change the array comparison next.

11579 EE=CLS(COL)

11580 IF EE>92 THEN I=I+1 ELSE 11595
11581 IF EE=93 THEN G1=G1+1 :: GOTO 11595
11582 IF EE=101 THEN G2=G2+1 :: GOTO 11595
11583 IF EE=109 THEN G3=G3+1 :: GOTO 11595
11584 IF EE=117 THEN G4=G4+1 :: GOTO 11595
11585 IF EE=125 THEN G5=G5+1 :: GOTO 11595
11586 IF EE=95 THEN G6=G6+1 :: GOTO 11595
11587 IF EE=103 THEN G7=G7+1 :: GOTO 11595
11588 IF EE=111 THEN G8=G8+1 :: GOTO 11595
11589 IF EE=119 THEN G9=G9+1 :: GOTO 11595
11590 IF EE=127 THEN G10=G10+1

At the very least, it saves a few bytes.

Share on other sites

Take these with a grain of salt.  There are two patterns to your value set.  I used these two sets to calculate two ON GOTO statements.  If you were using G as an array, I could calculate a subscript based upon those sets.  This is how I would program what you have given.  For compilation I would have to figure up a little more as numbers can only be integers and the check I make at 11580 and 11581 would always pass.

```11579 EE=CLS(COL) :: IF EE>92 AND EE<128 THEN I=I+1 ELSE 11595 ! RANGE CHECK HERE
11580 E1=(EE-85)/8 :: IF INT(E1)=E1 THEN ON E1 GOTO 11582,11583,11584,11585,11586
11581 E1=(EE-87)/8 :: IF INT(E1)=E1 THEN ON E1 GOTO 11587,11588,11589,11590,11591 :: ELSE 11595
11582 G1=G1+1 :: GOTO 11595
11583 G2=G2+1 :: GOTO 11595
11584 G3=G3+1 :: GOTO 11595
11585 G4=G4+1 :: GOTO 11595
11586 G5=G5+1 :: GOTO 11595
11587 G6=G6+1 :: GOTO 11595
11588 G7=G7+1 :: GOTO 11595
11589 G8=G8+1 :: GOTO 11595
11590 G9=G9+1 :: GOTO 11595
11591 G10=G10+1

11595 ! THIS IS THE TARGET```

I dunno.  I got crazy here, too.  Another option, if using G() instead of G1..G10, assuming G() is DIMmed G(10):

```11579 EE=CLS(COL) :: IF EE>92 AND EE<128 THEN I=I+1 :: ELSE 11595 ! RANGE CHECK HERE
11580 FOR E1=1 TO 10 :: IF EE=85+8*(E1+5*(E1>5))-2*(E1>5) THEN G(E1)=G(E1)+1
11581 NEXT E1

11595 ! THIS IS THE TARGET```

The EE formula can probably be optimized, too.  I am probably just being cheeky at this point.

Share on other sites

I don't see the big picture yet, but it looks like you are trying to find a faster way to read 10 consecutive bytes from the screen and see if they are all spaces.

If so, this will work and can be compiled:

(XB256 is needed here.)

From the manual:

VREAD reads the specified number of bytes from the VDP ram into a string variable of up
to 255 bytes. Up to 5 strings can read with one call to VREAD.

Edited by senior_falcon

Share on other sites
35 minutes ago, OLD CS1 said:

11579 EE=CLS(COL) :: IF EE>92 AND EE<128 THEN I=I+1 :: ELSE 11595 ! RANGE CHECK HERE 11580 FOR E1=1 TO 10 :: IF EE=85+8*(E1+5*(E1>5))-2*(E1>5) THEN G(E1)=G(E1)+1 11581 NEXT E1 11595 ! THIS IS THE TARGET

I cannot wrap my head around this! LOL

However, this made a very noticeable difference!

11579 EE=CLS(COL)

11580 IF EE>92 THEN I=I+1 ELSE 11595
11581 IF EE=93 THEN G1=G1+1 :: GOTO 11595
11582 IF EE=101 THEN G2=G2+1 :: GOTO 11595

I am running 10 gchars  statements  and this loops 10 times.  Very slow!

RXB has some nice GCHAR stuff, but I need to compile!

Share on other sites
2 minutes ago, senior_falcon said:

I don't see the big picture yet, but it looks like you are trying to find a faster way to read 10 consecutive bytes from the screen and see if they are all spaces.

If so, this will work and can be compiled:

(XB256 is needed here.)

From the manual:

VREAD reads the specified number of bytes from the VDP ram into a string variable of up
to 255 bytes. Up to 5 strings can read with one call to VREAD.

I can try this!  I am user XB256 of course!  I have scrolling etc. happening!

I have not used VREAD, can this take the place of GCHAR?

19000 CALL GCHAR(ROW,7,CLS(7)):: CALL GCHAR(ROW,8,CLS(8)):: CALL GCHAR(ROW,9,CLS(9))::CALL GCHAR(ROW,10,CLS(10)):: CALL GCHAR(ROW,11,CLS(11))
19005 CALL GCHAR(ROW,12,CLS(12)):: CALL GCHAR(ROW,13,CLS(13)):: CALL GCHAR(ROW,14,CLS(14)):: CALL GCHAR(ROW,15,CLS(15)):: CALL GCHAR(ROW,16,CLS(16))
19025 RETURN

This section is certainly the slowest piece of the SCAN loop.   I also do this over 10 rows.  So 100 GCHAR statements!

I tried more and less call gchar per line.  Multiple statements for GCHAR seem faster, as I always believed.

However, nesting the loop for the OR was MUCH faster!

Oh, need to find the vdpaddress!  Need to re-read the xb256 docs again!

Way to late for tonight!

Thank you all!

Share on other sites

I tried to make a test for vread  However, I get BAD ARGUMENT in 10

Can you re-write line 10 as an example for me?

My intention if to replace GCHAR for the 10 statements.  So stringing 5 vreads in 1 statement is the goal.  But I do need 10 variables returned.

Thanks for any help!

1 FOR ROW=1 TO 24
2 FOR COL=1 TO 32
20 DISPLAY AT(12,16):A1\$
30 NEXT COL
40 NEXT ROW

Share on other sites
1 hour ago, 1980gamer said:

Try:

Remember that you can read more than one byte into the string:

Share on other sites
52 minutes ago, senior_falcon said:

Try:

Remember that you can read more than one byte into the string:

Thank you!

I know I can read more than 1 value,  and I will try this as a replacement to the IF CLA(7) and CLS(8)....

However, this was an attempt at replacing GCHAR.

If I read the 10 chars in a string, I would still need to parse the string.

A little background,  I have items on a row.  If items are matched in any connecting fashion, they are removed.

Where S is a SPACE char(32)

row 1 "AACCABSSSS"

row 2 "ABSSSSSSSS"

row 3 "SSSSSSSSSS"

row 4 "BCABBSSSSS"

Row 3 Col 1 is replaced with an A

row 1 "AACCABSSSS"

row 2 "ABSSSSSSSS"

row 3 "ASSSSSSSSS"

row 4 "BCABBSSSSS"

Result:  X replaces the Matching A's

row 1 "XXCCABSSSS"

row 2 "XBSSSSSSSS"

row 3 "XSSSSSSSSS"

row 4 "BCABBSSSSS"

After Scan:

The Rows of remaining chars are shifted to the left.  It can be several rows and columns impacted.   It can leave multiple space gaps

row 1 "CCABSSSSSS"

row 2 "BSSSSSSSSS"

row 3 "SSSSSSSSSS"  <--  If the next scan comes around, I do not need to loop through this row!  This is were the And or Or came about.

row 4 "BCABBSSSSS"

So I currently read a row at a time and place the 10 values into an array.

I then loop through the array looing for the first Non-SPACE char and place that into another array and move on to the NEXT non-Space char.

S=Space

This in SSASAABBCS

Output AAABBCSSSS

During this "looping" I am also drawing the row with HCHAR on the fly.

I am also COUNTING each of these remaining chars.  So this remaining row has 3 A's  2 B's and 1 C.

I need to know this as my NEXT available "Piece" has to be a char that is on the play field.  I don't want a D as the Next Piece.

The loop is pretty tight now.

The bottle neck is the GCHAR   Up to 100 of them per playfield scan.

If I can read 5 values in one read, I can cut this to 20 reads!  OMG, that would make this work very well!

Tonight, I will test the VREAD.  I also don't understand the multiple reads per call?

Is it to 5 different variables?  Not talking about reading a string of 5 chars.  But 5 distinct Values.

I currently do not cascade the playfield....

But if this was fast enough I would consider it.  Bejeweled style.  Though I never intended to do that.  It could be an option.

Share on other sites
46 minutes ago, 1980gamer said:

Tonight, I will test the VREAD.  I also don't understand the multiple reads per call?

Is it to 5 different variables?  Not talking about reading a string of 5 chars.  But 5 distinct Values.

will read 16 bytes from screen position 0 (row 1,col 1) to A\$, 16 bytes from screen position 32 (row 2,col 1) to B\$, 16 bytes from screen position 64 (row 3,col 1) to C\$, and so on for D\$ and E\$

Share on other sites
18 minutes ago, senior_falcon said:

will read 16 bytes from screen position 0 (row 1,col 1) to A\$, 16 bytes from screen position 32 (row 2,col 1) to B\$, 16 bytes from screen position 64 (row 3,col 1) to C\$, and so on for D\$ and E\$

This is awesome!  I can't wait to try it!

Share on other sites

WOW all this effort to make XB fit into a faster emulator is exactly the opposite of the language BASIC in first place!

Beginners All-purpose Symbolic Instruction Code

This has become so specialized it is funny.

The entire reason for BASIC and XB was to keep it simple stupid.

Now it is more like a another version of Assembly.

Share on other sites
55 minutes ago, 1980gamer said:

This is awesome!  I can't wait to try it!

RXB has

CALL HGET(ROW,COL,16,A\$) ! The 16 is number of bytes to read from screen into A\$

this does exactly what

does but in a single string variable.

Or you could use RXB

CALL MOVES("V\$",16,0,A\$) ! Same result as CALL HGET but not specifically designed for this use as address is used instead of ROW,COL

If RXB was converted into XB256 it would eliminate a ton of these weird lines needed to created in emulation of XB or Basic.

RXB has been around since 1991 so not like it is not known or new as it is over 20 years old now.

Not to mention updated and debugged!

Edited by RXB
missing text

Share on other sites
1 hour ago, RXB said:

This has become so specialized it is funny.

The entire reason for BASIC and XB was to keep it simple stupid.

Now it is more like a another version of Assembly.

Truth, but at the same time, for better or for worse*, it allows people comfortable with a particular level of programming to write far more capable programs.

* There are plenty of good arguments, on both sides, on whether BASIC should have ever been used as a teaching tool or continue as a viable programming language.  Some people will say that something like Pascal is a better starter language, while others think C or C++, among other alternatives including assembler.  I have to admit that programming in BASIC got me locked into some bad habits, and Pascal was far better for me.  I moved on to 9900 and 6502 (more of the latter, honestly,) and have often lamented that my first TI programming book was not the Editor/Assembler.

• 2
• 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.