mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-09 14:32:41 +00:00
math/rand: add choice_bit_set
This commit is contained in:
@@ -939,19 +939,7 @@ map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
|
||||
|
||||
@builtin
|
||||
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||
when size_of(S) == 1 {
|
||||
return int(intrinsics.count_ones(transmute(u8)s))
|
||||
} else when size_of(S) == 2 {
|
||||
return int(intrinsics.count_ones(transmute(u16)s))
|
||||
} else when size_of(S) == 4 {
|
||||
return int(intrinsics.count_ones(transmute(u32)s))
|
||||
} else when size_of(S) == 8 {
|
||||
return int(intrinsics.count_ones(transmute(u64)s))
|
||||
} else when size_of(S) == 16 {
|
||||
return int(intrinsics.count_ones(transmute(u128)s))
|
||||
} else {
|
||||
#panic("Unhandled card bit_set size")
|
||||
}
|
||||
return int(intrinsics.count_ones(transmute(intrinsics.type_bit_set_underlying_type(S))s))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -687,3 +687,52 @@ choice_enum :: proc($T: typeid, gen := context.random_generator) -> T where intr
|
||||
return T(choice(values))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a random *set* bit from the provided `bit_set`.
|
||||
|
||||
Inputs:
|
||||
- set: The `bit_set` to choose a random set bit from
|
||||
|
||||
Returns:
|
||||
- res: The randomly selected bit, or the zero value if `not_empty` is `false`
|
||||
- not_empty: Whether the bit_set was not empty and thus `res` is actually a random set bit
|
||||
|
||||
Example:
|
||||
import "core:math/rand"
|
||||
import "core:fmt"
|
||||
|
||||
choice_bit_set_example :: proc() {
|
||||
Flags :: enum {
|
||||
A,
|
||||
B = 10,
|
||||
C,
|
||||
}
|
||||
|
||||
fmt.println(rand.choice_bit_set(bit_set[Flags]{}))
|
||||
fmt.println(rand.choice_bit_set(bit_set[Flags]{.B}))
|
||||
fmt.println(rand.choice_bit_set(bit_set[Flags]{.B, .C}))
|
||||
fmt.println(rand.choice_bit_set(bit_set[0..<15]{5, 1, 4}))
|
||||
}
|
||||
|
||||
Possible Output:
|
||||
A false
|
||||
B true
|
||||
C true
|
||||
5 true
|
||||
*/
|
||||
@(require_results)
|
||||
choice_bit_set :: proc(set: $T/bit_set[$E], gen := context.random_generator) -> (res: E, not_empty: bool) {
|
||||
total_set := card(set)
|
||||
if total_set == 0 {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
core_set := transmute(intrinsics.type_bit_set_underlying_type(T))set
|
||||
|
||||
for target := int_max(total_set, gen); target > 0; target -= 1 {
|
||||
core_set &= core_set - 1
|
||||
}
|
||||
|
||||
return E(intrinsics.count_trailing_zeros(core_set)), true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user