logical.odin 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. Copyright 2021 Jeroen van Rijn <[email protected]>.
  3. Made available under Odin's BSD-3 license.
  4. An arbitrary precision mathematics implementation in Odin.
  5. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
  6. The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
  7. This file contains logical operations like `and`, `or` and `xor`.
  8. */
  9. package math_big
  10. /*
  11. The `and`, `or` and `xor` binops differ in two lines only.
  12. We could handle those with a switch, but that adds overhead.
  13. TODO: Implement versions that take a DIGIT immediate.
  14. */
  15. /*
  16. 2's complement `and`, returns `dest = a & b;`
  17. */
  18. int_bit_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  19. assert_if_nil(dest, a, b)
  20. context.allocator = allocator
  21. internal_clear_if_uninitialized(a, b) or_return
  22. return #force_inline internal_int_and(dest, a, b)
  23. }
  24. bit_and :: proc { int_bit_and, }
  25. /*
  26. 2's complement `or`, returns `dest = a | b;`
  27. */
  28. int_bit_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  29. assert_if_nil(dest, a, b)
  30. context.allocator = allocator
  31. internal_clear_if_uninitialized(a, b) or_return
  32. return #force_inline internal_int_or(dest, a, b)
  33. }
  34. bit_or :: proc { int_bit_or, }
  35. /*
  36. 2's complement `xor`, returns `dest = a ^ b;`
  37. */
  38. int_bit_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  39. assert_if_nil(dest, a, b)
  40. context.allocator = allocator
  41. internal_clear_if_uninitialized(a, b) or_return
  42. return #force_inline internal_int_xor(dest, a, b)
  43. }
  44. bit_xor :: proc { int_bit_xor, }
  45. /*
  46. dest = ~src
  47. */
  48. int_bit_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
  49. /*
  50. Check that `src` and `dest` are usable.
  51. */
  52. assert_if_nil(dest, src)
  53. context.allocator = allocator
  54. internal_clear_if_uninitialized(dest, src) or_return
  55. return #force_inline internal_int_complement(dest, src)
  56. }
  57. bit_complement :: proc { int_bit_complement, }
  58. /*
  59. quotient, remainder := numerator >> bits;
  60. `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed.
  61. */
  62. int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
  63. assert_if_nil(quotient, numerator)
  64. context.allocator = allocator
  65. if err = internal_clear_if_uninitialized(quotient, numerator); err != nil { return err }
  66. return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits)
  67. }
  68. shrmod :: proc { int_shrmod, }
  69. int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
  70. return #force_inline shrmod(dest, nil, source, bits, allocator)
  71. }
  72. shr :: proc { int_shr, }
  73. /*
  74. Shift right by a certain bit count with sign extension.
  75. */
  76. int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
  77. assert_if_nil(dest, src)
  78. context.allocator = allocator
  79. internal_clear_if_uninitialized(dest, src) or_return
  80. return #force_inline internal_int_shr_signed(dest, src, bits)
  81. }
  82. shr_signed :: proc { int_shr_signed, }
  83. /*
  84. Shift left by a certain bit count.
  85. */
  86. int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
  87. assert_if_nil(dest, src)
  88. context.allocator = allocator
  89. internal_clear_if_uninitialized(dest, src) or_return
  90. return #force_inline internal_int_shl(dest, src, bits)
  91. }
  92. shl :: proc { int_shl, }