limes 3.1.0
Composable Calculus Expressions for C++20
Loading...
Searching...
No Matches
pow.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4#include <string>
5#include <cstddef>
6#include <cmath>
7#include "binary.hpp"
8
9namespace limes::expr {
10
11template<typename E, int N> struct Pow;
12
13template<typename E> inline constexpr bool is_pow_v = false;
14template<typename E, int N> inline constexpr bool is_pow_v<Pow<E, N>> = true;
15
16template<typename E> struct pow_base { using type = void; };
17template<typename E, int N> struct pow_base<Pow<E, N>> { using type = E; };
18template<typename E> using pow_base_t = typename pow_base<E>::type;
19
20template<typename E> inline constexpr int pow_exponent_v = 0;
21template<typename E, int N> inline constexpr int pow_exponent_v<Pow<E, N>> = N;
22
23// Pow<E, N>: Expression raised to a compile-time integer power N
24template<typename E, int N>
25struct Pow {
26 using value_type = typename E::value_type;
27 using base_type = E;
28 static constexpr std::size_t arity_v = E::arity_v;
29 static constexpr int exponent = N;
30
32
33 constexpr explicit Pow(E b) noexcept : base{b} {}
34
35 [[nodiscard]] constexpr value_type eval(std::span<value_type const> args) const {
36 if constexpr (N == 0) {
37 return value_type(1);
38 } else if constexpr (N == 1) {
39 return base.eval(args);
40 } else if constexpr (N == 2) {
41 auto v = base.eval(args);
42 return v * v;
43 } else if constexpr (N == 3) {
44 auto v = base.eval(args);
45 return v * v * v;
46 } else {
47 return std::pow(base.eval(args), N);
48 }
49 }
50
51 [[nodiscard]] [[deprecated("use eval() instead")]]
52 constexpr value_type evaluate(std::span<value_type const> args) const {
53 return eval(args);
54 }
55
56 // Power rule: d/dx[u^n] = n * u^(n-1) * du/dx
57 template<std::size_t Dim>
58 [[nodiscard]] constexpr auto derivative() const {
59 auto du = base.template derivative<Dim>();
60
61 if constexpr (N == 0) {
62 return Zero<value_type>{};
63 } else if constexpr (N == 1) {
64 return du;
65 } else if constexpr (N == 2) {
66 return Const<value_type>{value_type(2)} * base * du;
67 } else {
68 return Const<value_type>{value_type(N)} * Pow<E, N-1>{base} * du;
69 }
70 }
71
72 [[nodiscard]] std::string to_string() const {
73 return "(^ " + base.to_string() + " " + std::to_string(N) + ")";
74 }
75};
76
77// Factory: pow<N>(expr) with compile-time simplification
78template<int N, typename E>
79 requires is_expr_node_v<E>
80[[nodiscard]] constexpr auto pow(E e) {
81 if constexpr (N == 0) {
83 } else if constexpr (N == 1) {
84 return e;
85 } else {
86 return Pow<E, N>{e};
87 }
88}
89
90template<typename E>
91 requires is_expr_node_v<E>
92[[nodiscard]] constexpr auto square(E e) {
93 return Pow<E, 2>{e};
94}
95
96template<typename E>
97 requires is_expr_node_v<E>
98[[nodiscard]] constexpr auto cube(E e) {
99 return Pow<E, 3>{e};
100}
101
102} // namespace limes::expr
Expression layer for composable calculus.
Definition analysis.hpp:7
constexpr bool is_pow_v
Definition pow.hpp:13
constexpr int pow_exponent_v
Definition pow.hpp:20
typename pow_base< E >::type pow_base_t
Definition pow.hpp:18
constexpr auto square(E e)
Definition pow.hpp:92
constexpr auto cube(E e)
Definition pow.hpp:98
constexpr auto pow(L base, R exponent)
typename E::value_type value_type
Definition pow.hpp:26
constexpr auto derivative() const
Definition pow.hpp:58
constexpr Pow(E b) noexcept
Definition pow.hpp:33
static constexpr std::size_t arity_v
Definition pow.hpp:28
constexpr value_type eval(std::span< value_type const > args) const
Definition pow.hpp:35
static constexpr int exponent
Definition pow.hpp:29
constexpr value_type evaluate(std::span< value_type const > args) const
Definition pow.hpp:52
std::string to_string() const
Definition pow.hpp:72