I am currently fighting with templates and hyperdual numbers. I really want that for splines.
The idea is:
HyperDual is defined as a dual number with template types for real and dual parts. In practice, real part will be Base::DualNumber, and the dual part is either another DualNumber, or a hyperdual number itself.
The main use is to implement a ParaCurve::value method with hyperdual numbers, in order to support automatic computation of derivatives by U. Base::DualNumbers are for tracking solver-parameter derivatives, while the hyperdual's dual part is for tracking derivatives by U.
I'll simplify that, let's forget about derivatives by solver parameters for a moment.
If we compute
value(U) with doubles, we get just the value, no derivatives.
If we compute
value(HyperDual<double, double>(U, 1.0)), we get first derivative of the
value function, in addition to the value of the function.
If we compute
value(HyperDual<double, HyperDual<double, double> >(U, HyperDual<..>(1.0, 1.0))), we also get second derivative by U, as
value(...).du.du.
And so on, we can implicitly compute higher derivatives, although i think it will blow up into so much code that it gets inefficient.
Now, if I replace all
double's here with Base::DualNumber, I magically combine derivatives by U with derivatives by solver parameters.
Now comes the trick question. How do I implement math and operators, that support combinations between HyperDual<>, DualNumber and
double? Combinations between different flavors of HyperDuals should not be allowed, but all other combinations are. HyperDuals will always be built from
Base::DualNumber, there will never be a
double in hyperduals in practice.
I don't have any specific questions "how do I ...", i'm just trying to get a some comprehension of how to implement it. I haven't even ruled out manual definition of the hyperdual classes (it is certainly more writing and a lot of copy-pasting, but feels like it is going to be more readable)
Okay, while I was writing that down, i realized i don't need the type of real part of hyperduals be templated. Only the dual parts.
One specific question that I have is how to prevent C++ from trying to recursively call the function being implemented in situations like this:
Code: Select all
inline DualNumber sqrt(DualNumber x){
double re = ::sqrt(x.re);
return DualNumber(re, x.du * 0.5 / re);
}
This time, ::sqrt won't cut it, as I would need to call FCS::sqrt, possibly a (different) template version of one.