Skip to content

File numeric.h

File List > common > numeric.h

Go to the documentation of this file

#pragma once

#include <cstdint>
#include <limits>
#include <type_traits>

namespace simtix {

template <typename T, typename U>
constexpr T saturate_cast(U value) noexcept {
  if constexpr (std::is_signed_v<T> && std::is_unsigned_v<U>) {
    // Handle unsigned-to-signed conversion
    if (value > static_cast<U>(std::numeric_limits<T>::max())) {
      return std::numeric_limits<T>::max();
    }
  } else if constexpr (std::is_unsigned_v<T> && std::is_signed_v<U>) {
    // Handle signed-to-unsigned conversion
    if (value < 0) {
      return 0;
    }
  } else {
    // U and T have the same signedness
    if (value > static_cast<U>(std::numeric_limits<T>::max())) {
      return std::numeric_limits<T>::max();
    } else if (value < static_cast<U>(std::numeric_limits<T>::min())) {
      return std::numeric_limits<T>::min();
    }
  }

  // Perform the actual cast
  return static_cast<T>(value);
}

template <typename T>
uint32_t bit_width(T value) {
  return std::numeric_limits<T>::digits - __builtin_clz(value);
}

}  // namespace simtix