This is my third resend of this message. Previous (partial?) failures
appear to be due to that "reply" cannot be used and/or MIME attachments
cannot be used. Apologies to anyone seeing this message for the
umteenth time. (And this is the *only* mailing list that I have trouble
with...)
/Kent Karlsson
============================================================
Dave Tweed wrote:
> agree. Surely the best idea is to do something equivalent to the IEEE
> floating point standard which defines certain returned bit patterns to
> mean `over/underflow occurred', etc. The programmer can then handle this either
> in the simple way of calling error, or try to carry on in some suitable
> way. In a similar way there could be a tainted bit pattern for
> overflow, perhaps with testing functions built into the prelude. This
> would be even more useful since tainted bit-patterns in further
> calculations are defined to produce a tainted bit-pattern result, so
> overflow needn't be explicitly tested for each atomic operation.
I would just like to point out that IEEE 754 (a.k.a. IEC 559) does **NOT**
have any "tainted bit pattern"/"special value"/whatever-you-want-to-
call-it for overflow. What IEC 559 DOES specify is:
1. There should be the values positive and negative infinity
(it also specifies which bit patterns to use). These do
**NOT** mean that there was an overflow. They may be exact
values. Infinity arguments do NOT guarantee infinity results.
E.g. 1/+infinity returns +0 (without any underflow or other
'notification').
Haskell: It would thus be an error [sic] to always call 'error' when
an infinity is seen.
2. When rounding to nearest (and only then, other rounding modes
are available) and overflow is *not* trapped, negative overflow
returns negative infinity and positive overflow returns positive
infinity. The default according to IEEE 745 is non-trapping.
The default rounding is round-to-nearest.
3. When overflow is not trapped, an overflow sets a "sticky bit".
To get hold of the "sticky bits" (and maybe save or reset them) in Haskell
may be difficult. They are intended for imperative handling.
4. There are "tainted bit patterns" ((quiet) NaNs) to be returned
when an invalid operation occurred, e.g. 0/0, unless "invalid"
is trapped. NaNs are propagated the way you suggest for almost
all functions (there are suggestions to ignore NaNs in certain
circumstances). B.t.w., 1/(-0), e.g., is not 'invalid', it is
a 'divide-by-zero' and returns -infinity.
All of this is for floating point types and is commonly implemented.
No *similar* standard exists for integer types. What does exist
in term of standards for int(eger) arithmetic on computers,
ISO/IEC 10967-1:1994, Language Independent Arithmetic, part 1
(LIA-1), only specifies what is currently commonly implemented,
and does not attempt to impose "new" requirements on integer
types. Overflow checking is, unfortunately, optional, and there
are no specifications for integer NaNs or integer infinities.
(There is nothing stopping them either, but without hardware
support, their implementation is likely to be comparatively slow.)
That said, I think for "int" in Haskell overflow checking should
be done for all the present "int" functions that "can" overflow
(+, -, *, ^, ...). Special wrapping functions for some of these
(call them, say: +:, -:, *:, ...), should be added (in some library)
for those rare instances where wrapping is what is desired.
Ada, by comparison, have separate types for "overflowing" integers
(like 'Integer' or 'type Foo is range 0..2**16-1;'), where +, -, etc.
overflow when appropriate, and "modulo" integers (like 'type Bar
is mod 2**16;'), where the result of doing +, -, etc. is computed
modulo the "size" of the type.
R.
/kent k
========================
PS
There are no *signed* "wrapping" integer types in Ada, a.f.a.I.k.
By "functions" in point 4, I was referring to certain "standard" functions
that take floating point argument(s) and returns a floating point result.