When is it useful to write "0 - x" rather than "-x"? - c

I've occasionally noticed some C code insisting on using 0 - x to get the additive complement of x, rather than writing -x. Now, I suppose these are not equivalent for types smaller in size than int (edit: Nope, apparently equivalent even then), but otherwise - is there some benefit to the former rather than the latter form?

tl;dr: 0-x is useful for scrubbing the sign of floating-point zero.
(As #Deduplicator points out in a comment:)
Many of us tend to forget that, in floating-point types, we have both a "positive zero" and a "negative zero" value - flipping the sign bit on and off leaves the same mantissa and exponent. Read more on this here.
Well, it turns out that the two expressions behave differently on positive-signed zero, and the same on negative-signed zero, as per the following:
value of x
value of 0-x
value of -x
-.0
0
0
0
0
-.0
See this on Coliru.
So, when x is of a floating-point type,
If you want to "forget the sign of zero", use 0-x.
If you want to "keep the sign of zero", use x.
For integer types it shouldn't matter.
On the other hand, as #NateEldredge points out the expressions should be equivalent on small integer types, due to integer promotion - -x translates into a promotion of x into an int, then applying the minus sign.

There is no technical reason to do this today. At least not with integers. And at least not in a way that a sane (according to some arbitrary definition) coder would use. Sure, it could be the case that it causes a cast. I'm actually not 100% sure, but in that case I would use an explicit cast instead to clearly communicate the intention.
As M.M pointed out, there were reasons in the K&R time, when =- was equivalent to -=. This had the effect that x=-y was equivalent to x=x-y instead of x=0-y. This was undesirable effect, so the feature was removed.
Today, the reason would be readability. Especially if you're writing a mathematical formula and want to point out that a parameter is zero. One example would be the distance formula. The distance from (x,y) to origo is sqrt(pow(0-x, 2), pow(0-y, 2))

Related

Can I use "MAX" macros to check whether all bits are set?

I recently had an interview where I had to propose a function that checks whether all bits from a uint32_t are set or not.
I wrote the following code :
int checkStatus(uint32_t val) {
return val == UINT32_MAX;
}
I assumed it would return 0 if one bit isn't set, and 1 if both of the values are the same.
As I didn't see this solution anywhere else, I assume it's wrong. But I don't understand why. When I did it, I was thinking : "if all bits are set to 1, then the value should be the maximum unsigned integer represented otherwise not." Could you tell me if it was incorrect and why?
The problem with using UINT32_MAX here is that "maximum" is an arithmetic concept, not a bitwise logical concept. Although UINT32_MAX does, in fact, represent the (unsigned) number 0xFFFFFFFF in most scenarios, this is just a consequence of the way numbers are represented in twos-complement arithmetic.
Using UINT32_MAX here has the potential to mislead the reader, because it has this connotation of arithmetic, rather than of bitwise manipulation.
In C programming, we're all using to representing bit patterns as hex numbers. The number "0xFFFFFFFF" immediately expresses the notion that all bits are set, in a way that UNIT32_MAX does not. Similarly, it may not be appropriate to use the value "0xFFFFFFFF" to represent "minus 1" in an arithmetic expression, even if the values are, in practice, the same.
Because I make most of my living looking for errors in other people's code, I'm acutely aware of the differences in expressive powers of different ways of expressing the same thing. Sometimes we have to write inexpressive things for reasons of inefficiency; but I don't think we should do it just for the sake of it.

`nextafter` and `nexttoward`: why this particular interface?

What exactly is the reason behind this peculiar interface of nextafter (and nexttoward) functions? We specify the direction by specifying the value we want to move toward.
At the first sight it feels as if something non-obvious is hidden behind this idea. In my (naive) opinion the first choice for such functions would be something like a pair of single-parameter functions nextafter(a)/nextbefore(a). The next choice would be a two-parameter function nextafter(a, dir) in which the direction dir is specified explicitly (-1 and +1, some standard enum, etc.).
But instead we have to specify a value we want to move toward. Hence a number of questions
(A vague one). There might be some clever idea or idiomatic pattern that is so valuable that it influenced this choice of interface in these standard functions. Is there?
What if decide to just blindly use -DBL_MAX and +DBL_MAX as the second argument for nextafter to specify the negative and positive direction respectively. Are there any pitfalls in doing so?
(A refinement of 2). If I know for sure that b is [slightly] greater than a, is there any reason to prefer nextafter(a, b) over nextafter(a, DBL_MAX)? E.g. is there a chance of better performance for nextafter(a, b) version?
Is nextafter generally a heavy operation? I know that it is implementation-dependent. But, again, assuming an implementation that is based in IEEE 754 representations, is it fairly "difficult" to find the adjacent floating-point value?
With IEEE-754 binary floating point representations, if both arguments of nextafter are finite and the two arguments are not equal, then the result can be computed by either adding one to or subtracting one from the representation of the number reinterpreted as an unsigned integer [Note 1]. The (slight) complexity results from correctly dealing with the corner cases which do not meet those preconditions, but in general you'll find that it is extremely fast.
Aside from NaNs, the only thing that matters about the second argument is whether it is greater than, less than, or equal to the first argument.
The interface basically provides additional clarity for the corner case results, but it is also sometimes useful. In particular, the usage nextafter(x, 0), which truncates regardless of sign, is often convenient. You can also take advantage of the fact that nextafter(x, x); is x to clamp the result at an arbitrary value.
The difference between nextafter and nexttowards is that the latter allows you to use the larger dynamic range of long double; again, that helps with certain corner cases.
Strictly speaking, if the first argument is a zero of some sign and the other argument is a valid non-zero number of the opposite sign, then the argument needs to have its sign bit flipped before the increment. But it seemed too much legalese to add that to the list, and it is still hardly a complicated transform.

parC int division rounds up

I came across this code in parC.
I can't understand in which scenario (the yellow mark) it can happen?
I mean when does the result of division can round up when the value type is Int?
I know nothing about parC, but as far as C is considered, you're right: integer division of positive values is defined to truncate the fraction, that is to round towards zero.
However, there is another bug in the code: if the array is too long, the midpoint may be calculated incorrectly.
To be precise, if initial to is greater by 2 or more than a half of maximum value representable in int type (INT_MAX), then one of recursive call will get fr, to values both greater than (INT_MAX/2) and the expression (to+fr) will cause an arithmetic overflow. The result of (to+fr)/2 will be less than fr/2.
To avoid this, expression like fr + (to - fr)/2 is recommended instead of (to + fr)/2.
EDIT
There are also bugs in the description! See the image:
The (4,5) → (4, 5) recursion happens one level earlier than authors indicate, so one subtree should not actually appear in the graph. Additionally, if the program gets stuck in the red-arrow loop, then the (6,5) recursion will never happen – the process will never reach that branch.
Interesting, authors apparently overlooked yet another loop appearing in their drawing;
recursion (1,2) → (1,2) appears even earlier than those two mentioned above:
As a side note, I can't imagine how they obtained two different results of partitioning the same range:
(4,5) → (4,5) + (6,5) and (4,5) → (4,5) + (5,5)
(see green frames). Possibly they were so absorbed with forcing the idea of up-rounding that they neglected any reasoning about all other aspects of the problem.
Based on this single example I would recommend to put the book in a trash bin.
You are right, integer division for positive operands in C always rounded to floor of the division, check this question for more details. I'm not familiar with parC, but it's said to be full C++ language with some additions from other languages, so described task seems to be incorrect.
If there are concerns left, you always have opportunity to check task directly: setup environment for parC, type implementation of rsum() and execute rsum(A, 1, 5).
You might be reading a text which is older than 18 years.
In older versions of the C standard, division with negative operands could get rounded in an implementation-defined way: either downwards or upwards. Meaning that -3/2 could give you either -1 or -2 depending on compiler.
This was recognized as a design flaw in the language and was corrected with the C99 standard. Nowadays, C always uses "truncation towards zero" no matter compiler.

Saturation behavior upon floating-point to signed integer conversion in C11 or C99?

I'm just wondering what guarantees, if any, either C11 or C99 provides in this regard.
Empirically, it seems that when I convert a floating-point value (regardless of its precision) to a signed integer, I get "nice" saturation whenever the floating-point value isn't representable in that signed integer range, even in the event that the floating-point value is plus or minus infinity (but I don't know or care about the NaN case).
There's a subtle issue here, which is that differences in rounding behavior could cause saturation in some cases but not in others, particularly when we're right on the edge of the a saturation boundary. I'm not concerned about that. My question is whether, once the floating-point machinery has decided upon the integer that it needs to output (which is platform-dependent), but in the event that said integer lies outside of the target signed integer range (which is platform-independent), whether or not saturation is guaranteed by the spec.
My default understanding is that what I'm seeing is merely a convenience of the underlying hardware, and that such behavior is not guaranteed because signed overflow is undefined. I hope I'm wrong, because I hate signed overflow and am trying to avoid it. So yes I'm also interested in the case of conversion to unsigned integers.
While I'm at it, what about negative 0? Is this value guaranteed to convert to integer zero, even though in some sense you could think of it as negative epsilon, which conventionally would round to -1?
6.3.1.4 Real floating and integer
When a finite value of real floating type is converted to an integer type other than _Bool,
the fractional part is discarded (i.e., the value is truncated toward zero). If the value of
the integral part cannot be represented by the integer type, the behavior is undefined.)
phresnel has already done a nice job answering the main thrust of your question. Some other details to keep in mind:
So yes I'm also interested in the case of conversion to unsigned integers.
The situation for unsigned isn't any nicer. Footnote 61 in C11 (the same footnote is present in C99):
The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type. Thus, the range of portable real floating values is (−1, Utype_MAX+1)
Fortunately, this is easily remedied for both signed and unsigned conversions; simply clamp your input before converting if you need saturation.
While I'm at it, what about negative 0? Is this value guaranteed to convert to integer zero, even though in some sense you could think of it as negative epsilon, which conventionally would round to -1?
Yes, it is guaranteed to convert to integer zero. First, the value of -0 is exactly zero, not negative epsilon (contrary to the rumors you read on the internet). Second, conversions from floating-point to integer truncate the value, so even if the value were "negative epsilon" (whatever that means), the result would be zero because "negative epsilon" lies in the interval (-1, 1).
While I'm at it, what about negative 0? Is this value guaranteed to
convert to integer zero, even though in some sense you could think of
it as negative epsilon, which conventionally would round to -1?
It is truncated, so goes towards zero - meaning anything less than 1.0 and greater than -1.0 becomes 0. Negative zero is turned into zero as far as "typcial" platforms are concerned. I'm not entirely sure if this is guaranteed by the standard, but I believe in practice you can rely on it, even if the standard doesn't define it [unless you plan for your code to run on extremely "strange" equipment, such as DSP's or GPU's].

