Vuo  2.3.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  "dependencies": [
22  "VuoList_VuoInteger",
23  ],
24 });
25 #endif
27 
33 {
34  if (!js)
35  return 0;
36 
37  json_type t = json_object_get_type(js);
38  if (t == json_type_int)
39  return json_object_get_int64(js);
40  else if (t == json_type_double)
41  {
42  double d = json_object_get_double(js);
43  if (d == -INFINITY)
44  return LLONG_MIN;
45  if (d == INFINITY)
46  return LLONG_MAX;
47  return d;
48  }
49  else
50  {
51  // Use strtold() instead of json_object_get_int64(),
52  // since the latter doesn't support JSON strings with scientific notation.
53  // Use `long double strtold()` instead of `double atof()`
54  // since `long double` can precisely represent the int64 max value, whereas `double` can't.
55  const char *s = json_object_get_string(js);
56  if (s)
57  return strtold(s, NULL);
58  else
59  return 0;
60  }
61 }
62 
68 {
69  if (value == LLONG_MIN)
70  return json_object_new_double(-INFINITY);
71  else if (value == LLONG_MAX)
72  return json_object_new_double(INFINITY);
73  else
74  return json_object_new_int64(value);
75 }
76 
81 char * VuoInteger_getSummary(const VuoInteger value)
82 {
83  json_object *js = VuoInteger_getJson(value);
84  char *summary = strdup(json_object_to_json_string_ext(js,JSON_C_TO_STRING_PLAIN));
85  json_object_put(js);
86  return summary;
87 }
88 
93 {
94  unsigned long count = VuoListGetCount_VuoInteger(values);
95  if (count == 0)
96  {
97  *outputPosition = 0;
98  return 0;
99  }
100 
101  VuoInteger *integers = VuoListGetData_VuoInteger(values);
102  VuoInteger min = LONG_MAX;
103  for (unsigned long i = 0; i < count; ++i)
104  if (integers[i] < min)
105  {
106  min = integers[i];
107  *outputPosition = i + 1;
108  }
109 
110  return min;
111 }
112 
117 {
118  unsigned long count = VuoListGetCount_VuoInteger(values);
119  if (count == 0)
120  {
121  *outputPosition = 0;
122  return 0;
123  }
124 
125  VuoInteger *integers = VuoListGetData_VuoInteger(values);
126  VuoInteger max = LONG_MIN;
127  for (unsigned long i = 0; i < count; ++i)
128  if (integers[i] > max)
129  {
130  max = integers[i];
131  *outputPosition = i + 1;
132  }
133 
134  return max;
135 }
136 
141 {
142  VuoInteger count = VuoListGetCount_VuoInteger(values);
143  if (count == 0)
144  return 0;
145 
146  VuoInteger sum = 0;
147  for (VuoInteger i = 1; i <= count; ++i)
148  sum += VuoListGetValue_VuoInteger(values, i);
149 
150  return sum/count;
151 }
152 
158 {
159  VuoInteger rectifiedMin = (minimum < maximum) ? minimum : maximum;
160  VuoInteger rectifiedMax = (minimum < maximum) ? maximum : minimum;
161 
162  if (value > rectifiedMax)
163  return rectifiedMin + ((value-rectifiedMax-1) % (rectifiedMax-rectifiedMin+1));
164  else if (value < rectifiedMin)
165  return rectifiedMax + ((value-rectifiedMin+1) % (rectifiedMax-rectifiedMin+1));
166  else
167  return value;
168 }
169 
194 static u_int32_t VuoInteger_arc4random_uniform(u_int32_t upper_bound)
195 {
196  u_int32_t r, min;
197 
198  if (upper_bound < 2)
199  return 0;
200 
201 #if (ULONG_MAX > 0xffffffffUL)
202  min = 0x100000000UL % upper_bound;
203 #else
204  /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
205  if (upper_bound > 0x80000000)
206  min = 1 + ~upper_bound; /* 2**32 - upper_bound */
207  else {
208  /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
209  min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
210  }
211 #endif
212 
213  /*
214  * This could theoretically loop forever but each retry has
215  * p > 0.5 (worst case, usually far better) of selecting a
216  * number inside the range we need, so it should rarely need
217  * to re-roll.
218  */
219  for (;;) {
220  r = arc4random();
221  if (r >= min)
222  break;
223  }
224 
225  return r % upper_bound;
226 }
227 
235 VuoInteger VuoInteger_random(const VuoInteger minimum, const VuoInteger maximum)
236 {
237  if (minimum == maximum)
238  return minimum;
239 
240  VuoInteger actualMinimum = MIN(minimum,maximum);
241  VuoInteger actualMaximum = MAX(minimum,maximum);
242 
243  return VuoInteger_arc4random_uniform(actualMaximum - actualMinimum + 1) + actualMinimum;
244 }
245 
249 void VuoInteger_setRandomState(unsigned short state[3], const VuoInteger seed)
250 {
251  state[0] = seed & 0xffff;
252  state[1] = (seed >> 16) & 0xffff;
253  state[2] = (seed >> 32) & 0xffff;
254 }
255 
266 VuoInteger VuoInteger_randomWithState(unsigned short state[3], const VuoInteger minimum, const VuoInteger maximum)
267 {
268  if (minimum == maximum)
269  return minimum;
270 
271  VuoInteger actualMinimum = MIN(minimum,maximum);
272  VuoInteger actualMaximum = MAX(minimum,maximum);
273 
274  // Based on https://www.mikeash.com/pyblog/friday-qa-2011-03-18-random-numbers.html
275  VuoInteger topPlusOne = actualMaximum - actualMinimum + 1;
276  VuoInteger two31 = 1U << 31;
277  VuoInteger maxUsable = (two31 / topPlusOne) * topPlusOne;
278 
279  while (1)
280  {
281  VuoInteger num = jrand48(state);
282  if (num >= 0 && num < maxUsable)
283  return num % topPlusOne + actualMinimum;
284  }
285 }
286 
290 static const char VuoInteger_hexToDec[256] =
291 {
292  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
294  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
296  0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298  0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
302  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
303  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
304  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
305  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
308 };
309 
316 {
317  return VuoInteger_hexToDec[byte];
318 }
319 
323 bool VuoInteger_areEqual(const VuoInteger value1, const VuoInteger value2)
324 {
325  return value1 == value2;
326 }
327 
332 {
333  unsigned long count = VuoListGetCount_VuoInteger(values);
334  if (count <= 1)
335  return true;
336 
337  VuoInteger *integers = VuoListGetData_VuoInteger(values);
338  VuoInteger min, max;
339  min = max = integers[0];
340  for (unsigned long i = 1; i < count; ++i)
341  {
342  min = MIN(min, integers[i]);
343  max = MAX(max, integers[i]);
344  }
345  return (max - min) <= tolerance;
346 }
347 
352 {
353  return a < b;
354 }
355 
360 {
361  return minimum <= value && value <= maximum;
362 }