Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
14 KiB

  1. // stb_divide.h - v0.91 - public domain - Sean Barrett, Feb 2010
  2. // Three kinds of divide/modulus of signed integers.
  3. //
  4. // HISTORY
  5. //
  6. // v0.91 2010-02-27 Fix euclidean division by INT_MIN for non-truncating C
  7. // Check result with 64-bit math to catch such cases
  8. // v0.90 2010-02-24 First public release
  9. //
  10. // USAGE
  11. //
  12. // In *ONE* source file, put:
  13. //
  14. // #define STB_DIVIDE_IMPLEMENTATION
  15. // // #define C_INTEGER_DIVISION_TRUNCATES // see Note 1
  16. // // #define C_INTEGER_DIVISION_FLOORS // see Note 2
  17. // #include "stb_divide.h"
  18. //
  19. // Other source files should just include stb_divide.h
  20. //
  21. // Note 1: On platforms/compilers that you know signed C division
  22. // truncates, you can #define C_INTEGER_DIVISION_TRUNCATES.
  23. //
  24. // Note 2: On platforms/compilers that you know signed C division
  25. // floors (rounds to negative infinity), you can #define
  26. // C_INTEGER_DIVISION_FLOORS.
  27. //
  28. // You can #define STB_DIVIDE_TEST in which case the implementation
  29. // will generate a main() and compiling the result will create a
  30. // program that tests the implementation. Run it with no arguments
  31. // and any output indicates an error; run it with any argument and
  32. // it will also print the test results. Define STB_DIVIDE_TEST_64
  33. // to a 64-bit integer type to avoid overflows in the result-checking
  34. // which give false negatives.
  35. //
  36. // ABOUT
  37. //
  38. // This file provides three different consistent divide/mod pairs
  39. // implemented on top of arbitrary C/C++ division, including correct
  40. // handling of overflow of intermediate calculations:
  41. //
  42. // trunc: a/b truncates to 0, a%b has same sign as a
  43. // floor: a/b truncates to -inf, a%b has same sign as b
  44. // eucl: a/b truncates to sign(b)*inf, a%b is non-negative
  45. //
  46. // Not necessarily optimal; I tried to keep it generally efficient,
  47. // but there may be better ways.
  48. //
  49. // Briefly, for those who are not familiar with the problem, we note
  50. // the reason these divides exist and are interesting:
  51. //
  52. // 'trunc' is easy to implement in hardware (strip the signs,
  53. // compute, reapply the signs), thus is commonly defined
  54. // by many languages (including C99)
  55. //
  56. // 'floor' is simple to define and better behaved than trunc;
  57. // for example it divides integers into fixed-size buckets
  58. // without an extra-wide bucket at 0, and for a fixed
  59. // divisor N there are only |N| possible moduli.
  60. //
  61. // 'eucl' guarantees fixed-sized buckets *and* a non-negative
  62. // modulus and defines division to be whatever is needed
  63. // to achieve that result.
  64. //
  65. // See "The Euclidean definition of the functions div and mod"
  66. // by Raymond Boute (1992), or "Division and Modulus for Computer
  67. // Scientists" by Daan Leijen (2001)
  68. //
  69. // We assume of the built-in C division:
  70. // (a) modulus is the remainder for the corresponding division
  71. // (b) a/b truncates if a and b are the same sign
  72. //
  73. // Property (a) requires (a/b)*b + (a%b)==a, and is required by C.
  74. // Property (b) seems to be true of all hardware but is *not* satisfied
  75. // by the euclidean division operator we define, so it's possibly not
  76. // always true. If any such platform turns up, we can add more cases.
  77. // (Possibly only stb_div_trunc currently relies on property (b).)
  78. //
  79. // LICENSE
  80. //
  81. // See end of file for license information.
  82. #ifndef INCLUDE_STB_DIVIDE_H
  83. #define INCLUDE_STB_DIVIDE_H
  84. #ifdef __cplusplus
  85. extern "C" {
  86. #endif
  87. extern int stb_div_trunc(int value_to_be_divided, int value_to_divide_by);
  88. extern int stb_div_floor(int value_to_be_divided, int value_to_divide_by);
  89. extern int stb_div_eucl (int value_to_be_divided, int value_to_divide_by);
  90. extern int stb_mod_trunc(int value_to_be_divided, int value_to_divide_by);
  91. extern int stb_mod_floor(int value_to_be_divided, int value_to_divide_by);
  92. extern int stb_mod_eucl (int value_to_be_divided, int value_to_divide_by);
  93. #ifdef __cplusplus
  94. }
  95. #endif
  96. #ifdef STB_DIVIDE_IMPLEMENTATION
  97. #if defined(__STDC_VERSION) && __STDC_VERSION__ >= 19901
  98. #ifndef C_INTEGER_DIVISION_TRUNCATES
  99. #define C_INTEGER_DIVISION_TRUNCATES
  100. #endif
  101. #endif
  102. #ifndef INT_MIN
  103. #include <limits.h> // if you have no limits.h, #define INT_MIN yourself
  104. #endif
  105. // the following macros are designed to allow testing
  106. // other platforms by simulating them
  107. #ifndef STB_DIVIDE_TEST_FLOOR
  108. #define stb__div(a,b) ((a)/(b))
  109. #define stb__mod(a,b) ((a)%(b))
  110. #else
  111. // implement floor-style divide on trunc platform
  112. #ifndef C_INTEGER_DIVISION_TRUNCATES
  113. #error "floor test requires truncating division"
  114. #endif
  115. #undef C_INTEGER_DIVISION_TRUNCATES
  116. int stb__div(int v1, int v2)
  117. {
  118. int q = v1/v2, r = v1%v2;
  119. if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0))
  120. return q-1;
  121. else
  122. return q;
  123. }
  124. int stb__mod(int v1, int v2)
  125. {
  126. int r = v1%v2;
  127. if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0))
  128. return r+v2;
  129. else
  130. return r;
  131. }
  132. #endif
  133. int stb_div_trunc(int v1, int v2)
  134. {
  135. #ifdef C_INTEGER_DIVISION_TRUNCATES
  136. return v1/v2;
  137. #else
  138. if (v1 >= 0 && v2 <= 0)
  139. return -stb__div(-v1,v2); // both negative to avoid overflow
  140. if (v1 <= 0 && v2 >= 0)
  141. if (v1 != INT_MIN)
  142. return -stb__div(v1,-v2); // both negative to avoid overflow
  143. else
  144. return -stb__div(v1+v2,-v2)-1; // push v1 away from wrap point
  145. else
  146. return v1/v2; // same sign, so expect truncation
  147. #endif
  148. }
  149. int stb_div_floor(int v1, int v2)
  150. {
  151. #ifdef C_INTEGER_DIVISION_FLOORS
  152. return v1/v2;
  153. #else
  154. if (v1 >= 0 && v2 < 0)
  155. if ((-v1)+v2+1 < 0) // check if increasing v1's magnitude overflows
  156. return -stb__div(-v1+v2+1,v2); // nope, so just compute it
  157. else
  158. return -stb__div(-v1,v2) + ((-v1)%v2 ? -1 : 0);
  159. if (v1 < 0 && v2 >= 0)
  160. if (v1 != INT_MIN)
  161. if (v1-v2+1 < 0) // check if increasing v1's magnitude overflows
  162. return -stb__div(v1-v2+1,-v2); // nope, so just compute it
  163. else
  164. return -stb__div(-v1,v2) + (stb__mod(v1,-v2) ? -1 : 0);
  165. else // it must be possible to compute -(v1+v2) without overflowing
  166. return -stb__div(-(v1+v2),v2) + (stb__mod(-(v1+v2),v2) ? -2 : -1);
  167. else
  168. return v1/v2; // same sign, so expect truncation
  169. #endif
  170. }
  171. int stb_div_eucl(int v1, int v2)
  172. {
  173. int q,r;
  174. #ifdef C_INTEGER_DIVISION_TRUNCATES
  175. q = v1/v2;
  176. r = v1%v2;
  177. #else
  178. // handle every quadrant separately, since we can't rely on q and r flor
  179. if (v1 >= 0)
  180. if (v2 >= 0)
  181. return stb__div(v1,v2);
  182. else if (v2 != INT_MIN)
  183. q = -stb__div(v1,-v2), r = stb__mod(v1,-v2);
  184. else
  185. q = 0, r = v1;
  186. else if (v1 != INT_MIN)
  187. if (v2 >= 0)
  188. q = -stb__div(-v1,v2), r = -stb__mod(-v1,v2);
  189. else if (v2 != INT_MIN)
  190. q = stb__div(-v1,-v2), r = -stb__mod(-v1,-v2);
  191. else // if v2 is INT_MIN, then we can't use -v2, but we can't divide by v2
  192. q = 1, r = v1-q*v2;
  193. else // if v1 is INT_MIN, we have to move away from overflow place
  194. if (v2 >= 0)
  195. q = -stb__div(-(v1+v2),v2)-1, r = -stb__mod(-(v1+v2),v2);
  196. else
  197. q = stb__div(-(v1-v2),-v2)+1, r = -stb__mod(-(v1-v2),-v2);
  198. #endif
  199. if (r >= 0)
  200. return q;
  201. else
  202. return q + (v2 > 0 ? -1 : 1);
  203. }
  204. int stb_mod_trunc(int v1, int v2)
  205. {
  206. #ifdef C_INTEGER_DIVISION_TRUNCATES
  207. return v1%v2;
  208. #else
  209. if (v1 >= 0) { // modulus result should always be positive
  210. int r = stb__mod(v1,v2);
  211. if (r >= 0)
  212. return r;
  213. else
  214. return r + (v2 > 0 ? v2 : -v2);
  215. } else { // modulus result should always be negative
  216. int r = stb__mod(v1,v2);
  217. if (r <= 0)
  218. return r;
  219. else
  220. return r - (v2 > 0 ? v2 : -v2);
  221. }
  222. #endif
  223. }
  224. int stb_mod_floor(int v1, int v2)
  225. {
  226. #ifdef C_INTEGER_DIVISION_FLOORS
  227. return v1%v2;
  228. #else
  229. if (v2 >= 0) { // result should always be positive
  230. int r = stb__mod(v1,v2);
  231. if (r >= 0)
  232. return r;
  233. else
  234. return r + v2;
  235. } else { // result should always be negative
  236. int r = stb__mod(v1,v2);
  237. if (r <= 0)
  238. return r;
  239. else
  240. return r + v2;
  241. }
  242. #endif
  243. }
  244. int stb_mod_eucl(int v1, int v2)
  245. {
  246. int r = stb__mod(v1,v2);
  247. if (r >= 0)
  248. return r;
  249. else
  250. return r + (v2 > 0 ? v2 : -v2); // abs()
  251. }
  252. #ifdef STB_DIVIDE_TEST
  253. #include <stdio.h>
  254. #include <math.h>
  255. #include <limits.h>
  256. int show=0;
  257. void stbdiv_check(int q, int r, int a, int b, char *type, int dir)
  258. {
  259. if ((dir > 0 && r < 0) || (dir < 0 && r > 0))
  260. fprintf(stderr, "FAILED: %s(%d,%d) remainder %d in wrong direction\n", type,a,b,r);
  261. else
  262. if (b != INT_MIN) // can't compute abs(), but if b==INT_MIN all remainders are valid
  263. if (r <= -abs(b) || r >= abs(b))
  264. fprintf(stderr, "FAILED: %s(%d,%d) remainder %d out of range\n", type,a,b,r);
  265. #ifdef STB_DIVIDE_TEST_64
  266. {
  267. STB_DIVIDE_TEST_64 q64 = q, r64=r, a64=a, b64=b;
  268. if (q64*b64+r64 != a64)
  269. fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q);
  270. }
  271. #else
  272. if (q*b+r != a)
  273. fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q);
  274. #endif
  275. }
  276. void test(int a, int b)
  277. {
  278. int q,r;
  279. if (show) printf("(%+11d,%+d) | ", a,b);
  280. q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b);
  281. if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "trunc",a);
  282. q = stb_div_floor(a,b), r = stb_mod_floor(a,b);
  283. if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "floor",b);
  284. q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b);
  285. if (show) printf("(%+11d,%+2d)\n", q,r); stbdiv_check(q,r,a,b, "euclidean",1);
  286. }
  287. void testh(int a, int b)
  288. {
  289. int q,r;
  290. if (show) printf("(%08x,%08x) |\n", a,b);
  291. q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b); stbdiv_check(q,r,a,b, "trunc",a);
  292. if (show) printf(" (%08x,%08x)", q,r);
  293. q = stb_div_floor(a,b), r = stb_mod_floor(a,b); stbdiv_check(q,r,a,b, "floor",b);
  294. if (show) printf(" (%08x,%08x)", q,r);
  295. q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b); stbdiv_check(q,r,a,b, "euclidean",1);
  296. if (show) printf(" (%08x,%08x)\n ", q,r);
  297. }
  298. int main(int argc, char **argv)
  299. {
  300. if (argc > 1) show=1;
  301. test(8,3);
  302. test(8,-3);
  303. test(-8,3);
  304. test(-8,-3);
  305. test(1,2);
  306. test(1,-2);
  307. test(-1,2);
  308. test(-1,-2);
  309. test(8,4);
  310. test(8,-4);
  311. test(-8,4);
  312. test(-8,-4);
  313. test(INT_MAX,1);
  314. test(INT_MIN,1);
  315. test(INT_MIN+1,1);
  316. test(INT_MAX,-1);
  317. //test(INT_MIN,-1); // this traps in MSVC, so we leave it untested
  318. test(INT_MIN+1,-1);
  319. test(INT_MIN,-2);
  320. test(INT_MIN+1,2);
  321. test(INT_MIN+1,-2);
  322. test(INT_MAX,2);
  323. test(INT_MAX,-2);
  324. test(INT_MIN+1,2);
  325. test(INT_MIN+1,-2);
  326. test(INT_MIN,2);
  327. test(INT_MIN,-2);
  328. test(INT_MIN,7);
  329. test(INT_MIN,-7);
  330. test(INT_MIN+1,4);
  331. test(INT_MIN+1,-4);
  332. testh(-7, INT_MIN);
  333. testh(-1, INT_MIN);
  334. testh(1, INT_MIN);
  335. testh(7, INT_MIN);
  336. testh(INT_MAX-1, INT_MIN);
  337. testh(INT_MAX, INT_MIN);
  338. testh(INT_MIN, INT_MIN);
  339. testh(INT_MIN+1, INT_MIN);
  340. testh(INT_MAX-1, INT_MAX);
  341. testh(INT_MAX , INT_MAX);
  342. testh(INT_MIN , INT_MAX);
  343. testh(INT_MIN+1, INT_MAX);
  344. return 0;
  345. }
  346. #endif // STB_DIVIDE_TEST
  347. #endif // STB_DIVIDE_IMPLEMENTATION
  348. #endif // INCLUDE_STB_DIVIDE_H
  349. /*
  350. ------------------------------------------------------------------------------
  351. This software is available under 2 licenses -- choose whichever you prefer.
  352. ------------------------------------------------------------------------------
  353. ALTERNATIVE A - MIT License
  354. Copyright (c) 2017 Sean Barrett
  355. Permission is hereby granted, free of charge, to any person obtaining a copy of
  356. this software and associated documentation files (the "Software"), to deal in
  357. the Software without restriction, including without limitation the rights to
  358. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  359. of the Software, and to permit persons to whom the Software is furnished to do
  360. so, subject to the following conditions:
  361. The above copyright notice and this permission notice shall be included in all
  362. copies or substantial portions of the Software.
  363. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  364. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  365. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  366. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  367. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  368. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  369. SOFTWARE.
  370. ------------------------------------------------------------------------------
  371. ALTERNATIVE B - Public Domain (www.unlicense.org)
  372. This is free and unencumbered software released into the public domain.
  373. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  374. software, either in source code form or as a compiled binary, for any purpose,
  375. commercial or non-commercial, and by any means.
  376. In jurisdictions that recognize copyright laws, the author or authors of this
  377. software dedicate any and all copyright interest in the software to the public
  378. domain. We make this dedication for the benefit of the public at large and to
  379. the detriment of our heirs and successors. We intend this dedication to be an
  380. overt act of relinquishment in perpetuity of all present and future rights to
  381. this software under copyright law.
  382. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  383. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  384. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  385. AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  386. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  387. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  388. ------------------------------------------------------------------------------
  389. */