1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Tim Düsterhus <timwolla@php.net> |
14 | Go Kudo <zeriyoshi@php.net> |
15 | |
16 | Based on code from: Melissa O'Neill <oneill@pcg-random.org> |
17 +----------------------------------------------------------------------+
18 */
19
20 #ifndef PHP_RANDOM_UINT128_H
21 # define PHP_RANDOM_UINT128_H
22
23 # include <stdint.h>
24
25 # if !defined(__SIZEOF_INT128__) || defined(PHP_RANDOM_FORCE_EMULATE_128)
26 typedef struct _php_random_uint128_t {
27 uint64_t hi;
28 uint64_t lo;
29 } php_random_uint128_t;
30
php_random_uint128_hi(php_random_uint128_t num)31 static inline uint64_t php_random_uint128_hi(php_random_uint128_t num)
32 {
33 return num.hi;
34 }
35
php_random_uint128_lo(php_random_uint128_t num)36 static inline uint64_t php_random_uint128_lo(php_random_uint128_t num)
37 {
38 return num.lo;
39 }
40
php_random_uint128_constant(uint64_t hi,uint64_t lo)41 static inline php_random_uint128_t php_random_uint128_constant(uint64_t hi, uint64_t lo)
42 {
43 php_random_uint128_t r;
44
45 r.hi = hi;
46 r.lo = lo;
47
48 return r;
49 }
50
php_random_uint128_add(php_random_uint128_t num1,php_random_uint128_t num2)51 static inline php_random_uint128_t php_random_uint128_add(php_random_uint128_t num1, php_random_uint128_t num2)
52 {
53 php_random_uint128_t r;
54
55 r.lo = (num1.lo + num2.lo);
56 r.hi = (num1.hi + num2.hi + (r.lo < num1.lo));
57
58 return r;
59 }
60
php_random_uint128_multiply(php_random_uint128_t num1,php_random_uint128_t num2)61 static inline php_random_uint128_t php_random_uint128_multiply(php_random_uint128_t num1, php_random_uint128_t num2)
62 {
63 php_random_uint128_t r;
64 const uint64_t
65 x0 = num1.lo & 0xffffffffULL,
66 x1 = num1.lo >> 32,
67 y0 = num2.lo & 0xffffffffULL,
68 y1 = num2.lo >> 32,
69 z0 = (((x1 * y0) + (x0 * y0 >> 32)) & 0xffffffffULL) + x0 * y1;
70
71 r.hi = num1.hi * num2.lo + num1.lo * num2.hi;
72 r.lo = num1.lo * num2.lo;
73 r.hi += x1 * y1 + ((x1 * y0 + (x0 * y0 >> 32)) >> 32) + (z0 >> 32);
74
75 return r;
76 }
77
php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)78 static inline uint64_t php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)
79 {
80 const uint64_t
81 v = (num.hi ^ num.lo),
82 s = num.hi >> 58U;
83
84 return (v >> s) | (v << ((-s) & 63));
85 }
86 # else
87 typedef __uint128_t php_random_uint128_t;
88
php_random_uint128_hi(php_random_uint128_t num)89 static inline uint64_t php_random_uint128_hi(php_random_uint128_t num)
90 {
91 return (uint64_t) (num >> 64);
92 }
93
php_random_uint128_lo(php_random_uint128_t num)94 static inline uint64_t php_random_uint128_lo(php_random_uint128_t num)
95 {
96 return (uint64_t) num;
97 }
98
php_random_uint128_constant(uint64_t hi,uint64_t lo)99 static inline php_random_uint128_t php_random_uint128_constant(uint64_t hi, uint64_t lo)
100 {
101 php_random_uint128_t r;
102
103 r = ((php_random_uint128_t) hi << 64) + lo;
104
105 return r;
106 }
107
php_random_uint128_add(php_random_uint128_t num1,php_random_uint128_t num2)108 static inline php_random_uint128_t php_random_uint128_add(php_random_uint128_t num1, php_random_uint128_t num2)
109 {
110 return num1 + num2;
111 }
112
php_random_uint128_multiply(php_random_uint128_t num1,php_random_uint128_t num2)113 static inline php_random_uint128_t php_random_uint128_multiply(php_random_uint128_t num1, php_random_uint128_t num2)
114 {
115 return num1 * num2;
116 }
117
php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)118 static inline uint64_t php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)
119 {
120 const uint64_t
121 v = ((uint64_t) (num >> 64U)) ^ (uint64_t) num,
122 s = num >> 122U;
123
124 return (v >> s) | (v << ((-s) & 63));
125 }
126 # endif
127
128 #endif /* PHP_RANDOM_UINT128_H */
129