Library

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

View the Project on GitHub jellc/Library

:warning: Rational
(src/algebra/rational.hpp)

Depends on

Code

#pragma once

/**
 * @file rational.hpp
 * @brief Rational
 */

#include <cassert>

#include "lib/cxx17"
#include "system/operation.hpp"

namespace workspace {

/**
 * @brief Rational.
 * @tparam _Tp Ring structure
 */
template <class _Tp> class rational {
  _Tp __num, __den;

 public:
  _CXX14_CONSTEXPR rational(const _Tp &__x, const _Tp &__y) noexcept
      : __num(__x), __den(__y) {}

  _CXX14_CONSTEXPR rational(const _Tp &__x, _Tp &&__y) noexcept
      : __num(__x), __den(std::move(__y)) {}

  _CXX14_CONSTEXPR rational(_Tp &&__x, const _Tp &__y) noexcept
      : __num(std::move(__x)), __den(__y) {}

  _CXX14_CONSTEXPR rational(_Tp &&__x = 0, _Tp &&__y = 1) noexcept
      : __num(std::move(__x)), __den(std::move(__y)) {}

  _CXX14_CONSTEXPR rational(std::initializer_list<_Tp> __x) noexcept
      : __num(__x.size() > 0 ? *__x.begin() : _Tp(0)),
        __den(__x.size() > 1 ? *std::next(__x.begin()) : _Tp(1)) {}

  _CXX14_CONSTEXPR rational operator+() const noexcept { return *this; }

  _CXX14_CONSTEXPR rational operator-() const noexcept {
    return {-__num, __den};
  }

  _CXX14_CONSTEXPR rational operator+(const rational &__x) const noexcept {
    return {__num * __x.__den + __x.__num * __den, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator-(const rational &__x) const noexcept {
    return {__num * __x.__den - __x.__num * __den, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator*(const rational &__x) const noexcept {
    return {__num * __x.__num, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator/(const rational &__x) const noexcept {
    assert(__x.__num != _Tp(0));
    return {__num * __x.__den, __den * __x.__num};
  }

  _CXX14_CONSTEXPR rational &operator+=(const rational &__x) noexcept {
    (__num *= __x.__den) += __den * __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator-=(const rational &__x) noexcept {
    (__num *= __x.__den) -= __den * __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator*=(const rational &__x) noexcept {
    __num *= __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator/=(const rational &__x) noexcept {
    __num *= __x.__den, __den *= __x.__num;
    return *this;
  }

  _CXX14_CONSTEXPR bool operator==(const rational &__x) const noexcept {
    return __num * __x.__den == __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator!=(const rational &__x) const noexcept {
    return __num * __x.__den != __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator<(const rational &__x) const noexcept {
    return (__den > 0) ^ (__x.__den > 0)
               ? __num * __x.__den > __den * __x.__num
               : __num * __x.__den < __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator>(const rational &__x) const noexcept {
    return (__den > 0) ^ (__x.__den > 0)
               ? __num * __x.__den < __den * __x.__num
               : __num * __x.__den > __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator<=(const rational &__x) const noexcept {
    return !operator>(__x);
  }

  _CXX14_CONSTEXPR bool operator>=(const rational &__x) const noexcept {
    return !operator<(__x);
  }

  _CXX14_CONSTEXPR
  std::enable_if_t<std::is_swappable<_Tp>::value> swap(rational &__x) noexcept {
    std::swap(__num, __x.__num), std::swap(__den, __x.__den);
  }

  template <size_t _Nm> friend constexpr auto &get(rational &__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return __x.__den;
    return __x.__num;
  }

  template <size_t _Nm>
  friend constexpr const auto &get(const rational &__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return __x.__den;
    return __x.__num;
  }

  template <size_t _Nm> friend constexpr auto &&get(rational &&__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return std::move(__x.__den);
    return std::move(__x.__num);
  }
};

}  // namespace workspace

namespace std {

template <class _Tp>
struct tuple_size<workspace::rational<_Tp>> : integral_constant<size_t, 2> {};

template <class _Tp, size_t _Nm>
struct tuple_element<_Nm, workspace::rational<_Tp>> {
  using type = _Tp;
};

}  // namespace std
#line 2 "src/algebra/rational.hpp"

/**
 * @file rational.hpp
 * @brief Rational
 */

#include <cassert>

#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 2 "src/algebra/system/operation.hpp"

/**
 * @file operation.hpp
 * @brief Operation Traits
 */

#include <functional>
#include <type_traits>

#line 12 "src/algebra/system/operation.hpp"

namespace workspace {

// Unary `+`
template <class _Tp>
using require_unary_plus = std::enable_if_t<
    std::is_convertible<decltype(+std::declval<const _Tp &>()), _Tp>::value>;

template <class _Tp, class = void> struct has_unary_plus : std::false_type {};

template <class _Tp>
struct has_unary_plus<_Tp, require_unary_plus<_Tp>> : std::true_type {};

// Unary `-`
template <class _Tp>
using require_unary_minus = std::enable_if_t<
    std::is_convertible<decltype(-std::declval<const _Tp &>()), _Tp>::value>;

template <class _Tp, class = void> struct has_unary_minus : std::false_type {};

template <class _Tp>
struct has_unary_minus<_Tp, require_unary_minus<_Tp>> : std::true_type {};

// Binary `+`
template <class _Tp1, class _Tp2 = _Tp1>
using require_binary_plus =
    std::enable_if_t<std::is_convertible<decltype(std::declval<const _Tp1 &>() +
                                                  std::declval<const _Tp2 &>()),
                                         _Tp1>::value>;

template <class _Tp1, class _Tp2 = _Tp1, class = void>
struct has_binary_plus : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_binary_plus<_Tp1, _Tp2, require_binary_plus<_Tp1, _Tp2>>
    : std::true_type {};

// Binary `-`
template <class _Tp1, class _Tp2 = _Tp1>
using require_binary_minus =
    std::__void_t<decltype(std::declval<const _Tp1 &>() -
                           std::declval<const _Tp2 &>())>;

template <class _Tp1, class _Tp2 = _Tp1, class = void>
struct has_binary_minus : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_binary_minus<_Tp1, _Tp2, require_binary_minus<_Tp1, _Tp2>>
    : std::true_type {};

// Binary `*`
template <class _Tp1, class _Tp2 = _Tp1>
using require_binary_multiplies =
    std::enable_if_t<std::is_convertible<decltype(std::declval<const _Tp1 &>() *
                                                  std::declval<const _Tp2 &>()),
                                         _Tp1>::value>;

template <class _Tp1, class _Tp2 = _Tp1, class = void>
struct has_binary_multiplies : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_binary_multiplies<_Tp1, _Tp2, require_binary_multiplies<_Tp1, _Tp2>>
    : std::true_type {};

// Binary `/`
template <class _Tp1, class _Tp2 = _Tp1>
using require_binary_divides =
    std::enable_if_t<std::is_convertible<decltype(std::declval<const _Tp1 &>() /
                                                  std::declval<const _Tp2 &>()),
                                         _Tp1>::value>;

template <class _Tp1, class _Tp2 = _Tp1, class = void>
struct has_binary_divides : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_binary_divides<_Tp1, _Tp2, require_binary_divides<_Tp1, _Tp2>>
    : std::true_type {};

// Binary `%`
template <class _Tp1, class _Tp2 = _Tp1>
using require_binary_modulus =
    std::enable_if_t<std::is_convertible<decltype(std::declval<const _Tp1 &>() %
                                                  std::declval<const _Tp2 &>()),
                                         _Tp1>::value>;

template <class _Tp1, class _Tp2 = _Tp1, class = void>
struct has_binary_modulus : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_binary_modulus<_Tp1, _Tp2, require_binary_modulus<_Tp1, _Tp2>>
    : std::true_type {};

template <class _Tp1, class _Tp2 = _Tp1, class = void, class = void,
          class = void, class = void>
struct has_arithmetic : std::false_type {};

template <class _Tp1, class _Tp2>
struct has_arithmetic<_Tp1, _Tp2, require_binary_plus<_Tp1, _Tp2>,
                      require_binary_minus<_Tp1, _Tp2>,
                      require_binary_multiplies<_Tp1, _Tp2>,
                      require_binary_divides<_Tp1, _Tp2>> : std::true_type {};

template <class _Tp1, class _Tp2 = _Tp1>
using require_arithmetic = std::enable_if_t<has_arithmetic<_Tp1, _Tp2>::value>;

// Binary `<`
template <class _Tp, class = void> struct is_comparable : std::false_type {};

template <class _Tp>
struct is_comparable<_Tp, std::__void_t<decltype(std::declval<const _Tp &>() <
                                                 std::declval<const _Tp &>())>>
    : std::true_type {};

template <class _Tp, bool _Default = false> struct try_less : std::less<_Tp> {
  constexpr bool operator()(const _Tp &__x, const _Tp &__y) noexcept {
    if _CXX17_CONSTEXPR (is_comparable<_Tp>::value)
      return std::less<_Tp>::operator()(__x, __y);
    else
      return _Default;
  }
};

}  // namespace workspace
#line 12 "src/algebra/rational.hpp"

namespace workspace {

/**
 * @brief Rational.
 * @tparam _Tp Ring structure
 */
template <class _Tp> class rational {
  _Tp __num, __den;

 public:
  _CXX14_CONSTEXPR rational(const _Tp &__x, const _Tp &__y) noexcept
      : __num(__x), __den(__y) {}

  _CXX14_CONSTEXPR rational(const _Tp &__x, _Tp &&__y) noexcept
      : __num(__x), __den(std::move(__y)) {}

  _CXX14_CONSTEXPR rational(_Tp &&__x, const _Tp &__y) noexcept
      : __num(std::move(__x)), __den(__y) {}

  _CXX14_CONSTEXPR rational(_Tp &&__x = 0, _Tp &&__y = 1) noexcept
      : __num(std::move(__x)), __den(std::move(__y)) {}

  _CXX14_CONSTEXPR rational(std::initializer_list<_Tp> __x) noexcept
      : __num(__x.size() > 0 ? *__x.begin() : _Tp(0)),
        __den(__x.size() > 1 ? *std::next(__x.begin()) : _Tp(1)) {}

  _CXX14_CONSTEXPR rational operator+() const noexcept { return *this; }

  _CXX14_CONSTEXPR rational operator-() const noexcept {
    return {-__num, __den};
  }

  _CXX14_CONSTEXPR rational operator+(const rational &__x) const noexcept {
    return {__num * __x.__den + __x.__num * __den, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator-(const rational &__x) const noexcept {
    return {__num * __x.__den - __x.__num * __den, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator*(const rational &__x) const noexcept {
    return {__num * __x.__num, __den * __x.__den};
  }

  _CXX14_CONSTEXPR rational operator/(const rational &__x) const noexcept {
    assert(__x.__num != _Tp(0));
    return {__num * __x.__den, __den * __x.__num};
  }

  _CXX14_CONSTEXPR rational &operator+=(const rational &__x) noexcept {
    (__num *= __x.__den) += __den * __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator-=(const rational &__x) noexcept {
    (__num *= __x.__den) -= __den * __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator*=(const rational &__x) noexcept {
    __num *= __x.__num, __den *= __x.__den;
    return *this;
  }

  _CXX14_CONSTEXPR rational &operator/=(const rational &__x) noexcept {
    __num *= __x.__den, __den *= __x.__num;
    return *this;
  }

  _CXX14_CONSTEXPR bool operator==(const rational &__x) const noexcept {
    return __num * __x.__den == __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator!=(const rational &__x) const noexcept {
    return __num * __x.__den != __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator<(const rational &__x) const noexcept {
    return (__den > 0) ^ (__x.__den > 0)
               ? __num * __x.__den > __den * __x.__num
               : __num * __x.__den < __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator>(const rational &__x) const noexcept {
    return (__den > 0) ^ (__x.__den > 0)
               ? __num * __x.__den < __den * __x.__num
               : __num * __x.__den > __den * __x.__num;
  }

  _CXX14_CONSTEXPR bool operator<=(const rational &__x) const noexcept {
    return !operator>(__x);
  }

  _CXX14_CONSTEXPR bool operator>=(const rational &__x) const noexcept {
    return !operator<(__x);
  }

  _CXX14_CONSTEXPR
  std::enable_if_t<std::is_swappable<_Tp>::value> swap(rational &__x) noexcept {
    std::swap(__num, __x.__num), std::swap(__den, __x.__den);
  }

  template <size_t _Nm> friend constexpr auto &get(rational &__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return __x.__den;
    return __x.__num;
  }

  template <size_t _Nm>
  friend constexpr const auto &get(const rational &__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return __x.__den;
    return __x.__num;
  }

  template <size_t _Nm> friend constexpr auto &&get(rational &&__x) noexcept {
    static_assert(_Nm < 2);
    if _CXX17_CONSTEXPR (_Nm) return std::move(__x.__den);
    return std::move(__x.__num);
  }
};

}  // namespace workspace

namespace std {

template <class _Tp>
struct tuple_size<workspace::rational<_Tp>> : integral_constant<size_t, 2> {};

template <class _Tp, size_t _Nm>
struct tuple_element<_Nm, workspace::rational<_Tp>> {
  using type = _Tp;
};

}  // namespace std
Back to top page