Re: [Numpy-discussion] Float128 integer comparison

2011-11-01 Thread Matthew Brett
Hi,

On Sat, Oct 15, 2011 at 1:34 PM, Derek Homeier
de...@astro.physik.uni-goettingen.de wrote:
 On 15.10.2011, at 9:42PM, Aronne Merrelli wrote:


 On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett matthew.br...@gmail.com 
 wrote:
 Hi,

 Continuing the exploration of float128 - can anyone explain this behavior?

  np.float64(9223372036854775808.0) == 9223372036854775808L
 True
  np.float128(9223372036854775808.0) == 9223372036854775808L
 False
  int(np.float128(9223372036854775808.0)) == 9223372036854775808L
 True
  np.round(np.float128(9223372036854775808.0)) == 
  np.float128(9223372036854775808.0)
 True


 I know little about numpy internals, but while fiddling with this, I noticed 
 a possible clue:

  np.float128(9223372036854775808.0) == 9223372036854775808L
 False
  np.float128(4611686018427387904.0) == 4611686018427387904L
 True
  np.float128(9223372036854775808.0) - 9223372036854775808L
 Traceback (most recent call last):
   File stdin, line 1, in module
 TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long'
  np.float128(4611686018427387904.0) - 4611686018427387904L
 0.0


 My speculation - 9223372036854775808L is the first integer that is too big 
 to fit into a signed 64 bit integer. Python is OK with this but that means 
 it must be containing that value in some more complicated object. Since you 
 don't get the type error between float64() and long:

  np.float64(9223372036854775808.0) - 9223372036854775808L
 0.0

 Maybe there are some unimplemented pieces in numpy for dealing with 
 operations between float128 and python arbitrary longs? I could see the == 
 test just producing false in that case, because it defaults back to some 
 object equality test which isn't actually looking at the numbers.

 That seems to make sense, since even upcasting from a np.float64 still lets 
 the test fail:
 np.float128(np.float64(9223372036854775808.0)) == 9223372036854775808L
 False
 while
 np.float128(9223372036854775808.0) == np.uint64(9223372036854775808L)
 True

 and
 np.float128(9223372036854775809) == np.uint64(9223372036854775809L)
 False
 np.float128(np.uint(9223372036854775809L) == 
 np.uint64(9223372036854775809L)
 True

 Showing again that the normal casting to, or reading in of, a np.float128 
 internally inevitably
 calls the python float(), as already suggested in one of the parallel threads 
 (I think this
 also came up with some of the tests for precision) - leading to different 
 results than
 when you can convert from a np.int64 - this makes the outcome look even 
 weirder:

 np.float128(9223372036854775807.0) - 
 np.float128(np.int64(9223372036854775807))
 1.0
 np.float128(9223372036854775296.0) - 
 np.float128(np.int64(9223372036854775807))
 1.0
 np.float128(9223372036854775295.0) - 
 np.float128(np.int64(9223372036854775807))
 -1023.0
 np.float128(np.int64(9223372036854775296)) - 
 np.float128(np.int64(9223372036854775807))
 -511.0

 simply due to the nearest np.float64 always being equal to MAX_INT64 in the 
 two first cases
 above (or anything in between)...

Right - just for the record, I think there are four relevant problems.

1: values being cast to float128 appear to go through float64
--

In [119]: np.float128(2**54-1)
Out[119]: 18014398509481984.0

In [120]: np.float128(2**54)-1
Out[120]: 18014398509481983.0

2: values being cast from float128 to int appear to go through float64 again
---

In [121]: int(np.float128(2**54-1))
Out[121]: 18014398509481984

http://projects.scipy.org/numpy/ticket/1395

3: comparison to python long ints is always unequal
---

In [139]: 2**63 # 2*63 correctly represented in float128
Out[139]: 9223372036854775808L

In [140]: int(np.float64(2**63))
Out[140]: 9223372036854775808L

In [141]: int(np.float128(2**63))
Out[141]: 9223372036854775808L

In [142]: np.float128(2**63) == 2**63
Out[142]: False

In [143]: np.float128(2**63)-1 == 2**63-1
Out[143]: True

In [144]: np.float128(2**63) == np.float128(2**63)
Out[144]: True

Probably because, as y'all are saying, numpy tries to convert to
np.int64, fails, and falls back to an object array:

In [145]: np.array(2**63)
Out[145]: array(9223372036854775808L, dtype=object)

In [146]: np.array(2**63-1)
Out[146]: array(9223372036854775807L)

4 : any other operation of float128 with python long ints fails
--

In [148]: np.float128(0) + 2**63
---
TypeError Traceback (most recent call last)
/home/mb312/ipython-input-148-5cc20524867d in module()
 1 np.float128(0) + 2**63

TypeError: unsupported operand type(s) for +: 'numpy.float128' and 'long'

In [149]: 

[Numpy-discussion] Float128 integer comparison

2011-10-15 Thread Matthew Brett
Hi,

Continuing the exploration of float128 - can anyone explain this behavior?

 np.float64(9223372036854775808.0) == 9223372036854775808L
True
 np.float128(9223372036854775808.0) == 9223372036854775808L
False
 int(np.float128(9223372036854775808.0)) == 9223372036854775808L
True
 np.round(np.float128(9223372036854775808.0)) == 
 np.float128(9223372036854775808.0)
True

Thanks for any pointers,

Best,

Matthew
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] Float128 integer comparison

