blob: a4292011aef362c02d7d427aec7c0e8f7a7f9d77 [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package asm
/*
Tested with uint8s like this:
for a := 0; a <= 255; a++ {
for b := 0; b <= 127; b++ {
ovfl := a+b != int(uint8(a)+uint8(b))
if addOverflows(uint8(a), uint8(b)) != ovfl {
fmt.Printf("%d+%d fails\n", a, b)
break
}
}
}
for a := 0; a <= 255; a++ {
for b := 0; b <= 127; b++ {
ovfl := a-b != int(uint8(a)-uint8(b))
if subOverflows(uint8(a), uint8(b)) != ovfl {
fmt.Printf("%d-%d fails\n", a, b)
break
}
}
}
for a := 0; a <= 255; a++ {
for b := 0; b <= 255; b++ {
ovfl := a*b != int(uint8(a)*uint8(b))
if mulOverflows(uint8(a), uint8(b)) != ovfl {
fmt.Printf("%d*%d fails\n", a, b)
}
}
}
overflow := func(a, b int) bool {
for ; b > 0; b-- {
a <<= 1
if a >= 256 {
return true
}
}
return false
}
for a := 0; a <= 255; a++ {
for b := 0; b <= 255; b++ {
ovfl := overflow(a, b)
if shiftOverflows(uint8(a), uint8(b)) != ovfl {
fmt.Printf("%d<<%d fails\n", a, b)
}
}
}
*/
func addOverflows(a, b uint64) bool {
return a+b < a
}
func subOverflows(a, b uint64) bool {
return a-b > a
}
func mulOverflows(a, b uint64) bool {
if a <= 1 || b <= 1 {
return false
}
c := a * b
return c/b != a
}
func shiftOverflows(a, b uint64) bool {
c := a << b
return c>>b != a
}
/*
For the record, signed overflow:
const mostNegative = -(mostPositive + 1)
const mostPositive = 1<<63 - 1
func signedAddOverflows(a, b int64) bool {
if (a >= 0) != (b >= 0) {
// Different signs cannot overflow.
return false
}
if a >= 0 {
// Both are positive.
return a+b < 0
}
return a+b >= 0
}
func signedSubOverflows(a, b int64) bool {
if (a >= 0) == (b >= 0) {
// Same signs cannot overflow.
return false
}
if a >= 0 {
// a positive, b negative.
return a-b < 0
}
return a-b >= 0
}
func signedMulOverflows(a, b int64) bool {
if a == 0 || b == 0 || a == 1 || b == 1 {
return false
}
if a == mostNegative || b == mostNegative {
return true
}
c := a * b
return c/b != a
}
func signedShiftOverflows(a, b int64) bool {
// Avoid right shift of a negative number.
if a >= 0 {
c := a << b
return c>>b != a
}
// Otherwise it's negative, so we complement, which
// puts zeros at the top.
a = ^a
c := a << b
return c>>b != a
}
*/