Decimal Arithmetic Specification, version 1.70
Copyright (c) IBM Corporation, 2009. All rights reserved. ©
 7 Apr 2009 
[previous  contents  next]

This section describes miscellaneous operations on decimal numbers,
including nonnumeric comparisons, sign and other manipulations, and
logical operations.
The logical operations (and, invert, or,
and xor) take logical operands, which are finite
numbers with a sign of 0, an exponent of 0, and a
coefficient whose digits must all be either 0 or 1.^{[1]}
The length of the result will be at most precision digits
(all of which will be either 0 or 1); operands are truncated on the
left or padded with zeros on the left as necessary. The result of a
logical operation is never rounded and the only flag that
might be set is invalidoperation (set if an operand is
not a valid logical operand).
The operations described are:
Notes:

This section uses the simplified notation introduced in the previous
section to illustrate operations.

It is possible to express the results of all these operations as a
decimal number or string, but for some implementations other types may
be available and might be more efficient.^{[2]}
If an implementation does return types which are not decimal numbers
or strings then there must also be conversion operations provided to
convert from those types to decimal values or strings, so a
wholly decimal usage is possible.

As in the previous section, for any examples below, the context
(where relevant) is assumed to have precision set to 9,
rounding set to roundhalfup, and all
trapenablers set to 0.
and is a logical operation which takes two logical operands
(see above).
The result is the digitwise and of the two operands; each
digit of the result is the logical and of the corresponding digits of
the operands, aligned at the leastsignificant digit.
A result digit is 1 if both of the corresponding operand digits
are 1; otherwise it is 0.
Examples:
and(’0’, ’0’) ==> ’0’
and(’0’, ’1’) ==> ’0’
and(’1’, ’0’) ==> ’0’
and(’1’, ’1’) ==> ’1’
and(’1100’, ’1010’) ==> ’1000’
and(’1111’, ’10’) ==> ’10’
canonical takes one operand. The result has the same value
as the operand but always uses a canonical encoding.
The definition of canonical is implementationdefined; if
more than one internal encoding for a given NaN, Infinity, or finite
number is possible then one ‘preferred’ encoding is deemed
canonical. This operation then returns the value using that
preferred encoding.
If all possible operands have just one internal encoding each, then
canonical always returns the operand unchanged (that is, it
has the same effect as copy).
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Example:
canonical(’2.50’) ==> ’2.50’
class takes one operand. The result is an indication of the
class of the operand, where the class is one of ten
possibilities, corresponding to one of the strings "sNaN"
(signaling NaN), "NaN" (quiet NaN), "Infinity"
(negative infinity), "Normal" (negative normal finite
number), "Subnormal" (negative subnormal finite
number), "Zero" (negative zero), "+Zero"
(nonnegative zero), "+Subnormal" (positive subnormal finite
number), "+Normal" (positive normal finite number),
or "+Infinity" (positive infinity).
This operation is quiet; no flags are changed in the
context.
Implementations may indicate the class using a more easily tested
representation than a string (for example, an integer or an
enumeration), but in this case a mechanism for converting that
representation to the corresponding class string listed above must be
provided.
Finite numbers can only be classified as subnormal
if the exponent range is limited (that is, there is a known value for
E_{min}).
In the following examples, E_{min} is assumed to be
–999.
Examples:
class(’Infinity’) ==> "+Infinity"
class(’1E10’) ==> "+Normal"
class(’2.50’) ==> "+Normal"
class(’0.1E999’) ==> "+Subnormal"
class(’0’) ==> "+Zero"
class(’0’) ==> "Zero"
class(’0.1E999’) ==> "Subnormal"
class(’1E10’) ==> "Normal"
class(’2.50’) ==> "Normal"
class(’Infinity’) ==> "Infinity"
class(’NaN’) ==> "NaN"
class(’NaN’) ==> "NaN"
class(’sNaN’) ==> "sNaN"
Note that unlike the special values in the model, the sign of any NaN
is ignored in the classification, as required by IEEE 754.
comparetotal takes two operands and compares them using
their abstract representation rather than their numerical value.
A total ordering is defined for all possible abstract
representations, as described below. If the first operand is lower
in the total order than the second operand then the result
is ’1’, if the operands have the same abstract representation
then the result is ’0’, and if the first operand is higher in
the total order than the second operand then the result is ’1’.
The total ordering is defined as follows.

The following items describe the ordering for representations whose
sign is 0. If the sign is 1, the order is reversed.
A representation with a sign of 1 is always lower in the
ordering than one with a sign of 0.

