Skip to content

Commit

Permalink
add math backends: arma, blaze
Browse files Browse the repository at this point in the history
  • Loading branch information
foolnotion committed May 16, 2024
1 parent dc627a3 commit c43769b
Show file tree
Hide file tree
Showing 10 changed files with 872 additions and 26 deletions.
20 changes: 16 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,22 @@ endif()

message(STATUS "MATH: ${MATH_BACKEND}")

if (MATH_BACKEND STREQUAL "Fastor")
if (MATH_BACKEND STREQUAL "Arma")
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
find_package(Armadillo REQUIRED)
target_link_libraries(operon_operon PUBLIC BLAS::BLAS LAPACK::LAPACK ${ADMADILLO_LIBRARIES})
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_ARMA)
elseif (MATH_BACKEND STREQUAL "Blaze")
find_package(blaze REQUIRED)
find_package(sleef REQUIRED)
target_link_libraries(operon_operon INTERFACE sleef::sleef)
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_BLAZE BLAZE_USE_SHARED_MEMORY_PARALLELIZATION=0 BLAZE_USE_SLEEF=1 EIGEN_DONT_PARALLELIZE)
elseif (MATH_BACKEND STREQUAL "Fastor")
find_package(Fastor REQUIRED)
target_link_libraries(operon_operon PUBLIC Fastor::Fastor)
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_FASTOR)
find_package(sleef REQUIRED)
target_link_libraries(operon_operon PUBLIC Fastor::Fastor sleef::sleef)
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_FASTOR FASTOR_USE_SLEEF_U35)
elseif (MATH_BACKEND STREQUAL "Eve")
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_EVE)
elseif (MATH_BACKEND STREQUAL "Vdt")
Expand All @@ -156,7 +168,7 @@ elseif (MATH_BACKEND STREQUAL "Vdt")
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_VDT)
elseif (MATH_BACKEND STREQUAL "Eigen")
message(STATUS "Using Eigen backend")
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_EIGEN)
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_EIGEN EIGEN_DONT_PARALLELIZE)
elseif(MATH_BACKEND STREQUAL "Stl")
target_compile_definitions(operon_operon PUBLIC OPERON_MATH_STL)
elseif (MATH_BACKEND STREQUAL "Fast_v1")
Expand Down
42 changes: 21 additions & 21 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

buildInputs = (with pkgs; [
aria-csv
armadillo
blaze
ceres-solver
cpp-sort
cxxopts
Expand All @@ -63,6 +65,7 @@
pratt-parser.packages.${system}.default
simdutf_4 # required by scnlib
scnlib
sleef
taskflow
unordered_dense
vdt.packages.${system}.default
Expand All @@ -75,6 +78,7 @@
ned14-quickcpplib
ned14-status-code
xad
xsimd
xxHash
zstd
]);
Expand Down
9 changes: 9 additions & 0 deletions include/operon/interpreter/backend/arma.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright 2019-2024 Heal Research

#ifndef OPERON_BACKEND_ARMA_HPP
#define OPERON_BACKEND_ARMA_HPP

#include "arma/derivatives.hpp"

#endif
192 changes: 192 additions & 0 deletions include/operon/interpreter/backend/arma/derivatives.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright 2019-2023 Heal Research

#ifndef OPERON_BACKEND_ARMA_DERIVATIVES_HPP
#define OPERON_BACKEND_ARMA_DERIVATIVES_HPP

#include "operon/core/node.hpp"
#include "functions.hpp"

namespace Operon::Backend {
namespace detail {
template<typename T>
inline auto IsNaN(T value) { return std::isnan(value); }

template<typename Compare>
struct FComp {
auto operator()(auto x, auto y) const {
using T = std::common_type_t<decltype(x), decltype(y)>;
if ((IsNaN(x) && IsNaN(y)) || (x == y)) {
return std::numeric_limits<T>::quiet_NaN();
}
if (IsNaN(x)) { return T{0}; }
if (IsNaN(y)) { return T{1}; }
return static_cast<T>(Compare{}(T{x}, T{y}));
}
};
} // namespace detail

template<typename T, std::size_t S>
auto Add(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> /*primal*/, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j).fill(T{1});
}

template<typename T, std::size_t S>
auto Mul(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
Col(trace, j) = Col(primal, i) / Col(primal, j);
}

template<typename T, std::size_t S>
auto Sub(std::vector<Operon::Node> const& nodes, Backend::View<T const, S> /*primal*/, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
auto v = (nodes[i].Arity == 1 || j < i-1) ? T{-1} : T{+1};
Col(trace, j).fill(v);
}

