overflow.h 950 B

12345678910111213141516171819202122232425262728293031323334353637383940
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <algorithm>
  5. #include <type_traits>
  6. #include "bit_cast.h"
  7. namespace Common {
  8. template <typename T>
  9. requires(std::is_integral_v<T> && std::is_signed_v<T>)
  10. inline T WrappingAdd(T lhs, T rhs) {
  11. using U = std::make_unsigned_t<T>;
  12. U lhs_u = BitCast<U>(lhs);
  13. U rhs_u = BitCast<U>(rhs);
  14. return BitCast<T>(lhs_u + rhs_u);
  15. }
  16. template <typename T>
  17. requires(std::is_integral_v<T> && std::is_signed_v<T>)
  18. inline bool CanAddWithoutOverflow(T lhs, T rhs) {
  19. #ifdef _MSC_VER
  20. if (lhs >= 0 && rhs >= 0) {
  21. return WrappingAdd(lhs, rhs) >= std::max(lhs, rhs);
  22. } else if (lhs < 0 && rhs < 0) {
  23. return WrappingAdd(lhs, rhs) <= std::min(lhs, rhs);
  24. } else {
  25. return true;
  26. }
  27. #else
  28. T res;
  29. return !__builtin_add_overflow(lhs, rhs, &res);
  30. #endif
  31. }
  32. } // namespace Common