fvar<T> divide by zero - nan return?

Come across something, just wanted to check if this was expected behaviour.

When dividing an fvar<double> by a double, the operator is defined as:

template <typename T>
inline fvar<T> operator/(const fvar<T>& x1, double x2) {
  return fvar<T>(x1.val_ / x2, x1.d_ / x2);
}

That is, the calculated derivative should only depend on the input derivative, and not the input value. But this isn’t the case when dividing by zero. If an fvar<double> has value 0 (e.g. fvar<double>(0.0,1.0)), then dividing by zero results in nan for both the value and derivative:

#include <stan/math/fwd/core.hpp>
#include <iostream>

int main() {
  using stan::math::fvar;

  fvar<double> fv01(0.0,1.0);
  fvar<double> fv10(1.0,0.0);
  fvar<double> fv11(1.0,1.0);
  fvar<double> out = fv01 / 0.0;
  fvar<double> out2 = fv11 / 0.0;
  fvar<double> out3 = fv10 / 0.0;

  std::cout << "fvar<double>(0.0,1.0) / 0.0:" << std::endl << "val:" << out.val_ 
            << std::endl << "d:" << out.d_ << std::endl;

  std::cout << "fvar<double>(1.0,0.0) / 0.0:" << std::endl << "val:" << out3.val_ 
            << std::endl << "d:" << out3.d_ << std::endl;

  std::cout << "fvar<double>(1.0,1.0) / 0.0:" << std::endl << "val:" << out2.val_ 
            << std::endl << "d:" << out2.d_ << std::endl;
}

Results in:

fvar<double>(0.0,1.0) / 0.0:
val_:nan
d_:nan

fvar<double>(1.0,0.0) / 0.0:
val_:inf
d_:nan

fvar<double>(1.0,1.0) / 0.0:
val_:inf
d_:inf

Is this correct or is this a bug?

I think for fvar we set the derivative to NaN if the value is NaN. This is expensive to do, but we did it to make sure errors can be trapped quickly as we’re developing forward mode.

And I just verified that this is the behavior we have by looking at the source: https://github.com/stan-dev/math/blob/develop/stan/math/fwd/core/fvar.hpp#L87

Ah that clears things up, thanks for checking that

1 Like

Yes, that’s what’s being done now in the constructor.

I don’t think it’s worth the cost and should be changed in the future if we want performant forward-mode.

1 Like

Agreed.