25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

135 satır
3.6 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. //
  14. // The Random number generators
  15. // ————————————————————————————
  16. //
  17. #include <lol/base/features.h>
  18. #include <cassert>
  19. #include <cstdlib>
  20. #include <stdint.h>
  21. namespace lol
  22. {
  23. /* Random number generators */
  24. template<typename T> lol_attr_nodiscard static inline T rand();
  25. template<typename T> lol_attr_nodiscard static inline T rand(T a);
  26. template<typename T> lol_attr_nodiscard static inline T rand(T a, T b);
  27. /* One-value random number generators */
  28. template<typename T> lol_attr_nodiscard static inline T rand(T a)
  29. {
  30. return a ? rand<T>() % a : T(0);
  31. }
  32. #if 0
  33. template<> lol_attr_nodiscard inline half rand<half>(half a)
  34. {
  35. float f = (float)std::rand() / (float)RAND_MAX;
  36. return (half)(a * f);
  37. }
  38. #endif
  39. template<> lol_attr_nodiscard inline float rand<float>(float a)
  40. {
  41. auto f = (float)std::rand() / (float)RAND_MAX;
  42. return a * f;
  43. }
  44. template<> lol_attr_nodiscard inline double rand<double>(double a)
  45. {
  46. auto f = (double)std::rand() / (double)RAND_MAX;
  47. return a * f;
  48. }
  49. template<> lol_attr_nodiscard inline long double rand<long double>(long double a)
  50. {
  51. auto f = (long double)std::rand() / (long double)RAND_MAX;
  52. return a * f;
  53. }
  54. /* Two-value random number generator -- no need for specialisation */
  55. template<typename T> lol_attr_nodiscard static inline T rand(T a, T b)
  56. {
  57. return a + rand<T>(b - a);
  58. }
  59. /* Default random number generator */
  60. template<typename T> lol_attr_nodiscard static inline T rand()
  61. {
  62. switch (sizeof(T))
  63. {
  64. case 1:
  65. return static_cast<T>(std::rand() & 0x7f);
  66. case 2:
  67. {
  68. uint16_t ret = std::rand();
  69. if (RAND_MAX < 0x7fff)
  70. ret = (ret << 7) ^ std::rand();
  71. return static_cast<T>(ret & 0x7fffu);
  72. }
  73. case 4:
  74. {
  75. uint32_t ret = std::rand();
  76. if (RAND_MAX >= 0xffff)
  77. ret = (ret << 16) ^ std::rand();
  78. else
  79. {
  80. ret = (ret << 8) ^ std::rand();
  81. ret = (ret << 8) ^ std::rand();
  82. ret = (ret << 8) ^ std::rand();
  83. }
  84. return static_cast<T>(ret & 0x7fffffffu);
  85. }
  86. case 8:
  87. {
  88. uint64_t ret = std::rand();
  89. if (RAND_MAX >= 0xffff)
  90. {
  91. ret = (ret << 16) ^ std::rand();
  92. ret = (ret << 16) ^ std::rand();
  93. ret = (ret << 16) ^ std::rand();
  94. }
  95. else
  96. {
  97. ret = (ret << 8) ^ std::rand();
  98. ret = (ret << 8) ^ std::rand();
  99. ret = (ret << 8) ^ std::rand();
  100. ret = (ret << 8) ^ std::rand();
  101. ret = (ret << 8) ^ std::rand();
  102. ret = (ret << 8) ^ std::rand();
  103. ret = (ret << 8) ^ std::rand();
  104. }
  105. return static_cast<T>(ret & (~(uint64_t)0 >> 1));
  106. }
  107. default:
  108. assert(false);
  109. return 0;
  110. }
  111. }
  112. #if 0
  113. template<> lol_attr_nodiscard inline half rand<half>() { return rand<half>(1.f); }
  114. #endif
  115. template<> lol_attr_nodiscard inline float rand<float>() { return rand<float>(1.f); }
  116. template<> lol_attr_nodiscard inline double rand<double>() { return rand<double>(1.0); }
  117. template<> lol_attr_nodiscard inline long double rand<long double>() { return rand<long double>(1.0); }
  118. } /* namespace lol */