I'm trying to understand what this code does. This is supposed to negate the coefficient coeff
of type uint64_t*
of a polynomial with coefficients modulus modulus_value
of type const uint64_t
:
std::int64_t non_zero = (*coeff != 0);
*coeff = (modulus_value - *coeff) & static_cast<std::uint64_t>(-non_zero);
What's up with the & static_cast<std::uint64_t>(-non_zero)
? How does this negate anything?
The code is from here.
CodePudding user response:
This code is a branchless version of
if (*coeff) *coeff = (modulus_value - *coeff);
// else *coeff = *coeff;
The negation is (modulus_value - *coeff)
.
The & static_cast<std::uint64_t>(-non_zero)
implements the condition without a branch, and is totally unrelated to negation.
FWIW you're probably better off with the easy-to-understand if
statement version. Architectures with a "conditional MOV" will use it instead of a branch, and compilers for other architectures will almost invariably know how to optimize a conditional assignment to the branchless version.
Two other equivalent versions are:
*coeff = (*coeff) ? (modulus_value - *coeff) : (*coeff);
and
*coeff = (*coeff) ? (modulus_value - *coeff) : 0;
all of which are easier to understand for both humans and compilers than the version in the question.
CodePudding user response:
non_zero
will be either 1
or 0
.
-non_zero
will turn that into -1
or 0
.
static_cast<std::uint64_t>(-non_zero)
will tell the compiler to treat the signed number as unsigned, which will turn 0
into 0
, and -1
into 0xffffffffffffffff
.
Then the bitwise AND will either clear all bits of (modulus_value - *coeff)
(if non_zero
is 0
) or keep all the bits of (modulus_value - *coeff)
as they are (i.e. it's a no-op really).
So the result assigned back to *coeff
will be either 0
or modulus_value - *coeff
.
It's equivalent to (modulus_value - *coeff) * non_zero
. Or in shorter form (modulus_value - *coeff) * !!*coeff
.