|
1 | 1 | from cpython.long cimport PyLong_Check
|
2 | 2 | from flint.flint_base.flint_base cimport flint_scalar
|
3 | 3 | from flint.utils.conversion cimport chars_from_str
|
4 |
| -from flint.flintlib.types.flint cimport slong, pylong_as_slong |
| 4 | +from flint.flintlib.types.flint cimport slong, ulong, pylong_as_slong |
5 | 5 | from flint.flintlib.types.flint cimport PyObject
|
6 |
| -from flint.flintlib.functions.fmpz cimport fmpz_t, fmpz_set_str, fmpz_set_si |
| 6 | +from flint.flintlib.functions.fmpz cimport fmpz_t, fmpz_set_si, fmpz_set_signed_ui_array |
| 7 | +import sys |
7 | 8 |
|
8 | 9 | cdef int fmpz_set_any_ref(fmpz_t x, obj)
|
9 | 10 | cdef fmpz_get_intlong(fmpz_t x)
|
10 | 11 |
|
| 12 | +cdef int is_big_endian = int(sys.byteorder == "big") |
| 13 | + |
| 14 | +cdef inline ulong ulong_from_little_endian(unsigned char *ptr): |
| 15 | + # Read a ulong from little-endian bytes |
| 16 | + cdef ulong w = 0 |
| 17 | + for i in range(sizeof(ulong) // 8): |
| 18 | + w = (w << 8) | ptr[i] |
| 19 | + return w |
| 20 | + |
11 | 21 | cdef inline int fmpz_set_pylong(fmpz_t x, obj):
|
12 | 22 | cdef int overflow
|
13 | 23 | cdef slong longval
|
| 24 | + cdef slong size |
| 25 | + cdef bytes b |
| 26 | + cdef ulong w |
| 27 | + cdef ulong *words |
| 28 | + cdef int i |
| 29 | + |
14 | 30 | longval = pylong_as_slong(<PyObject*>obj, &overflow)
|
15 | 31 | if overflow:
|
16 |
| - s = "%x" % obj |
17 |
| - fmpz_set_str(x, chars_from_str(s), 16) |
| 32 | + # make sure the sign bit fits |
| 33 | + # we need 8 * sizeof(ulong) * size > obj.bit_length() |
| 34 | + size = obj.bit_length() // (8 * sizeof(ulong)) + 1 |
| 35 | + b = obj.to_bytes(sizeof(ulong) * size, "little", signed=True) |
| 36 | + # b is a local Python object, we access the internal pointer |
| 37 | + words = <ulong*>(<char *>b) |
| 38 | + if is_big_endian: |
| 39 | + for i in range(size): |
| 40 | + words[i] = ulong_from_little_endian(<unsigned char *>(words + i)) |
| 41 | + fmpz_set_signed_ui_array(x, words, size) |
18 | 42 | else:
|
19 | 43 | fmpz_set_si(x, longval)
|
20 | 44 |
|
|
0 commit comments