]> git.lizzy.rs Git - minetest.git/blobdiff - src/noise.cpp
CollisionMoveSimple: Collide with 'ignore' nodes
[minetest.git] / src / noise.cpp
index c57c98ccbb8480a45b0d2997bfa268d8921492fb..8b84803b392ba014de32c5f184916e6c4a659975 100644 (file)
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <math.h>
+#include <cmath>
 #include "noise.h"
 #include <iostream>
-#include <string.h> // memset
+#include <cstring> // memset
 #include "debug.h"
 #include "util/numeric.h"
 #include "util/string.h"
@@ -47,8 +47,8 @@ typedef float (*Interp3dFxn)(
                float x, float y, float z);
 
 float cos_lookup[16] = {
-       1.0,  0.9238,  0.7071,  0.3826, 0, -0.3826, -0.7071, -0.9238,
-       1.0, -0.9238, -0.7071, -0.3826, 0,  0.3826,  0.7071,  0.9238
+       1.0f,  0.9238f,  0.7071f,  0.3826f, .0f, -0.3826f, -0.7071f, -0.9238f,
+       1.0f, -0.9238f, -0.7071f, -0.3826f, .0f,  0.3826f,  0.7071f,  0.9238f
 };
 
 FlagDesc flagdesc_noiseparams[] = {
@@ -93,22 +93,31 @@ u32 PcgRandom::range(u32 bound)
        // If the bound is 0, we cover the whole RNG's range
        if (bound == 0)
                return next();
+
        /*
-       If the bound is not a multiple of the RNG's range, it may cause bias,
-       e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
-       Using rand() % 3, the number 0 would be twice as likely to appear.
-       With a very large RNG range, the effect becomes less prevalent but
-       still present.  This can be solved by modifying the range of the RNG
-       to become a multiple of bound by dropping values above the a threshold.
-       In our example, threshold == 4 - 3 = 1 % 3 == 1, so reject 0, thus
-       making the range 3 with no bias.
-
-       This loop looks dangerous, but will always terminate due to the
-       RNG's property of uniformity.
+               This is an optimization of the expression:
+                 0x100000000ull % bound
+               since 64-bit modulo operations typically much slower than 32.
        */
        u32 threshold = -bound % bound;
        u32 r;
 
+       /*
+               If the bound is not a multiple of the RNG's range, it may cause bias,
+               e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
+               Using rand() % 3, the number 0 would be twice as likely to appear.
+               With a very large RNG range, the effect becomes less prevalent but
+               still present.
+
+               This can be solved by modifying the range of the RNG to become a
+               multiple of bound by dropping values above the a threshold.
+
+               In our example, threshold == 4 % 3 == 1, so reject values < 1
+               (that is, 0), thus making the range == 3 with no bias.
+
+               This loop may look dangerous, but will always terminate due to the
+               RNG's property of uniformity.
+       */
        while ((r = next()) < threshold)
                ;
 
@@ -121,7 +130,9 @@ s32 PcgRandom::range(s32 min, s32 max)
        if (max < min)
                throw PrngException("Invalid range (max < min)");
 
-       u32 bound = max - min + 1;
+       // We have to cast to s64 because otherwise this could overflow,
+       // and signed overflow is undefined behavior.
+       u32 bound = (s64)max - (s64)min + 1;
        return range(bound) + min;
 }
 
@@ -251,8 +262,8 @@ float noise2d_gradient(float x, float y, s32 seed, bool eased)
        // Interpolate
        if (eased)
                return biLinearInterpolation(v00, v10, v01, v11, xl, yl);
-       else
-               return biLinearInterpolationNoEase(v00, v10, v01, v11, xl, yl);
+
+       return biLinearInterpolationNoEase(v00, v10, v01, v11, xl, yl);
 }
 
 
@@ -281,12 +292,12 @@ float noise3d_gradient(float x, float y, float z, s32 seed, bool eased)
                        v000, v100, v010, v110,
                        v001, v101, v011, v111,
                        xl, yl, zl);
-       } else {
-               return triLinearInterpolationNoEase(
-                       v000, v100, v010, v110,
-                       v001, v101, v011, v111,
-                       xl, yl, zl);
        }
+
+       return triLinearInterpolationNoEase(
+               v000, v100, v010, v110,
+               v001, v101, v011, v111,
+               xl, yl, zl);
 }
 
 
@@ -424,10 +435,6 @@ Noise::Noise(NoiseParams *np_, s32 seed, u32 sx, u32 sy, u32 sz)
        this->sy   = sy;
        this->sz   = sz;
 
-       this->persist_buf  = NULL;
-       this->gradient_buf = NULL;
-       this->result       = NULL;
-
        allocBuffers();
 }
 
@@ -771,7 +778,7 @@ float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
 
 
 void Noise::updateResults(float g, float *gmap,
-       float *persistence_map, size_t bufsize)
+       const float *persistence_map, size_t bufsize)
 {
        // This looks very ugly, but it is 50-70% faster than having
        // conditional statements inside the loop