Bläddra i källkod

math: move rand() to its own header, ensure it only returns

positive values, and add a unit test for rand<int>.
legacy
Sam Hocevar sam 11 år sedan
förälder
incheckning
700520d4d6
16 ändrade filer med 219 tillägg och 113 borttagningar
  1. +7
    -6
      src/Makefile.am
  2. +6
    -6
      src/core.h
  3. +3
    -3
      src/lol/base/all.h
  4. +3
    -3
      src/lol/debug/all.h
  5. +3
    -3
      src/lol/gpu/all.h
  6. +3
    -3
      src/lol/image/all.h
  7. +4
    -3
      src/lol/math/all.h
  8. +114
    -0
      src/lol/math/rand.h
  9. +0
    -1
      src/lol/math/vector.h
  10. +3
    -3
      src/lol/sys/all.h
  11. +7
    -5
      src/lolcore.vcxproj
  12. +8
    -5
      src/lolcore.vcxproj.filters
  13. +0
    -71
      src/numeric.h
  14. +2
    -1
      test/Makefile.am
  15. +1
    -0
      test/testsuite.vcxproj
  16. +55
    -0
      test/unit/rand.cpp

+ 7
- 6
src/Makefile.am Visa fil

@@ -31,26 +31,27 @@ EXTRA_DIST = easymesh/easymesh-scanner.l easymesh/easymesh-parser.y \
gpu/lolfx-scanner.l gpu/lolfx-parser.y

liblolcore_headers = \
lol/base/base.h \
lol/base/all.h \
lol/base/log.h lol/base/array.h lol/base/types.h lol/base/array.h \
lol/base/assert.h lol/base/string.h lol/base/hash.h lol/base/map.h \
\
lol/math/math.h \
lol/math/all.h \
lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \
lol/math/remez.h lol/math/math.h lol/math/geometry.h lol/math/interp.h \
lol/math/rand.h \
\
lol/sys/sys.h \
lol/sys/all.h \
lol/sys/init.h lol/sys/file.h lol/sys/thread.h lol/sys/atomic.h \
lol/sys/timer.h \
\
lol/image/image.h \
lol/image/all.h \
lol/image/color.h \
\
lol/gpu/gpu.h \
lol/gpu/all.h \
lol/gpu/shader.h lol/gpu/indexbuffer.h lol/gpu/vertexbuffer.h \
lol/gpu/framebuffer.h lol/gpu/texture.h lol/gpu/lolfx.h \
\
lol/debug/debug.h \
lol/debug/all.h \
lol/debug/line.h \
\
lol/unit.h


+ 6
- 6
src/core.h Visa fil

@@ -91,12 +91,12 @@ static inline int isnan(float f)
#endif

// Base types
#include <lol/base/base.h>
#include <lol/math/math.h>
#include <lol/sys/sys.h>
#include <lol/image/image.h>
#include <lol/gpu/gpu.h>
#include <lol/debug/debug.h>
#include <lol/base/all.h>
#include <lol/math/all.h>
#include <lol/sys/all.h>
#include <lol/image/all.h>
#include <lol/gpu/all.h>
#include <lol/debug/all.h>

#include "numeric.h"



src/lol/base/base.h → src/lol/base/all.h Visa fil

@@ -8,8 +8,8 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_BASE_BASE_H__
#define __LOL_BASE_BASE_H__
#if !defined __LOL_BASE_ALL_H__
#define __LOL_BASE_ALL_H__

#include <lol/base/types.h>
#include <lol/base/log.h>
@@ -19,5 +19,5 @@
#include <lol/base/hash.h>
#include <lol/base/map.h>

#endif // __LOL_BASE_BASE_H__
#endif // __LOL_BASE_ALL_H__


src/lol/debug/debug.h → src/lol/debug/all.h Visa fil

@@ -8,10 +8,10 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_DEBUG_DEBUG_H__
#define __LOL_DEBUG_DEBUG_H__
#if !defined __LOL_DEBUG_ALL_H__
#define __LOL_DEBUG_ALL_H__

#include <lol/debug/lines.h>

#endif // __LOL_DEBUG_DEBUG_H__
#endif // __LOL_DEBUG_ALL_H__


src/lol/gpu/gpu.h → src/lol/gpu/all.h Visa fil

@@ -8,8 +8,8 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_GPU_GPU_H__
#define __LOL_GPU_GPU_H__
#if !defined __LOL_GPU_ALL_H__
#define __LOL_GPU_ALL_H__