template<typename T, std::size_t S>
auto Div(std::vector<Operon::Node> const& nodes, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
auto const& n = nodes[i];
if (n.Arity == 1) {
Col(trace, j) = -T{1} / (arma::square(Col(primal, j)));
} else {
Col(trace, j) = (j == i-1 ? T{1} : T{-1}) * Col(primal, i) / Col(primal, j);
}
}

template<typename T, std::size_t S>
auto Aq(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
if (j == i-1) {
Col(trace, j) = Col(primal, i) / Col(primal, j);
} else {
Col(trace, j) = -Col(primal, j) % arma::pow(Col(primal, i), T{3}) / arma::square(Col(primal, i-1));
}
}

template<typename T, std::size_t S>
auto Pow(std::vector<Operon::Node> const& nodes, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
if (j == i-1) {
auto const k = j - (nodes[j].Length + 1);
Col(trace, j) = Col(primal, i) % Col(primal, k) / Col(primal, j);
} else {
auto const k = i-1;
Col(trace, j) = Col(primal, i) % arma::log(Col(primal, k));
}
}

template<typename T, std::size_t S>
auto Min(std::vector<Operon::Node> const& nodes, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
auto k = j == i - 1 ? (j - nodes[j].Length - 1) : i - 1;
auto const* jp = Ptr(primal, j);
auto const* kp = Ptr(primal, k);
std::transform(jp, jp+S, kp, Ptr(trace, j), detail::FComp<std::less<>>{});
}

template<typename T, std::size_t S>
auto Max(std::vector<Operon::Node> const& nodes, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
auto k = j == i - 1 ? (j - nodes[j].Length - 1) : i - 1;
auto const* jp = Ptr(primal, j);
auto const* kp = Ptr(primal, k);
std::transform(jp, jp+S, kp, Ptr(trace, j), detail::FComp<std::greater<>>{});
}

template<typename T, std::size_t S>
auto Square(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{2} * Col(primal, j);
}

template<typename T, std::size_t S>
auto Abs(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::sign(Col(primal, j));
}

template<typename T, std::size_t S>
auto Ceil(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::ceil(Col(primal, j));
}

template<typename T, std::size_t S>
auto Floor(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::floor(Col(primal, j));
}

template<typename T, std::size_t S>
auto Exp(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
Col(trace, j) = Col(primal, i);
}

template<typename T, std::size_t S>
auto Log(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} / (Col(primal, j));
}

template<typename T, std::size_t S>
auto Log1p(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} / (T{1} + Col(primal, j));
}

template<typename T, std::size_t S>
auto Logabs(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::sign(Col(primal, j)) / arma::abs(Col(primal, j));
}

template<typename T, std::size_t S>
auto Sin(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::cos(Col(primal, j));
}

template<typename T, std::size_t S>
auto Cos(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = -arma::sin(Col(primal, j));
}

template<typename T, std::size_t S>
auto Tan(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} + arma::square(arma::tan(Col(primal, j)));
}

template<typename T, std::size_t S>
auto Sinh(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::cosh(Col(primal, j));
}

template<typename T, std::size_t S>
auto Cosh(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = arma::sinh(Col(primal, j));
}

template<typename T, std::size_t S>
auto Tanh(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} - arma::square(arma::tanh(Col(primal, j)));
}

template<typename T, std::size_t S>
auto Asin(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} / (arma::sqrt(T{1} - arma::square(Col(primal, j))));
}

template<typename T, std::size_t S>
auto Acos(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = -T{1} / (arma::sqrt(((T{1} - arma::square(Col(primal, j))))));
}

template<typename T, std::size_t S>
auto Atan(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto /*i*/, std::integral auto j) {
Col(trace, j) = T{1} / (T{1} + arma::square(Col(primal, j)));
}

template<typename T, std::size_t S>
auto Sqrt(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
Col(trace, j) = T{1} / (T{2} * Col(primal, i));
}

template<typename T, std::size_t S>
auto Sqrtabs(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
Col(trace, j) = arma::sign(Col(primal, j)) / (T{2} * Col(primal, i));
}

template<typename T, std::size_t S>
auto Cbrt(std::vector<Operon::Node> const& /*nodes*/, Backend::View<T const, S> primal, Backend::View<T> trace, std::integral auto i, std::integral auto j) {
Col(trace, j) = T{1} / (T{3} * arma::square(Col(primal, i)));
}
} // namespace Operon::Backend

#endif
Loading

0 comments on commit c43769b

Please sign in to comment.