aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/arrays.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib/arrays.c')
-rw-r--r--src/stdlib/arrays.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/src/stdlib/arrays.c b/src/stdlib/arrays.c
index b018012f..2941d2e0 100644
--- a/src/stdlib/arrays.c
+++ b/src/stdlib/arrays.c
@@ -307,6 +307,8 @@ public void Array$shuffle(Array_t *arr, OptionalClosure_t random_int64, int64_t
char tmp[padded_item_size];
for (int64_t i = arr->length-1; i > 1; i--) {
int64_t j = rng_fn(0, i, random_int64.userdata);
+ if unlikely (j < 0 || j > arr->length-1)
+ fail("The provided random number function returned an invalid value: ", j, " (not between 0 and ", i, ")");
memcpy(tmp, arr->data + i*padded_item_size, (size_t)padded_item_size);
memcpy((void*)arr->data + i*padded_item_size, arr->data + j*padded_item_size, (size_t)padded_item_size);
memcpy((void*)arr->data + j*padded_item_size, tmp, (size_t)padded_item_size);
@@ -327,6 +329,8 @@ public void *Array$random(Array_t arr, OptionalClosure_t random_int64)
int64_t (*rng_fn)(int64_t, int64_t, void*) = random_int64.fn;
int64_t index = rng_fn(0, arr.length-1, random_int64.userdata);
+ if unlikely (index < 0 || index > arr.length-1)
+ fail("The provided random number function returned an invalid value: ", index, " (not between 0 and ", (int64_t)arr.length, ")");
return arr.data + arr.stride*index;
}
@@ -370,11 +374,6 @@ public Array_t Array$sample(Array_t arr, Int_t int_n, Array_t weights, OptionalC
if (arr.length == 0)
fail("There are no elements in this array!");
- Array_t selected = {
- .data=arr.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size)) : GC_MALLOC((size_t)(n * padded_item_size)),
- .length=n,
- .stride=padded_item_size, .atomic=arr.atomic};
-
if (weights.length != arr.length)
fail("Array has ", (int64_t)arr.length, " elements, but there are ", (int64_t)weights.length, " weights given");
@@ -433,9 +432,18 @@ public Array_t Array$sample(Array_t arr, Int_t int_n, Array_t weights, OptionalC
aliases[i].alias = i;
double (*rng_fn)(void*) = random_num.fn ? random_num.fn : _default_random_num;
+
+ Array_t selected = {
+ .data=arr.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size)) : GC_MALLOC((size_t)(n * padded_item_size)),
+ .length=n,
+ .stride=padded_item_size, .atomic=arr.atomic};
for (int64_t i = 0; i < n; i++) {
- double r = (double)arr.length * rng_fn(random_num.userdata);
+ double r = rng_fn(random_num.userdata);
+ if unlikely (r < 0.0 || r >= 1.0)
+ fail("The random number function returned a value not between 0.0 (inclusive) and 1.0 (exclusive): ", r);
+ r *= (double)arr.length;
int64_t index = (int64_t)r;
+ assert(index >= 0 && index < arr.length);
if ((r - (double)index) > aliases[index].odds)
index = aliases[index].alias;
memcpy(selected.data + i*selected.stride, arr.data + index*arr.stride, (size_t)padded_item_size);