15

Sometimes when coding in ZX Spectrum Basic I need to evaluate logical expressions that are formed by two operands and a logical xor like this:

IF (left operand) xor (right operand) THEN

Since ZX Basic does only know NOT, OR and AND I have to resort to some sort of fancy calculation which includes multiple uses of left/right operands. This is awkward since it consumes time and memory, both sparse if you're working on an 8-bit machine. I wonder if there's a neat trick to mimic the xor operator.

To test the outcome I provide a small code sample:

 5 DEF FN x(a,b)=(a ??? b) : REM the xor formula, change here
10 FOR a=-1 TO 1 : REM left operand
20 FOR b=-1 TO 1 : REM right operand
30 LET r=FN x(a,b) : REM compute xor
40 PRINT "a:";a;" b:";b;" => ";r
50 NEXT b
60 NEXT a

Can you help me find a performant solution? So far I tried DEF FN x(a,b)=(a AND NOT b) OR (b AND NOT a) but it's somewhat clumsy.

Edit:

If you want to test your idea I suggest the BasinC v1.69 ZX emulator (Windows only).

As @Jeff pointed out most Basics, such as ZX one's, do consider zero values as false and non-zero ones as true.

I have adapted the sample to test with a variety of non-zero values.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
yacc
  • 2,915
  • 4
  • 19
  • 33
  • 1
    Logically, NOT(A AND B) AND (A OR B) ? – Worse_Username Sep 07 '17 at 13:30
  • @Worse_Username that would work, but it doesn't speed up the code I have so far. ^^ – yacc Sep 07 '17 at 13:36
  • I like the `<>` answer below, but another purely logical possibility if ZX BASIC supports function-style IF-ELSE would be IF A THEN (NOT B) ELSE (B) - in C, you could write it `a?!b:b` – Jeff Zeitlin Sep 07 '17 at 14:22
  • @JeffZeitlin I like the `<>` answer too, but it doesn't solve all cases. In fact I had statements like `50 IF a THEN GOTO 100` `60 IF NOT b...` `100 IF b THEN ...` mimicking the ternary operator but all the gotos make this a maintenance nightmare. – yacc Sep 07 '17 at 14:37
  • I'm still looking for neat solutions, feel free to answer. Any idea is welcome. – yacc Sep 23 '17 at 03:16
  • Seems my one (and more so its update) perform best? :-) – Ed. Sep 24 '17 at 19:37
  • Don't forget the existence of https://retrocomputing.stackexchange.com for a lot of similar wonderful questions. – peterh Dec 08 '17 at 15:45

4 Answers4

11

The logical xor is semantically equivalent to not equal.

IF (left operand) <> (right operand) THEN

should work.

Edit: In the case of integer operands you can use

IF ((left operand) <> 0) <> ((right operand) <> 0) THEN
clemens
  • 16,716
  • 11
  • 50
  • 65
5
DEF FN x(a,b)=((NOT a) <> (NOT b))

Using NOT as coercion to a boolean value.

EDIT Previously had each side with NOT NOT which is unnecessary for establishing difference between the two, as one will still coerce!

EDIT 2 Added parens to sort out precedence issue.

Ed.
  • 1,992
  • 1
  • 13
  • 30
  • I just realised it only needs one `NOT` on each side. Edited accordingly. – Ed. Sep 24 '17 at 17:30
  • With your update I now get a 0 with `a=-1` and `b=0`, because `NOT` has lower precedence. Did you even test any of your proposals? – yacc Sep 25 '17 at 00:53
  • Sorry, I'm afraid I couldn't get the environment to install. Added parens, should sort. – Ed. Sep 25 '17 at 01:29
  • 1
    There are still some parens that could be squeezed, but it looks acceptable now. – yacc Sep 25 '17 at 02:04
  • 2
    Sorry I've been afk for a while. The shortest version I could derive from your answer so far is: `DEF FN x(a,b)=(NOT a) <> NOT b`. – yacc Oct 16 '17 at 01:23
5

Considering very interesting and fun this question and the answers in here, I would like to share the results of some performance tests (performed on an emulator): enter image description here

elapsed times are in seconds , less is best. the x1 test is only to see if the expression meets the requirements and includes the print out of results, the x256 repeat the same test 256times without printing any output; the without FN tests are the same but without factoring the expression in an FN statement.

I share also the code and test suite on github: https://github.com/rondinif/XOR-in-ZX-Spectrum-basic for the benefit of all retro computing fanatics (..like me) and share our opinions

Franco Rondini
  • 10,841
  • 8
  • 51
  • 77
  • I did my best but at present I have carried out a few checks and may inadvertently commit involuntary inaccuracies; you can possibly open issues on github or fork-it/pull-request if you see possible improvements. – Franco Rondini Sep 24 '17 at 10:35
  • Franco, if you have the infrastructure set up already could you try my answer out for performance? – Ed. Sep 24 '17 at 17:33
  • 1
    @Ed. [(NOT a <> NOT b)](https://github.com/rondinif/XOR-in-ZX-Spectrum-basic/blob/master/src/main/basic/xor07b.bas) performs quite well, I updated answer and git repo. – Franco Rondini Sep 24 '17 at 18:55
  • I read that as, if we eliminate your number 5 (since it only works with 1 and 0, not all valid boolean values in BASIC), my two (numbers 3 and 7) are the fastest? – Ed. Sep 24 '17 at 19:36
  • Further update of my answer - previous two should probably be zapped from comparison as apparently they are incorrect too! – Ed. Sep 25 '17 at 01:31
  • 1
    The shortest version I could derive from Eds answer so far is: `DEF FN x(a,b)=(NOT a) <> NOT b`. Would be great to have it in the table. @FrancoRondini – yacc Oct 16 '17 at 01:24
2

Keep in mind, value are integer: I think mathematical operation could be fun : (A-B)*(A-B) should work It should be less time consuming based on simple operation.

Or with ABS : ABS (A-B)

  • 2
    This won't work because A and B are not just 0 or 1. In Basic an operand is True if <> 0. For instance if A is 2 and B is -1, you still need A xor B evaluate to 0 (False). – yacc Sep 22 '17 at 02:18
  • 2
    It works with the sample provided :) It depends on your way to manage boolean. It's basically easy to have it on boolean form by using A AND A or A OR A. – Christophe Durieux Sep 22 '17 at 16:23
  • Yes, the question is about that. Find a performant way to get to boolean form 0/1 and do the xor. Maybe with SGN, idk? – yacc Sep 24 '17 at 11:56