115 lines · c
1//===-- Comparison operations on floating point numbers ---------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H10#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H11 12#include "FEnvImpl.h"13#include "FPBits.h"14#include "src/__support/CPP/type_traits.h"15#include "src/__support/macros/config.h"16 17namespace LIBC_NAMESPACE_DECL {18namespace fputil {19 20// All predicates are hereby implemented as per IEEE Std 754-201921// Implements compareQuietEqual predicate22// Rules for comparison within the same floating point type23// 1. +0 = −024// 2. (i) +inf = +inf25// (ii) -inf = -inf26// (iii) -inf != +inf27// 3. Any comparison with NaN returns false28template <typename T>29LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,30 T y) {31 using FPBits = FPBits<T>;32 FPBits x_bits(x);33 FPBits y_bits(y);34 35 if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())36 fputil::raise_except_if_required(FE_INVALID);37 38 // NaN == x returns false for every x39 if (x_bits.is_nan() || y_bits.is_nan())40 return false;41 42 // +/- 0 == +/- 043 if (x_bits.is_zero() && y_bits.is_zero())44 return true;45 46 return x_bits.uintval() == y_bits.uintval();47}48 49// Implements compareSignalingLess predicate50// Section 5.11 Rules:51// 1. -inf < x (x != -inf)52// 2. x < +inf (x != +inf)53// 3. Any comparison with NaN return false54template <typename T>55LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,56 T y) {57 using FPBits = FPBits<T>;58 FPBits x_bits(x);59 FPBits y_bits(y);60 61 // Any comparison with NaN returns false62 if (x_bits.is_nan() || y_bits.is_nan()) {63 fputil::raise_except_if_required(FE_INVALID);64 return false;65 }66 67 if (x_bits.is_zero() && y_bits.is_zero())68 return false;69 70 if (x_bits.is_neg() && y_bits.is_pos())71 return true;72 73 if (x_bits.is_pos() && y_bits.is_neg())74 return false;75 76 // since floating-point numbers are stored in the format: s | e | m77 // we can directly compare the uintval's78 79 // both negative80 if (x_bits.is_neg())81 return x_bits.uintval() > y_bits.uintval();82 83 // both positive84 return x_bits.uintval() < y_bits.uintval();85}86 87// Implements compareSignalingGreater predicate88// x < y => y > x89template <typename T>90LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>91greater_than(T x, T y) {92 return less_than(y, x);93}94 95// Implements compareSignalingLessEqual predicate96// x <= y => (x < y) || (x == y)97template <typename T>98LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>99less_than_or_equals(T x, T y) {100 return less_than(x, y) || equals(x, y);101}102 103// Implements compareSignalingGreaterEqual predicate104// x >= y => (x > y) || (x == y) => (y < x) || (x == y)105template <typename T>106LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>107greater_than_or_equals(T x, T y) {108 return less_than(y, x) || equals(x, y);109}110 111} // namespace fputil112} // namespace LIBC_NAMESPACE_DECL113 114#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H115