overflow.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*Package overflow offers overflow-checked integer arithmetic operations
  2. for int, int32, and int64. Each of the operations returns a
  3. result,bool combination. This was prompted by the need to know when
  4. to flow into higher precision types from the math.big library.
  5. For instance, assuing a 64 bit machine:
  6. 10 + 20 -> 30
  7. int(math.MaxInt64) + 1 -> -9223372036854775808
  8. whereas
  9. overflow.Add(10,20) -> (30, true)
  10. overflow.Add(math.MaxInt64,1) -> (0, false)
  11. Add, Sub, Mul, Div are for int. Add64, Add32, etc. are specifically sized.
  12. If anybody wishes an unsigned version, submit a pull request for code
  13. and new tests. */
  14. package overflow
  15. //go:generate ./overflow_template.sh
  16. import "math"
  17. func _is64Bit() bool {
  18. maxU32 := uint(math.MaxUint32)
  19. return ((maxU32 << 1) >> 1) == maxU32
  20. }
  21. /********** PARTIAL TEST COVERAGE FROM HERE DOWN *************
  22. The only way that I could see to do this is a combination of
  23. my normal 64 bit system and a GopherJS running on Node. My
  24. understanding is that its ints are 32 bit.
  25. So, FEEL FREE to carefully review the code visually.
  26. *************************************************************/
  27. // Unspecified size, i.e. normal signed int
  28. // Add sums two ints, returning the result and a boolean status.
  29. func Add(a, b int) (int, bool) {
  30. if _is64Bit() {
  31. r64, ok := Add64(int64(a), int64(b))
  32. return int(r64), ok
  33. }
  34. r32, ok := Add32(int32(a), int32(b))
  35. return int(r32), ok
  36. }
  37. // Sub returns the difference of two ints and a boolean status.
  38. func Sub(a, b int) (int, bool) {
  39. if _is64Bit() {
  40. r64, ok := Sub64(int64(a), int64(b))
  41. return int(r64), ok
  42. }
  43. r32, ok := Sub32(int32(a), int32(b))
  44. return int(r32), ok
  45. }
  46. // Mul returns the product of two ints and a boolean status.
  47. func Mul(a, b int) (int, bool) {
  48. if _is64Bit() {
  49. r64, ok := Mul64(int64(a), int64(b))
  50. return int(r64), ok
  51. }
  52. r32, ok := Mul32(int32(a), int32(b))
  53. return int(r32), ok
  54. }
  55. // Div returns the quotient of two ints and a boolean status
  56. func Div(a, b int) (int, bool) {
  57. if _is64Bit() {
  58. r64, ok := Div64(int64(a), int64(b))
  59. return int(r64), ok
  60. }
  61. r32, ok := Div32(int32(a), int32(b))
  62. return int(r32), ok
  63. }
  64. // Quotient returns the quotient, remainder and status of two ints
  65. func Quotient(a, b int) (int, int, bool) {
  66. if _is64Bit() {
  67. q64, r64, ok := Quotient64(int64(a), int64(b))
  68. return int(q64), int(r64), ok
  69. }
  70. q32, r32, ok := Quotient32(int32(a), int32(b))
  71. return int(q32), int(r32), ok
  72. }
  73. /************* Panic versions for int ****************/
  74. // Addp returns the sum of two ints, panicking on overflow
  75. func Addp(a, b int) int {
  76. r, ok := Add(a, b)
  77. if !ok {
  78. panic("addition overflow")
  79. }
  80. return r
  81. }
  82. // Subp returns the difference of two ints, panicking on overflow.
  83. func Subp(a, b int) int {
  84. r, ok := Sub(a, b)
  85. if !ok {
  86. panic("subtraction overflow")
  87. }
  88. return r
  89. }
  90. // Mulp returns the product of two ints, panicking on overflow.
  91. func Mulp(a, b int) int {
  92. r, ok := Mul(a, b)
  93. if !ok {
  94. panic("multiplication overflow")
  95. }
  96. return r
  97. }
  98. // Divp returns the quotient of two ints, panicking on overflow.
  99. func Divp(a, b int) int {
  100. r, ok := Div(a, b)
  101. if !ok {
  102. panic("division failure")
  103. }
  104. return r
  105. }