## Z? and N? - test for integer and natural numbers

Post here to share useful tips and tricks, to ask questions about using your DM42 or to report software-related problems
whuyse
Posts: 158
Joined: Thu Dec 21, 2017 1:23 pm

### Z? and N? - test for integer and natural numbers

If you want to write your own functions, and make them behave like built-in ones, these tests may come in handy:
they will test whether the X register contains an integer (Z?) or a non-negative integer (N?). (Yes I know that is technically N0? - but it's easier to subsequently test for 0 than the other way round).

Code: Select all

00 { 53-Byte Prgm }
01▸LBL "N?"
02 XEQ 10 @ integer?
03 STR? @ aff
04 RTNNO
05 X<0?
06 GTO 05
07 RTNYES
08▸LBL 10
09▸LBL "Z?"
10 REAL?
11 GTO 00
12 STR?
13 1
14 REAL?
15 X=0? @ aff
16 4
17 RTNNO
18▸LBL 00
19 IP
20 X=? ST L
21 RTNYES
22▸LBL 05
23 5
24 RTNNO
25 END
Use it as follows:

test for integers:

Code: Select all

00 XEQ "Z?"
00 STR? @ always false filler
00 RTNERR IND ST X
test for natural numbers (strictly positive):

Code: Select all

00 XEQ "N?"
00 X<0? @ aff
00 RTNERR IND ST X
00 X=0?
00 RTNERR 5
That way, the tests will raise 'Alpha Data is invalid' if X contains a string, 'Invalid Type' if X does not contain a Real, and 'Invalid Data' if it is not a (positive) integer, in line with the error handling of the 42S.

Now, there is a tiny problem with these routines: I would like them to not disturb the stack when no error occurs, and to have the error number in X when an error does occur. I can't use FUNC 00, because that will always restore the stack. As it is, L is destroyed when no error occurs. I can solve this with a local variable, but that's clumsy. Suggestions welcome.
(and yes, to make it more elegant, the tests should be "^N?" and "^Z?", then the aff's would not be needed).

Cheers, Werner
42S #3249S01123
DM42 #00345
DM41X #01215
whuyse
Posts: 158
Joined: Thu Dec 21, 2017 1:23 pm

### Re: Z? and N? - test for integer and natural numbers

UPDATE 20210914: better "Z?"
Decided to split it into tests that work exactly like the built-in ones (REAL, MAT? etc.), and a test meant for argument checking:
- integer test, working like the built-in ones:

Code: Select all

00 { 34-Byte Prgm }
01▸LBL "N?"
02 XEQ 00
03 X<0? @ or X<=0?
04 RTNNO
05 RTNYES
06▸LBL 00
07▸LBL "Z?"
08 FUNC 00
09 REAL?
10 FP
11 REAL?
12 X#0?
13 RTNNO
14 RTNYES
15 END
- non-integer test-and-err

Code: Select all

00 { 34-Byte Prgm }
01▸LBL "!Z?"
02 REAL?
03 GTO 00
04 STR?
05 1
06 REAL?
07 X=0? @ aff
08 4
09 RTNYES
10▸LBL 00
11 IP
12 X=? ST L
13 RTNNO
14 5
15 RTNYES
16 END
So now the argument check for a natural number (excluding zero), would be:

Code: Select all

00 XEQ "!Z?"
00 RTNERR IND ST X
00 X<=0? @ additional test for natural number
00 RTNERR 5
Cheers, Werner
42S #3249S01123
DM42 #00345
DM41X #01215