Re: SRFI-47 -- types and declarations. Aubrey Jaffer 29 Nov 2003 22:17 UTC

 | Date: Thu, 20 Nov 2003 21:15:43 -0800 (PST)
 | From: bear <xxxxxx@sonic.net>
 |
 | On Thu, 20 Nov 2003, Aubrey Jaffer wrote:
 |
 | > | Date: Thu, 20 Nov 2003 11:58:30 -0800 (PST)
 | > | From: bear <xxxxxx@sonic.net>
 | >
 | >Uniform arrays are just that -- uniform!  If you want to mix exact and
 | >inexact numbers in an array, just make its type be vector.
 |
 | Okay.  That's a decision.  Good.  So let's make it explicit.  I have
 | three specific suggestions for making that clear in your SRFI.
 |
 | First, I'd suggest that if you have an inexact number, you can store
 | it in a uniform array of inexact numbers, and retrieve an inexact
 | number from the location where you stored it.  But since there is a
 | chance that the number you retrieve won't be equal? to the number you
 | stored, this document needs to say so.  This doesn't have to be an
 | error -- in fact I'm pretty sure it shouldn't be -- but you need to
 | say so explicitly.
 |
 | Second, I'd suggest that if you have an exact number, and an
 | exact-number typed array, then any operation involving the array that
 | would result in a roundoff, wraparound, or truncation of that number
 | or the array contents ought to be an error.  You shouldn't be able to
 | store an exact number and then retrieve from that location a number
 | that's not equal?  to the one you stored, nor add two exact numbers
 | from an array and get an answer that's not the answer you'd get if you
 | added two exact numbers from a vector.  In specifying representation
 | you are not giving implementors any "wiggle room" to switch to
 | different representation in order to give exact results where they are
 | otherwise required, so you need to be explicit that operations which
 | don't *allow* exact results within the specified representation type
 | (overflow, wraparounds, roundoffs, etc) are errors.
 |
 | Finally, I'd suggest that if you have an inexact number, and you try
 | to store it in an array of an exact numeric type, or vice versa, that
 | should be an error.  If people want automatic type conversions on
 | store, they're easy to implement on top of the arrays you've
 | specified, any problems they introduce needn't be your fault and
 | needn't be behavior users can't get around.

Thanks for the suggestions.  Does this specify them:

 * All the elements of arrays of type au8, au16, au32, au64, as8,
   as16, as32, or as64 are exact.

 * All the elements of arrays of type ar32, ar64, ac32, or ac64 are
   inexact.

 * The value retrieved from an exact array element will equal (=) the
   value stored in that element.

 * Assigning a non-integer to array-type au8, au16, au32, au64, as8,
   as16, as32, or as64 is an error.

 * Assigning number larger than can be represented in array-type au8,
   au16, au32, au64, as8, as16, as32, or as64 is an error.

 * Assigning a negative number to array-type au8, au16, au32, or au64
   is an error.

 * Assigning an inexact number to array-type au8, au16, au32, au64,
   as8, as16, as32, or as64 is an error.

 * When assigning an exact number to array-type ar32, ar64, ac32, or
   ac64, the procedure may report a violation of an implementation
   restriction.

 * Assigning a non-real number (eg. real? returns #f) to an ar64 or
   ar32 array is an error.

 * An implementation may reduce the precision of a number assigned to
   an inexact array.

 |
 | >Two's-complement integers are in widespread use and well understood.
 | >The type-checking enforced by uniform-arrays has proven to be a
 | >benefit to debugging large-data-set numerical algorithms.
 |
 | Hmm, that brings up another question -- at the point where it becomes
 | useful for the programmer to *know* individual bits of representation
 | such as whether the number is represented as twos-complement, you're
 | dealing with a hardware interface -- frequently, that means type
 | punning based on bit patterns being interpretable as varying numbers
 | of different types.

There is no hardware exposed.  Inexacts are stored in whatever form
the implementation uses.  Exacts are stored twos-complement.  The
semantics of twos-complement representation are not
hardware-dependent.

 | One thing I haven't seen addressed with make-shared-array is whether
 | you're going to allow type punning.  IOW, can two arrays of different
 | types share storage?  Can I have, say, an array of au64's that shares
 | space with an array of 8 times as many au8's and with an array of 64
 | times as many at1, and manipulate the contents of the au64 array by
 | frobbing with its individual bits-n-bytes through the at1 and at8
 | interfaces?

Make-shared-array returns an array with the same type as its first
argument.

 | That could be very useful for implementing hardware interfaces and
 | FFI's, but I don't think the operation is sufficiently described and I
 | can't tell for sure here whether it's a functionality you intended to
 | provide.

That would expose endianness and data formats.  SRFI-47 does not do
that.

 | > Assigning a non-integer to array-type u8, u16, u32, u64, s8, s16,
 | > s32, or s64 is an error.
 |
 | > Assigning a negative number to array-type u8, u16, u32, or u64 is an
 | > error.
 |
 | > Assigning a non-real number to a r64 or r32 array is an error.
 |
 | By non-real, you mean to say, complex or imaginary?  Or do you mean to
 | say, integral or rational?

No.  (real? <number>) ==> #f

 | According to R5RS, some real numbers are integers, and some are not
 | integers.  Some real numbers are exact and some are inexact.  So
 | for compatibility with the rest of the language, could you please
 | describe these specifically as exact and inexact, rather than just
 | giving a hardware type?  The problem is that in some
 | implementations you have such things as exact floats or inexact
 | rationals or integers, and people will want to store 'em in your
 | typed arrays.

I believe the new restrictions language above does this:

 * All the elements of arrays of type au8, au16, au32, au64, as8,
   as16, as32, or as64 are exact.

 * All the elements of arrays of type ar32, ar64, ac32, or ac64 are
   inexact.

 | > Uniform arrays don't favor interpreters over compilers, they can just
 | > make the performance difference negligible.
 |
 | I think the same may be said of optional declarations.  At least I'm
 | not sure why it wouldn't be so.

Declarations enforced by an interpreter add additional overhead; they
go slower.

Thanks for the suggestions.