Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub jellc/Library

:warning: Extended Numeric Type
(src/algebra/extended.hpp)

Code

#pragma once

/**
 * @file extended.hpp
 * @brief Extended Numeric Type
 */

#include <cstdint>
#include <type_traits>

#include "lib/cxx17"

namespace workspace {

template <class _Tp> constexpr auto sign_of(const _Tp &__x) noexcept {
  return __x != _Tp(0) ? (__x > _Tp(0) ? +1 : -1) : 0;
}

// Extended numeric type.
template <class _Tp> class extended {
  bool infinite{};
  int_least8_t sign{};  // in {0, +1, -1}
  _Tp value{};          // is 0 if infinite

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const extended &__x) noexcept {
    return __x.infinite ? __os << (__x.sign > 0 ? '+' : '-') << "infinity"
                        : __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, extended &__x) noexcept {
    __x.infinite = false;
    __is >> __x.value;
    __x.sign = sign_of(__x.value);
    return __is;
  }

  constexpr extended(bool __x, int_least8_t __y, const _Tp &__z) noexcept
      : infinite(__x), sign(__y), value(__z) {}

 public:
  constexpr static extended infinity{true, +1, 0};

  constexpr extended() noexcept {}

  constexpr extended(const _Tp &__x) noexcept
      : sign(sign_of(__x)), value(__x) {}

  constexpr std::enable_if_t<std::is_swappable<_Tp>::value> swap(
      extended &__x) noexcept {
    std::swap(infinite, __x.infinite);
    std::swap(sign, __x.sign);
    std::swap(value, __x.value);
  }

  template <class _U> constexpr operator _U const &() const noexcept {
    if _CXX17_CONSTEXPR (std::is_same_v<_U, bool>) return sign;
    return value;
  }

  template <class _U> constexpr operator _U() const noexcept {
    if _CXX17_CONSTEXPR (std::is_same_v<_U, bool>) return sign;
    return value;
  }

  constexpr extended operator+() const noexcept { return *this; }

  constexpr extended operator-() const noexcept {
    return extended(infinite, -sign, -value);
  }