#include <lol/gpu/shader.h>
#include <lol/gpu/indexbuffer.h>
@@ -18,5 +18,5 @@
#include <lol/gpu/framebuffer.h>
#include <lol/gpu/lolfx.h>

#endif // __LOL_GPU_GPU_H__
#endif // __LOL_GPU_ALL_H__


src/lol/image/image.h → src/lol/image/all.h Visa fil

@@ -8,10 +8,10 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_IMAGE_IMAGE_H__
#define __LOL_IMAGE_IMAGE_H__
#if !defined __LOL_IMAGE_ALL_H__
#define __LOL_IMAGE_ALL_H__

#include <lol/image/color.h>

#endif // __LOL_IMAGE_IMAGE_H__
#endif // __LOL_IMAGE_ALL_H__


src/lol/math/math.h → src/lol/math/all.h Visa fil

@@ -8,8 +8,8 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_MATH_MATH_H__
#define __LOL_MATH_MATH_H__
#if !defined __LOL_MATH_ALL_H__
#define __LOL_MATH_ALL_H__

#include <lol/math/functions.h>
#include <lol/math/half.h>
@@ -17,6 +17,7 @@
#include <lol/math/vector.h>
#include <lol/math/geometry.h>
#include <lol/math/interp.h>
#include <lol/math/rand.h>

#endif // __LOL_MATH_MATH_H__
#endif // __LOL_MATH_ALL_H__


+ 114
- 0
src/lol/math/rand.h Visa fil

@@ -0,0 +1,114 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

//
// The Random number generators
// ----------------------------
//

#if !defined __LOL_MATH_RAND_H__
#define __LOL_MATH_RAND_H__

#include <cstdlib>
#include <stdint.h>

namespace lol
{

/* Random number generators */
template<typename T> static inline T rand();
template<typename T> static inline T rand(T a);
template<typename T> static inline T rand(T a, T b);

/* One-value random number generators */
template<typename T> static inline T rand(T a)
{
return rand<T>() % a;
}

template<>
inline half rand<half>(half a) { return a * std::rand() / RAND_MAX; }
template<>
inline float rand<float>(float a) { return a * std::rand() / RAND_MAX; }
template<>
inline double rand<double>(double a) { return a * std::rand() / RAND_MAX; }
template<>
inline ldouble rand<ldouble>(ldouble a) { return a * std::rand() / RAND_MAX; }

/* Two-value random number generator -- no need for specialisation */
template<typename T> static inline T rand(T a, T b)
{
return a + rand<T>(b - a);
}

/* Default random number generator */
template<typename T> static inline T rand()
{
switch (sizeof(T))
{
case 1:
return static_cast<T>(std::rand() & 0x7f);
case 2:
{
uint16_t ret = std::rand();
if (RAND_MAX < 0x7fff)
ret = (ret << 7) ^ std::rand();
return static_cast<T>(ret & 0x7fffu);
}
case 4:
{
uint32_t ret = std::rand();
if (RAND_MAX >= 0xffff)
ret = (ret << 16) ^ std::rand();
else
{
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
}
return static_cast<T>(ret & 0x7fffffffu);
}
case 8:
{
uint64_t ret = std::rand();
if (RAND_MAX >= 0xffff)
{
ret = (ret << 16) ^ std::rand();
ret = (ret << 16) ^ std::rand();
ret = (ret << 16) ^ std::rand();
}
else
{
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
ret = (ret << 8) ^ std::rand();
}
return static_cast<T>(ret & 0x7fffffffffffffffllu);
}
default:
ASSERT(false, "rand() doesn’t support types of size %d\n",
(int)sizeof(T));
return 0;
}
}

template<> inline half rand<half>() { return rand<half>(1.f); }
template<> inline float rand<float>() { return rand<float>(1.f); }
template<> inline double rand<double>() { return rand<double>(1.0); }
template<> inline ldouble rand<ldouble>() { return rand<ldouble>(1.0); }

} /* namespace lol */

#endif // __LOL_MATH_RAND_H__


+ 0
- 1
src/lol/math/vector.h Visa fil

@@ -19,7 +19,6 @@
#include <stdint.h>
#include <ostream>

#include <lol/math/math.h>
#include <lol/math/half.h>
#include <lol/math/real.h>



src/lol/sys/sys.h → src/lol/sys/all.h Visa fil

@@ -8,8 +8,8 @@
// http://www.wtfpl.net/ for more details.
//

