b2/python/src/mpfr_export.cpp
2025-01-14 01:15:53 +01:00

520 lines
12 KiB
C++

//This file is part of Bertini 2.
//
//python/mpfr_export.cpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//python/mpfr_export.cpp is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with python/mpfr_export.cpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2016-2018 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
//
// silviana amethyst
// University of Wisconsin - Eau Claire
// Fall 2017, Spring 2018
//
// James Collins
// West Texas A&M University
// Spring 2016
//
//
//
// python/mpfr_export.cpp: Source file for exposing all multiprecision data types, those from boost and bertini::complex.
#include "mpfr_export.hpp"
namespace bertini{
namespace python{
template<typename T>
template<typename PyClass>
void PrecisionVisitor<T>::visit(PyClass& cl) const
{
cl
.def("precision", get_prec)
.def("precision", set_prec)
;
}
template<typename T>
template<typename PyClass>
void RealStrVisitor<T>::visit(PyClass& cl) const
{
cl
.def("__str__", &RealStrVisitor::__str__)
.def("__repr__", &RealStrVisitor::__repr__)
;
}
template<typename T>
template<typename PyClass>
void EqualitySelfVisitor<T>::visit(PyClass& cl) const
{
cl
.def(self == self)
.def(self != self)
;
}
template<typename T, typename S>
template<typename PyClass>
void EqualityVisitor<T,S>::visit(PyClass& cl) const
{
cl
.def(self == other<S>())
.def(self != other<S>())
.def(other<S>() == self)
.def(other<S>() != self)
;
}
template<typename T, typename S>
template<typename PyClass>
void RingVisitor<T,S>::visit(PyClass& cl) const
{
cl
.def("__add__",&RingVisitor::__add__)
.def("__iadd__",&RingVisitor::__iadd__)
.def("__radd__",&RingVisitor::__radd__)
.def("__sub__",&RingVisitor::__sub__)
.def("__isub__",&RingVisitor::__isub__)
.def("__rsub__",&RingVisitor::__rsub__)
.def("__mul__",&RingVisitor::__mul__)
.def("__imul__",&RingVisitor::__imul__)
.def("__rmul__",&RingVisitor::__rmul__)
;
}
template<typename T>
template<typename PyClass>
void RingSelfVisitor<T>::visit(PyClass& cl) const
{
cl
.def("__add__",&RingSelfVisitor::__add__)
.def("__iadd__",&RingSelfVisitor::__iadd__)
.def("__sub__",&RingSelfVisitor::__sub__)
.def("__isub__",&RingSelfVisitor::__isub__)
.def("__mul__",&RingSelfVisitor::__mul__)
.def("__imul__",&RingSelfVisitor::__imul__)
.def("__neg__",&RingSelfVisitor::__neg__)
;
}
template<typename T>
template<typename PyClass>
void RealFreeVisitor<T>::visit(PyClass& cl) const
{
def("abs", &RealFreeVisitor::__abs__); // free
}
template<typename T, typename S>
template<typename PyClass>
void FieldVisitor<T,S>::visit(PyClass& cl) const
{
cl
.def("__div__",&FieldVisitor::__div__)
.def("__idiv__",&FieldVisitor::__idiv__)
.def("__rdiv__",&FieldVisitor::__rdiv__)
.def("__truediv__",&FieldVisitor::__div__)
.def("__itruediv__",&FieldVisitor::__idiv__)
.def("__rtruediv__",&FieldVisitor::__rdiv__)
.def(RingVisitor<T,S>())
;
}
template<typename T>
template<typename PyClass>
void FieldSelfVisitor<T>::visit(PyClass& cl) const
{
cl
.def("__div__",&FieldSelfVisitor::div)
.def("__idiv__",&FieldSelfVisitor::idiv)
.def("__truediv__",&FieldSelfVisitor::div)
.def("__itruediv__",&FieldSelfVisitor::idiv)
.def(RingSelfVisitor<T>())
;
}
template<typename T, typename S>
template<typename PyClass>
void PowVisitor<T,S>::visit(PyClass& cl) const
{
cl
.def("__pow__",&PowVisitor::__pow__)
;
}
template<typename T, typename S>
template<typename PyClass>
void GreatLessVisitor<T,S>::visit(PyClass& cl) const
{
cl
.def(self < other<S>())
.def(self <= other<S>())
.def(self > other<S>())
.def(self >= other<S>())
.def(other<S>() < self)
.def(other<S>() <= self)
.def(other<S>() > self)
.def(other<S>() >= self)
;
}
template<typename T>
template<typename PyClass>
void GreatLessSelfVisitor<T>::visit(PyClass& cl) const
{
cl
.def(self < self)
.def(self <= self)
.def(self > self)
.def(self >= self)
;
}
template<typename T>
template<typename PyClass>
void TranscendentalVisitor<T>::visit(PyClass& cl) const
{
def("exp", &TranscendentalVisitor::__exp__);
def("log", &TranscendentalVisitor::__log__);
def("sqrt", &TranscendentalVisitor::__sqrt__);
def("sin", &TranscendentalVisitor::__sin__);
def("cos", &TranscendentalVisitor::__cos__);
def("tan", &TranscendentalVisitor::__tan__);
def("asin", &TranscendentalVisitor::__asin__);
def("acos", &TranscendentalVisitor::__acos__);
def("atan", &TranscendentalVisitor::__atan__);
def("sinh", &TranscendentalVisitor::__sinh__);
def("cosh", &TranscendentalVisitor::__cosh__);
def("tanh", &TranscendentalVisitor::__tanh__);
def("asinh",&TranscendentalVisitor::__asinh__);
def("acosh",&TranscendentalVisitor::__acosh__);
def("atanh",&TranscendentalVisitor::__atanh__);
}
template<typename T>
template<class PyClass>
void ComplexVisitor<T>::visit(PyClass& cl) const
{
// MPFRFloatBaseVisitor<T>().visit(cl);
cl
.add_property("real", &ComplexVisitor::get_real, &ComplexVisitor::set_real)
.add_property("imag", &ComplexVisitor::get_imag, &ComplexVisitor::set_imag)
.def("__str__", &ComplexVisitor::__str__)
.def("__repr__", &ComplexVisitor::__repr__)
;
// these complex-specific functions are free in python
using boost::multiprecision::real;
using boost::multiprecision::imag;
mpfr_float (*reeeal)(const T&) = &boost::multiprecision::real;
mpfr_float (*imaaag)(const T&) = &boost::multiprecision::real;
def("real",reeeal); //,return_value_policy<copy_const_reference>()
def("imag",imaaag); //,return_value_policy<copy_const_reference>()
// and then a few more free functions
// def("abs2",&T::abs2);
mpfr_complex (*pooolar)(const mpfr_float&,const mpfr_float&) = &boost::multiprecision::polar;
def("polar",pooolar);
// def("norm",&T::norm);
def("conj",&ComplexVisitor::conj);
mpfr_float (*aaaarg)(const T&) = &boost::multiprecision::arg;
def("arg",aaaarg);
// def("square",&square);
// def("cube",&cube);
// def("inverse", &inverse);
def("abs", &ComplexVisitor::__abs__); // free
}
template <typename T>
unsigned get_precision_vector(Eigen::Ref<Vec<T>> x)
{
return bertini::Precision(x);
}
#define IMPLICITLY_CONVERTIBLE(T1,T2) \
boost::python::implicitly_convertible<T1,T2>();
void ExposeFreeNumFns()
{
unsigned (*def_prec1)() = &bertini::DefaultPrecision;
void (*def_prec2)(unsigned) = &bertini::DefaultPrecision;
def("default_precision", def_prec1);
def("default_precision", def_prec2);
}
void ExposeInt()
{
using T = mpz_int;
class_<mpz_int>("Int", init<>())
.def(init<int>())
.def(init<T>())
.def(RealStrVisitor<T>())
.def(RingSelfVisitor<T>())
.def(PowVisitor<T,int>())
.def(GreatLessSelfVisitor<T>())
.def(GreatLessVisitor<T,int>())
.def(EqualitySelfVisitor<T>())
.def(EqualityVisitor<T, int>())
.def(RealFreeVisitor<T>())
;
}
void ExposeRational()
{
using T = mpq_rational;
class_<mpq_rational>("Rational", init<>())
.def(init<int>())
.def(init<int, int>())
.def(init<mpz_int>())
.def(init<mpz_int,mpz_int>())
.def(init<mpq_rational>())
.def(RealStrVisitor<T>())
.def(FieldSelfVisitor<T>())
.def(FieldVisitor<T, mpz_int>())
// .def(PowVisitor<T,int>()) // deliberately commented out...
// pow(Q,Z) not defined...
.def(GreatLessSelfVisitor<T>())
.def(GreatLessVisitor<T,int>())
.def(GreatLessVisitor<T,mpz_int>())
.def(EqualitySelfVisitor<T>())
.def(EqualityVisitor<T, int>())
.def(EqualityVisitor<T, mpz_int>())
.def(RealFreeVisitor<T>())
;
}
void ExposeFloat()
{
using T = mpfr_float;
class_<T>("Float", init<>())
.def(init<std::string>())
.def(init<int>())
.def(init<long int>())
.def(init<T>())
.def(init<mpz_int>())
.def(RealStrVisitor<T>())
.def(PrecisionVisitor<T>())
.def(FieldSelfVisitor<T>())
.def(FieldVisitor<T, int>())
.def(FieldVisitor<T, mpz_int>())
.def(FieldVisitor<T, mpq_rational>())
.def(PowVisitor<T,T>())
.def(PowVisitor<T,int>())
.def(TranscendentalVisitor<T>())
.def(GreatLessSelfVisitor<T>())
.def(GreatLessVisitor<T,int>())
.def(GreatLessVisitor<T,double>())
.def(RealFreeVisitor<T>())
;
eigenpy::registerNewType<T>();
eigenpy::registerCommonUfunc<T>();
eigenpy::registerCast<T,long>(false);
eigenpy::registerCast<long,T>(true);
eigenpy::registerCast<T,int>(false);
eigenpy::registerCast<int,T>(true);;
eigenpy::registerCast<T,int64_t>(false);
eigenpy::registerCast<int64_t,T>(true);
IMPLICITLY_CONVERTIBLE(int,T);
IMPLICITLY_CONVERTIBLE(long,T);
IMPLICITLY_CONVERTIBLE(int64_t,T);
eigenpy::EigenToPyConverter<Vec<T>>::registration();
eigenpy::EigenToPyConverter<Mat<T>>::registration();
eigenpy::EigenFromPyConverter<Vec<T>>::registration();
eigenpy::EigenFromPyConverter<Mat<T>>::registration();
}
size_t get_default_align(){return EIGENPY_DEFAULT_ALIGN_BYTES;}
void ExposeComplex()
{
using T = bertini::mpfr_complex;
class_<T>("Complex", init<>())
.def(init<double>()) // this should probably be made an explicit constructor rather than implicit
.def(init<mpfr_float>())
.def(init<std::string>())
.def(init<mpfr_float,mpfr_float>())
.def(init<double, double>()) // this should probably be made an explicit constructor rather than implicit
.def(init<std::string, mpfr_float>())
.def(init<mpfr_float, std::string>())
.def(init<std::string, std::string>())
.def(init<T>())
.def(init<mpz_int>())
.def(init<mpz_int, mpz_int>())
.def(ComplexVisitor<T>())
.def(FieldSelfVisitor<T>())
.def(FieldVisitor<T, mpz_int>())
.def(FieldVisitor<T, mpq_rational>())
.def(FieldVisitor<T, mpfr_float>())
.def(FieldVisitor<T, int>())
.def(PowVisitor<T,T>())
.def(PowVisitor<T,int>())
.def(PowVisitor<T,mpfr_float>())
.def(TranscendentalVisitor<T>())
.def(PrecisionVisitor<T>())
;
eigenpy::registerNewType<T>();
eigenpy::registerUfunct_without_comparitors<T>();
// eigenpy::registerCast<T,long>(false);
eigenpy::registerCast<long,T>(true);
// eigenpy::registerCast<T,int>(false);
eigenpy::registerCast<int,T>(true);
// eigenpy::registerCast<T,int64_t>(false);
eigenpy::registerCast<int64_t,T>(true);
IMPLICITLY_CONVERTIBLE(int,T);
IMPLICITLY_CONVERTIBLE(long,T);
IMPLICITLY_CONVERTIBLE(int64_t,T);
eigenpy::EigenToPyConverter<Vec<T>>::registration();
eigenpy::EigenToPyConverter<Mat<T>>::registration();
eigenpy::EigenFromPyConverter<Vec<T>>::registration();
eigenpy::EigenFromPyConverter<Mat<T>>::registration();
eigenpy::exposeType<T>();
eigenpy::exposeType<T, Eigen::RowMajor>();
boost::python::def("precision", &get_precision_vector<mpfr_complex>, "get the precision of a vector of complexes");
boost::python::def("default_align_bytes", &get_default_align);
}
void ExportMpfr()
{
scope current_scope;
std::string new_submodule_name(extract<const char*>(current_scope.attr("__name__")));
new_submodule_name.append(".multiprec");
object new_submodule(borrowed(PyImport_AddModule(new_submodule_name.c_str())));
current_scope.attr("multiprec") = new_submodule;
scope new_submodule_scope = new_submodule;
ExposeInt();
ExposeFloat();
ExposeRational();
ExposeComplex();
ExposeFreeNumFns();
};
#undef IMPLICITLY_CONVERTIBLE
} //namespace python
} // namespace bertini