6.1.0120 + plus CORE

( n1 | u1 n2 | u2 -- n3 | u3 )

Add n2 | u2 to n1 | u1, giving the sum n3 | u3.

See:

Testing:

T{        0  5 + ->          5 }T
T{        5  0 + ->          5 }T
T{        0 -5 + ->         -5 }T
T{       -5  0 + ->         -5 }T
T{        1  2 + ->          3 }T
T{        1 -2 + ->         -1 }T
T{       -1  2 + ->          1 }T
T{       -1 -2 + ->         -3 }T
T{       -1  1 + ->          0 }T
T{ MID-UINT  1 + -> MID-UINT+1 }T

ContributeContributions

mcondronavatar of mcondron [81] Overflow/underflowRequest for clarification2019-05-21 23:30:20

After realizing that +LOOP can overflow or underflow, it occurred to me...is that state something that ALL the arithmetic operators should detect? Should it be 1) ignored, 2) a flag that a program can test, 3) an error/exception?? Maybe this issue is addressed somewhere in sections 1-4 of the Standard?

AntonErtlavatar of AntonErtl

Section 3.2.2.2 specifies the behaviour on overflow or underflow. The next standard will refine this; see the proposal 2s-Complement Wrap-Around Integers.

Reply New Version

ruvavatar of ruv [341] Usage of the `n|u` data typeRequest for clarification2024-06-01 15:39:34

For the word + the standard specifies the stack diagram ( n1|u1 n2|u2 -- n3|u3 ).

Is this diagram equivalent to ( n1 n2 -- n3 | u1 u2 -- u3 )?

In other words, is + formally defined for the input types ( n1 u1 ) and ( u1 n1 ), or not?

BerndPaysanavatar of BerndPaysan

See A.3.2.1 how deeply the assumptions of two's complement are rooted into Forth. Therefore, the operations + and - work interchangeable for unsigned and signed, and even mixed. If your system is not two's complement, unsigned is restricted to +n.

IIRC, not using two's complement is no longer an option.

AntonErtlavatar of AntonErtl

For the moment, let's take the Forth-94/2012 position that the result on integer overflow (i.e. where a mathematical integer addition produces a result outside the target range) is implementation-defined. Let's say I want to avoid that; even then I can construct cases for various combinations of n and u; to make things more concrete, let's assume that the range of n is -32768..32767 and for u it is 0..65535:

1 1 + \ gives 2; +n1 +n2 -- +n (where +n is both u and n)
33000 -1 + \ gives 32999; u1 n2 -- u
33000 -1000 + \ gives 32000; u1 n2 -- +n
1 -2 + \ gives -1; +n1 n2 -- n
-1 -1 + \ gives -2; n1 n2 -- n
20000 20000 + \ gives 40000; +n1 +n2 -- u

For the stack diagrams with +n, you could produce either one with n or with u instead of the +n, which means that in the first case you can have all 8 combinations.

These are all standard Forth programs where the mathematical integer result is in the target range, so no, the diagram is not limited to be equivalent to ( n1 n2 -- n3 | u1 u2 -- u3 ). My take is that n|u means a range of -32768..65535 for the example ranges above, just as +n (i.e., n&u) means 0..32767.

In 2015 the committee accepted 2s-Complement Wrap-Around Integers, which defines what happens in those cases where the result does not fit in the target range; with that it is up to the programmer in all cases how to interpret the arguments and the results of +; e.g., the -1 -1 + case for the ranges given above can also be interpreted as:

65535 65535 + \ gives 65534; u1 u2 -- u

ruvavatar of ruv

One idea, why the operations + and - should be defined when one argument in u, and the other argument in n is that these operations on any integer arguments should be equal to a series of operations on 0 and 1.

Any number in u that is outside of the n range can be represented as the sum of several numbers in n.
For example, max-uint is the sum of numbers (max-int, max-int, 1), (supposing two's complement).

Thus, an operation on numbers in n and u should be equivalent to several operations in n only, resulting in n (taking into account the overflow rule) (1).

Any number in n that is outside of the u range can be represented as the subtraction of two numbers in u.
For example, min-int is the subtraction of unsigned( max-int + 1) from 0 (assuming two's complement).

Thus, an operation on numbers in n and u should be equivalent to several operations in u only, resulting in u (taking into account the overflow rule) (2).

I don't sure whether (1) and (2) both are always true for one's complement and sign-magnitude representations, but they are true for two's complement representation.

It means, that the result of + and - , when one argument in n, and the other in u, always belongs to both u and n data types, and in some cases it also belongs to the +n data type.

Also, if one (and not the other) of the arguments is in addr, the result (in the general case) is in u and in addr , but not in n.


It seems, (1) and (2) are also true for * ( n1|u1 n2|u2 -- n3|u3 ) .

Reply New Version