What are ordered and unordered LLVM CmpInst compare instructions? - llvm

The definition of CmpInst::Predicate type in "llvm/IR/InstrTypes.h" which describes the type of compare instruction in LLVM goes like this:
enum Predicate {
// Opcode U L G E Intuitive operation
FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded)
FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal
FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than
FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal
FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than
FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal
FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal
FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans)
FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y)
FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal
FCMP_UGT = 10, ///< 1 0 1 0 True if unordered or greater than
FCMP_UGE = 11, ///< 1 0 1 1 True if unordered, greater than, or equal
FCMP_ULT = 12, ///< 1 1 0 0 True if unordered or less than
FCMP_ULE = 13, ///< 1 1 0 1 True if unordered, less than, or equal
FCMP_UNE = 14, ///< 1 1 1 0 True if unordered or not equal
FCMP_TRUE = 15, ///< 1 1 1 1 Always true (always folded)
FIRST_FCMP_PREDICATE = FCMP_FALSE,
LAST_FCMP_PREDICATE = FCMP_TRUE,
BAD_FCMP_PREDICATE = FCMP_TRUE + 1,
ICMP_EQ = 32, ///< equal
ICMP_NE = 33, ///< not equal
ICMP_UGT = 34, ///< unsigned greater than
ICMP_UGE = 35, ///< unsigned greater or equal
ICMP_ULT = 36, ///< unsigned less than
ICMP_ULE = 37, ///< unsigned less or equal
ICMP_SGT = 38, ///< signed greater than
ICMP_SGE = 39, ///< signed greater or equal
ICMP_SLT = 40, ///< signed less than
ICMP_SLE = 41, ///< signed less or equal
FIRST_ICMP_PREDICATE = ICMP_EQ,
LAST_ICMP_PREDICATE = ICMP_SLE,
BAD_ICMP_PREDICATE = ICMP_SLE + 1
};
I am wondering what are "ordered" and "unordered" predicates (like "if ordered and equal" or "if unordered, greater than, or equal" compared to the normal ones that are just "unsigned greater or equal").

