On Apr 13, 2016 9:08 AM, "Robert Kern" <robert.k...@gmail.com> wrote: > > On Wed, Apr 13, 2016 at 3:17 AM, Antony Lee <antony....@berkeley.edu> wrote: > > > > This kind of issue (see also https://github.com/numpy/numpy/issues/3511) > > has become more annoying now that indexing requires integers (indexing with > > a float raises a VisibleDeprecationWarning). The argument "dividing an > > uint by an int may give a result that does not fit in an uint nor in an > > int" does not sound very convincing to me, > > It shouldn't because that's not the rule that numpy follows. The range of the > result is never considered. Both *inputs* are cast to the same type that can > represent the full range of either input type (for that matter, the actual > *values* of the inputs are also never considered). In the case of uint64 and > int64, there is no really good common type (the integer hierarchy has to top > out somewhere), but float64 merely loses resolution rather than cutting off > half of the range of uint64.
Let me play devil's advocate for a moment, since I've just been playing out this debate in my own mind and you've done a good job of articulating the case for that side :-). The counter argument is: it doesn't really matter about having a common type or not; what matters is whether the operation can be defined sensibly. For uint64 <op> int64, this is actually not a problem: we provide 2s complement signed ints, so uint64 and int64 are both integers-mod-2**64, just choosing different representatives for the equivalence classes in the upper half of the ring. In particular, the uint64 and int64 ranges are isomorphic to each other. or with less jargon: casting between uint64 and int64 commutes with all arithmetic operations, so you actually get the same result performing the operation in infinite precision and then casting to uint64 or int64, or casting both operations to uint64 or int64 and then casting the result to uint64 or int64. Basically the operations are totally well-defined even if we stick within integers, and the casting is just another form of integer wraparound; we're already happy to tolerate wraparound for int64 <op> int64 or uint64 <op> uint64, so it's not entirely clear why we go all the way to float to avoid it for uint64 <op> int64. [On second thought... I'm actually not 100% sure that the all-operations-commute-with-casting thing is true in the case of //'s rounding behavior. I would have to squint a lot to figure that out. I guess comparison operations are another exception -- a < b != np.uint64(a) < np.uint64(b) in general.] -n _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org https://mail.scipy.org/mailman/listinfo/numpy-discussion