| 
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 extern from "byteswap.h":  | 
 | 13 | +    """  | 
 | 14 | +    #if FLINT_BITS == 32  | 
 | 15 | +    #define bswap_ulong bswap_32  | 
 | 16 | +    #elif FLINT_BITS == 64  | 
 | 17 | +    #define bswap_ulong bswap_64  | 
 | 18 | +    #else  | 
 | 19 | +    #error FLINT_BITS must be 32 or 64  | 
 | 20 | +    #endif  | 
 | 21 | +    """  | 
 | 22 | +    ulong bswap_ulong(ulong x)  | 
 | 23 | + | 
11 | 24 | cdef inline int fmpz_set_pylong(fmpz_t x, obj):  | 
12 | 25 |     cdef int overflow  | 
13 | 26 |     cdef slong longval  | 
 | 27 | +    cdef slong size  | 
 | 28 | +    cdef bytes b  | 
 | 29 | +    cdef ulong *words  | 
 | 30 | + | 
14 | 31 |     longval = pylong_as_slong(<PyObject*>obj, &overflow)  | 
15 | 32 |     if overflow:  | 
16 |  | -        s = "%x" % obj  | 
17 |  | -        fmpz_set_str(x, chars_from_str(s), 16)  | 
 | 33 | +        # make sure the sign bit fits  | 
 | 34 | +        # we need sizeof(ulong) * size > obj.bit_length()  | 
 | 35 | +        size = obj.bit_length() // sizeof(ulong) + 1  | 
 | 36 | +        b = obj.to_bytes(sizeof(ulong) * size, "little", signed=True)  | 
 | 37 | +        # b is a local Python object, we access the internal pointer  | 
 | 38 | +        words = <ulong*>(<char *>b)  | 
 | 39 | +        # sys must be imported by the caller  | 
 | 40 | +        if sys.byteorder == "big":  | 
 | 41 | +            for i in range(size):  | 
 | 42 | +                words[i] = bswap_ulong(words[i])  | 
 | 43 | +        fmpz_set_signed_ui_array(x, words, size)  | 
18 | 44 |     else:  | 
19 | 45 |         fmpz_set_si(x, longval)  | 
20 | 46 | 
 
  | 
 | 
0 commit comments