Forward Mode

When using forward mode, we only have three choices of activity values, Dual, DualOnly and Const. Dual arguments get a second "shadow" variable. Usually we will only seed the shadow variable of one Dual input to one and all others to zero, and then read the shadow values of our output arguments. We can also seed more then one input shadow, in which case the shadow of output variables will be a linear combination based on the seed values. If we use a &mut reference as input and output argument and mark it as Dual, the corresponding shadow seed might get overwritten. Otherwise, the seed value will remain unchanged.

ActivityDualDualOnlyConst
Non integer input TAccept T,TAccept byVal(T), TUnchanged
Integer scalar inputN/AN/AUnchanged
f32 or f64 output TReturn (T,T)Return TUnchanged
Other output typesN/AN/AUnchanged

DualOnly is a potentially faster version of Dual.

When applied to a return type, it will cause the primal return to not be computed. So in the case of fn f(x: f32) -> f32 { x * x }, we would now only return 2.0 * x, instead of (x * x, 2.0 * x), which we would get with Dual.

In the case of an input variable, DualOnly will cause the first value to be passed by Value, even when passed by Reference in the original function. So fn f(x: &f32, out: &mut f32) {..} would become fn df(x: f32, dx &mut f32, out: f32, dout: &mut f32) {..}.
This makes x and out inaccessible for the user, so we can use it as buffer and potentially skip certain computations. This is mostly valuable for larger Types, or more complex functions.