Re: [AD] div-by-zero... math3d.c |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Vincent Penquerc'h wrote:
against this sort of stupidity, but users that pass "small
vectors" to a
function should be aware of a possible crash.
They should be aware of it, even if the docs don't mention it.
Normalization of a vector does not change its orientation, and
the zero vector has no orientation. Mathematically, it is not
possible to normalize the zero vector. Unless you consider any
unit vector to be a valid normalization of the zero vector.
I think you are right about the zero vector, we may well leave the
result undefined. But I also think the current implementation may give
strange results for vectors close to but different from zero, because if
their squares are zero then vector_length() returns zero. What about
the following algorithm:
void normalize_vector_f(float *x, float *y, float *z)
{
float length = vector_length_f(*x, *y, *z);
float scale;
if (length == 0.0f) {
float max = MAX(ABS(*x), MAX(ABS(*y), ABS(*z)));
float max_inv = 1/max;
*x *= max;
*y *= max;
*z *= max;
length = vector_length_f(*x, *y, *z);
}
scale = 1.0 / length;
*x *= scale;
*y *= scale;
*z *= scale;
}
It's untested, but I think it should work:
1. If length == 0.0 in the if(), then one of two things has happened:
1.1. All arguments were 0. Then max becomes zero, and everything
returned is NaN. This is ok: you're not allowed to pass all
arguments zero.
1.2. At least one argument was different from zero, but all
arguments were so small that their squares are zero. Then we
first scale up the arguments so that the biggest (in absolute
value) is +-1.0, and normalize the result.
2. If length > 0.0 in the if(), then at least one argument is so big
that its square is nonzero. Hence length is also so big that its
square is nonzero. Thus length is already moderately far away from
zero and the rest of the code should be ok.
Also, the new test shouldn't add too much relative speed penalty, since
we are already doing a square root. I don't think we need to bother
about speed in the rare case that the if()'s condition evaluates to true.
Sven