On 10/26/05, Fernando Perez <Fernando.Perez@colorado.edu> wrote:
Charles R Harris wrote:
> Yes, I agree with this. The only problem I see is if someone wants to save
> space when taking the sqrt of an integral array. There are at least three
> possiblilities:
>
> 1. cast the result to a float
> 2. cast the argument to a float
> 3. use a special sqrtf function
>
> The first two options use more temporary space, take more time, and look
> uglier (IMHO). On the other hand, the needed commands are already
> implemented. The last option is clear and concise, but needs a new ufunc.
Well, while I agree with the recently posted design guideline from Guido of
using different functions for different purposes rather than flags, this may
be a case where a flag would be a good choice. Especially because we already
have a conceptual precedent for the accumulators of specifying the return type
via a flag: a.sum(rtype=int).
Since the 'mental slot' is already in scipy's users heads for saying 'modify
the default output of this function to accumulate/store data in a different
type', I think it would be reasonable to offer
sqrt(a,rtype=float)
as an optional way to prevent automatic upcasting in cases where users want
that kind of very fine level control. This can be done uniformly across the
library, rather than growing a zillion foof/food/foo* post-fixed forms of
every ufunc in the library.
We would then have:
- A basic principle for how upcasting is done, driven by the idea of
'protecting precision even at the cost of storage'. This principle forces
sqrt(2) to be a double and anint_array.sum() to accumulate to a wider type.
- A uniform mechanism for overriding upcasting across the library, via the
rtype flag. If most/all of scipy implements this, it seems like a small price
of learning to pay for a reasonable balance between convenience, correctness
and efficiency.
Yes, I think that would work well. Most of us, most of the time, could
then rely on the unmodified functions to do the right thing. On the
rare occasion that space really mattered, there would be a fallback
position. It would also be easy to use a global type string mytype =
'Float32' and call everything critical with rtype=mytype. That would
make it easy to change the behaviour of fairly large programs.
Chuck