1

Could someone clarify why using NOT operator twice like in the following example:

setBits += !!(n & mask); // if some bits match between n and mask, setBits = 1, else setBits = 0

Which basically works in C language, and also work after I had rewritten it this way:

setBits += if (n & mask) != 0 {1} else {0};

Does not work as intended in Rust? As of now, it returns the value of n & mask, while I want to force twice NOT at the bytecode level and avoid branching (cmp instructions).

NB: I just checked the assembly code and apparently the Rust compiler optimize it away...
However !!value is not equivalent to value

Any way to force NOT x2 and avoid CMP instruction?

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81

1 Answers1

2

Rust's Not operator (!) does not return bool but rather the bitwise negation of the value. It is more akin to C/C++'s bitwise not operator (~):

let bits = 0u32;
println!("{:#010X}", bits);
println!("{:#010X}", !bits);
0x00000000
0xFFFFFFFF

So this is why !! would typically not do anything.

You can still do this without an if by converting the bool from != 0 into an integer:

setBits += (n & mask != 0) as u32; // assuming u32s
kmdreko
  • 42,554
  • 6
  • 57
  • 106
  • You beat me by 5 seconds, and provide a better answer to boot. :) – user4815162342 Mar 11 '21 at 19:32
  • I was testing locally and just found out that as well that not is equivalent to ~ neg. It is very confusing, I don't understand the design choice to use `!` instead of `~` for `NEG`, especially if Rust is looking to attract C and C++ developers. Anyways there is no way, in Rust, to call `NOT`? – Antonin GAVREL Mar 11 '21 at 19:47
  • @AntoninGAVREL Which `NOT` instruction are you referring to? [The x86 one does what Rust does, not what C does.](https://www.felixcloutier.com/x86/not) – trent Mar 11 '21 at 19:52
  • The C and C++ one – Antonin GAVREL Mar 11 '21 at 19:53
  • 2
    Yes, it's spelled `x == 0` – trent Mar 11 '21 at 19:54
  • I would call `!` for integers in Rust a _bitwise NOT_ rather than _logical NOT_. It's logical NOT for Boolean values, but bitwise NOT for integers. – Sven Marnach Mar 11 '21 at 20:04
  • @SvenMarnach I'm inclined to agree with you. I rewrote the wording a couple times because *negation* would be `-x` and also felt *bitwise negation* is more appropriate to what its doing, but the [docs](https://doc.rust-lang.org/std/ops/trait.Not.html) call it the "unary logical negation operator" so idk what to think. – kmdreko Mar 11 '21 at 20:07
  • FWIW [the book](https://doc.rust-lang.org/book/appendix-02-operators.html) calls it a "bitwise or logical complement" (logical presumably to cover `bool` where "bitwise complement" might be imprecise), which sounds reasonable. Maybe the trait docs should be updated to use that term? – user4815162342 Mar 11 '21 at 21:02
  • IIRC, on LLVM IR level rust bools are 1 bit unsigned integers, so it is still bitwise, at least in theory. – Ivan C Mar 11 '21 at 21:05