Мой коллега показал мне следующий макрос из LLVM исходный код:
#define IMPLEMENT_UNORDERED(TY, X,Y) \
if (TY->isFloatTy()) { \
if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) { \
return Dest; \
} \
} else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) { \
Dest.IntVal = APInt(1,true); \
return Dest; \
}
Вот как они используют этот макрос:
static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2,
Type *Ty) {
GenericValue Dest;
IMPLEMENT_UNORDERED(Ty, Src1, Src2)
return executeFCMP_OEQ(Src1, Src2, Ty);
}
Ниже вы можете увидеть определение GenericValue:
struct GenericValue {
union {
double DoubleVal;
float FloatVal;
PointerTy PointerVal;
struct { unsigned int first; unsigned int second; } UIntPairVal;
unsigned char Untyped[8];
};
APInt IntVal; // also used for long doubles
GenericValue() : DoubleVal(0.0), IntVal(1,0) {}
explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { }
};
Мой вопрос: почему внутри макроса есть следующий критерий неравенства:
X.FloatVal != X.FloatVal
Я предполагаю, что они проверяют на NaN (не число): если x
имеет значение NaN, x != x
доходность true
,
Других решений пока нет …