Numbers (representations which are not NaNs) are ordered such that a
larger numerical value is higher in the ordering. If two
representations have the same numerical value then the exponent is
taken into account; larger (more positive) exponents are higher in
the ordering.

All quiet NaNs are higher in the total ordering than all signaling NaNs.

Quiet NaNs and signaling NaNs are ordered according to their
payload; a larger payload is higher in the ordering.
For example, the following values are ordered from lowest to
highest: NaN sNaN Infinity 127 1.00 1 0.000 0 0 1.2300
1.23 1E+9 Infinity sNaN NaN NaN456.
Examples:
comparetotal(’12.73’, ’127.9’) ==> ’1’
comparetotal(’127’, ’12’) ==> ’1’
comparetotal(’12.30’, ’12.3’) ==> ’1’
comparetotal(’12.30’, ’12.30’) ==> ’0’
comparetotal(’12.3’, ’12.300’) ==> ’1’
comparetotal(’12.3’, ’NaN’) ==> ’1’
Notes:

The result of comparetotal is always finite, exact, and unrounded.

The compare operation can be used
when a numerical comparison of values is required.
comparetotalmagnitude takes two operands and compares them
using their abstract representation rather than their numerical value
and with their sign ignored and assumed to be 0. The result
is identical to that obtained by using comparetotal on two
operands which are the copyabs copies of the operands to
comparetotalmagnitude; that is:
comparetotalmagnitude(x, y)
is given by
comparetotal(copyabs(x), copyabs(y))
copy takes one operand. The result is a copy of the
operand. This operation is unaffected by context and is quiet –
no flags are changed in the context.
Examples:
copy(’2.1’) ==> ’2.1’
copy(’1.00’) ==> ’1.00’
copyabs takes one operand. The result is a copy of the
operand with the sign set to 0.
Unlike the abs operation, this operation is
unaffected by context and is quiet – no flags are
changed in the context.
Examples:
copyabs(’2.1’) ==> ’2.1’
copyabs(’100’) ==> ’100’
copynegate takes one operand. The result is a copy of the
operand with the sign inverted (a sign of 0 becomes
1 and vice versa).
Unlike the minus operation, this operation is
unaffected by context and is quiet – no flags are
changed in the context.
Examples:
copynegate(’101.5’) ==> ’101.5’
copynegate(’101.5’) ==> ’101.5’
copysign takes two operands. The result is a copy of the
first operand with the sign set to be the same as the
sign of the second operand.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
copysign( ’1.50’, ’7.33’) ==> ’1.50’
copysign(’1.50’, ’7.33’) ==> ’1.50’
copysign( ’1.50’, ’7.33’) ==> ’1.50’
copysign(’1.50’, ’7.33’) ==> ’1.50’
invert is a logical operation which takes one logical operand
(see above).
The result is the digitwise inversion of the
operand; each digit of the result is the inverse of the
corresponding digit of the operand.
A result digit is 1 if the corresponding operand digit
is 0; otherwise it is 0.
Examples:
invert(’0’) ==> ’111111111’
invert(’1’) ==> ’111111110’
invert(’111111111’) ==> ’0’
invert(’101010101’) ==> ’10101010’
iscanonical takes one operand. The result is 1 if
the operand is canonical; otherwise it is 0.
The definition of canonical is implementationdefined; if
more than one internal encoding for a given NaN, Infinity, or finite
number is possible then one ‘preferred’ encoding is deemed
canonical. This operation then tests whether the internal encoding is
that preferred encoding.
If all possible operands have just one internal encoding each, then
iscanonical always returns 1.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Example:
iscanonical(’2.50’) ==> ’1’
isfinite takes one operand. The result is 1 if the operand
is neither infinite nor a NaN (that is, it is a normal number, a
subnormal number, or a zero); otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
isfinite(’2.50’) ==> ’1’
isfinite(’0.3’) ==> ’1’
isfinite(’0’) ==> ’1’
isfinite(’Inf’) ==> ’0’
isfinite(’NaN’) ==> ’0’
isinfinite takes one operand. The result is 1 if
the operand is an Infinity; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
isinfinite(’2.50’) ==> ’0’
isinfinite(’Inf’) ==> ’1’
isinfinite(’NaN’) ==> ’0’
isNaN takes one operand. The result is 1 if
the operand is a NaN (quiet or signaling); otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
isNaN(’2.50’) ==> ’0’
isNaN(’NaN’) ==> ’1’
isNaN(’sNaN’) ==> ’1’
isnormal takes one operand. The result is 1 if
the operand is a positive or negative normal
number; otherwise it is 0.
This operation is quiet; no flags are changed in the
context.
Finite numbers can only be classified as normal or
subnormal if the exponent range is limited (that is, there
is a known value for E_{min}); if E_{min} is unknown,
1 is returned. In the following examples, E_{min} is assumed
to be –999.
Examples:
isnormal(’2.50’) ==> ’1’
isnormal(’0.1E999’) ==> ’0’
isnormal(’0.00’) ==> ’0’
isnormal(’Inf’) ==> ’0’
isnormal(’NaN’) ==> ’0’
isqNaN takes one operand. The result is 1 if
the operand is a quiet NaN; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
isqNaN(’2.50’) ==> ’0’
isqNaN(’NaN’) ==> ’1’
isqNaN(’sNaN’) ==> ’0’
issigned takes one operand. The result is 1 if
the sign of the operand is 1; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
issigned(’2.50’) ==> ’0’
issigned(’12’) ==> ’1’
issigned(’0’) ==> ’1’
issNaN takes one operand. The result is 1 if
the operand is a signaling NaN; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
issNaN(’2.50’) ==> ’0’
issNaN(’NaN’) ==> ’0’
issNaN(’sNaN’) ==> ’1’
issubnormal takes one operand. The result is 1 if
the operand is a positive or negative subnormal
number; otherwise it is 0.
This operation is quiet; no flags are changed in the
context.
Finite numbers can only be classified as normal or
subnormal if the exponent range is limited (that is, there
is a known value for E_{min}); if E_{min} is unknown,
0 is returned. In the following examples, E_{min} is assumed
to be –999.
Examples:
issubnormal(’2.50’) ==> ’0’
issubnormal(’0.1E999’) ==> ’1’
issubnormal(’0.00’) ==> ’0’
issubnormal(’Inf’) ==> ’0’
issubnormal(’NaN’) ==> ’0’
iszero takes one operand. The result is 1 if the operand is a
zero; otherwise it is 0.
This operation is unaffected by context and is quiet – no
flags are changed in the context.
Examples:
iszero(’0’) ==> ’1’
iszero(’2.50’) ==> ’0’
iszero(’0E+2’) ==> ’1’
logb takes one operand. If the operand is a NaN then the
general arithmetic rules apply. If the operand is infinite
then +Infinity is returned. If the operand is a zero, then
–Infinity is returned and the Division by zero
exceptional condition is raised.
Otherwise, the result is the integer which is the exponent of the
magnitude of the most significant digit of the operand (as though the
operand were truncated to a single digit while maintaining the value
of that digit and without limiting the resulting exponent).
All results are exact unless an integer result does not fit in the
available precision.
Examples:
logb(’250’) ==> ’2’
logb(’2.50’) ==> ’0’
logb(’0.03’) ==> ’2’
logb(’0’) ==> ’Infinity’
Note: The scaleb operation can be
used to change the exponent of a number.
or is a logical operation which takes two logical operands
(see above).
The result is the digitwise inclusive or of the two
operands; each digit of the result is the logical or of the
corresponding digits of the operands, aligned at the
leastsignificant digit.
A result digit is 1 if either or both of the corresponding operand digits
is 1; otherwise it is 0.
Examples:
or(’0’, ’0’) ==> ’0’
or(’0’, ’1’) ==> ’1’
or(’1’, ’0’) ==> ’1’
or(’1’, ’1’) ==> ’1’
or(’1100’, ’1010’) ==> ’1110’
or(’1110’, ’10’) ==> ’1110’
radix takes no operands. The result is the radix (base) in
which arithmetic is effected; for this specification the result will
have the value 10.^{[3]}
Example:
radix() ==> ’10’
rotate takes two operands. The second operand must be an
integer (with an exponent of 0) in the range
–precision through precision. If the first
operand is a NaN then the general arithmetic rules apply, and if it
is infinite then the result is the Infinity unchanged.
Otherwise (the first operand is finite) the result has the same
sign and exponent as the first operand, and a
coefficient which is a rotated copy of the digits in the
coefficient of the first operand.
The number of places of rotation is taken from the absolute value of
the second operand, with the rotation being to the left if the second
operand is positive or to the right otherwise.
If the coefficient of the first operand has fewer than
precision digits, it is treated as though it were padded on
the left with zeros to length precision before the rotation.
Similarly, if the coefficient of the first operand has more than
precision digits, it is truncated on the left before use.
The only flag that might be set is
invalidoperation (set if the first operand is an sNaN or
the second is not valid).
Examples:
rotate(’34’, ’8’) ==> ’400000003’
rotate(’12’, ’9’) ==> ’12’
rotate(’123456789’, ’2’) ==> ’891234567’
rotate(’123456789’, ’0’) ==> ’123456789’
rotate(’123456789’, ’+2’) ==> ’345678912’
The shift operation can be used to shift rather
than rotate a coefficient.
samequantum takes two operands, and returns 1 if the two
operands have the same exponent or 0 otherwise.
The result is never affected by either the sign or the coefficient of
either operand.
If either operand is a special value, 1 is returned only if
both operands are NaNs or both are infinities.
samequantum does not change any flags in the context.
Implementations which support the concept of a boolean type may
return true for 1 and false for 0.
Examples:
samequantum(’2.17’, ’0.001’) ==> ’0’
samequantum(’2.17’, ’0.01’) ==> ’1’
samequantum(’2.17’, ’0.1’) ==> ’0’
samequantum(’2.17’, ’1’) ==> ’0’
samequantum(’Inf’, ’Inf’) ==> ’1’
samequantum(’NaN’, ’NaN’) ==> ’1’
scaleb takes two operands. If either operand is a NaN then
the general arithmetic rules apply. Otherwise, the second operand
must be a finite integer with an exponent of zero^{[4]}
and in the range ±2 × (E_{max} +
precision) inclusive, where E_{max} is the
largest value that can be returned by the logb
operation at the same precision setting.^{[5]}
(If is is not, the Invalid Operation condition is raised
and the result is NaN.)
If the first operand is infinite then that Infinity is returned,
otherwise the result is the first operand modified by adding the
value of the second operand to its exponent. The result may
Overflow or Underflow.
Examples:
scaleb(’7.50’, ’2’) ==> ’0.0750’
scaleb(’7.50’, ’0’) ==> ’7.50’
scaleb(’7.50’, ’3’) ==> ’7.50E+3’
shift takes two operands. The second operand must be an
integer (with an exponent of 0) in the range
–precision through precision. If the first
operand is a NaN then the general arithmetic rules apply, and if it
is infinite then the result is the Infinity unchanged.
Otherwise (the first operand is finite) the result has the same
sign and exponent as the first operand, and a
coefficient which is a shifted copy of the digits in the
coefficient of the first operand. The number of places to shift is
taken from the absolute value of the second operand, with the
shift being to the left if the second operand is positive or to the
right otherwise.
Digits shifted into the coefficient are zeros.
The only flag that might be set is
invalidoperation (set if the first operand is an sNaN or
the second is not valid).
Examples:
shift(’34’, ’8’) ==> ’400000000’
shift(’12’, ’9’) ==> ’0’
shift(’123456789’, ’2’) ==> ’1234567’
shift(’123456789’, ’0’) ==> ’123456789’
shift(’123456789’, ’+2’) ==> ’345678900’
The rotate operation can be used to rotate rather
than shift a coefficient.
xor is a logical operation which takes two logical operands
(see above).
The result is the digitwise exclusive or of the two
operands; each digit of the result is the logical exclusiveor of the
corresponding digits of the operands, aligned at the
leastsignificant digit.
A result digit is 1 if one of the corresponding operand digits
is 1 and the other is 0; otherwise it is 0.
Examples:
xor(’0’, ’0’) ==> ’0’
xor(’0’, ’1’) ==> ’1’
xor(’1’, ’0’) ==> ’1’
xor(’1’, ’1’) ==> ’0’
xor(’1100’, ’1010’) ==> ’110’
xor(’1111’, ’10’) ==> ’1101’
Footnotes:
[1] 
This digitwise representation of bits in a decimal
representation has been used since the 1950s; see, for example,
Binary and truthfunction operations on a decimal computer with an
extract command, William H. Kautz, Communications of the ACM, Vol. 1
#5, pp1213, ACM Press, May 1958.

[2] 
For example, the operations which test whether a value is in a
particular class might return a boolean.

[3] 
This might be 1E+1 in the extraordinary case of precision=1.

[4] 
Strictly speaking this is more restrictive that IEEE 754, which would
allow 1E+1 for the second operand; however, it is in the spirit of IEEE
754 also permitting that the second operand be specifiable as an
integer.

[5] 
This E_{max} is the same as that described in IEEE 754.

[previous  contents  next]