Re: [eigen] inverse unit test

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]




On Thu, Jun 10, 2010 at 9:14 AM, Hauke Heibel <hauke.heibel@xxxxxxxxxxxxxx> wrote:
Granted, the proposed solution is too lax though it is only happening
in the vicinity of zero.

Here is an alternative. Why not introduce another test that is used in
particular for those cases where we want to check against being close
to zero?

static inline bool isApproxZero(const Scalar& x, const
RealScalar& thresh = NumTraits<Scalar>::epsilon())
{
 ei_abs(x) < thresh);
}

VERIFY_IS_APPROX_ZERO(something_near_zero)
VERIFY(isApproxZero(something_near_zero))


"close to zero" compared to what? I mean the notion of "close to zero" has to be defined relatively to some reference values. For instance 1 can be considered to be zero if you consider float values in the order of 1e10.  This is exactly the purpose of isMuchSmallerThan(x,ref) which could also be called isZeroComparedTo. So no need for an additional isApproxZero.

gael
 

- Hauke

On Thu, Jun 10, 2010 at 1:05 AM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:
> 2010/6/9 Hauke Heibel <hauke.heibel@xxxxxxxxxxxxxx>:
>> Maybe this simple hack is all we need:
>>
>> static inline bool isApprox(const Scalar& x, const Scalar& y, const
>> RealScalar& prec)
>> {
>>  return (ei_abs(x - y) <= std::min(ei_abs(x), ei_abs(y)) * prec ||
>> ei_abs(x - y) < NumTraits<Scalar>::epsilon());
>> }
>
> No, that is not correct to do in such generality (at the level of
> isApprox), because it would imply that
>
>   isApprox(1e-10, 1e-30) == true
>
> even though these values are very different (one is 1e+20 bigger than
> the other). Our FP fuzzy compares are completely 'relative', they do
> not declare any particular order of magnitude to be 'negligible'.
>
> But you are right: any comparison of the form
>
>  VERIFY_IS_APPROX(something_near_zero, something_else_near_zero)
>
> is inherently bogus, since, as you noted, it fails when these values
> are actually exactly zero. The fix is going to look what you suggest
> above, except that it must be local to this unit-test and not
> generalized to isApprox(). In the particular context of the unit test,
> we have a good frame of reference to compare the difference with,
> namely, let's just compare it with 1. So, replace
>
>   VERIFY_IS_APPROX(x, y)
>
> by
>
>  VERIFY_IS_MUCH_SMALLER_THAN( x-y, 1)
>
> Cheers,
> Benoit
>
>>
>> - Hauke
>>
>> On Thu, Jun 10, 2010 at 12:43 AM, Hauke Heibel
>> <hauke.heibel@xxxxxxxxxxxxxx> wrote:
>>> On MSVC the inverse unit test fails here:
>>>
>>>  //Second: a rank one matrix (not invertible, except for 1x1 matrices)
>>>  VectorType v3 = VectorType::Random(rows);
>>>  MatrixType m3 = v3*v3.transpose(), m4(rows,cols);
>>>  m3.computeInverseAndDetWithCheck(m4, det, invertible);
>>>  VERIFY( rows==1 ? invertible : !invertible );
>>>  VERIFY_IS_APPROX(det, m3.determinant());
>>>  m3.computeInverseWithCheck(m4, invertible);
>>>  VERIFY( rows==1 ? invertible : !invertible );
>>>
>>> We expect a determinant of 0 since the matrix is not invertible and
>>> then this check fails
>>>
>>>  VERIFY_IS_APPROX(det, m3.determinant());
>>>
>>> VERIFY_IS_APPROX will always fail in case one of the two parameters is
>>> zero and in case both values are small it is likely to fail as well
>>> because
>>>
>>> abs(x-y) <= min(abs(x),abs(y)) * 1e-3
>>>
>>> here, we take the minimal value and make it even smaller.
>>>
>>> Here are some nice comparison methods we might try to adapt:
>>> http://www.boost.org/doc/libs/1_32_0/boost/test/floating_point_comparison.hpp
>>>
>>> - Hauke
>>>
>>
>>
>>
>
>
>





Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/