  constexpr extended &operator+=(const extended &__x) noexcept {
    if (__x.infinite) return *this = __x;
    return operator+=(__x.value);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator+=(const _U &__x) noexcept {
    if (!infinite) sign = sign_of(value += __x);
    return *this;
  }

  constexpr extended &operator-=(const extended &__x) noexcept {
    return operator+=(-__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator-=(const _U &__x) noexcept {
    return operator+=(-__x);
  }

  constexpr extended &operator*=(const extended &__x) noexcept {
    if (sign *= __x.sign)
      infinite = infinite || __x.infinite, value *= __x.value;
    else
      infinite = false, value = 0;
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator*=(const _U &__x) noexcept {
    if (sign *= sign_of(__x))
      value *= __x;
    else
      infinite = false, value = 0;
    return *this;
  }

  constexpr extended &operator/=(const extended &__x) noexcept {
    if (__x.infinite)
      infinite = false, sign = 0, value = 0;
    else if (__x.sign)
      (value /= __x.value) ? sign *= __x.sign : sign = 0;
    else
      infinite = true, value = 0;
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator/=(const _U &__x) noexcept {
    auto __s = sign_of(__x);
    if (__s)
      (value /= __x) ? sign *= __s : sign = 0;
    else
      infinite = true, value = 0;
    return *this;
  }

  constexpr extended &operator%=(const extended &__x) noexcept {
    if (!__x.infinite) sign = sign_of(value %= __x);
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator%=(const _U &__x) noexcept {
    sign = sign_of(value %= __x);
    return *this;
  }

  constexpr extended operator+(const extended &__x) const noexcept {
    return extended(*this) += __x;
  }

  constexpr extended operator-(const extended &__x) const noexcept {
    return extended(*this) -= __x;
  }

  constexpr extended operator*(const extended &__x) const noexcept {
    return extended(*this) *= __x;
  }

  constexpr extended operator/(const extended &__x) const noexcept {
    return extended(*this) /= __x;
  }

  constexpr extended operator%(const extended &__x) const noexcept {
    return extended(*this) %= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator+(const _U &__x) const noexcept {
    return extended(*this) += __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator-(const _U &__x) const noexcept {
    return extended(*this) -= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator*(const _U &__x) const noexcept {
    return extended(*this) *= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator/(const _U &__x) const noexcept {
    return extended(*this) /= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator%(const _U &__x) const noexcept {
    return extended(*this) %= __x;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator+(const _U &__x, const extended &__y) noexcept {
    return extended(__x) += __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator-(const _U &__x, const extended &__y) noexcept {
    return extended(__x) -= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator*(const _U &__x, const extended &__y) noexcept {
    return extended(__x) *= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator/(const _U &__x, const extended &__y) noexcept {
    return extended(__x) /= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator%(const _U &__x, const extended &__y) noexcept {
    return extended(__x) %= __y;
  }

  constexpr bool operator==(const extended &__x) const noexcept {
    return infinite == __x.infinite && sign == __x.sign && value == __x.value;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator==(const _U &__x) const noexcept {
    return !infinite && value == static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator==(const _U &__x, const extended &__y) noexcept {
    return __y.operator==(__x);
  }

  constexpr bool operator!=(const extended &__x) const noexcept {
    return !operator==(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator!=(const _U &__x) const noexcept {
    return !operator==(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator!=(const _U &__x, const extended &__y) noexcept {
    return __y.operator!=(__x);
  }

  constexpr bool operator<(const extended &__x) const noexcept {
    auto __l = sign * infinite, __r = __x.sign * __x.infinite;
    return __l != __r ? __l < __r : value < __x.value;
  }

  constexpr bool operator<=(const extended &__x) const noexcept {
    auto __l = sign * infinite, __r = __x.sign * __x.infinite;
    return __l != __r ? __l < __r : value <= __x.value;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<(const _U &__x) const noexcept {
    return infinite ? sign < 0 : value < static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<=(const _U &__x) const noexcept {
    return infinite ? sign < 0 : value <= static_cast<_Tp>(__x);
  }

  constexpr bool operator>(const extended &__x) const noexcept {
    return __x.operator<(*this);
  }

  constexpr bool operator>=(const extended &__x) const noexcept {
    return __x.operator<=(*this);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>(const _U &__x) const noexcept {
    return infinite ? sign > 0 : value > static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>=(const _U &__x) const noexcept {
    return infinite ? sign > 0 : value >= static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<(const _U &__x, const extended &__y) noexcept {
    return __y.operator>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>(const _U &__x, const extended &__y) noexcept {
    return __y.operator<(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<=(const _U &__x, const extended &__y) noexcept {
    return __y.operator>=(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>=(const _U &__x, const extended &__y) noexcept {
    return __y.operator<=(__x);
  }
};

}  // namespace workspace
#line 2 "src/algebra/extended.hpp"

/**
 * @file extended.hpp
 * @brief Extended Numeric Type
 */

#include <cstdint>
#include <type_traits>

#line 2 "lib/cxx17"

#line 2 "lib/cxx14"

#ifndef _CXX14_CONSTEXPR
#if __cplusplus >= 201402L
#define _CXX14_CONSTEXPR constexpr
#else
#define _CXX14_CONSTEXPR
#endif
#endif
#line 4 "lib/cxx17"

#ifndef _CXX17_CONSTEXPR
#if __cplusplus >= 201703L
#define _CXX17_CONSTEXPR constexpr
#else
#define _CXX17_CONSTEXPR
#endif
#endif

#ifndef _CXX17_STATIC_ASSERT
#if __cplusplus >= 201703L
#define _CXX17_STATIC_ASSERT static_assert
#else
#define _CXX17_STATIC_ASSERT assert
#endif
#endif

#include <iterator>

#if __cplusplus < 201703L

namespace std {

/**
 *  @brief  Return the size of a container.
 *  @param  __cont  Container.
 */
template <typename _Container>
constexpr auto size(const _Container& __cont) noexcept(noexcept(__cont.size()))
    -> decltype(__cont.size()) {
  return __cont.size();
}

/**
 *  @brief  Return the size of an array.
 */
template <typename _Tp, size_t _Nm>
constexpr size_t size(const _Tp (&)[_Nm]) noexcept {
  return _Nm;
}

/**
 *  @brief  Return whether a container is empty.
 *  @param  __cont  Container.
 */
template <typename _Container>
[[nodiscard]] constexpr auto empty(const _Container& __cont) noexcept(
    noexcept(__cont.empty())) -> decltype(__cont.empty()) {
  return __cont.empty();
}

/**
 *  @brief  Return whether an array is empty (always false).
 */
template <typename _Tp, size_t _Nm>
[[nodiscard]] constexpr bool empty(const _Tp (&)[_Nm]) noexcept {
  return false;
}

/**
 *  @brief  Return whether an initializer_list is empty.
 *  @param  __il  Initializer list.
 */
template <typename _Tp>
[[nodiscard]] constexpr bool empty(initializer_list<_Tp> __il) noexcept {
  return __il.size() == 0;
}

struct monostate {};

}  // namespace std

#else

#include <variant>

#endif
#line 12 "src/algebra/extended.hpp"

namespace workspace {

template <class _Tp> constexpr auto sign_of(const _Tp &__x) noexcept {
  return __x != _Tp(0) ? (__x > _Tp(0) ? +1 : -1) : 0;
}

// Extended numeric type.
template <class _Tp> class extended {
  bool infinite{};
  int_least8_t sign{};  // in {0, +1, -1}
  _Tp value{};          // is 0 if infinite

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const extended &__x) noexcept {
    return __x.infinite ? __os << (__x.sign > 0 ? '+' : '-') << "infinity"
                        : __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, extended &__x) noexcept {
    __x.infinite = false;
    __is >> __x.value;
    __x.sign = sign_of(__x.value);
    return __is;
  }

  constexpr extended(bool __x, int_least8_t __y, const _Tp &__z) noexcept
      : infinite(__x), sign(__y), value(__z) {}

 public:
  constexpr static extended infinity{true, +1, 0};

  constexpr extended() noexcept {}

  constexpr extended(const _Tp &__x) noexcept
      : sign(sign_of(__x)), value(__x) {}

  constexpr std::enable_if_t<std::is_swappable<_Tp>::value> swap(
      extended &__x) noexcept {
    std::swap(infinite, __x.infinite);
    std::swap(sign, __x.sign);
    std::swap(value, __x.value);
  }

  template <class _U> constexpr operator _U const &() const noexcept {
    if _CXX17_CONSTEXPR (std::is_same_v<_U, bool>) return sign;
    return value;
  }

  template <class _U> constexpr operator _U() const noexcept {
    if _CXX17_CONSTEXPR (std::is_same_v<_U, bool>) return sign;
    return value;
  }

  constexpr extended operator+() const noexcept { return *this; }

  constexpr extended operator-() const noexcept {
    return extended(infinite, -sign, -value);
  }

  constexpr extended &operator+=(const extended &__x) noexcept {
    if (__x.infinite) return *this = __x;
    return operator+=(__x.value);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator+=(const _U &__x) noexcept {
    if (!infinite) sign = sign_of(value += __x);
    return *this;
  }

  constexpr extended &operator-=(const extended &__x) noexcept {
    return operator+=(-__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator-=(const _U &__x) noexcept {
    return operator+=(-__x);
  }

  constexpr extended &operator*=(const extended &__x) noexcept {
    if (sign *= __x.sign)
      infinite = infinite || __x.infinite, value *= __x.value;
    else
      infinite = false, value = 0;
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator*=(const _U &__x) noexcept {
    if (sign *= sign_of(__x))
      value *= __x;
    else
      infinite = false, value = 0;
    return *this;
  }

  constexpr extended &operator/=(const extended &__x) noexcept {
    if (__x.infinite)
      infinite = false, sign = 0, value = 0;
    else if (__x.sign)
      (value /= __x.value) ? sign *= __x.sign : sign = 0;
    else
      infinite = true, value = 0;
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator/=(const _U &__x) noexcept {
    auto __s = sign_of(__x);
    if (__s)
      (value /= __x) ? sign *= __s : sign = 0;
    else
      infinite = true, value = 0;
    return *this;
  }

  constexpr extended &operator%=(const extended &__x) noexcept {
    if (!__x.infinite) sign = sign_of(value %= __x);
    return *this;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended &>
  operator%=(const _U &__x) noexcept {
    sign = sign_of(value %= __x);
    return *this;
  }

  constexpr extended operator+(const extended &__x) const noexcept {
    return extended(*this) += __x;
  }

  constexpr extended operator-(const extended &__x) const noexcept {
    return extended(*this) -= __x;
  }

  constexpr extended operator*(const extended &__x) const noexcept {
    return extended(*this) *= __x;
  }

  constexpr extended operator/(const extended &__x) const noexcept {
    return extended(*this) /= __x;
  }

  constexpr extended operator%(const extended &__x) const noexcept {
    return extended(*this) %= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator+(const _U &__x) const noexcept {
    return extended(*this) += __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator-(const _U &__x) const noexcept {
    return extended(*this) -= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator*(const _U &__x) const noexcept {
    return extended(*this) *= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator/(const _U &__x) const noexcept {
    return extended(*this) /= __x;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, extended>
  operator%(const _U &__x) const noexcept {
    return extended(*this) %= __x;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator+(const _U &__x, const extended &__y) noexcept {
    return extended(__x) += __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator-(const _U &__x, const extended &__y) noexcept {
    return extended(__x) -= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator*(const _U &__x, const extended &__y) noexcept {
    return extended(__x) *= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator/(const _U &__x, const extended &__y) noexcept {
    return extended(__x) /= __y;
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value,
                                    extended>
  operator%(const _U &__x, const extended &__y) noexcept {
    return extended(__x) %= __y;
  }

  constexpr bool operator==(const extended &__x) const noexcept {
    return infinite == __x.infinite && sign == __x.sign && value == __x.value;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator==(const _U &__x) const noexcept {
    return !infinite && value == static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator==(const _U &__x, const extended &__y) noexcept {
    return __y.operator==(__x);
  }

  constexpr bool operator!=(const extended &__x) const noexcept {
    return !operator==(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator!=(const _U &__x) const noexcept {
    return !operator==(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator!=(const _U &__x, const extended &__y) noexcept {
    return __y.operator!=(__x);
  }

  constexpr bool operator<(const extended &__x) const noexcept {
    auto __l = sign * infinite, __r = __x.sign * __x.infinite;
    return __l != __r ? __l < __r : value < __x.value;
  }

  constexpr bool operator<=(const extended &__x) const noexcept {
    auto __l = sign * infinite, __r = __x.sign * __x.infinite;
    return __l != __r ? __l < __r : value <= __x.value;
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<(const _U &__x) const noexcept {
    return infinite ? sign < 0 : value < static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<=(const _U &__x) const noexcept {
    return infinite ? sign < 0 : value <= static_cast<_Tp>(__x);
  }

  constexpr bool operator>(const extended &__x) const noexcept {
    return __x.operator<(*this);
  }

  constexpr bool operator>=(const extended &__x) const noexcept {
    return __x.operator<=(*this);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>(const _U &__x) const noexcept {
    return infinite ? sign > 0 : value > static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>=(const _U &__x) const noexcept {
    return infinite ? sign > 0 : value >= static_cast<_Tp>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<(const _U &__x, const extended &__y) noexcept {
    return __y.operator>(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>(const _U &__x, const extended &__y) noexcept {
    return __y.operator<(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator<=(const _U &__x, const extended &__y) noexcept {
    return __y.operator>=(__x);
  }

  template <class _U>
  constexpr friend std::enable_if_t<std::is_convertible<_U, _Tp>::value, bool>
  operator>=(const _U &__x, const extended &__y) noexcept {
    return __y.operator<=(__x);
  }
};

}  // namespace workspace
Back to top page