File Coverage

lib/Math/Random/PCG32.xs
Criterion Covered Total %
statement 70 71 98.5
branch 47 58 81.0
condition n/a
subroutine n/a
pod n/a
total 117 129 90.7


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6              
7             #include "ppport.h"
8              
9             #include "pcg.h"
10              
11             MODULE = Math::Random::PCG32 PACKAGE = Math::Random::PCG32
12              
13             PROTOTYPES: ENABLE
14              
15             pcg32_random_t *
16             new(CLASS, initstate, initseq)
17             char *CLASS
18             UV initstate
19             UV initseq
20             CODE:
21 1           Newxz(RETVAL, 1, pcg32_random_t);
22 1 50         if (RETVAL == NULL) croak("Could not allocate state memory");
23 1           pcg32_srandom_r(RETVAL, initstate, initseq);
24             OUTPUT:
25             RETVAL
26              
27             UV
28             coinflip(pcg32_random_t *rng)
29             CODE:
30 6           RETVAL = pcg32_random_r(rng) & 1;
31             OUTPUT:
32             RETVAL
33              
34             UV
35             decay(pcg32_random_t *rng, uint32_t odds, uint32_t min, uint32_t max)
36             PREINIT:
37             uint32_t count;
38             CODE:
39             count = min;
40 14 100         while (count < max) {
41 12 100         if (pcg32_random_r(rng) < odds) break;
42 11           count++;
43             }
44 3           RETVAL = count;
45             OUTPUT:
46             RETVAL
47              
48             UV
49             irand(pcg32_random_t *rng)
50             CODE:
51 6           RETVAL = pcg32_random_r(rng);
52             OUTPUT:
53             RETVAL
54              
55             UV
56             irand64(pcg32_random_t *rng)
57             CODE:
58 1           RETVAL = ((uint64_t) pcg32_random_r(rng) << 32) | pcg32_random_r(rng);
59             OUTPUT:
60             RETVAL
61              
62             UV
63             irand_in(pcg32_random_t *rng, uint32_t min, uint32_t max)
64             CODE:
65 7 50         if (max == min) RETVAL = min;
66 7 50         else if (min > max) croak("max must be greater than min");
67 7           else RETVAL = min + pcg32_random_r(rng) % (max - min + 1);
68             OUTPUT:
69             RETVAL
70              
71             void
72             irand_way(pcg32_random_t *rng, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
73             PREINIT:
74             int32_t dx, dy, magx;
75             PPCODE:
76 23 100         if (x1 == x2 && y1 == y2) XSRETURN_UNDEF;
77 20 50         EXTEND(SP, 2);
78 20           dx = x2 - x1;
79 20           dy = y2 - y1;
80 20 100         if (dx == 0) goto MOVE_Y;
81 16 100         else if (dy == 0) goto MOVE_X;
82 14           magx = abs(dx);
83 14 100         if (pcg32_random_r(rng) % (magx + abs(dy)) < magx) {
84             MOVE_X:
85 10 100         mPUSHs(newSViv(x1 + (dx > 0 ? 1 : -1)));
86 10           mPUSHs(newSViv(y1));
87             } else {
88             MOVE_Y:
89 10           mPUSHs(newSViv(x1));
90 10 100         mPUSHs(newSViv(y1 + (dy > 0 ? 1 : -1)));
91             }
92              
93             double
94             rand(pcg32_random_t *rng, ...)
95             PROTOTYPE: $;$
96             PREINIT:
97             double factor;
98             CODE:
99 2 100         if (items > 1) {
100 1 50         if (!SvIOK(ST(1)) && !SvNOK(ST(1)))
101 0           croak("factor must be a number");
102 1 50         factor = SvNV(ST(1));
103             } else factor = 1.0;
104             /* "binary floating point constant for 2^-32" from PCG blog
105             * post "Efficiently Generating a Number in a Range" (fast,
106             * but biased) */
107 2           RETVAL = 0x1.0p-32 * pcg32_random_r(rng) * factor;
108             OUTPUT:
109             RETVAL
110              
111             SV *
112             rand_elm(pcg32_random_t *rng, avref)
113             AV *avref;
114             PREINIT:
115             SSize_t len;
116             SV **svp;
117             CODE:
118 1           len = av_len(avref) + 1;
119 1 50         if (len == 0) XSRETURN_UNDEF;
120 1           svp = av_fetch(avref, pcg32_random_r(rng) % len, FALSE);
121 1           SvREFCNT_inc(*svp);
122 1           RETVAL = *svp;
123             OUTPUT:
124             RETVAL
125              
126             SV *
127             rand_from(pcg32_random_t *rng, avref)
128             AV *avref;
129             PREINIT:
130             SSize_t i, len, rnd;
131             SV *dunno, **src, **dst;
132             CODE:
133 6           len = av_len(avref) + 1;
134 6 100         if (len == 0) XSRETURN_UNDEF;
135 5           rnd = pcg32_random_r(rng) % len;
136 5           dunno = av_delete(avref, rnd, 0);
137 5 100         if (rnd != len - 1) {
138 2           dst = &AvARRAY(avref)[rnd];
139 2           src = dst + 1;
140 7 100         for (i = rnd; i < len - 1; i++) *dst++ = *src++;
141 2           AvFILLp(avref) -= 1;
142 2           AvMAX(avref) -= 1;
143             }
144             SvREFCNT_inc(dunno);
145             RETVAL = dunno;
146             OUTPUT:
147             RETVAL
148              
149             UV
150             rand_idx(pcg32_random_t *rng, avref)
151             AV *avref;
152             PREINIT:
153             SSize_t len;
154             CODE:
155 1           len = av_len(avref) + 1;
156 1 50         if (len == 0) XSRETURN_UNDEF;
157 1           else RETVAL = pcg32_random_r(rng) % len;
158             OUTPUT:
159             RETVAL
160              
161             UV
162             roll(pcg32_random_t *rng, uint32_t count, uint32_t sides)
163             PREINIT:
164             uint32_t sum;
165             CODE:
166 6 50         if (count == 0) croak("count must be positive");
167 6 50         if (sides == 0) croak("sides must be positive");
168             sum = count;
169 24 100         while (count--) sum += pcg32_random_r(rng) % sides;
170 6           RETVAL = sum;
171             OUTPUT:
172             RETVAL
173              
174             void
175             sample(pcg32_random_t *rng, uint32_t count, avref)
176             AV *avref;
177             PREINIT:
178             AV* smpl;
179             SSize_t len, i;
180             uint32_t total;
181             PPCODE:
182 4           smpl = newAV();
183 4           len = av_len(avref) + 1;
184 4 100         if (len == 0 || count == 0) goto DONE;
185 2 100         if (count >= len) {
186 1           av_extend(smpl, len - 1);
187 6 100         for (i = 0; i < len; i++) {
188 5           SV *sv = *av_fetch(avref, i, FALSE);
189 5           av_push(smpl, sv);
190             }
191             } else {
192 1           total = len;
193 1           av_extend(smpl, count - 1);
194 5 50         for (i = 0; i < len; i++) {
195 5 100         if (pcg32_random_r(rng) < ( count * ( UINT32_MAX / total ) )) {
196 3           SV *sv = *av_fetch(avref, i, FALSE);
197 3           av_push(smpl, sv);
198 3 100         if (--count == 0) break;
199             }
200 4           total--;
201             }
202             }
203             DONE:
204 4           ST(0) = sv_2mortal( newRV_inc((SV *) smpl) );
205 4           XSRETURN(1);
206              
207             void
208             DESTROY(pcg32_random_t *rng)
209             PPCODE:
210 1           Safefree(rng);