123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- /*
- Copyright 2021 Jeroen van Rijn <[email protected]>.
- Made available under Odin's BSD-3 license.
- An arbitrary precision mathematics implementation in Odin.
- For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
- The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
- This file contains logical operations like `and`, `or` and `xor`.
- */
- package math_big
- /*
- The `and`, `or` and `xor` binops differ in two lines only.
- We could handle those with a switch, but that adds overhead.
- TODO: Implement versions that take a DIGIT immediate.
- */
- /*
- 2's complement `and`, returns `dest = a & b;`
- */
- int_bit_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a, b)
- context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_int_and(dest, a, b)
- }
- bit_and :: proc { int_bit_and, }
- /*
- 2's complement `or`, returns `dest = a | b;`
- */
- int_bit_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a, b)
- context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_int_or(dest, a, b)
- }
- bit_or :: proc { int_bit_or, }
- /*
- 2's complement `xor`, returns `dest = a ^ b;`
- */
- int_bit_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a, b)
- context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_int_xor(dest, a, b)
- }
- bit_xor :: proc { int_bit_xor, }
- /*
- dest = ~src
- */
- int_bit_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- /*
- Check that `src` and `dest` are usable.
- */
- assert_if_nil(dest, src)
- context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_complement(dest, src)
- }
- bit_complement :: proc { int_bit_complement, }
- /*
- quotient, remainder := numerator >> bits;
- `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed.
- */
- int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(quotient, numerator)
- context.allocator = allocator
- if err = internal_clear_if_uninitialized(quotient, numerator); err != nil { return err }
- return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits)
- }
- shrmod :: proc { int_shrmod, }
- int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- return #force_inline shrmod(dest, nil, source, bits, allocator)
- }
- shr :: proc { int_shr, }
- /*
- Shift right by a certain bit count with sign extension.
- */
- int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src)
- context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_shr_signed(dest, src, bits)
- }
- shr_signed :: proc { int_shr_signed, }
- /*
- Shift left by a certain bit count.
- */
- int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src)
- context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_shl(dest, src, bits)
- }
- shl :: proc { int_shl, }
|