Page MenuHomec4science

operations.hh
No OneTemporary

File Metadata

Created
Fri, Mar 29, 06:04

operations.hh

/**
* @file
*
* @author Lucas Frérot <lucas.frerot@epfl.ch>
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de
* Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des
* Solides)
*
* Expolit is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Expolit 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 Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Expolit. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef OPERATIONS_HH
#define OPERATIONS_HH
#include "types.hh"
#include <functional>
#include <ostream>
#include <utility>
namespace expolit {
/**
* @brief Type for unary operation
*/
template <typename T, typename Op>
struct UnaryOperation : Expression<UnaryOperation<T, Op>> {
/// Construct from an expression
constexpr UnaryOperation(const Expression<T>& t) : expression(t.downcast()) {}
/// Evaluate operation
template <typename Val>
constexpr auto operator()(Val&& v) const {
return op(expression(v));
}
const T expression;
const Op op = Op();
};
/**
* @brief Type for binary operation
*
* Handles binary operations between two arbitrary expressions
*/
template <typename T, typename U, typename Op>
struct BinaryOperation : Expression<BinaryOperation<T, U, Op>> {
/// Construct from two expressions
constexpr BinaryOperation(const Expression<T>& t, const Expression<U>& u)
: operands(t.downcast(), u.downcast()) {}
/// Evaluate operation
template <typename Val>
constexpr auto operator()(Val&& v) const {
return op(operands.first(v), operands.second(v));
}
constexpr auto commute() const {
return BinaryOperation<U, T, Op>(operands.second, operands.first);
}
/// Product operarands
const std::pair<T, U> operands;
const Op op = Op();
};
/// Symmetric of T, U
template <typename T, typename U, typename Op>
using SBinaryOperation = BinaryOperation<U, T, Op>;
/// Product expression
template <typename T, typename U>
using Product = BinaryOperation<T, U, std::multiplies<>>;
/// Sum expression
template <typename T, typename U>
using Sum = BinaryOperation<T, U, std::plus<>>;
/// Difference expression
template <typename T, typename U>
using Difference = BinaryOperation<T, U, std::minus<>>;
/// Division expression
template <typename T, typename U>
using Division = BinaryOperation<T, U, std::divides<>>;
/* -------------------------------------------------------------------------- */
/* Algebraic rules */
/* -------------------------------------------------------------------------- */
/// Product operator
template <typename Der1, typename Der2>
constexpr auto operator*(const Expression<Der1>& e1,
const Expression<Der2>& e2) {
return Product<Der1, Der2>(e1, e2);
}
/// Sum operator
template <typename Der1, typename Der2>
constexpr auto operator+(const Expression<Der1>& e1,
const Expression<Der2>& e2) {
return Sum<Der1, Der2>(e1, e2);
}
/// Difference operator
template <typename Der1, typename Der2>
constexpr auto operator-(const Expression<Der1>& e1,
const Expression<Der2>& e2) {
return Difference<Der1, Der2>(e1, e2);
}
/// Division operator
template <typename Der1, typename Der2>
constexpr auto operator/(const Expression<Der1>& e1,
const Expression<Der2>& e2) {
return Division<Der1, Der2>(e1, e2);
}
namespace detail {
template <UInt n>
struct power_acc {
template <typename DerAcc, typename Derived>
static constexpr auto accumulate(const Expression<DerAcc>& acc,
const Expression<Derived>& e) {
return power_acc<n - 1>::accumulate(acc.downcast() * e.downcast(), e);
}
};
template <>
struct power_acc<1> {
template <typename DerAcc, typename Derived>
static constexpr auto accumulate(const Expression<DerAcc>& acc,
const Expression<Derived>&) {
return acc.downcast();
}
};
} // namespace detail
template <UInt n, typename Derived>
constexpr auto pow(const Expression<Derived>& e) {
return detail::power_acc<n>::accumulate(e, e);
}
/* -------------------------------------------------------------------------- */
/* Output */
/* -------------------------------------------------------------------------- */
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const Product<T, U>& p) {
os << "(" << p.operands.first << ")"
<< " * "
<< "(" << p.operands.second << ")";
return os;
}
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const Division<T, U>& p) {
os << "(" << p.operands.first << ")"
<< " / "
<< "(" << p.operands.second << ")";
return os;
}
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const Difference<T, U>& p) {
os << p.operands.first << " - " << p.operands.second;
return os;
}
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const Sum<T, U>& p) {
os << p.operands.first << " + " << p.operands.second;
return os;
}
} // namespace expolit
#endif

Event Timeline