| 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.