-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversion from mpz to numpy longdouble is incorrect #507
Comments
I don't think it's a gmpy2 issue. numpy.longdouble constructor just don't call >>> import gmpy2, numpy
>>> class Spam:
... def __int__(self):
... return 123
...
>>> numpy.longdouble(Spam())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: float() argument must be a string or a real number, not 'Spam' |
Ah, I see. This will work if gmpy2 types will have @pearu, is this The Right Way to coerce scalars like mpz to numpy datatypes? |
@skirpichev , import gmpy2
import numpy
class BigIntArray:
def __init__(self, obj):
self.obj = obj
def __array__(self, dtype):
return numpy.array(int(self.obj), dtype=dtype)
i = 5579686107214117131790972086716881
x1 = numpy.longdouble(BigIntArray(i))
x2 = numpy.longdouble(BigIntArray(gmpy2.mpz(i)))
print(x1, x2) # outputs 5.579686107214117132e+33 5.579686107214117132e+33 |
Notice that the def __array__(self, dtype):
import numpy
return numpy.array(int(self.obj), dtype=dtype) |
I think, that a hard dependence on the numpy is no-go. Runtime dependency will a kinda work, but... probably this will be to slow. This might be a good idea for something like fmpz_mat (python-flint). But gmpy2 has only scalar types and I believe, that explicit type casts are better. |
IMHO, this is acceptable as the issue is about silent incorrectness. In fact, repeated import is equivalent to dictionary access anyway: In [8]: import numpy
In [9]: %timeit import numpy
64 ns ± 0.114 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [10]: d = {"foo": 2}
In [11]: %timeit d['foo']
24.9 ns ± 0.124 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) while creating longdouble is more expensive than import: In [24]: %timeit numpy.longdouble(1)
319 ns ± 1.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) |
(Hmm, I would guess it's because npy_longdouble_from_PyLong() don't do it numerically.) On another hand, why numpy doesn't call |
It should not call |
Sorry, I meant |
pr is ready for review: #514 |
As in the title.
Reproducer (using gmpy2 version 2.1.2):
Notice that
that is, it looks like the conversion
mpz->longdouble
usesmpz->double->longdouble
while it should usempz->int->longdouble
.The text was updated successfully, but these errors were encountered: