math/rand: support non-contiguous enums in choice_enum

This commit is contained in:
Laytan Laats
2024-10-25 20:41:57 +02:00
parent bcf2b93c6e
commit bb4fc9979a
+15 -15
View File
@@ -670,20 +670,20 @@ choice :: proc(array: $T/[]$E, gen := context.random_generator) -> (res: E) {
@(require_results) @(require_results)
choice_enum :: proc($T: typeid, gen := context.random_generator) -> T choice_enum :: proc($T: typeid, gen := context.random_generator) -> T where intrinsics.type_is_enum(T) {
where when size_of(T) <= 8 && len(T) == cap(T) {
intrinsics.type_is_enum(T), when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
size_of(T) <= 8, u64(max(T)) > u64(max(i64)) {
len(T) == cap(T) /* Only allow contiguous enum types */ \ i := uint64(gen) % u64(len(T))
{ i += u64(min(T))
when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) && return T(i)
u64(max(T)) > u64(max(i64)) { } else {
i := uint64(gen) % u64(len(T)) i := int63_max(i64(len(T)), gen)
i += u64(min(T)) i += i64(min(T))
return T(i) return T(i)
}
} else { } else {
i := int63_max(i64(len(T)), gen) values := runtime.type_info_base(type_info_of(T)).variant.(runtime.Type_Info_Enum).values
i += i64(min(T)) return T(choice(values))
return T(i)
} }
} }