Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/hyperjet/hyperjet.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,12 +578,14 @@ class DDScalar {
return vars;
}

template <index T>
// std::array is sized by std::size_t, so T has to be as well or the size
// can never be deduced from the argument.
template <std::size_t T>
static std::conditional_t<TSize == Dynamic, std::vector<Type>,
std::array<Type, T>>
variables(const std::array<Scalar, T> &values) {
if constexpr (!is_dynamic()) {
static_assert(T == TSize);
static_assert(index(T) == TSize);
}

const index s = length(values);
Expand All @@ -595,7 +597,7 @@ class DDScalar {
}
return vars;
} else {
std::array<Type, TSize> vars;
std::array<Type, T> vars;
for (index i = 0; i < s; i++) {
vars[i] = variable(i, values[i], s);
}
Expand Down
2 changes: 1 addition & 1 deletion python/src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ template <typename T> auto bind(py::module &m, const std::string &name) {
.def_static(
"variables",
[](const std::array<typename T::Scalar, T::static_size()> &values) {
return T::template variables<T::static_size()>(values);
return T::variables(values);
},
"values"_a);
}
Expand Down
40 changes: 40 additions & 0 deletions test/src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,43 @@ TEST_CASE("SScalar Hypot") {
REQUIRE(r2.d("y") == doctest::Approx(4.4400151526317840));
REQUIRE(r2.d("z") == doctest::Approx(2.4076700872634590));
}

// The C++ usage example from the README. Its values are pinned here so the
// example cannot silently stop compiling or start lying.

TEST_CASE("README example") {
auto [x, y] = DDScalar<2, double, 2>::variables(std::array{3.0, 6.0});

const auto f = (x * y) / (x - y);

REQUIRE(f.f() == doctest::Approx(-6.0));
REQUIRE(f.g(0) == doctest::Approx(-4.0));
REQUIRE(f.g(1) == doctest::Approx(1.0));

// the same computation as the Python quickstart, whose output the README
// shows as well
REQUIRE(f.h(0, 0) == doctest::Approx(-2.6666666666666667));
REQUIRE(f.h(0, 1) == doctest::Approx(1.3333333333333333));
REQUIRE(f.h(1, 1) == doctest::Approx(-0.6666666666666666));
}

TEST_CASE("Variables from an array") {
const auto s = DDScalar<2, double, 2>::variables(std::array{3.0, 6.0});

REQUIRE(s.size() == 2);
REQUIRE(s[0].f() == doctest::Approx(3.0));
REQUIRE(s[0].g(0) == doctest::Approx(1.0));
REQUIRE(s[0].g(1) == doctest::Approx(0.0));
REQUIRE(s[1].f() == doctest::Approx(6.0));
REQUIRE(s[1].g(0) == doctest::Approx(0.0));
REQUIRE(s[1].g(1) == doctest::Approx(1.0));

// the dynamic variant returns a vector, sized from the array
const auto d = DDScalar<2, double, Dynamic>::variables(std::array{3.0, 6.0});

REQUIRE(d.size() == 2);
REQUIRE(d[0].size() == 2);
REQUIRE(d[0].f() == doctest::Approx(3.0));
REQUIRE(d[0].g(0) == doctest::Approx(1.0));
REQUIRE(d[1].g(1) == doctest::Approx(1.0));
}
Loading