diff --git a/NEWS.md b/NEWS.md index ba31e4d..3e583cc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +# boostmath 1.5.0 + * Functions (excluding distributions and polynomials) now support vectorised inputs + # boostmath 1.4.0 * Added `logit` and `logistic_sigmoid` functions * Added `log_pi` constant diff --git a/src/boostmath/as_cpp.hpp b/src/boostmath/as_cpp.hpp new file mode 100644 index 0000000..f812ed2 --- /dev/null +++ b/src/boostmath/as_cpp.hpp @@ -0,0 +1,125 @@ +#ifndef BOOSTMATH_AS_CPP_HPP +#define BOOSTMATH_AS_CPP_HPP + +#include +#include +#include "./type_traits.hpp" + +namespace boostmath { + namespace internal { + template >::value>* = nullptr> + T as_cpp_arithmetic_container_impl(SEXP x, std::index_sequence) { + return {REAL_ELT(x, Is)...}; + } + + template ::value>* = nullptr> + T as_cpp_arithmetic_container_impl(SEXP x, std::index_sequence) { + return {INTEGER_ELT(x, Is)...}; + } + } + + template >::value>* = nullptr> + inline std::complex as_cpp(SEXP x) { + Rcomplex r_complex = COMPLEX_ELT(x, 0); + return {r_complex.r, r_complex.i}; + } + + template >>::value>* = nullptr> + inline std::vector> as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::vector> result(n); + for (R_xlen_t i = 0; i < n; ++i) { + Rcomplex r_complex = COMPLEX_ELT(x, i); + result[i] = {r_complex.r, r_complex.i}; + } + return result; + } + + template >::value>* = nullptr> + inline std::vector as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::vector result(n); + for (R_xlen_t i = 0; i < n; ++i) { + result[i] = static_cast(Rf_isInteger(x) ? INTEGER_ELT(x, i) : REAL_ELT(x, i)); + } + return result; + } + + template >::value>* = nullptr> + inline std::vector as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::vector result(n); + for (R_xlen_t i = 0; i < n; ++i) { + result[i] = static_cast(Rf_isInteger(x) ? INTEGER_ELT(x, i) : REAL_ELT(x, i)); + } + return result; + } + + template >::value>* = nullptr> + inline std::vector as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::vector result(n); + for (R_xlen_t i = 0; i < n; ++i) { + result[i] = static_cast(Rf_isInteger(x) ? INTEGER_ELT(x, i) : REAL_ELT(x, i)); + } + return result; + } + + template >::value>* = nullptr> + inline std::vector as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::vector result(n); + for (R_xlen_t i = 0; i < n; ++i) { + result[i] = static_cast(Rf_isInteger(x) ? INTEGER_ELT(x, i) : REAL_ELT(x, i)); + } + return result; + } + + template >::value>* = nullptr> + inline std::list as_cpp(SEXP x) { + R_xlen_t n = Rf_xlength(x); + std::list result(n); + for (R_xlen_t i = 0; i < n; ++i) { + result.push_back(static_cast(Rf_isInteger(x) ? INTEGER_ELT(x, i) : REAL_ELT(x, i))); + } + return result; + } + + template >>::value>* = nullptr> + inline std::vector> as_cpp(SEXP x) { + if (Rf_isNewList(x)) { + const R_xlen_t n = Rf_xlength(x); + std::vector> result(n); + for (R_xlen_t i = 0; i < n; ++i) { + SEXP xi = VECTOR_ELT(x, i); + result[i] = as_cpp>(xi); + } + return result; + } + return {as_cpp>(x)}; + } + + template ::value>* = nullptr> + inline T as_cpp(SEXP x) { + return internal::as_cpp_arithmetic_container_impl(x, std::make_index_sequence::value>{}); + } + + template ::value>* = nullptr> + inline T as_cpp(SEXP x) { + using array_type = typename T::value_type; + R_xlen_t n = Rf_xlength(x); + T result; + result.reserve(n); + for (R_xlen_t i = 0; i < n; ++i) { + SEXP xi = VECTOR_ELT(x, i); + result.push_back(as_cpp(xi)); + } + return result; + } + + template ::value>* = nullptr> + inline T as_cpp(SEXP x) { + return cpp11::as_cpp(x); + } +} +#endif diff --git a/src/boostmath/as_sexp.hpp b/src/boostmath/as_sexp.hpp new file mode 100644 index 0000000..5fcb2ef --- /dev/null +++ b/src/boostmath/as_sexp.hpp @@ -0,0 +1,152 @@ +#ifndef BOOSTMATH_AS_SEXP_HPP +#define BOOSTMATH_AS_SEXP_HPP + +#include +#include +#include "./type_traits.hpp" +#include "Rinternals.h" + +namespace boostmath { + namespace internal { + template >::value>* = nullptr> + auto as_sexp_arithmetic_container_impl(const T& x, std::index_sequence) { + SEXP data = cpp11::safe[Rf_allocVector](REALSXP, sizeof...(Is)); + double* ptr = REAL(data); + ((ptr[Is] = std::get(x)), ...); + return data; + } + + template ::value>* = nullptr> + auto as_sexp_arithmetic_container_impl(const T& x, std::index_sequence) { + SEXP data = cpp11::safe[Rf_allocVector](INTSXP, sizeof...(Is)); + int* ptr = INTEGER(data); + ((ptr[Is] = std::get(x)), ...); + return data; + } + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + SEXP data = cpp11::safe[Rf_allocVector](CPLXSXP, 1); + Rcomplex* r_complex = COMPLEX(data); + r_complex->r = x.real(); + r_complex->i = x.imag(); + return data; + } + + template >>::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](CPLXSXP, n); + Rcomplex* r_complex = COMPLEX(data); + for (R_xlen_t i = 0; i < n; ++i) { + r_complex[i].r = x[i].real(); + r_complex[i].i = x[i].imag(); + } + return data; + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](REALSXP, n); + double* ptr = REAL(data); + size_t i = 0; + for (const auto& value : x) { + ptr[i++] = value; + } + return data; + } + + template >>::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](VECSXP, n); + PROTECT(data); + for (R_xlen_t i = 0; i < n; ++i) { + SET_VECTOR_ELT(data, i, as_sexp(x[i])); + } + UNPROTECT(1); + return data; + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](INTSXP, n); + int* ptr = INTEGER(data); + for (R_xlen_t i = 0; i < n; ++i) { + ptr[i] = static_cast(x[i]); + } + return data; + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](INTSXP, n); + int* ptr = INTEGER(data); + for (R_xlen_t i = 0; i < n; ++i) { + ptr[i] = static_cast(x[i]); + } + return data; + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](INTSXP, n); + int* ptr = INTEGER(data); + for (R_xlen_t i = 0; i < n; ++i) { + ptr[i] = static_cast(x[i]); + } + return data; + } + + template >::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](REALSXP, n); + double* ptr = REAL(data); + for (R_xlen_t i = 0; i < n; ++i) { + ptr[i] = static_cast(x[i]); + } + return data; + } + + template >>::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](VECSXP, n); + PROTECT(data); + for (R_xlen_t i = 0; i < n; ++i) { + SET_VECTOR_ELT(data, i, as_sexp(x[i])); + } + UNPROTECT(1); + return data; + } + + template ::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + return internal::as_sexp_arithmetic_container_impl(x, std::make_index_sequence::value>{}); + } + + template ::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + R_xlen_t n = x.size(); + SEXP data = cpp11::safe[Rf_allocVector](VECSXP, n); + PROTECT(data); + for (R_xlen_t i = 0; i < n; ++i) { + SET_VECTOR_ELT(data, i, as_sexp(x[i])); + } + UNPROTECT(1); + return data; + } + + template ::value>* = nullptr> + inline SEXP as_sexp(const T& x) { + return cpp11::as_sexp(x); + } +} + +#endif // BOOSTMATH_SEXP_HPP diff --git a/src/boostmath/boost_function.hpp b/src/boostmath/boost_function.hpp new file mode 100644 index 0000000..fe9a7ac --- /dev/null +++ b/src/boostmath/boost_function.hpp @@ -0,0 +1,58 @@ +#ifndef BOOSTMATH_UTILS_HPP +#define BOOSTMATH_UTILS_HPP + +#include +#include "as_sexp.hpp" +#include "scalar_container.hpp" +#include +#include +#include + +namespace boostmath { + namespace internal { + template + auto make_containers_tuple_impl(ArgsTupleT&& args, std::index_sequence) { + return std::make_tuple(boostmath::scalar_container>(std::get(args))...); + } + } + + template + auto make_containers_tuple(ArgsTupleT&& args) { + constexpr auto tuple_index_seq = std::make_index_sequence>>{}; + return internal::make_containers_tuple_impl(std::forward(args), tuple_index_seq); + } + + template + struct invoke_rtn { + using type = std::invoke_result_t; + }; + + template + struct invoke_rtn> { + using type = std::invoke_result_t; + }; + + template + using invoke_rtn_t = typename invoke_rtn::type; + + template + SEXP boost_function(F&& f, ArgsTupleT&& args) { + const auto containers_tuple = make_containers_tuple(std::forward(args)); + + using containers_tuple_t = decltype(containers_tuple); + size_t max_n = std::apply([](auto&&... conts) { return std::max({conts.size()...}); }, + std::forward(containers_tuple)); + + std::vector> results(max_n); + for (size_t i = 0; i < max_n; ++i) { + results[i] = std::apply([&](auto&&... conts){ return f(conts[i]...); }, + std::forward(containers_tuple)); + } + if (max_n == 1) { + return boostmath::as_sexp(results[0]); + } + return boostmath::as_sexp(results); + } +} + +#endif // BOOSTMATH_UTILS_HPP diff --git a/src/boostmath/macros.hpp b/src/boostmath/macros.hpp index 566e099..f867650 100644 --- a/src/boostmath/macros.hpp +++ b/src/boostmath/macros.hpp @@ -2,7 +2,9 @@ #define BOOSTMATH_MACROS_HPP #include -#include "sexp.hpp" +#include "as_sexp.hpp" +#include "as_cpp.hpp" +#include "boost_function.hpp" #define NOARG_BOOST_MEMBER(name) \ extern "C" SEXP name##_() { \ @@ -21,166 +23,161 @@ #define UNARY_BOOST_FUNCTION(name, arg_type) \ extern "C" SEXP name##_(SEXP x_) { \ BEGIN_CPP11 \ - const arg_type x = boostmath::as_cpp(x_); \ - return boostmath::as_sexp(boost::math::name(x)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_)); \ END_CPP11 \ } #define UNARY_BOOST_FUNCTION_NOTYPE(name, arg_type) \ extern "C" SEXP name##_(SEXP x_) { \ BEGIN_CPP11 \ - const arg_type x = boostmath::as_cpp(x_); \ - return boostmath::as_sexp(boost::math::name(x)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_)); \ END_CPP11 \ } #define UNARY_BOOST_FUNCTION_NAMESPACE(namespace, name, arg_type) \ extern "C" SEXP name##_(SEXP x_) { \ BEGIN_CPP11 \ - arg_type x = boostmath::as_cpp(x_); \ - return boostmath::as_sexp(boost::math::namespace::name(x)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_)); \ END_CPP11 \ } #define UNARY_BOOST_FUNCTION_SUFFIX(name, suffix, arg_type) \ extern "C" SEXP name##_##suffix(SEXP x_) { \ BEGIN_CPP11 \ - const arg_type x = boostmath::as_cpp(x_); \ - return boostmath::as_sexp(boost::math::name(x)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_)); \ END_CPP11 \ } #define BINARY_BOOST_FUNCTION(name, arg1_type, arg2_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - return boostmath::as_sexp(boost::math::name(x, y)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_)); \ END_CPP11 \ } #define BINARY_BOOST_FUNCTION_TYPE(name, template_type, arg1_type, arg2_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - return boostmath::as_sexp(boost::math::name(x, y)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_)); \ END_CPP11 \ } #define BINARY_BOOST_FUNCTION_NAMESPACE(namespace, name, arg1_type, arg2_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - return boostmath::as_sexp(boost::math::namespace::name(x, y)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_)); \ END_CPP11 \ } #define BINARY_BOOST_FUNCTION_VECTOR_SUFFIX(name, suffix, arg1_type, arg2_type) \ extern "C" SEXP name##_##suffix(SEXP x_, SEXP y_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - std::vector results; \ - boost::math::name(x, y, std::back_inserter(results)); \ - return boostmath::as_sexp(results); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { \ + std::vector results; \ + boost::math::name(args..., std::back_inserter(results)); \ + return results; \ + }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_)); \ END_CPP11 \ } #define BINARY_BOOST_FUNCTION_SUFFIX(name, suffix, arg1_type, arg2_type) \ extern "C" SEXP name##_##suffix(SEXP x_, SEXP y_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - return boostmath::as_sexp(boost::math::name(x, y)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_)); \ END_CPP11 \ } #define TERNARY_BOOST_FUNCTION(name, arg1_type, arg2_type, arg3_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_, SEXP z_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - return boostmath::as_sexp(boost::math::name(x, y, z)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_)); \ END_CPP11 \ } #define TERNARY_BOOST_FUNCTION_NAMESPACE(namespace, name, arg1_type, arg2_type, arg3_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_, SEXP z_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - return boostmath::as_sexp(boost::math::namespace::name(x, y, z)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_)); \ END_CPP11 \ } #define TERNARY_BOOST_FUNCTION_VECTOR_SUFFIX(name, suffix, arg1_type, arg2_type, arg3_type) \ extern "C" SEXP name##_##suffix(SEXP x_, SEXP y_, SEXP z_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - std::vector results; \ - boost::math::name(x, y, z, std::back_inserter(results)); \ - return boostmath::as_sexp(results); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { \ + std::vector results; \ + boost::math::name(args..., std::back_inserter(results)); \ + return results; \ + }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_)); \ END_CPP11 \ } #define TERNARY_BOOST_FUNCTION_SUFFIX(name, suffix, arg1_type, arg2_type, arg3_type) \ extern "C" SEXP name##_##suffix(SEXP x_, SEXP y_, SEXP z_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - return boostmath::as_sexp(boost::math::name(x, y, z)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_)); \ END_CPP11 \ } #define QUARTERNARY_BOOST_FUNCTION(name, arg1_type, arg2_type, arg3_type, arg4_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_, SEXP z_, SEXP w_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - const arg4_type w = boostmath::as_cpp(w_); \ - return boostmath::as_sexp(boost::math::name(x, y, z, w)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_, w_)); \ END_CPP11 \ } #define QUARTERNARY_BOOST_FUNCTION_NAMESPACE(namespace, name, arg1_type, arg2_type, arg3_type, arg4_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_, SEXP z_, SEXP w_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - const arg4_type w = boostmath::as_cpp(w_); \ - return boostmath::as_sexp(boost::math::namespace::name(x, y, z, w)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_, w_)); \ END_CPP11 \ } #define QUARTERNARY_BOOST_FUNCTION_NAMESPACE_SUFFIX(namespace, name, suffix, arg1_type, arg2_type, arg3_type, arg4_type) \ extern "C" SEXP name##_##suffix(SEXP x_, SEXP y_, SEXP z_, SEXP w_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - const arg4_type w = boostmath::as_cpp(w_); \ - return boostmath::as_sexp(boost::math::namespace::name(x, y, z, w)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_, w_)); \ END_CPP11 \ } #define PENTA_BOOST_FUNCTION_NAMESPACE(namespace, name, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type) \ extern "C" SEXP name##_(SEXP x_, SEXP y_, SEXP z_, SEXP w_, SEXP v_) { \ BEGIN_CPP11 \ - const arg1_type x = boostmath::as_cpp(x_); \ - const arg2_type y = boostmath::as_cpp(y_); \ - const arg3_type z = boostmath::as_cpp(z_); \ - const arg4_type w = boostmath::as_cpp(w_); \ - const arg4_type v = boostmath::as_cpp(v_); \ - return boostmath::as_sexp(boost::math::namespace::name(x, y, z, w, v)); \ + using args_type = std::tuple; \ + const auto f = [](auto&&... args) { return boost::math::namespace::name(args...); }; \ + return boostmath::boost_function(f, std::forward_as_tuple(x_, y_, z_, w_, v_)); \ END_CPP11 \ } diff --git a/src/boostmath/scalar_container.hpp b/src/boostmath/scalar_container.hpp new file mode 100644 index 0000000..b964ce1 --- /dev/null +++ b/src/boostmath/scalar_container.hpp @@ -0,0 +1,27 @@ +#ifndef BOOSTMATH_SCALAR_CONTAINER_HPP +#define BOOSTMATH_SCALAR_CONTAINER_HPP + +#include +#include +#include "as_cpp.hpp" + +namespace boostmath { + template + struct scalar_container { + std::vector value_; + size_t size_; + bool is_scalar_; + + scalar_container() = default; + scalar_container(SEXP x) : + value_(boostmath::as_cpp>(x)), + size_(value_.size()), + is_scalar_(size_ == 1) {} + + T operator[](size_t i) const { return is_scalar_ ? value_[0] : value_[i]; } + size_t size() const { return size_; } + + }; +} + +#endif diff --git a/src/boostmath/sexp.hpp b/src/boostmath/sexp.hpp deleted file mode 100644 index 8f41f88..0000000 --- a/src/boostmath/sexp.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef BOOSTMATH_SEXP_HPP -#define BOOSTMATH_SEXP_HPP - -#include -#include -#include "./type_traits.hpp" - -namespace boostmath { - namespace internal { - template >::value>* = nullptr> - T as_cpp_arithmetic_container_impl(SEXP x, std::index_sequence) { - return {REAL_ELT(x, Is)...}; - } - - template ::value>* = nullptr> - T as_cpp_arithmetic_container_impl(SEXP x, std::index_sequence) { - return {INTEGER_ELT(x, Is)...}; - } - - template >::value>* = nullptr> - auto as_sexp_arithmetic_container_impl(const T& x, std::index_sequence) { - SEXP data = cpp11::safe[Rf_allocVector](REALSXP, sizeof...(Is)); - double* ptr = REAL(data); - ((ptr[Is] = std::get(x)), ...); - return data; - } - - template ::value>* = nullptr> - auto as_sexp_arithmetic_container_impl(const T& x, std::index_sequence) { - SEXP data = cpp11::safe[Rf_allocVector](INTSXP, sizeof...(Is)); - int* ptr = INTEGER(data); - ((ptr[Is] = std::get(x)), ...); - return data; - } - } - - template >::value>* = nullptr> - inline std::complex as_cpp(SEXP x) { - Rcomplex r_complex = COMPLEX_ELT(x, 0); - return {r_complex.r, r_complex.i}; - } - - template ::value>* = nullptr> - inline T as_cpp(SEXP x) { - return internal::as_cpp_arithmetic_container_impl(x, std::make_index_sequence::value>{}); - } - - template ::value>* = nullptr> - inline T as_cpp(SEXP x) { - using array_type = typename T::value_type; - R_xlen_t n = Rf_xlength(x); - T result; - result.reserve(n); - for (R_xlen_t i = 0; i < n; ++i) { - SEXP xi = VECTOR_ELT(x, i); - result.push_back(as_cpp(xi)); - } - return result; - } - - template ::value>* = nullptr> - inline T as_cpp(SEXP x) { - return cpp11::as_cpp(x); - } - - template >::value>* = nullptr> - inline SEXP as_sexp(const T& x) { - SEXP data = cpp11::safe[Rf_allocVector](CPLXSXP, 1); - Rcomplex* r_complex = COMPLEX(data); - r_complex->r = x.real(); - r_complex->i = x.imag(); - return data; - } - - template ::value>* = nullptr> - inline SEXP as_sexp(const T& x) { - return internal::as_sexp_arithmetic_container_impl(x, std::make_index_sequence::value>{}); - } - - template ::value>* = nullptr> - inline SEXP as_sexp(const T& x) { - R_xlen_t n = x.size(); - SEXP data = cpp11::safe[Rf_allocVector](VECSXP, n); - for (R_xlen_t i = 0; i < n; ++i) { - SET_VECTOR_ELT(data, i, as_sexp(x[i])); - } - return data; - } - - template ::value>* = nullptr> - inline SEXP as_sexp(const T& x) { - return cpp11::as_sexp(x); - } - -} - -#endif // BOOSTMATH_SEXP_HPP diff --git a/src/boostmath/type_traits.hpp b/src/boostmath/type_traits.hpp index cda274b..ce9c488 100644 --- a/src/boostmath/type_traits.hpp +++ b/src/boostmath/type_traits.hpp @@ -1,9 +1,12 @@ #ifndef BOOSTMATH_TYPE_TRAITS_HPP #define BOOSTMATH_TYPE_TRAITS_HPP +#include +#include #include #include #include +#include namespace boostmath { template @@ -26,18 +29,33 @@ namespace boostmath { struct is_arithmetic_pair> : std::conjunction, std::is_arithmetic> {}; template - struct is_vector_of_arithmetic_containers : std::false_type {}; + struct is_arithmetic_list : std::false_type {}; - template - struct is_vector_of_arithmetic_containers>> : std::is_arithmetic {}; + template + struct is_arithmetic_list> : std::is_arithmetic {}; template using is_arithmetic_container = std::disjunction, is_arithmetic_array, is_arithmetic_pair>; + template + struct is_vector_of_arithmetic_containers : std::false_type {}; + + template + struct is_vector_of_arithmetic_containers> : is_arithmetic_container {}; + + template using is_cpp11 = std::negation< std::disjunction< std::is_same>, + std::is_same>>, + std::is_same>, + std::is_same>, + std::is_same>>, + std::is_same>>, + std::is_same>, + std::is_same>, + std::is_same>, is_arithmetic_container, is_vector_of_arithmetic_containers, std::is_void diff --git a/src/quadrature_and_differentiation/numerical_differentiation.cpp b/src/quadrature_and_differentiation/numerical_differentiation.cpp index 6fb1a97..d864156 100644 --- a/src/quadrature_and_differentiation/numerical_differentiation.cpp +++ b/src/quadrature_and_differentiation/numerical_differentiation.cpp @@ -1,7 +1,8 @@ #include #include #include -#include "../boostmath/sexp.hpp" +#include "../boostmath/as_sexp.hpp" +#include "../boostmath/as_cpp.hpp" extern "C" { SEXP finite_difference_derivative_(SEXP f_, SEXP x_, SEXP order_) { diff --git a/src/rootfinding_and_minimisation/with_derivatives.cpp b/src/rootfinding_and_minimisation/with_derivatives.cpp index ddcac38..2684d09 100644 --- a/src/rootfinding_and_minimisation/with_derivatives.cpp +++ b/src/rootfinding_and_minimisation/with_derivatives.cpp @@ -1,6 +1,6 @@ #include #include -#include "../boostmath/sexp.hpp" +#include "../boostmath/as_cpp.hpp" extern "C" { SEXP newton_raphson_iterate_(SEXP f_, SEXP guess_, SEXP min_, SEXP max_, SEXP digits_, SEXP max_iter_) { @@ -65,4 +65,4 @@ extern "C" { return cpp11::as_sexp(result); END_CPP11 } -} \ No newline at end of file +} diff --git a/src/special_functions/logistic_functions.cpp b/src/special_functions/logistic_functions.cpp index 65ddeec..e50865d 100644 --- a/src/special_functions/logistic_functions.cpp +++ b/src/special_functions/logistic_functions.cpp @@ -3,4 +3,4 @@ #include "../boostmath/macros.hpp" UNARY_BOOST_FUNCTION(logit, double) -UNARY_BOOST_FUNCTION(logistic_sigmoid, double) \ No newline at end of file +UNARY_BOOST_FUNCTION(logistic_sigmoid, double)