-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add unit * update README desc
- Loading branch information
Showing
8 changed files
with
994 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef HEADER_NUMBERS_H | ||
#define HEADER_NUMBERS_H | ||
|
||
#include "integer.hh" | ||
#include "uinteger.hh" | ||
|
||
using Int8 = Integer<int8_t>; | ||
using Int16 = Integer<int16_t>; | ||
using Int32 = Integer<int32_t>; | ||
using Int64 = Integer<int64_t>; | ||
|
||
Integer<int8_t> operator"" _i8(unsigned long long val) { return Integer<int8_t>(val); } | ||
|
||
Integer<int16_t> operator"" _i16(unsigned long long val) { return Integer<int16_t>(val); } | ||
|
||
Integer<int32_t> operator"" _i32(unsigned long long val) { return Integer<int32_t>(val); } | ||
|
||
Integer<int64_t> operator"" _i64(unsigned long long val) { return Integer<int64_t>(val); } | ||
|
||
using Uint8 = Uinteger<uint8_t>; | ||
using Uint16 = Uinteger<uint16_t>; | ||
using Uint32 = Uinteger<uint32_t>; | ||
using Uint64 = Uinteger<uint64_t>; | ||
|
||
Uint8 operator"" _u8(unsigned long long val) { return Uint8(val); } | ||
|
||
Uint16 operator"" _u16(unsigned long long val) { return Uint16(val); } | ||
|
||
Uint32 operator"" _u32(unsigned long long val) { return Uint32(val); } | ||
|
||
Uint64 operator"" _u64(unsigned long long val) { return Uint64(val); } | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,209 @@ | ||
#ifndef HEADER_UNINTEGER_H | ||
#define HEADER_UNINTEGER_H | ||
|
||
#include <iostream> | ||
#include <limits> | ||
#include <optional> | ||
#include <type_traits> | ||
|
||
template <typename T, typename = std::enable_if_t<std::is_unsigned<T>::value>> | ||
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> | ||
class Uinteger { | ||
public: | ||
// unimplemented! | ||
public: | ||
constexpr static T MIN = std::numeric_limits<T>::min(); | ||
constexpr static T MAX = std::numeric_limits<T>::max(); | ||
|
||
Uinteger() noexcept : num_{} {} | ||
Uinteger(T num) noexcept : num_{num} {} | ||
|
||
constexpr Uinteger operator+(const Uinteger<T> &other) noexcept(false) { | ||
if (add_overflow(num_, other.num_)) { | ||
throw std::runtime_error("add overflow"); | ||
} | ||
return Uinteger(num_ + other.num_); | ||
} | ||
|
||
constexpr Uinteger wrapping_add(const Uinteger<T> &other) noexcept { return Uinteger(num_ + other.num_); } | ||
|
||
constexpr std::optional<Uinteger> checked_add(const Uinteger<T> &other) noexcept { | ||
if (add_overflow(num_, other.num_)) { | ||
return {}; | ||
} | ||
return Uinteger(num_ + other.num_); | ||
} | ||
|
||
constexpr std::tuple<Uinteger<T>, bool> overflowing_add(const Uinteger<T> &other) noexcept { | ||
return {Uinteger(num_ + other.num_), add_overflow(num_, other.num_)}; | ||
} | ||
|
||
constexpr Uinteger<T> saturating_add(const Uinteger<T> &other) noexcept { | ||
if (add_overflow(num_, other.num_)) { | ||
return Uinteger(MAX); | ||
} | ||
return Uinteger(num_ + other.num_); | ||
} | ||
|
||
constexpr Uinteger operator-(const Uinteger<T> &other) noexcept(false) { | ||
if (sub_overflow(num_, other.num_)) { | ||
throw std::runtime_error("sub overflow"); | ||
} | ||
return Uinteger(num_ - other.num_); | ||
} | ||
|
||
constexpr Uinteger wrapping_sub(const Uinteger<T> &other) noexcept { return Uinteger(num_ - other.num_); } | ||
|
||
constexpr std::optional<Uinteger> checked_sub(const Uinteger<T> &other) noexcept { | ||
if (sub_overflow(num_, other.num_)) { | ||
return {}; | ||
} | ||
return Uinteger(num_ - other.num_); | ||
} | ||
|
||
constexpr std::tuple<Uinteger<T>, bool> overflowing_sub(const Uinteger<T> &other) noexcept { | ||
return {Uinteger(num_ - other.num_), sub_overflow(num_, other.num_)}; | ||
} | ||
|
||
constexpr Uinteger saturating_sub(const Uinteger<T> &other) noexcept { | ||
if (sub_overflow(num_, other.num_)) { | ||
return MIN; | ||
} | ||
return Uinteger(num_ - other.num_); | ||
} | ||
|
||
constexpr Uinteger operator/(const Uinteger<T> &other) { | ||
if (div_overflow(num_, other.num_)) { | ||
throw std::runtime_error("div overflow"); | ||
} | ||
return Uinteger(num_ / other.num_); | ||
} | ||
|
||
constexpr Uinteger wrapping_div(const Uinteger<T> &other) noexcept(false) { return Uinteger(num_ / other.num_); } | ||
|
||
constexpr std::optional<Uinteger> checked_div(const Uinteger<T> &other) noexcept { | ||
if (div_overflow(num_, other.num_)) { | ||
return {}; | ||
} | ||
return Uinteger(num_ / other.num_); | ||
} | ||
|
||
constexpr std::tuple<Uinteger<T>, bool> overflowing_div(const Uinteger<T> &other) noexcept { | ||
return {Uinteger(num_ / other.num_), div_overflow(num_, other.num_)}; | ||
} | ||
|
||
constexpr Uinteger saturating_div(const Uinteger<T> &other) noexcept { | ||
if (div_overflow(num_, other.num_)) { | ||
return MIN; | ||
} | ||
return Uinteger(num_ / other.num_); | ||
} | ||
|
||
constexpr Uinteger operator*(const Uinteger<T> &other) { | ||
if (mul_overflow(num_, other.num_)) { | ||
throw std::runtime_error("mul overflow"); | ||
} | ||
return Uinteger(num_ * other.num_); | ||
} | ||
|
||
constexpr Uinteger wrapping_mul(const Uinteger<T> &other) noexcept(false) { return Uinteger(num_ * other.num_); } | ||
|
||
constexpr std::optional<Uinteger> checked_mul(const Uinteger<T> &other) noexcept { | ||
if (mul_overflow(num_, other.num_)) { | ||
return {}; | ||
} | ||
return Uinteger(num_ * other.num_); | ||
} | ||
|
||
constexpr std::tuple<Uinteger<T>, bool> overflowing_mul(const Uinteger<T> &other) noexcept { | ||
return {Uinteger(num_ * other.num_), mul_overflow(num_, other.num_)}; | ||
} | ||
|
||
constexpr Uinteger saturating_mul(const Uinteger<T> &other) noexcept { | ||
if (mul_overflow(num_, other.num_)) { | ||
return MAX; | ||
} | ||
return Uinteger(num_ * other.num_); | ||
} | ||
|
||
constexpr Uinteger operator-() const noexcept(false) { | ||
if (num_ == MIN) { | ||
return Uinteger(num_); | ||
} | ||
throw std::runtime_error("neg overflow"); | ||
} | ||
|
||
constexpr std::optional<Uinteger> checked_neg() noexcept { | ||
if (num_ == MIN) { | ||
return Uinteger(MIN); | ||
} | ||
return {}; | ||
} | ||
|
||
constexpr std::tuple<Uinteger, bool> overflowing_neg() noexcept { | ||
if (num_ == MIN) { | ||
return {Uinteger(MIN), false}; | ||
} | ||
return {Uinteger(-num_), true}; | ||
} | ||
|
||
constexpr Uinteger wrapping_neg() noexcept { | ||
if (num_ == MIN) { | ||
return Uinteger(MIN); | ||
} | ||
return Uinteger(-num_); | ||
} | ||
|
||
constexpr bool operator==(const Uinteger<T> &other) const { return num_ == other.num_; } | ||
constexpr bool operator==(const T &other) const { return num_ == other; } | ||
|
||
constexpr bool operator<(const Uinteger<T> &other) const { return num_ < other.num_; } | ||
constexpr bool operator<(const T &other) const { return num_ < other; } | ||
|
||
constexpr bool operator>(const Uinteger<T> &other) const { return num_ > other.num_; } | ||
constexpr bool operator>(const T &other) const { return num_ > other; } | ||
|
||
// prefix ++ | ||
constexpr Uinteger &operator++() { | ||
if (add_overflow(num_, 1)) { | ||
throw std::runtime_error("prefix ++ overflow"); | ||
} | ||
num_ += 1; | ||
return *this; | ||
} | ||
|
||
// postfix ++ | ||
constexpr Uinteger operator++(int) { | ||
if (add_overflow(num_, 1)) { | ||
throw std::runtime_error("postfix ++ overflow"); | ||
} | ||
Uinteger<T> tmp = *this; | ||
num_ += 1; | ||
return tmp; | ||
} | ||
|
||
template <typename U, typename = std::enable_if<std::is_convertible_v<T, U>>> | ||
explicit operator Uinteger<U>() const { | ||
return Uinteger<U>(static_cast<U>(num_)); | ||
} | ||
|
||
explicit operator T() const { return num_; } | ||
|
||
friend std::ostream &operator<<(std::ostream &os, const Uinteger<T> &num) { | ||
os << num.num_; | ||
return os; | ||
} | ||
|
||
private: | ||
constexpr bool add_overflow(T a, T b) const { return b > MAX - a; } | ||
|
||
constexpr bool sub_overflow(T minuend, T subtrahend) const { return minuend < subtrahend; } | ||
|
||
constexpr bool div_overflow(T a, T b) const { return false; } | ||
|
||
constexpr bool mul_overflow(T a, T b) const { | ||
T res; | ||
return __builtin_mul_overflow(a, b, &res); | ||
} | ||
|
||
private: | ||
T num_; | ||
}; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.