chromium/third_party/pdfium/core/fxcrt/numerics/clamped_math_impl.h

// Copyright 2024 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CORE_FXCRT_NUMERICS_CLAMPED_MATH_IMPL_H_
#define CORE_FXCRT_NUMERICS_CLAMPED_MATH_IMPL_H_

#include <stddef.h>
#include <stdint.h>

#include <climits>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <type_traits>

#include "core/fxcrt/numerics/checked_math.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/numerics/safe_math_shared_impl.h"

namespace pdfium {
namespace internal {

template <typename T,
          typename std::enable_if<std::is_integral<T>::value &&
                                  std::is_signed<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {}

template <typename T,
          typename std::enable_if<std::is_integral<T>::value &&
                                  !std::is_signed<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {}

template <
    typename T,
    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {}

template <typename T,
          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
constexpr T SaturatedAbsWrapper(T value) {}

template <
    typename T,
    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T SaturatedAbsWrapper(T value) {}

template <typename T, typename U, class Enable = void>
struct ClampedAddOp {};

ClampedAddOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedSubOp {};

ClampedSubOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedMulOp {};

ClampedMulOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedDivOp {};

ClampedDivOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedModOp {};

ClampedModOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedLshOp {};

// Left shift. Non-zero values saturate in the direction of the sign. A zero
// shifted by any value always results in zero.
ClampedLshOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedRshOp {};

// Right shift. Negative values saturate to -1. Positive or 0 saturates to 0.
ClampedRshOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedAndOp {};

ClampedAndOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedOrOp {};

// For simplicity we promote to unsigned integers.
ClampedOrOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedXorOp {};

// For simplicity we support only unsigned integers.
ClampedXorOp<T, U, typename std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedMaxOp {};

ClampedMaxOp<T, U, typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type>;

template <typename T, typename U, class Enable = void>
struct ClampedMinOp {};

ClampedMinOp<T, U, typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type>;

// This is just boilerplate that wraps the standard floating point arithmetic.
// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
#define BASE_FLOAT_ARITHMETIC_OPS

BASE_FLOAT_ARITHMETIC_OPS
BASE_FLOAT_ARITHMETIC_OPS
BASE_FLOAT_ARITHMETIC_OPS
BASE_FLOAT_ARITHMETIC_OPS

#undef BASE_FLOAT_ARITHMETIC_OPS

}  // namespace internal
}  // namespace pdfium

#endif  // CORE_FXCRT_NUMERICS_CLAMPED_MATH_IMPL_H_