nk 1.0.0
C++ Numerical Computing Runtime
Loading...
Searching...
No Matches
callback_eval.hpp
1// ops/callback_eval.hpp
2//
3// Thin Value<->double wrappers around a nk::FnHandle MATLAB-style callback,
4// so the ops iterative solver kernels (root_solve: brent/findBracket/brentMin/
5// nelderMead) can run in native double precision while the public objective
6// stays a generic `void(Span<const Value>, Span<Value>)` handle. Core-free
7// (value layer only); FnHandle is value/fn_handle.hpp (L0).
8
9#pragma once
10
11#include <cstddef>
12#include <memory_resource>
13#include <nk/value/error.hpp>
14#include <nk/value/fn_handle.hpp>
15#include <nk/value/span.hpp>
16#include <nk/value/value.hpp>
17#include <utility>
18
19namespace nk::ops {
20
23inline double evalScalar(FnHandle fn, double x, std::pmr::memory_resource *mr)
24{
25 Value arg = Value::scalar(x, mr);
26 Value out;
27 Span<const Value> args(&arg, 1);
28 Span<Value> outs(&out, 1);
29 fn(args, outs, mr);
30 if (!out.isScalar() && out.numel() != 1)
31 throw Error("callback: handle must return a scalar value", 0, 0, "callback", "",
32 "nk:callback:nonScalar");
33 return out.elemAsDouble(0);
34}
35
38inline double evalVecToScalar(FnHandle fn, const double *x, std::size_t n,
39 std::pmr::memory_resource *mr)
40{
41 Value v = Value::matrix(1, n, ValueType::DOUBLE, mr);
42 if (n) {
43 double *d = v.doubleDataMut();
44 for (std::size_t i = 0; i < n; ++i) d[i] = x[i];
45 }
46 Value out;
47 Value args[1] = {std::move(v)};
48 fn(Span<const Value>(args, 1), Span<Value>(&out, 1), mr);
49 return out.toScalar();
50}
51
52} // namespace nk::ops