Vuo  2.0.2
VuoInteger.c
Go to the documentation of this file.
1 
10 #include "type.h"
11 #include <limits.h>
12 #include <string.h>
13 
15 #ifdef VUO_COMPILER
17  "title" : "Integer",
18  "description" : "A signed 64-bit integer.",
19  "keywords" : [ "number", "signed" ],
20  "version" : "1.0.0"
21  });
22 #endif
23 
30 {
31  if (!js)
32  return 0;
33 
34  json_type t = json_object_get_type(js);
35  if (t == json_type_int)
36  return json_object_get_int64(js);
37  else
38  {
39  // Use strtold() instead of json_object_get_int64(),
40  // since the latter doesn't support JSON strings with scientific notation.
41  // Use `long double strtold()` instead of `double atof()`
42  // since `long double` can precisely represent the int64 max value, whereas `double` can't.
43  const char *s = json_object_get_string(js);
44  if (s)
45  return strtold(s, NULL);
46  else
47  return 0;
48  }
49 }
50 
56 {
57  return json_object_new_int64(value);
58 }
59 
64 char * VuoInteger_getSummary(const VuoInteger value)
65 {
66  json_object *js = VuoInteger_getJson(value);
67  char *summary = strdup(json_object_to_json_string_ext(js,JSON_C_TO_STRING_PLAIN));
68  json_object_put(js);
69  return summary;
70 }
71 
75 VuoInteger VuoInteger_min(VuoInteger *terms, unsigned long termsCount, VuoInteger *outputPosition)
76 {
77  if (termsCount == 0)
78  {
79  *outputPosition = 0;
80  return 0;
81  }
82 
83  VuoInteger min = LONG_MAX;
84  for (unsigned long i = 0; i < termsCount; ++i)
85  if (terms[i] < min)
86  {
87  min = terms[i];
88  *outputPosition = i + 1;
89  }
90 
91  return min;
92 }
93 
97 VuoInteger VuoInteger_max(VuoInteger *terms, unsigned long termsCount, VuoInteger *outputPosition)
98 {
99  if (termsCount == 0)
100  {
101  *outputPosition = 0;
102  return 0;
103  }
104 
105  VuoInteger max = LONG_MIN;
106  for (unsigned long i = 0; i < termsCount; ++i)
107  if (terms[i] > max)
108  {
109  max = terms[i];
110  *outputPosition = i + 1;
111  }
112 
113  return max;
114 }
115 
121 {
122  VuoInteger rectifiedMin = (minimum < maximum) ? minimum : maximum;
123  VuoInteger rectifiedMax = (minimum < maximum) ? maximum : minimum;
124 
125  if (value > rectifiedMax)
126  return rectifiedMin + ((value-rectifiedMax-1) % (rectifiedMax-rectifiedMin+1));
127  else if (value < rectifiedMin)
128  return rectifiedMax + ((value-rectifiedMin+1) % (rectifiedMax-rectifiedMin+1));
129  else
130  return value;
131 }
132 
157 static u_int32_t VuoInteger_arc4random_uniform(u_int32_t upper_bound)
158 {
159  u_int32_t r, min;
160 
161  if (upper_bound < 2)
162  return 0;
163 
164 #if (ULONG_MAX > 0xffffffffUL)
165  min = 0x100000000UL % upper_bound;
166 #else
167  /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
168  if (upper_bound > 0x80000000)
169  min = 1 + ~upper_bound; /* 2**32 - upper_bound */
170  else {
171  /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
172  min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
173  }
174 #endif
175 
176  /*
177  * This could theoretically loop forever but each retry has
178  * p > 0.5 (worst case, usually far better) of selecting a
179  * number inside the range we need, so it should rarely need
180  * to re-roll.
181  */
182  for (;;) {
183  r = arc4random();
184  if (r >= min)
185  break;
186  }
187 
188  return r % upper_bound;
189 }
190 
198 VuoInteger VuoInteger_random(const VuoInteger minimum, const VuoInteger maximum)
199 {
200  if (minimum == maximum)
201  return minimum;
202 
203  VuoInteger actualMinimum = MIN(minimum,maximum);
204  VuoInteger actualMaximum = MAX(minimum,maximum);
205 
206  return VuoInteger_arc4random_uniform(actualMaximum - actualMinimum + 1) + actualMinimum;
207 }
208 
212 void VuoInteger_setRandomState(unsigned short state[3], const VuoInteger seed)
213 {
214  state[0] = seed & 0xffff;
215  state[1] = (seed >> 16) & 0xffff;
216  state[2] = (seed >> 32) & 0xffff;
217 }
218 
229 VuoInteger VuoInteger_randomWithState(unsigned short state[3], const VuoInteger minimum, const VuoInteger maximum)
230 {
231  if (minimum == maximum)
232  return minimum;
233 
234  VuoInteger actualMinimum = MIN(minimum,maximum);
235  VuoInteger actualMaximum = MAX(minimum,maximum);
236 
237  // Based on https://www.mikeash.com/pyblog/friday-qa-2011-03-18-random-numbers.html
238  VuoInteger topPlusOne = actualMaximum - actualMinimum + 1;
239  VuoInteger two31 = 1U << 31;
240  VuoInteger maxUsable = (two31 / topPlusOne) * topPlusOne;
241 
242  while (1)
243  {
244  VuoInteger num = jrand48(state);
245  if (num >= 0 && num < maxUsable)
246  return num % topPlusOne + actualMinimum;
247  }
248 }
249 
253 static const char VuoInteger_hexToDec[256] =
254 {
255  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
257  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
258  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
259  0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261  0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
269  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
270  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
271 };
272 
279 {
280  return VuoInteger_hexToDec[byte];
281 }
282 
286 bool VuoInteger_areEqual(const VuoInteger value1, const VuoInteger value2)
287 {
288  return value1 == value2;
289 }
290 
295 {
296  return a < b;
297 }