#if !defined __LOL_SYS_SYS_H__
#define __LOL_SYS_SYS_H__
#if !defined __LOL_SYS_ALL_H__
#define __LOL_SYS_ALL_H__

#include <lol/sys/thread.h>
#include <lol/sys/atomic.h>
@@ -17,5 +17,5 @@
#include <lol/sys/file.h>
#include <lol/sys/timer.h>

#endif // __LOL_SYS_SYS_H__
#endif // __LOL_SYS_ALL_H__


+ 7
- 5
src/lolcore.vcxproj Visa fil

@@ -196,33 +196,35 @@
<ClInclude Include="light.h" />
<ClInclude Include="loldebug.h" />
<ClInclude Include="lolgl.h" />
<ClInclude Include="lol\base\all.h" />
<ClInclude Include="lol\base\array.h" />
<ClInclude Include="lol\base\assert.h" />
<ClInclude Include="lol\base\base.h" />
<ClInclude Include="lol\base\hash.h" />
<ClInclude Include="lol\base\log.h" />
<ClInclude Include="lol\base\map.h" />
<ClInclude Include="lol\base\string.h" />
<ClInclude Include="lol\base\types.h" />
<ClInclude Include="lol\debug\debug.h" />
<ClInclude Include="lol\debug\all.h" />
<ClInclude Include="lol\debug\lines.h" />
<ClInclude Include="lol\gpu\all.h" />
<ClInclude Include="lol\gpu\framebuffer.h" />
<ClInclude Include="lol\gpu\gpu.h" />
<ClInclude Include="lol\gpu\indexbuffer.h" />
<ClInclude Include="lol\gpu\lolfx.h" />
<ClInclude Include="lol\gpu\shader.h" />
<ClInclude Include="lol\gpu\texture.h" />
<ClInclude Include="lol\gpu\vertexbuffer.h" />
<ClInclude Include="lol\image\all.h" />
<ClInclude Include="lol\image\color.h" />
<ClInclude Include="lol\image\image.h" />
<ClInclude Include="lol\math\all.h" />
<ClInclude Include="lol\math\functions.h" />
<ClInclude Include="lol\math\geometry.h" />
<ClInclude Include="lol\math\half.h" />
<ClInclude Include="lol\math\interp.h" />
<ClInclude Include="lol\math\math.h" />
<ClInclude Include="lol\math\rand.h" />
<ClInclude Include="lol\math\real.h" />
<ClInclude Include="lol\math\remez.h" />
<ClInclude Include="lol\math\vector.h" />
<ClInclude Include="lol\sys\all.h" />
<ClInclude Include="lol\sys\atomic.h" />
<ClInclude Include="lol\sys\file.h" />
<ClInclude Include="lol\sys\init.h" />


+ 8
- 5
src/lolcore.vcxproj.filters Visa fil

@@ -326,7 +326,10 @@
<ClInclude Include="lol\math\half.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\math.h">
<ClInclude Include="lol\math\all.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\rand.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\real.h">
@@ -521,7 +524,7 @@
<ClInclude Include="easymesh\csgbsp.h">
<Filter>easymesh</Filter>
</ClInclude>
<ClInclude Include="lol\base\base.h">
<ClInclude Include="lol\base\all.h">
<Filter>lol\base</Filter>
</ClInclude>
<ClInclude Include="lol\sys\atomic.h">
@@ -539,10 +542,10 @@
<ClInclude Include="lol\gpu\indexbuffer.h">
<Filter>lol\gpu</Filter>
</ClInclude>
<ClInclude Include="lol\image\image.h">
<ClInclude Include="lol\image\all.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\gpu\gpu.h">
<ClInclude Include="lol\gpu\all.h">
<Filter>lol\gpu</Filter>
</ClInclude>
<ClInclude Include="lol\sys\init.h">
@@ -566,7 +569,7 @@
<ClInclude Include="lol\gpu\vertexbuffer.h">
<Filter>lol\gpu</Filter>
</ClInclude>
<ClInclude Include="lol\sys\sys.h">
<ClInclude Include="lol\sys\all.h">
<Filter>lol\sys</Filter>
</ClInclude>
<ClInclude Include="lol\gpu\lolfx.h">


+ 0
- 71
src/numeric.h Visa fil

