brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · ff62ce0 Raw
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