mitsuba-renderer / drjit

Dr.Jit — A Just-In-Time-Compiler for Differentiable Rendering
BSD 3-Clause "New" or "Revised" License
593 stars 43 forks source link

Bug in cbrt function for input values of 0 #160

Closed Microno95 closed 1 year ago

Microno95 commented 1 year ago

There is a bug in the cbrt function implementation where if the input value is 0, i.e. the mantissa extracted from the input has a value of exactly 0, the resulting output is exactly 0.337986261.

This occurs because the polynomial approximation to the cube root of the mantissa gives a value of 0.402389795 which is very far off. This is normally not an issue because for all non-zero values, the range of inputs to the polynomial approximation is in [0.5, 1), but this guarantee is broken for the case of 0.

https://github.com/mitsuba-renderer/drjit/blob/8af56c1d5553c4497dfba0a4409290c4051199b5/include/drjit/math.h#L1446-L1450

Putting that value through the newton-raphson iterations improves the result, but still gives an approximation to the cube root too far away from the true value and thus leads to a final result that is wildly incorrect.

The python API obfuscates this issue because it falls back on math.pow(arg, 1/3) whenever the individual elements of the input are not an array type. e.g. when used in a mitsuba3 scalar_* variant context.

https://github.com/mitsuba-renderer/drjit/blob/8af56c1d5553c4497dfba0a4409290c4051199b5/drjit/router.py#L2899-L2902

I believe a simple solution would be to change the select condition from isfinite(x) to isfinite(x) && neq(x, 0) here:

https://github.com/mitsuba-renderer/drjit/blob/8af56c1d5553c4497dfba0a4409290c4051199b5/include/drjit/math.h#L1467

njroussel commented 1 year ago

Hi @Microno95

Thank you for the detailed bug report :pray:. I pushed a fix in https://github.com/mitsuba-renderer/drjit/commit/98fb5be8ace4e3c2aace0467f5c7520900ee5b91