Skip to content

Commit 530376e

Browse files
authored
Differentiate between exp and expm1 (#15)
* need to differentiate between exp and exp1m because it provides different usecases.
1 parent faf23b6 commit 530376e

File tree

3 files changed

+75
-12
lines changed

3 files changed

+75
-12
lines changed

src/CubicInterpolation/Axis.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ template <typename T> std::ostream &operator<<(std::ostream &out, const Axis<T>
8181
/**
8282
* @brief Exponential axis to interpolate over many different scales. As basis
8383
* the euler number choosen by default if no further specified. Nodes will
84-
* distributed in form of \f$ \text{low} \cdot (\exp(n \cdot \text{stepsize} + \log(2)) - 1) \f$
84+
* distributed in form of \f$ \exp(n \cdot \text{stepsize}) \f$
8585
*/
8686
template <typename T> class ExpAxis : public Axis<T> {
8787

@@ -109,6 +109,32 @@ template <typename T> class ExpAxis : public Axis<T> {
109109
T back_derive(T t) const final;
110110
};
111111

112+
/**
113+
* @brief Exponential axis to interpolate over many different scales. As basis
114+
* the euler number choosen by default if no further specified. Nodes will
115+
* distributed in form of \f$ \text{low} \cdot (\exp(n \cdot \text{stepsize} + \log(2)) -
116+
* 1) \f$
117+
*/
118+
template <typename T> class ExpM1Axis : public Axis<T> {
119+
120+
void print(std::ostream &os) const {
121+
os << "ExpM1Axis(";
122+
Axis<T>::print(os);
123+
os << ")";
124+
}
125+
126+
public:
127+
ExpM1Axis(T _low, T _high, T _stepsize = 1);
128+
129+
ExpM1Axis(T _low, T _high, size_t _nodes);
130+
131+
T transform(T x) const final;
132+
T back_transform(T t) const final;
133+
134+
T derive(T x) const final;
135+
T back_derive(T t) const final;
136+
};
137+
112138
/**
113139
* @brief Linear axis to describe data which varify not to much in orders of
114140
* magnitudes. It's the fastest axis evaluation.

src/detail/Axis.cxx

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,64 @@ template <typename T> unsigned int Axis<T>::required_nodes() const {
1111
return std::round(transform(high) + 1u);
1212
}
1313

14+
//
15+
// Exp Axis
16+
//
17+
1418
template <typename T>
1519
ExpAxis<T>::ExpAxis(T _low, T _high, T _stepsize) : Axis<T>(_low, _high, _stepsize) {}
1620

1721
template <typename T>
1822
ExpAxis<T>::ExpAxis(T _low, T _high, size_t _nodes) : Axis<T>(_low, _high, 0.f) {
19-
this->stepsize = (std::log1p(_high / _low) - M_LN2) / static_cast<T>(_nodes - 1);
23+
this->stepsize = std::log(_high / _low) / static_cast<T>(_nodes - 1);
2024
}
2125

2226
template <typename T> T ExpAxis<T>::transform(T x) const {
23-
return (std::log1p(x / this->low) - M_LN2) / this->stepsize;
27+
return std::log(x / this->low) / this->stepsize;
2428
}
2529

2630
template <typename T> T ExpAxis<T>::back_transform(T t) const {
27-
return this->low * std::expm1(t * this->stepsize + M_LN2);
31+
return this->low * std::exp(t * this->stepsize);
2832
}
2933
template <typename T> T ExpAxis<T>::derive(T x) const {
30-
return 1. / (this->stepsize * (x + this->low));
34+
return 1. / (x * this->stepsize);
3135
}
3236

3337
template <typename T> T ExpAxis<T>::back_derive(T t) const {
38+
return this->low * this->stepsize * std::exp(t * this->stepsize);
39+
}
40+
41+
//
42+
// ExpM1 Axis
43+
//
44+
45+
template <typename T>
46+
ExpM1Axis<T>::ExpM1Axis(T _low, T _high, T _stepsize) : Axis<T>(_low, _high, _stepsize) {}
47+
48+
template <typename T>
49+
ExpM1Axis<T>::ExpM1Axis(T _low, T _high, size_t _nodes) : Axis<T>(_low, _high, 0.f) {
50+
this->stepsize = (std::log1p(_high / _low) - M_LN2) / static_cast<T>(_nodes - 1);
51+
}
52+
53+
template <typename T> T ExpM1Axis<T>::transform(T x) const {
54+
return (std::log1p(x / this->low) - M_LN2) / this->stepsize;
55+
}
56+
57+
template <typename T> T ExpM1Axis<T>::back_transform(T t) const {
58+
return this->low * std::expm1(t * this->stepsize + M_LN2);
59+
}
60+
template <typename T> T ExpM1Axis<T>::derive(T x) const {
61+
return 1. / (this->stepsize * (x + this->low));
62+
}
63+
64+
template <typename T> T ExpM1Axis<T>::back_derive(T t) const {
3465
return this->low * this->stepsize * std::exp(t * this->stepsize + M_LN2);
3566
}
3667

68+
//
69+
// LinAxis
70+
//
71+
3772
template <typename T>
3873
LinAxis<T>::LinAxis(T _low, T _high, T _stepsize) : Axis<T>(_low, _high, _stepsize) {}
3974

@@ -60,4 +95,6 @@ template class LinAxis<double>;
6095
template class LinAxis<float>;
6196
template class ExpAxis<double>;
6297
template class ExpAxis<float>;
98+
template class ExpM1Axis<double>;
99+
template class ExpM1Axis<float>;
63100
} // namespace cubic_splines

tests/TestCubicSplines.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ TEST(CubicSplines, evaluate_exp_distributed_nodes) {
9292
auto func = [](double x) { return std::exp(x); };
9393
auto def = spline_def_t();
9494
def.f = func;
95-
def.axis = std::make_unique<cubic_splines::ExpAxis<double>>(low, high, N);
95+
def.axis = std::make_unique<cubic_splines::ExpM1Axis<double>>(low, high, N);
9696
auto spline = cubic_splines::Interpolant<spline_t>(std::move(def), "", "");
9797
std::uniform_real_distribution<double> dis(low, high);
9898
for (int i = 0; i < 10'000; ++i) {
@@ -108,8 +108,8 @@ TEST(CubicSplines, evaluate_log_func_values_and_axis) {
108108
auto def = spline_def_t();
109109
auto func = [](double x) { return x*x*std::log(x); };
110110
def.f = func;
111-
def.f_trafo = std::make_unique<cubic_splines::ExpAxis<double>>(1, 0);
112-
def.axis = std::make_unique<cubic_splines::ExpAxis<double>>(low, high, N);
111+
def.f_trafo = std::make_unique<cubic_splines::ExpM1Axis<double>>(1, 0);
112+
def.axis = std::make_unique<cubic_splines::ExpM1Axis<double>>(low, high, N);
113113
auto spline = cubic_splines::Interpolant<spline_t>(std::move(def), "", "");
114114
std::uniform_real_distribution<double> dis(low, high);
115115
for (int i = 0; i < 10'000; ++i) {
@@ -126,8 +126,8 @@ TEST(CubicSplines, evaluate_log_func_values_and_axis_trivial_integrand) {
126126
// this function should be a straight line in the transformed space
127127
auto func = [](double x) { return std::pow(x+1, 10); };
128128
def.f = func;
129-
def.f_trafo = std::make_unique<cubic_splines::ExpAxis<double>>(1, 0);
130-
def.axis = std::make_unique<cubic_splines::ExpAxis<double>>(low, high, N);
129+
def.f_trafo = std::make_unique<cubic_splines::ExpM1Axis<double>>(1, 0);
130+
def.axis = std::make_unique<cubic_splines::ExpM1Axis<double>>(low, high, N);
131131
auto spline = cubic_splines::Interpolant<spline_t>(std::move(def), "", "");
132132
std::uniform_real_distribution<double> dis(low, high);
133133
for (int i = 0; i < 10'000; ++i) {
@@ -161,7 +161,7 @@ TEST(CubicSplines, prime_x_trafo) {
161161
auto func = [](double x) { return x * x + x + 1; };
162162
auto df_dx = [](double x) { return 2 * x + 1; };
163163
def.f = func;
164-
def.axis = std::make_unique<cubic_splines::ExpAxis<double>>(low, high, N);
164+
def.axis = std::make_unique<cubic_splines::ExpM1Axis<double>>(low, high, N);
165165
auto spline = cubic_splines::Interpolant<spline_t>(std::move(def), "", "");
166166
std::uniform_real_distribution<double> dis(low, high);
167167
for (int i = 0; i < 10'000; ++i) {
@@ -178,7 +178,7 @@ TEST(CubicSplines, prime_y_trafo) {
178178
auto func = [](double x) { return x * x + x + 1; };
179179
auto df_dx = [](double x) { return 2 * x + 1; };
180180
def.f = func;
181-
def.f_trafo = std::make_unique<cubic_splines::ExpAxis<double>>(1, 0);
181+
def.f_trafo = std::make_unique<cubic_splines::ExpM1Axis<double>>(1, 0);
182182
def.axis = std::make_unique<cubic_splines::LinAxis<double>>(low, high, N);
183183
auto spline = cubic_splines::Interpolant<spline_t>(std::move(def), "", "");
184184
std::uniform_real_distribution<double> dis(low, high);

0 commit comments

Comments
 (0)