2011-10-15 Thread Aronne Merrelli
On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett matthew.br...@gmail.comwrote:

 Hi,

 Continuing the exploration of float128 - can anyone explain this behavior?

  np.float64(9223372036854775808.0) == 9223372036854775808L
 True
  np.float128(9223372036854775808.0) == 9223372036854775808L
 False
  int(np.float128(9223372036854775808.0)) == 9223372036854775808L
 True
  np.round(np.float128(9223372036854775808.0)) ==
 np.float128(9223372036854775808.0)
 True


I know little about numpy internals, but while fiddling with this, I noticed
a possible clue:

 np.float128(9223372036854775808.0) == 9223372036854775808L
False
 np.float128(4611686018427387904.0) == 4611686018427387904L
True
 np.float128(9223372036854775808.0) - 9223372036854775808L
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long'
 np.float128(4611686018427387904.0) - 4611686018427387904L
0.0


My speculation - 9223372036854775808L is the first integer that is too big
to fit into a signed 64 bit integer. Python is OK with this but that means
it must be containing that value in some more complicated object. Since you
don't get the type error between float64() and long:

 np.float64(9223372036854775808.0) - 9223372036854775808L
0.0

Maybe there are some unimplemented pieces in numpy for dealing with
operations between float128 and python arbitrary longs? I could see the ==
test just producing false in that case, because it defaults back to some
object equality test which isn't actually looking at the numbers.

Aronne
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] Float128 integer comparison

2011-10-15 Thread Derek Homeier
On 15.10.2011, at 9:42PM, Aronne Merrelli wrote:

 
 On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett matthew.br...@gmail.com 
 wrote:
 Hi,
 
 Continuing the exploration of float128 - can anyone explain this behavior?
 
  np.float64(9223372036854775808.0) == 9223372036854775808L
 True
  np.float128(9223372036854775808.0) == 9223372036854775808L
 False
  int(np.float128(9223372036854775808.0)) == 9223372036854775808L
 True
  np.round(np.float128(9223372036854775808.0)) == 
  np.float128(9223372036854775808.0)
 True
 
  
 I know little about numpy internals, but while fiddling with this, I noticed 
 a possible clue:
 
  np.float128(9223372036854775808.0) == 9223372036854775808L
 False
  np.float128(4611686018427387904.0) == 4611686018427387904L
 True
  np.float128(9223372036854775808.0) - 9223372036854775808L
 Traceback (most recent call last):
   File stdin, line 1, in module
 TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long'
  np.float128(4611686018427387904.0) - 4611686018427387904L
 0.0
 
 
 My speculation - 9223372036854775808L is the first integer that is too big to 
 fit into a signed 64 bit integer. Python is OK with this but that means it 
 must be containing that value in some more complicated object. Since you 
 don't get the type error between float64() and long:
 
  np.float64(9223372036854775808.0) - 9223372036854775808L
 0.0
 
 Maybe there are some unimplemented pieces in numpy for dealing with 
 operations between float128 and python arbitrary longs? I could see the == 
 test just producing false in that case, because it defaults back to some 
 object equality test which isn't actually looking at the numbers.

That seems to make sense, since even upcasting from a np.float64 still lets the 
test fail:
 np.float128(np.float64(9223372036854775808.0)) == 9223372036854775808L
False
while
 np.float128(9223372036854775808.0) == np.uint64(9223372036854775808L)
True

and 
 np.float128(9223372036854775809) == np.uint64(9223372036854775809L)
False
 np.float128(np.uint(9223372036854775809L) == np.uint64(9223372036854775809L)
True

Showing again that the normal casting to, or reading in of, a np.float128 
internally inevitably 
calls the python float(), as already suggested in one of the parallel threads 
(I think this 
also came up with some of the tests for precision) - leading to different 
results than 
when you can convert from a np.int64 - this makes the outcome look even weirder:

 np.float128(9223372036854775807.0) - 
 np.float128(np.int64(9223372036854775807)) 
1.0
 np.float128(9223372036854775296.0) - 
 np.float128(np.int64(9223372036854775807)) 
1.0
 np.float128(9223372036854775295.0) - 
 np.float128(np.int64(9223372036854775807)) 
-1023.0
 np.float128(np.int64(9223372036854775296)) - 
 np.float128(np.int64(9223372036854775807)) 
-511.0

simply due to the nearest np.float64 always being equal to MAX_INT64 in the two 
first cases 
above (or anything in between)... 

Cheers,
Derek


___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion