aboutsummaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2025-10-14 23:30:12 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2025-10-14 23:30:38 +0200
commitee93f48729e0cd7a2ba79ea9d2a3b13a3bbe5a40 (patch)
tree7bc4900efe09cdf906d0e12b07726eedb6a13387 /core/math
parent347eae3a66a1e528254b1742162e1d17318fa434 (diff)
core:math/bits: Finish docs, add `bitfield_extract` + `bitfield_insert` test.
Diffstat (limited to 'core/math')
-rw-r--r--core/math/bits/bits.odin920
1 files changed, 886 insertions, 34 deletions
diff --git a/core/math/bits/bits.odin b/core/math/bits/bits.odin
index 1edafebf4..1e8d765dd 100644
--- a/core/math/bits/bits.odin
+++ b/core/math/bits/bits.odin
@@ -234,57 +234,261 @@ rotate_left :: proc "contextless" (x: uint, k: int) -> uint {
return x << s | x >> (n-s)
}
+/*
+Returns unsigned integer `i`
+
+NOTE: A byte has no endianness, so `from_be_u8` exists to be complementary to `from_be_*`.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`
+*/
@(require_results)
from_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+/*
+Returns unsigned integer `i`
+
+NOTE: A byte has no endianness, so `from_le_u8` exists to be complementary to `from_le_*`.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`
+*/
@(require_results)
from_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
from_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+/*
+Returns unsigned integer `i`
+
+NOTE: A byte has no endianness, so `to_be_u8` exists to be complementary to `to_be_*`.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`
+*/
@(require_results)
to_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
@(require_results)
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
to_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a little endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
+/*
+Returns unsigned integer `i`
+
+NOTE: A byte has no endianness, so `to_le_u8` exists to be complementary to `to_le_*`.
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`
+*/
@(require_results)
to_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+
+Inputs:
+- i: The unsigned integer
+
+Returns:
+- res: `i`, optionally byte-swapped
+*/
@(require_results)
to_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
-@(require_results)
-to_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+/*
+Returns unsigned integer `i`, byte-swapped if we're on a big endian target.
+Inputs:
+- i: The unsigned integer
+Returns:
+- res: `i`, optionally byte-swapped
+*/
+@(require_results)
+to_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
+
+// returns the minimum number of bits required to represent x
@(require_results)
len_u8 :: proc "contextless" (x: u8) -> int {
return int(len_u8_table[x])
}
+
+// returns the minimum number of bits required to represent x
@(require_results)
len_u16 :: proc "contextless" (x: u16) -> (n: int) {
x := x
@@ -294,6 +498,8 @@ len_u16 :: proc "contextless" (x: u16) -> (n: int) {
}
return n + int(len_u8_table[x])
}
+
+// returns the minimum number of bits required to represent x
@(require_results)
len_u32 :: proc "contextless" (x: u32) -> (n: int) {
x := x
@@ -307,6 +513,8 @@ len_u32 :: proc "contextless" (x: u32) -> (n: int) {
}
return n + int(len_u8_table[x])
}
+
+// returns the minimum number of bits required to represent x
@(require_results)
len_u64 :: proc "contextless" (x: u64) -> (n: int) {
x := x
@@ -324,6 +532,8 @@ len_u64 :: proc "contextless" (x: u64) -> (n: int) {
}
return n + int(len_u8_table[x])
}
+
+// returns the minimum number of bits required to represent x
@(require_results)
len_uint :: proc "contextless" (x: uint) -> (n: int) {
when size_of(uint) == size_of(u64) {
@@ -336,23 +546,60 @@ len_uint :: proc "contextless" (x: uint) -> (n: int) {
// returns the minimum number of bits required to represent x
len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint}
+/*
+Add with carry
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- carry: Carry in
+Returns:
+- sum: The sum
+- carry_out: Carry out
+*/
@(require_results)
add_u32 :: proc "contextless" (x, y, carry: u32) -> (sum, carry_out: u32) {
tmp_carry, tmp_carry2: bool
- sum, tmp_carry = intrinsics.overflow_add(x, y)
+ sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u32(tmp_carry | tmp_carry2)
return
}
+
+/*
+Add with carry
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- carry: Carry in
+
+Returns:
+- sum: The sum
+- carry_out: Carry out
+*/
@(require_results)
add_u64 :: proc "contextless" (x, y, carry: u64) -> (sum, carry_out: u64) {
tmp_carry, tmp_carry2: bool
- sum, tmp_carry = intrinsics.overflow_add(x, y)
+ sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u64(tmp_carry | tmp_carry2)
return
}
+
+/*
+Add with carry
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- carry: Carry in
+
+Returns:
+- sum: The sum
+- carry_out: Carry out
+*/
@(require_results)
add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) {
when size_of(uint) == size_of(u64) {
@@ -363,17 +610,54 @@ add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) {
}
return uint(a), uint(b)
}
+
+/*
+Add with carry
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- carry: Carry in
+
+Returns:
+- sum: The sum
+- carry_out: Carry out
+*/
add :: proc{add_u32, add_u64, add_uint}
+/*
+Subtract with borrow
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- borrow: Borrow in
+
+Returns:
+- diff: The difference
+- borrow_out: Borrow out
+*/
@(require_results)
sub_u32 :: proc "contextless" (x, y, borrow: u32) -> (diff, borrow_out: u32) {
tmp_borrow, tmp_borrow2: bool
- diff, tmp_borrow = intrinsics.overflow_sub(x, y)
+ diff, tmp_borrow = intrinsics.overflow_sub(x, y)
diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow)
borrow_out = u32(tmp_borrow | tmp_borrow2)
return
}
+
+/*
+Subtract with borrow
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- borrow: Borrow in
+
+Returns:
+- diff: The difference
+- borrow_out: Borrow out
+*/
@(require_results)
sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) {
tmp_borrow, tmp_borrow2: bool
@@ -382,6 +666,19 @@ sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) {
borrow_out = u64(tmp_borrow | tmp_borrow2)
return
}
+
+/*
+Subtract with borrow
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- borrow: Borrow in
+
+Returns:
+- diff: The difference
+- borrow_out: Borrow out
+*/
@(require_results)
sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint) {
when size_of(uint) == size_of(u64) {
@@ -392,15 +689,50 @@ sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint)
}
return uint(a), uint(b)
}
+
+/*
+Subtract with borrow
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+- borrow: Borrow in
+
+Returns:
+- diff: The difference
+- borrow_out: Borrow out
+*/
sub :: proc{sub_u32, sub_u64, sub_uint}
+/*
+Multiply two words and return the result in high and low word
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+Returns:
+- hi: The result's high word
+- lo: The result's low word
+*/
@(require_results)
mul_u32 :: proc "contextless" (x, y: u32) -> (hi, lo: u32) {
z := u64(x) * u64(y)
hi, lo = u32(z>>32), u32(z)
return
}
+
+/*
+Multiply two words and return the result in high and low word
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+
+Returns:
+- hi: The result's high word
+- lo: The result's low word
+*/
@(require_results)
mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) {
prod_wide := u128(x) * u128(y)
@@ -408,6 +740,17 @@ mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) {
return
}
+/*
+Multiply two words and return the result in high and low word
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+
+Returns:
+- hi: The result's high word
+- lo: The result's low word
+*/
@(require_results)
mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) {
when size_of(uint) == size_of(u32) {
@@ -419,9 +762,31 @@ mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) {
return uint(a), uint(b)
}
+/*
+Multiply two words and return the result in high and low word
+
+Inputs:
+- x: The unsigned integer
+- y: Another unsigned integer
+
+Returns:
+- hi: The result's high word
+- lo: The result's low word
+*/
mul :: proc{mul_u32, mul_u64, mul_uint}
+/*
+Divide a 64-bit unsigned integer (in two 32-bit words) by a 32-bit divisor
+
+Inputs:
+- hi: High word of 64-bit integer
+- lo: Low word of 64-bit integer
+- y: Divisor
+Returns:
+- quo: 32-bit quotient
+- rem: 32-bit remainder
+*/
@(require_results)
div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) {
assert(y != 0 && y <= hi)
@@ -429,6 +794,19 @@ div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) {
quo, rem = u32(z/u64(y)), u32(z%u64(y))
return
}
+
+/*
+Divide a 128-bit unsigned integer (in two 64-bit words) by a 64-bit divisor
+
+Inputs:
+- hi: High word of 128-bit integer
+- lo: Low word of 128-bit integer
+- y: Divisor
+
+Returns:
+- quo: 64-bit quotient
+- rem: 64-bit Remainder
+*/
@(require_results)
div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) {
y := y
@@ -475,6 +853,19 @@ div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) {
return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s
}
+
+/*
+Divide an unsigned integer (in two words) by a divisor
+
+Inputs:
+- hi: High word of input
+- lo: Low word of input
+- y: Divisor
+
+Returns:
+- quo: Quotient
+- rem: Remainder
+*/
@(require_results)
div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) {
when size_of(uint) == size_of(u32) {
@@ -485,31 +876,150 @@ div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) {
}
return uint(a), uint(b)
}
+
+/*
+Divide an unsigned integer (in two words) by a divisor
+
+Inputs:
+- hi: High word of input
+- lo: Low word of input
+- y: Divisor
+
+Returns:
+- quo: Quotient
+- rem: Remainder
+*/
div :: proc{div_u32, div_u64, div_uint}
+/*
+Checks whether an unsigned number is a power of two
+Inputs:
+- i: Unsigned number
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_u8 :: proc "contextless" (i: u8) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_u8 :: proc "contextless" (i: u8) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_i8 :: proc "contextless" (i: i8) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_i8 :: proc "contextless" (i: i8) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_u16 :: proc "contextless" (i: u16) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_u16 :: proc "contextless" (i: u16) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_i16 :: proc "contextless" (i: i16) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_i16 :: proc "contextless" (i: i16) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_u32 :: proc "contextless" (i: u32) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_u32 :: proc "contextless" (i: u32) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_i32 :: proc "contextless" (i: i32) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_i32 :: proc "contextless" (i: i32) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_u64 :: proc "contextless" (i: u64) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_u64 :: proc "contextless" (i: u64) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_i64 :: proc "contextless" (i: i64) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_i64 :: proc "contextless" (i: i64) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_uint :: proc "contextless" (i: uint) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_uint :: proc "contextless" (i: uint) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
@(require_results)
-is_power_of_two_int :: proc "contextless" (i: int) -> bool { return i > 0 && (i & (i-1)) == 0 }
+is_power_of_two_int :: proc "contextless" (i: int) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 }
+
+/*
+Checks whether an unsigned number is a power of two
+Inputs:
+- i: Unsigned number
+
+Returns:
+- is_pot: `true` if `i` is a power of two, `false` otherwise
+*/
is_power_of_two :: proc{
is_power_of_two_u8, is_power_of_two_i8,
is_power_of_two_u16, is_power_of_two_i16,
@@ -532,20 +1042,101 @@ len_u8_table := [256]u8{
128..<256 = 8,
}
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_u8 :: proc "contextless" (value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1) }
+bitfield_extract_u8 :: proc "contextless" (value: u8, offset, bits: uint) -> (res: u8) { return (value >> offset) & u8(1<<bits - 1) }
+
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_u16 :: proc "contextless" (value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1) }
+bitfield_extract_u16 :: proc "contextless" (value: u16, offset, bits: uint) -> (res: u16) { return (value >> offset) & u16(1<<bits - 1) }
+
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_u32 :: proc "contextless" (value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1) }
+bitfield_extract_u32 :: proc "contextless" (value: u32, offset, bits: uint) -> (res: u32) { return (value >> offset) & u32(1<<bits - 1) }
+
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_u64 :: proc "contextless" (value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1) }
+bitfield_extract_u64 :: proc "contextless" (value: u64, offset, bits: uint) -> (res: u64) { return (value >> offset) & u64(1<<bits - 1) }
+
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_u128 :: proc "contextless" (value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1) }
+bitfield_extract_u128 :: proc "contextless" (value: u128, offset, bits: uint) -> (res: u128) { return (value >> offset) & u128(1<<bits - 1) }
+
+/*
+Extracts bits from an unsigned integer
+
+Inputs:
+- value: Unsigned integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
-bitfield_extract_uint :: proc "contextless" (value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1) }
+bitfield_extract_uint :: proc "contextless" (value: uint, offset, bits: uint) -> (res: uint) { return (value >> offset) & uint(1<<bits - 1) }
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_i8 :: proc "contextless" (value: i8, offset, bits: uint) -> i8 {
v := (u8(value) >> offset) & u8(1<<bits - 1)
@@ -553,6 +1144,18 @@ bitfield_extract_i8 :: proc "contextless" (value: i8, offset, bits: uint) -> i8
r := (v~m) - m
return i8(r)
}
+
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_i16 :: proc "contextless" (value: i16, offset, bits: uint) -> i16 {
v := (u16(value) >> offset) & u16(1<<bits - 1)
@@ -560,6 +1163,18 @@ bitfield_extract_i16 :: proc "contextless" (value: i16, offset, bits: uint) -> i
r := (v~m) - m
return i16(r)
}
+
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_i32 :: proc "contextless" (value: i32, offset, bits: uint) -> i32 {
v := (u32(value) >> offset) & u32(1<<bits - 1)
@@ -567,6 +1182,18 @@ bitfield_extract_i32 :: proc "contextless" (value: i32, offset, bits: uint) -> i
r := (v~m) - m
return i32(r)
}
+
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_i64 :: proc "contextless" (value: i64, offset, bits: uint) -> i64 {
v := (u64(value) >> offset) & u64(1<<bits - 1)
@@ -574,6 +1201,18 @@ bitfield_extract_i64 :: proc "contextless" (value: i64, offset, bits: uint) -> i
r := (v~m) - m
return i64(r)
}
+
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_i128 :: proc "contextless" (value: i128, offset, bits: uint) -> i128 {
v := (u128(value) >> offset) & u128(1<<bits - 1)
@@ -581,6 +1220,18 @@ bitfield_extract_i128 :: proc "contextless" (value: i128, offset, bits: uint) ->
r := (v~m) - m
return i128(r)
}
+
+/*
+Extracts bits from a signed integer
+
+Inputs:
+- value: Signed integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
@(require_results)
bitfield_extract_int :: proc "contextless" (value: int, offset, bits: uint) -> int {
v := (uint(value) >> offset) & uint(1<<bits - 1)
@@ -589,7 +1240,17 @@ bitfield_extract_int :: proc "contextless" (value: int, offset, bits: uint) -> i
return int(r)
}
+/*
+Extracts bits from an integer
+
+Inputs:
+- value: Integer
+- offset: Offset (counting from LSB) at which to extract
+- bits: Number of bits to extract
+Returns:
+- res: `bits` bits starting at offset `offset`
+*/
bitfield_extract :: proc{
bitfield_extract_u8,
bitfield_extract_u16,
@@ -605,69 +1266,260 @@ bitfield_extract :: proc{
bitfield_extract_int,
}
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> u8 {
+bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> (res: u8) {
mask := u8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_u16 :: proc "contextless" (base, insert: u16, offset, bits: uint) -> u16 {
+bitfield_insert_u16 :: proc "contextless" (base, insert: u16, offset, bits: uint) -> (res: u16) {
mask := u16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_u32 :: proc "contextless" (base, insert: u32, offset, bits: uint) -> u32 {
+bitfield_insert_u32 :: proc "contextless" (base, insert: u32, offset, bits: uint) -> (res: u32) {
mask := u32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_u64 :: proc "contextless" (base, insert: u64, offset, bits: uint) -> u64 {
+bitfield_insert_u64 :: proc "contextless" (base, insert: u64, offset, bits: uint) -> (res: u64) {
mask := u64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_u128 :: proc "contextless" (base, insert: u128, offset, bits: uint) -> u128 {
+bitfield_insert_u128 :: proc "contextless" (base, insert: u128, offset, bits: uint) -> (res: u128) {
mask := u128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_uint :: proc "contextless" (base, insert: uint, offset, bits: uint) -> uint {
+bitfield_insert_uint :: proc "contextless" (base, insert: uint, offset, bits: uint) -> (res: uint) {
mask := uint(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_i8 :: proc "contextless" (base, insert: i8, offset, bits: uint) -> i8 {
+bitfield_insert_i8 :: proc "contextless" (base, insert: i8, offset, bits: uint) -> (res: i8) {
mask := i8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_i16 :: proc "contextless" (base, insert: i16, offset, bits: uint) -> i16 {
+bitfield_insert_i16 :: proc "contextless" (base, insert: i16, offset, bits: uint) -> (res: i16) {
mask := i16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_i32 :: proc "contextless" (base, insert: i32, offset, bits: uint) -> i32 {
+bitfield_insert_i32 :: proc "contextless" (base, insert: i32, offset, bits: uint) -> (res: i32) {
mask := i32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_i64 :: proc "contextless" (base, insert: i64, offset, bits: uint) -> i64 {
+bitfield_insert_i64 :: proc "contextless" (base, insert: i64, offset, bits: uint) -> (res: i64) {
mask := i64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_i128 :: proc "contextless" (base, insert: i128, offset, bits: uint) -> i128 {
+bitfield_insert_i128 :: proc "contextless" (base, insert: i128, offset, bits: uint) -> (res: i128) {
mask := i128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
@(require_results)
-bitfield_insert_int :: proc "contextless" (base, insert: int, offset, bits: uint) -> int {
+bitfield_insert_int :: proc "contextless" (base, insert: int, offset, bits: uint) -> (res: int) {
mask := int(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+/*
+Insert a subset of bits from one integer into another integer
+
+Copies `bits` number of `insert`'s lower bits to `base` at `offset`.
+
+Inputs:
+- base: Original integer to insert bits into
+- insert: Integer to copy bits from
+- offset: Bit offset in `base` at which to place `insert`'s bits
+- bits: Number of bits to copy
+
+Returns:
+- res: `base` with `bits` bits at `offset` replaced with `insert`'s
+*/
bitfield_insert :: proc{
bitfield_insert_u8,
bitfield_insert_u16,
@@ -681,4 +1533,4 @@ bitfield_insert :: proc{
bitfield_insert_i64,
bitfield_insert_i128,
bitfield_insert_int,
-}
+} \ No newline at end of file