@@ -22,77 +22,6 @@
namespace lol
{

/* Random number generators */
template<typename T> static inline T rand();
template<typename T> static inline T rand(T a);
template<typename T> static inline T rand(T a, T b);

/* One-value random number generators */
template<typename T> static inline T rand(T a)
{
return rand<T>() % a;
}

template<>
inline half rand<half>(half a) { return a * std::rand() / RAND_MAX; }
template<>
inline float rand<float>(float a) { return a * std::rand() / RAND_MAX; }
template<>
inline double rand<double>(double a) { return a * std::rand() / RAND_MAX; }
template<>
inline ldouble rand<ldouble>(ldouble a) { return a * std::rand() / RAND_MAX; }

/* Two-value random number generator -- no need for specialisation */
template<typename T> static inline T rand(T a, T b)
{
return a + rand<T>(b - a);
}

/* Default random number generator */
template<typename T> static inline T rand()
{
switch (sizeof(T))
{
case 1:
return static_cast<T>(std::rand() & 0xff);
case 2:
if (RAND_MAX >= 0xffff)
return static_cast<T>(std::rand());
else
return static_cast<T>((std::rand() << 8) ^ std::rand());
case 4:
if (RAND_MAX >= 0xffff)
return static_cast<T>((std::rand() << 16) ^ std::rand());
else
return static_cast<T>((std::rand() << 24) ^ (std::rand() << 16)
^ (std::rand() << 8) ^ std::rand());
case 8:
if (RAND_MAX >= 0xffff)
return static_cast<T>(((uint64_t)std::rand() << 48)
^ ((uint64_t)std::rand() << 32)
^ ((uint64_t)std::rand() << 16)
^ ((uint64_t)std::rand()));
else
return static_cast<T>(((uint64_t)std::rand() << 56)
^ ((uint64_t)std::rand() << 48)
^ ((uint64_t)std::rand() << 40)
^ ((uint64_t)std::rand() << 32)
^ ((uint64_t)std::rand() << 24)
^ ((uint64_t)std::rand() << 16)
^ ((uint64_t)std::rand() << 8)
^ ((uint64_t)std::rand()));
default:
ASSERT(false, "rand() doesn’t support types of size %d\n",
(int)sizeof(T));
}
}

template<> inline half rand<half>() { return rand<half>(1.f); }
template<> inline float rand<float>() { return rand<float>(1.f); }
template<> inline double rand<double>() { return rand<double>(1.0); }
template<> inline ldouble rand<ldouble>() { return rand<ldouble>(1.0); }


/* Next power of two. */
template <typename T> static inline T PotUp(T val)
{


+ 2
- 1
test/Makefile.am Visa fil

@@ -21,7 +21,8 @@ testsuite_SOURCES = testsuite.cpp \
unit/vector.cpp unit/matrix.cpp unit/half.cpp unit/trig.cpp \
unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \
unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \
unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp
unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \
unit/rand.cpp
testsuite_CPPFLAGS = $(AM_CPPFLAGS)
testsuite_DEPENDENCIES = @LOL_DEPENDENCIES@



+ 1
- 0
test/testsuite.vcxproj Visa fil

@@ -47,6 +47,7 @@
<ClCompile Include="unit\map.cpp" />
<ClCompile Include="unit\matrix.cpp" />
<ClCompile Include="unit\quat.cpp" />
<ClCompile Include="unit\rand.cpp" />
<ClCompile Include="unit\real.cpp" />
<ClCompile Include="unit\rotation.cpp" />
<ClCompile Include="unit\string.cpp" />


+ 55
- 0
test/unit/rand.cpp Visa fil

@@ -0,0 +1,55 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "core.h"
#include "lol/unit.h"

namespace lol
{

LOLUNIT_FIXTURE(RandTest)
{
void SetUp() {}

void TearDown() {}

LOLUNIT_TEST(Int32Bits)
{
int const rolls = 2000;

int bits[32];
memset(bits, 0, sizeof(bits));

for (int i = 0; i < rolls; ++i)
{
uint32_t r = rand<int>();
for (int k = 0; k < 31; k++)
{
bits[k] += r & 1;
r >>= 1;
}
}

for (int k = 0; k < 31; k++)
{
LOLUNIT_SET_CONTEXT(k);
LOLUNIT_ASSERT_GREATER(bits[k], rolls / 3);
LOLUNIT_ASSERT_LESS(bits[k], rolls * 2 / 3);
LOLUNIT_UNSET_CONTEXT(k);
}
}
};

} /* namespace lol */


Laddar…
Avbryt
Spara