Fpylll makes heavy use to Cython to expose Fplll’s functionality to Python. Fplll, in turn, makes use of C++ templates. For example, double
, long double
, dd_real
(http://crd.lbl.gov/~dhbailey/mpdist/) and mpfr_t
(http://www.mpfr.org/) are supported as floating point types. While Cython supports C++ templates, we still have to generate code for all possible instantiations of the C++ templates for Python to use/call. The way I implemented these bindings is showing its limitations. For example, here’s how attribute access to the dimension of the Gram-Schmidt object looks like:
@property def d(self): """ Number of rows of ``B`` (dimension of the lattice). >>> from fpylll import IntegerMatrix, GSO, set_precision >>> A = IntegerMatrix(11, 11) >>> M = GSO.Mat(A) >>> M.d 11 """ if self._type == gso_mpz_d: return self._core.mpz_d.d IF HAVE_LONG_DOUBLE: if self._type == gso_mpz_ld: return self._core.mpz_ld.d if self._type == gso_mpz_dpe: return self._core.mpz_dpe.d IF HAVE_QD: if self._type == gso_mpz_dd: return self._core.mpz_dd.d if self._type == gso_mpz_qd: return self._core.mpz_qd.d if self._type == gso_mpz_mpfr: return self._core.mpz_mpfr.d if self._type == gso_long_d: return self._core.long_d.d IF HAVE_LONG_DOUBLE: if self._type == gso_long_ld: return self._core.long_ld.d if self._type == gso_long_dpe: return self._core.long_dpe.d IF HAVE_QD: if self._type == gso_long_dd: return self._core.long_dd.d if self._type == gso_long_qd: return self._core.long_qd.d if self._type == gso_long_mpfr: return self._core.long_mpfr.d raise RuntimeError("MatGSO object '%s' has no core."%self)
In the code above uppercase IF
and ELSE
are compile-time conditionals, lowercase if
and else
are run-time checks. If we wanted to add Z_NR<double>
to the list of supported integer types (yep, Fplll supports that), then the above Python approximation of a switch/case statement would grow by a factor 50%. The same would have to be repeated for every member function or attribute. There must be a more better way.