Cython plans to deprecate conditional compilation (IF)
Cython will deprecate compile time conditionals, see https://github.com/cython/cython/issues/4310
For us, this is really bad because we rely on them all over the place. We should investigate if some of the Cython features they're mentioning would work for us or if we should try to petition them to keep them.
Cython migration guide: https://docs.cython.org/en/latest/src/userguide/migrating_to_cy30.html#deprecation-of-def-if
We explain how we rely on the Cython preprocessor (IF, THEN, ELSE)
We define a union that can be any of the supported underlying types supported by the FPLLL library. This library may or may not be built with libqd support which we recognise at built dime as HAVE_QD.
Note that we could not compile the line MatGSOInterface[Z_NR[mpz_t], FP_NR[dd_t]] *mpz_dd when HAVE_QD is not set because the data types wouldn’t be defined. Thus, we guard this with HAVE_QD.
IF HAVE_QD:
ctypedef union mat_gso_core_t:
MatGSOInterface[Z_NR[mpz_t], FP_NR[d_t]] *mpz_d
MatGSOInterface[Z_NR[mpz_t], FP_NR[ld_t]] *mpz_ld
MatGSOInterface[Z_NR[mpz_t], FP_NR[dpe_t]] *mpz_dpe
MatGSOInterface[Z_NR[mpz_t], FP_NR[dd_t]] *mpz_dd
MatGSOInterface[Z_NR[mpz_t], FP_NR[qd_t]] *mpz_qd
MatGSOInterface[Z_NR[mpz_t], FP_NR[mpfr_t]] *mpz_mpfr
ELSE:
ctypedef union mat_gso_core_t:
MatGSOInterface[Z_NR[mpz_t], FP_NR[d_t]] *mpz_d
MatGSOInterface[Z_NR[mpz_t], FP_NR[ld_t]] *mpz_ld
MatGSOInterface[Z_NR[mpz_t], FP_NR[dpe_t]] *mpz_dpe
MatGSOInterface[Z_NR[mpz_t], FP_NR[mpfr_t]] *mpz_mpfr
The constructor of the Python object supports all underlying data types in one object. It constructs the appropriate object and stores it in the union, remembering its type. Here, too, we need IF HAVE_QD because we cannot compile with e.g. dd_t when this type isn’t defined.
cdef class MatGSO:
def __init__(self, IntegerMatrix B, U=None, UinvT=None,
int flags=GSO_DEFAULT, float_type="double", gram=False, update=False):
cdef FloatType float_type_ = check_float_type(float_type)
self._alg = mat_gso_gso_t
if B._type == ZT_MPZ:
if float_type_ == FT_DOUBLE:
self._type = mat_gso_mpz_d
self._core.mpz_d = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[d_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[d_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
elif float_type_ == FT_LONG_DOUBLE:
IF HAVE_LONG_DOUBLE:
self._type = mat_gso_mpz_ld
self._core.mpz_ld = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[ld_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[ld_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
ELSE:
raise ValueError("Float type '%s' not understood." % float_type)
elif float_type_ == FT_DPE:
self._type = mat_gso_mpz_dpe
self._core.mpz_dpe = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[dpe_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[dpe_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
elif float_type_ == FT_MPFR:
self._type = mat_gso_mpz_mpfr
self._core.mpz_mpfr = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[mpfr_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[mpfr_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
else:
IF HAVE_QD: ## <- LOOK HERE
if float_type_ == FT_DD:
self._type = mat_gso_mpz_dd
self._core.mpz_dd = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[dd_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[dd_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
elif float_type_ == FT_QD:
self._type = mat_gso_mpz_qd
self._core.mpz_qd = <MatGSOInterface_c[Z_NR[mpz_t],FP_NR[qd_t]]*>\
new MatGSO_c[Z_NR[mpz_t],FP_NR[qd_t]](b_m[0], u_m[0], u_inv_t_m[0], flags)
else:
raise ValueError("Float type '%s' not understood."%float_type)
ELSE:
raise ValueError("Float type '%s' not understood."%float_type)