If you don't know what NaN is, start from the last paragraph :)
Ordered and unordered floating point comparisons are different on what the result of comparison is if at least one of the operands are NaN. See fcmp instruction in the IR lang ref for more details. In particular this sentence is important: "Ordered means that neither operand is a QNAN while unordered means that either operand may be a QNAN". Note that LLVM (AFAIK) does not support SNaN, that is why lang ref exclusively talks about QNaN.
The reason for the naming is that NaN cannot be compared with floating point numbers. You cannot say NaN is smaller or larger than zero. So NaN is unordered. So unordered comparison return true if one of the operands is NaN. Ordered comparison expects both operands to be numbers.
This is the wikipedia page on NaN if you need background on that. Briefly speaking when the result of some floating point computation is not a number, a special result is generated that is called NaN (Not a Number). For example `std::sqrt' generates NaN if you ask for the square root of a negative number. There are two variants of NaN. SNaN and QNan. Wikipedia describes it. For the purpose of your question, you can ignore the difference as only QNaN matters. SNaN is not supported by LLVM AFAIK.

Related

Shifting elements of a container and filling shifted place with default constructed elements

For example:
c = {"aaa", "aaa"} -> c >> 1 -> c = {"", "aaa"}
I thought I can use std::shift_right but it uses std::move internally and moved from object are left unspecified state:
std::vector<bool> bv(5, true);
std::shift_left(begin(bv), end(bv), 4); // prints 1 1 1 1 1
After some search come up with this but wonder is there a better solution:
std::rotate(begin(bv), begin(bv) + 4, end(bv));
std::fill_n(begin(bv), 4, false); // 0 0 0 0 1
While it is true that std::move() leaves objects in an unspecified state, you can still assign a new value to the element. So the following is perfectly fine.
constexpr size_t N = 4;
std::vector<bool> bv(5, true);
std::shift_right(bv.begin(), bv.end(), N); // prints 1 1 1 1 1 (but the first 4 elements are in an unspecified state).
std::fill_n(bv.begin(), 4, false); // 0 0 0 0 1

Why is x^0 = x?

I have a very simple question.
Why is a number when XOR'ed with 0 gives the number itself.
Can someone please give the proof using an example.
Lets say I have the number 5
5^0==>
I think the answer should be just the last bit of 5 XOR'ed with 0, but the answer is still 5.
0 is false, and 1 is true.
As per the definition, XOR operation A XOR B is "A or B, but not, A and B". So, since B is false, so the result will be A.
Also, XOR truth table shows that it outputs true whenever the inputs differ:
Input Output
A B XOR Result
0 0 0
0 1 1
1 0 1
1 1 0
As you can see, whatever be the value of A, if it is XORed with 0, the result is the bit itself.
So, as you say:
5 = 101, 0 = 000
When performing XOR operation on the individual bits:
101
000
----
101 = 5.
Hence, the result of X^0 is X itself.
What is there that you did not understand. Please read about XOR
00000101 // = 5
00000000 // = 0
--------
00000101 // = 5
Bit-wise operations operates on set of bits in number - not just on last bit.
So if you perform some bit-wise operation on 32-bit integer, then all 32 bits are affected. So integer 5 is 0.....0000101 (32 bits). If you need just the resulting last bit after xor operation apply binary AND with 1:
<script>
console.log("%i\n",(5^0)&1);
console.log("%i\n",(6^0)&1);
</script>

What does the & operator mean? [duplicate]

This question already has an answer here:
What does & stands for in C and mmap()
(1 answer)
Closed 8 years ago.
I am trying to understand the condition of an if-else statement in c++, here is the snippet where this statement is in (not it's a shorthand version):
for (int i = 0; i < 8; ++i)
{
Point newCenter = center;
newCenter.x += oneEighth.x * (i&4 ? 0.5f : -0.5f);
}
I do understand that the 0.5f holds if the condition is true and -0.5f otherwise, but what does the i&4 mean?
This here is using two things, firstly it is using the bitwise AND operator &, this takes the binary representation of the two integers (i and 4) and computes the bitwise AND of both of these (i.e. for each position in the resulting binary representation of the number we look at the bits at the corresponding position in the two arguments and set the resultant bit to 1 if and only if both bits in the arguments are 1), secondly, it is using the implicit int to bool conversion which returns true if the integer is not equal to 0.
For example, if we have i=7, then the internal bitwise representation of this in two's complement would be:
/*24 0s*/ 0 0 0 0 0 1 1 1
And the two's complement representation of 4 is /*24 0s*/ 0 0 0 0 0 1 0 0 and so the bitwise AND is /*24 0s*/ 0 0 0 0 0 1 0 0 and as this is not equal to zero it is implictly converted to true and so the condition is met.
Alternatively, if we consider i=2, then we have the internal representation:
/*24 0s*/ 0 0 0 0 0 0 1 0
And thus the bitwise AND gives /*24 0s*/ 0 0 0 0 0 0 0 0 and thus the condition is not met.
The operator is Bitwise AND.
Bitwise binary AND does the logical AND of the bits in each position of a number in its binary form.
So, in your code, i&4 is true when i is 4, 5, 6, 7, because the base-2 representation of 4 is 100. i&4 will be true when the base-2 representation of i has 1 in the 3-rd position(right-left)

Comparing Bitfields of Different Sizes

What happens if you use a bitwise operator (&, |, etc.) to compare two bitfields of different sizes?
For example, comparing 0 1 1 0 with 0 0 1 0 0 0 0 1:
0 1 1 0 0 0 0 0 The smaller one is extended with zeros and pushed to the
0 0 1 0 0 0 0 1 most-significant side.
Or...
0 0 0 0 0 1 1 0 The smaller one is extended with zeros and pushed to the
0 0 1 0 0 0 0 1 least-significant side.
Or...
0 1 1 0 The longer one is truncated from its least-significant side,
0 0 1 0 keeping its most significant side.
Or...
0 1 1 0 The longer one is truncated from its most-significant side,
0 0 0 1 keeping its least-significant side.
The bitwise operators always work on promoted operands. So exactly what might happen can depend on whether one (or both) bitfields are signed (as that may result in sign extension).
So, for your example values, the bit-field with the binary value 0 1 1 0 will be promoted to the int 6, and the bit-field with the binary value 0 0 1 0 0 0 0 1 will be promoted to the int 33, and those are the operands that will be used with whatever the operation is.
0 0 0 0 0 1 1 0 The smaller one is extended with zeros and pushed to the
0 0 1 0 0 0 0 1 least-significant side.
If you're actually using the values as bitfields, what's the meaning of comparing bitfields of different sizes? Would it generate a meaningful result for you?
That said, both operands will be promoted to a minimum size of int/unsigned with signedness depending on the signedness of the original operands. Then these promoted values will be compared with the bitwise operator.
This behaves as your second example: The smaller one is padded with zeroes on the MSB side (pushed to LSB side if you prefer).
If one operand is signed and negative while the other is unsigned, the negative one will be converted to the congruent unsigned number before the bit operation takes place.
If instead of integral numbers you mean std::bitset, you can't do bitwise operations on bitsets of differing sizes.

Warning about data loss c++/c

I am getting a benign warning about possible data loss
warning C4244: 'argument' : conversion from 'const int' to 'float', possible loss of data
Question
I remember as if float has a larger precision than int. So how can data be lost if I convert from a smaller data type (int) to a larger data type (float)?
Because float numbers are not precise. You cannot represent every possible value an int can hold into a float, even though the maximum value of a float is much higher.
For instance, run this simple program:
#include <stdio.h>
int main()
{
for(int i = 0; i < 2147483647; i++)
{
float value = i;
int ivalue = value;
if(i != ivalue)
printf("Integer %d is represented as %d in a float\n", i, ivalue);
}
}
You'll quickly see that there are thousands billions of integers that can't be represented as floats. For instance, all integers between the range 16,777,219 and 16,777,221 are represented as 16,777,220.
EDIT again Running that program above indicates that there are 2,071,986,175 positive integers that cannot be represented precisely as floats. Which leaves you roughly with only 100 millions of positive integer that fit correctly into a float. This means only one integer out of 21 is right when you put it into a float.
I expect the numbers to be the same for the negative integers.
On most architectures int and float are the same size, in that they have the same number of bits. However, in a float those bits are split between exponent and mantissa, meaning that there are actually fewer bits of precision in the float than the int. This is only likely to be a problem for larger integers, though.
On systems where an int is 32 bits, a double is usually 64 bits and so can exactly represent any int.
Both types are composed of 4 bytes (32 bits).
Only one of them allows a fraction (the float).
Take this for a float example;
34.156
(integer).(fraction)
Now use your logic;
If one of them must save fraction information (after all it should represent a number) then it means that it has less bits for the integer part.
Thus, a float can represent a maximal integer number which is smaller than the int's type capability.
To be more specific, an "int" uses 32 bits to represent an integer number (maximal unsigned integer of 4,294,967,296). A "float" uses 23 bits to do so (maximal unsigned integer of 8,388,608).
That's why when you convert from int to float you might lose data.
Example:
int = 1,158,354,125
You cannot store this number in a "float".
More information at:
http://en.wikipedia.org/wiki/Single_precision_floating-point_format
http://en.wikipedia.org/wiki/Integer_%28computer_science%29
Precision does not matter. The precision of int is 1, while the precision of a typical float (IEEE 754 single precision) is approximately 5.96e-8. What matters is the sets of numbers that the two formats can represent. If there are numbers that int can represent exactly that float cannot, then there is a possible loss of data.
Floats and ints are typically both 32 bits these days, but that's not guaranteed. Assuming it is the case on your machine, it follows that there must be int values that float cannot represent exactly, because there are obviously float values that int cannot represent exactly. The range of one format cannot be a proper super-set of the other if both formats use the same number of bits efficiently.
A 32 bit int effectively has 31 bits that code for the absolute value of the number. An IEEE 754 float effectively has only 24 bits that code for the mantissa (one implicit).
The fact is that both a float and an int are represented using 32 bits. The integer value uses all 32 bits so it can accommodate numbers from -231 to 231-1. However, a float uses 1 bit for the sign (including -0.0f) and 8 bits for the exponent. The means 32 - 9 = 23 bits left for the mantissa. However, the float assumes that if the mantissa and exponent are not zero, then the mantissa starts with a 1. So you more or less have 24 bits for your integer, instead of 32. However, because it can be shifted, it accommodates more than 224 integers.
A floating point uses a Sign, an eXponent, and a Mantissa
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M
An integer has a Sign, and a Mantissa
S M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M
So, a 29 bit integer such as:
0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
fits in a float because it can be shifted:
0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
| | |
| +-----------+ +-----------+
| | |
v v v
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M
0 1 0 0 1 1 0 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0
The eXponent represents a biased shift (the shift of the mantissa minus 128, if I'm correct—the shift counts from the decimal point). This clearly shows you that if you have to shift by 5 bits, you're going to lose the 5 lower bits.
So this other integer can be converted to a float with a lose of 2 bits (i.e. when you convert back to an integer, the last two bits (11) are set to zero (00) because they were not saved in the float):
1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1
| ||
| || complement
| vv
| 0 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1
| | | | | | | |
| +-----------+ +-----------+ +-+-+-+-+--> lost bits
| | |
v v v
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M
1 1 0 0 1 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 1 1 1
Note: For negative numbers, we first generate the complement, which is subtracting 1 then reversing all the bits from 0 to 1. That complement is what gets saved in the mantissa. The sign, however, still gets copied as is.
Pretty simple stuff really.
IMPORTANT NOTE: Yes, the first 1 in the integer is the sign, then the next 1 is not copied in the mantissa, it is assumed to be 1 so it is not required.
A float is usually in the standard IEEE single-precision format. This means there are only 24 bits of precision in a float, while an int is likely to be 32-bit. So, if your int contains a number whose absolute value cannot fit in 24 bits, you are likely to have it rounded to the nearest representable number.
My stock answer to such questions is to read this - What Every Computer Scientist Should Know About Floating-Point Arithmetic.