Bitmasks on signed types

612 views
Skip to first unread message

Dave MacFarlane

unread,
Jun 14, 2016, 1:16:41 PM6/14/16
to golang-nuts
Is this supposed to be legal in Go:

var x int32 = 3

fmt.Printf("%d", x & 0xFFFFFFFF)?

The language spec just says the bitwise operator "applies to integers only" and
"yields a result of the same type as the first operand" that I can see, but it's giving
me a compiler error:

./main.go:10: constant 4294967295 overflows int32

with go 1.6.2.

Is this a compiler bug, or am I missing something else in the spec that makes it impossible
to mask out the high bit in a signed integer type without converting to an unsigned equivalent first?

- Dave

Jan Mercl

unread,
Jun 14, 2016, 1:24:10 PM6/14/16
to Dave MacFarlane, golang-nuts
All binary operators, except shifts, require identical left and right types. Untyped values will be coerced to the type of the other side, if representable as such after the conversion. That's not the case in this example.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

-j

Dave MacFarlane

unread,
Jun 14, 2016, 1:45:22 PM6/14/16
to Jan Mercl, golang-nuts
What I'm not understanding is why that's not the case in this example. It's a 32 bit bitwise operation on a 32 bit signed type.  Shouldn't 0xFFFFFFFF be coerced to a value of -1?
--
- Dave

Jan Mercl

unread,
Jun 14, 2016, 1:48:21 PM6/14/16
to Dave MacFarlane, golang-nuts
The untyped integer constant 0xFFFFFFFF represents a positive number not representable by any int32 value.
--

-j

Rob Pike

unread,
Jun 14, 2016, 2:00:45 PM6/14/16
to Jan Mercl, Dave MacFarlane, golang-nuts
Please read blog.golang.org/constants.

-rob

Ian Lance Taylor

unread,
Jun 14, 2016, 2:16:28 PM6/14/16
to Dave MacFarlane, Jan Mercl, golang-nuts
On Tue, Jun 14, 2016 at 10:44 AM, Dave MacFarlane <dri...@gmail.com> wrote:
> What I'm not understanding is why that's not the case in this example. It's
> a 32 bit bitwise operation on a 32 bit signed type. Shouldn't 0xFFFFFFFF be
> coerced to a value of -1?

Why don't you just write -1?

I don't actually understand what you are doing. Given an int32 value
x, x & 0xFFFFFFF (assuming that were valid) is always simply x. What
else could it be? If you want to mask out the sign bit you should
write x & 0x7FFFFFFF.

Ian

Dave MacFarlane

unread,
Jun 14, 2016, 2:42:03 PM6/14/16
to Ian Lance Taylor, Jan Mercl, golang-nuts
I'm not actually trying to do x & -1, that would be pointless, as you say. It was just
the easiest way to demonstrate the behaviour that I didn't understand in a minimal
way. I understand the problem now--I was thinking of 0x as a prefix representing a bitmask
when used as a constant with a bitwise operation, while Go thinks of it as a prefix
representing a hexadecimal number even in that context.

What I *really* want to do is multiply 2 x/image/math/fixed.Int26_6 variables. I don't
want to lose the precision that x*y >> 6 would unnecessarily as x or y get large, so I wanted
to extract the first 26 bits, multiply them, and then separately multiply the decimal portion and add 
it back shifted into the correct location.

(Int26_6 is defined as `type Int26_6 int32`)
--
- Dave

Matt Harden

unread,
Jun 14, 2016, 3:41:26 PM6/14/16
to Dave MacFarlane, Ian Lance Taylor, Jan Mercl, golang-nuts
Consider coercing them to int64, multiply, then shift and coerce back to Int26_6. I suspect that would be faster than splitting with shifts and ANDs, two int32 multiplies, shift and add.

Dave MacFarlane

unread,
Jun 14, 2016, 4:09:19 PM6/14/16
to Matt Harden, Ian Lance Taylor, Jan Mercl, golang-nuts
You're right. I've already written it the ugly way, but at least it
has the benefit of being generalizable to fixed.Int52_12,
while there is no int128.

Would a patch that adds a Mult receiver function to Int52_12 and
Int26_6 be welcome in x/image/math/fixed? I've already
worked out the stupid shifting/bitwise arithmetic so you don't end up
with things like multiplying by fixed.I(1) overflowing. It seems
like the type of thing that users of the package shouldn't have to
derive from scratch if they just want to multiply 2 fixed point
numbers.

- Dave
--
- Dave

Michael Jones

unread,
Jun 14, 2016, 4:44:14 PM6/14/16
to Dave MacFarlane, Matt Harden, Ian Lance Taylor, Jan Mercl, golang-nuts
I have fought this many times. 

What I almost always do is cast all variables involved as unsigned so that I can express the logical operations as desired. The exception is right shift which must be signed if the expected outcome for signed values is to happen.

Keith Randall

unread,
Jun 15, 2016, 10:27:32 AM6/15/16
to golang-nuts, dri...@gmail.com, matt....@gmail.com, ia...@golang.org, 0xj...@gmail.com
I do x & (0xffffffff - 1<<32).

Nigel Tao

unread,
Jun 15, 2016, 8:17:41 PM6/15/16
to Dave MacFarlane, Matt Harden, Ian Lance Taylor, Jan Mercl, golang-nuts
On Wed, Jun 15, 2016 at 6:08 AM, Dave MacFarlane <dri...@gmail.com> wrote:
> Would a patch that adds a Mult receiver function to Int52_12 and
> Int26_6 be welcome in x/image/math/fixed?

Yeah, I'd take that.

For Int26_6, I'd convert to int64, multiply, then shift and convert
back to Int26_6, as Matt Harden said.
Reply all
Reply to author
Forward
0 new messages