Can bad stuff happen when dividing 1/a very small float?

If I want to check that positive float A is less than the inverse square of another positive float B (in C99), could something go wrong if B is very small?
I could imagine checking it like
if(A<1/(B*B))
But if B is small enough, would this possibly result in infinity? If that were to happen, would the code still work correctly in all situations?
In a similar vein, I might do
if(1/A>B*B)
... which might be slightly better because B*B might be zero if B is small (is this true?)
Finally, a solution that I can't imagine being wrong is
if(sqrt(1/A)>B)
which I don't think would ever result in zero division, but still might be problematic if A is close to zero.
So basically, my questions are:
Can 1/X ever be infinity if X is greater than zero (but small)?
Can X*X ever be zero if X is greater than zero?
Will comparisons with infinity work the way I would expect them to?
EDIT: for those of you who are wondering, I ended up doing
if(B*A*B<1)
I did it in that order as it is visually unambiguous which multiplication occurs first.
If you want to handle the entire range of possible values of A and B, then you need to be a little bit careful, but this really isn't too complicated.
The suggestion of using a*b*b < 1. is a good one; if b is so tiny that a*b*b underflows to zero, then a is necessarily smaller than 1./(b*b). Conversely, if b is so large that a*b*b overflows to infinity, then the condition will (correctly) not be satisfied. (Potatoswatter correctly points out in a comment on another post that this does not work properly if you write it b*b*a, because b*b might overflow to infinity even when the condition should be true, if a happens to be denormal. However, in C, multiplication associates left-to-right, so that is not an issue if you write it a*b*b and your platform adheres to a reasonable numerics model.)
Because you know a priori that a and b are both positive numbers, there is no way for a*b*b to generate a NaN, so you needn't worry about that condition. Overflow and underflow are the only possible misbehaviors, and we have accounted for them already. If you needed to support the case where a or b might be zero or infinity, then you would need to be somewhat more careful.
To answer your direct questions: (answers assume IEEE-754 arithmetic)
Can 1/X ever be infinity if X is greater than zero (but small)?
Yes! If x is a small positive denormal value, then 1/x can overflow and produce infinity. For example, in double precision in the default rounding mode, 1 / 0x1.0p-1024 will overflow.
Can X*X ever be zero if X is greater than zero?
Yes! In double precision in the default rounding mode, all values of x smaller than 0x1.0p-538 (thats 2**-578 in the C99 hex format) or so have this property.
Will comparisons with infinity work the way I would expect them to?
Yes! This is one of the best features of IEEE-754.
OK, reposting as an answer.
Try using arithmetically equivalent comparison like if ( A*B*B < 1. ). You might get in trouble with really big numbers though.
Take a careful look at the IEEE 754 for your corner cases.
You want to avoid divisions so the trick is to modify the equation. You can multiply both sides of your first equation by (b*b) to get:
b*b*a < 1.0
This won't have any divisions so should be ok.
Division per se isn't so bad. However, standard IEEE 754 FP types allow for a greater negative negative range of exponents than positive, due to denormalized numbers. For example, float ranges from 1.4×10-45 to 3.4×10-38, so you cannot take the inverse of 2×10-44.
Therefore, as Jeremy suggests, start by multiplying A by B, where one has a positive exponent and the other has a negative exponent, to avoid overflow.
This is why A*B*B<1 is the proper answer.

Resources