192 4. 3D Math for Games
On some CPUs, the code shown above can be optimized even further by
using a rather handy multiply-and-add instruction, usually denoted madd. This
instruction multiplies its fi rst two arguments and then adds the result to its
third argument. Unfortunately SSE doesn’t support a madd instruction, but we
can fake it reasonably well with a macro like this:
#define_mm_madd_ps(a, b, c) \
_mm_add_ps(_mm_mul_ps((a), (b)), (c))
__m128 mulVectorMatrixFinal(__m128 v,
__m128 Mrow1, __m128 Mrow2,
__m128 Mrow3, __m128 Mrow4)
{
__m128 result;
result = _mm_mul_ps (_mm_replicate_x_ps(v), Mrow1);
result = _mm_madd_ps(_mm_replicate_y_ps(v), Mrow2,
result);
result = _mm_madd_ps(_mm_replicate_z_ps(v), Mrow3,
result);
result = _mm_madd_ps(_mm_replicate_w_ps(v), Mrow4,
result);
return result;
}
We can of course perform matrix-matrix multiplication using a similar
approach. Check out htt p://msdn.microsoft .com for a full listing of the SSE
intrinsics for the Microsoft Visual Studio compiler.
4.8 Random Number Generation
Random numbers are ubiquitous in game engines, so it behooves us to have
a brief look at the two most common random number generators, the linear
congruential generator and the Mersenne Twister. It’s important to realize that
random number generators are just very complicated but totally deterministic
pre-defi ned sequences of numbers. For this reason, we call the sequences they
produce pseudo-random. What diff erentiates a good generator from a bad one
is how long the sequence of numbers is before it repeats (its period), and how
well the sequences hold up under various well-known randomness tests.
4.8.1. Linear Congruential Generators
Linear congruential generators are a very fast and simple way to generate a
sequence of pseudo-random numbers. Depending on the platform, this algo-
rithm is sometimes used in the standard C library’s rand() function. How-