競技プログラミング用 C++ ライブラリ
components/integer_arithmetic.hpp · GitHub で見る
共通ページ
整数除算 と 等比数列の和 が使う内部部品です。通常は各ライブラリの公開 API を使ってください。
全て integer_arithmetic_detail 名前空間にあります。
| 型・操作 | 内容 |
|---|---|
integer<T> |
bool 以外の組込み整数型および __int128_t・__uint128_t なら true となる bool 定数 |
add(a, b) |
同じ型 T の const T& を 2 つ受け取り、和を T で返す |
multiply(a, b) |
同じ型 T の const T& を 2 つ受け取り、積を T で返す |
add・multiply は integer<T> が true の場合、演算結果が T に収まらなければ std::overflow_error を送出します。それ以外の型はそれぞれ a + b・a * b を評価し、型自身の演算規則に従います。型の演算が対応していれば constexpr で使えます。既定引数はありません。
組込み整数型と 128 bit 整数型では各操作が \(O(1)\) 時間・追加空間です。他の型では、その型の加算・乗算および返り値の構築に必要な時間・空間を使います。
#ifndef INTEGER_ARITHMETIC_HPP
#define INTEGER_ARITHMETIC_HPP
#include <cstdint>
#include <stdexcept>
#include <type_traits>
namespace integer_arithmetic_detail {
template <class T>
inline constexpr bool integer = (std::is_integral_v<T> || std::is_same_v<T, __int128_t> || std::is_same_v<T, __uint128_t>) && !std::is_same_v<T, bool>;
template <class T>
constexpr T add(const T &a, const T &b) {
if constexpr (integer<T>) {
T result;
if (__builtin_add_overflow(a, b, &result)) throw std::overflow_error("integer addition");
return result;
} else return a + b;
}
template <class T>
constexpr T multiply(const T &a, const T &b) {
if constexpr (integer<T>) {
T result;
if (__builtin_mul_overflow(a, b, &result)) throw std::overflow_error("integer multiplication");
return result;
} else return a * b;
}
}
#endif
#line 1 "components/integer_arithmetic.hpp"
#include <cstdint>
#include <stdexcept>
#include <type_traits>
namespace integer_arithmetic_detail {
template <class T>
inline constexpr bool integer = (std::is_integral_v<T> || std::is_same_v<T, __int128_t> || std::is_same_v<T, __uint128_t>) && !std::is_same_v<T, bool>;
template <class T>
constexpr T add(const T &a, const T &b) {
if constexpr (integer<T>) {
T result;
if (__builtin_add_overflow(a, b, &result)) throw std::overflow_error("integer addition");
return result;
} else return a + b;
}
template <class T>
constexpr T multiply(const T &a, const T &b) {
if constexpr (integer<T>) {
T result;
if (__builtin_mul_overflow(a, b, &result)) throw std::overflow_error("integer multiplication");
return result;
} else return a * b;
}
}