diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-03 17:33:18 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-03 17:33:18 -0400 |
| commit | 68b34cf00b8a52509c0bed7b1e66b3e40de0c4f5 (patch) | |
| tree | 04ffa2538865b4a342c78d677026b3703f6e4d41 | |
| parent | 99b00530ceaf787a936cd37894e2dbf5b6e612ce (diff) | |
Fix array:random() to return a random item using correct RNG logic,
rather than a reference.
| -rw-r--r-- | builtins/array.c | 7 | ||||
| -rw-r--r-- | builtins/array.h | 1 | ||||
| -rw-r--r-- | compile.c | 2 | ||||
| -rw-r--r-- | typecheck.c | 3 |
4 files changed, 7 insertions, 6 deletions
diff --git a/builtins/array.c b/builtins/array.c index 3b1b7c6d..9b0e4206 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -13,6 +13,7 @@ #include "array.h" #include "functions.h" #include "halfsiphash.h" +#include "integers.h" #include "types.h" #include "util.h" @@ -160,7 +161,7 @@ public void Array$shuffle(array_t *arr, int64_t padded_item_size) char tmp[padded_item_size]; for (int64_t i = arr->length-1; i > 1; i--) { - int32_t j = arc4random_uniform(i+1); + int64_t j = Int$random(0, i); memcpy(tmp, arr->data + i*padded_item_size, padded_item_size); memcpy((void*)arr->data + i*padded_item_size, arr->data + j*padded_item_size, padded_item_size); memcpy((void*)arr->data + j*padded_item_size, tmp, padded_item_size); @@ -171,7 +172,7 @@ public void *Array$random(array_t arr) { if (arr.length == 0) return NULL; // fail("Cannot get a random item from an empty array!"); - uint32_t index = arc4random_uniform(arr.length); + int64_t index = Int$random(0, arr.length-1); return arr.data + arr.stride*index; } @@ -203,7 +204,7 @@ public array_t Array$sample(array_t arr, int64_t n, array_t weights, int64_t pad if (total == 0.0) { for (int64_t i = 0; i < n; i++) { - uint32_t index = arc4random_uniform(arr.length); + int64_t index = Int$random(0, arr.length-1); memcpy(selected.data + i*padded_item_size, arr.data + arr.stride*index, padded_item_size); } } else { diff --git a/builtins/array.h b/builtins/array.h index c05aeae9..6d5c3015 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -60,6 +60,7 @@ void Array$sort(array_t *arr, closure_t comparison, int64_t padded_item_size); array_t Array$sorted(array_t arr, closure_t comparison, int64_t padded_item_size); void Array$shuffle(array_t *arr, int64_t padded_item_size); void *Array$random(array_t arr); +#define Array$random_value(arr, t) ({ array_t _arr = arr; if (_arr.length == 0) fail("Cannot get a random value from an empty array!"); *(t*)Array$random(_arr); }) array_t Array$sample(array_t arr, int64_t n, array_t weights, int64_t padded_item_size); void Array$clear(array_t *array); void Array$compact(array_t *arr, int64_t padded_item_size); @@ -1861,7 +1861,7 @@ CORD compile(env_t *env, ast_t *ast) } else if (streq(call->name, "random")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); - return CORD_all("Array$random(", self, ")"); + return CORD_all("Array$random_value(", self, ", ", compile_type(item_t), ")"); } else if (streq(call->name, "sample")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="count", .type=Type(IntType, .bits=64), diff --git a/typecheck.c b/typecheck.c index 49ebe582..a790f73d 100644 --- a/typecheck.c +++ b/typecheck.c @@ -667,8 +667,7 @@ type_t *get_type(env_t *env, ast_t *ast) else if (streq(call->name, "sort")) return Type(VoidType); else if (streq(call->name, "sorted")) return self_value_t; else if (streq(call->name, "shuffle")) return Type(VoidType); - else if (streq(call->name, "random")) - return Type(PointerType, .pointed=Match(self_value_t, ArrayType)->item_type, .is_optional=true, .is_readonly=true); + else if (streq(call->name, "random")) return Match(self_value_t, ArrayType)->item_type; else if (streq(call->name, "sample")) return self_value_t; else if (streq(call->name, "clear")) return Type(VoidType); else if (streq(call->name, "from")) return self_value_t; |
