Skip to content

Instantly share code, notes, and snippets.

@tjkendev
Last active August 4, 2019 09:36
Show Gist options
  • Save tjkendev/bb587733b3739ea1ffc33b91be33a687 to your computer and use it in GitHub Desktop.
Save tjkendev/bb587733b3739ea1ffc33b91be33a687 to your computer and use it in GitHub Desktop.
主にlong long intに対するオーバーフロー検知用クラス。とりあえず作ったので置いとく。
using lli = long long int;
template<typename T>
class NumValid {
T testVal;
__int128 val128;
public:
NumValid() : testVal(0), val128(0) {}
NumValid(T val) : testVal(val), val128(val) {}
operator lli() { return testVal; }
const T get() const { return testVal; }
lli operator=(lli val) { return testVal = val128 = val; }
int operator=(int val) { return testVal = val128 = val; }
void operator+=(lli val) {
if(testVal + val != val128 + val) {
cout << "overflowed!! (" << testVal << " * " << val << ")" << endl;
assert(0);
}
testVal += val; val128 += val;
}
void operator*=(lli val) {
if(testVal * val != val128 * val) {
cout << "overflowed!! (" << testVal << " * " << val << ")" << endl;
assert(0);
}
testVal *= val; val128 *= val;
}
void operator%=(lli val) { testVal %= val; val128 %= val; }
void operator%=(const NumValid<T> val) {
*this %= val.testVal;
}
void operator>>=(lli val) {
testVal >>= val; val128 >>= val;
}
void operator<<=(lli val) {
if(testVal << val != val128 << val) {
cout << "overflowed!! (" << testVal << " << " << val << ")" << endl;
assert(0);
}
testVal <<= val; val128 <<= val;
}
void operator+=(const NumValid<T> val) {
if(testVal + val.testVal != val128 + val.testVal) {
cout << "overflowed!! (" << testVal << " * " << val.testVal << ")" << endl;
assert(0);
}
testVal += val.testVal; val128 += val.testVal;
}
void operator*=(const NumValid<T> val) {
if(testVal * val.testVal != val128 * val.testVal) {
cout << "overflowed!! (" << testVal << " * " << val.testVal << ")" << endl;
assert(0);
}
testVal *= val.testVal; val128 *= val.testVal;
}
NumValid<T>& operator++() {
testVal++; val128++; return *this;
}
NumValid<T>& operator--() {
testVal++; val128++; return *this;
}
NumValid<T> operator++(int) {
val128++;
return NumValid<T>(testVal++);
}
NumValid<T> operator--(int) {
val128--;
return NumValid<T>(testVal--);
}
friend NumValid<T> operator+(const NumValid<T> &left, const lli right) {
if(left.testVal + right != left.val128 + right) {
cout << "overflowed!! (" << left.testVal << " + " << right << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal + right);
}
friend NumValid<T> operator+(const NumValid<T> &left, const int right) { return left + (lli) right; }
friend NumValid<T> operator+(const int left, const NumValid<T> &right) { return left + right.testVal; }
friend NumValid<T> operator-(const NumValid<T> &left, const lli right) {
if(left.testVal - right != left.val128 - right) {
cout << "overflowed!! (" << left.testVal << " - " << right << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal - right);
}
friend NumValid<T> operator-(const NumValid<T> &left, const int right) { return left - (lli) right; }
friend NumValid<T> operator-(const NumValid<T> &left, const size_t right) { return left - (lli) right; }
friend NumValid<T> operator*(const NumValid<T> &left, const lli right) {
if(left.testVal * right != left.val128 * right) {
cout << "overflowed!! (" << left.testVal << " * " << right << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal * right);
}
friend NumValid<T> operator*(const NumValid<T> &left, const int right) { return left * (lli) right; }
friend NumValid<T> operator*(const int left, const NumValid<T> &right) { return left * right.testVal; }
friend NumValid<T> operator/(const NumValid<T> &left, const lli right) {
return NumValid<T>(left.testVal / right);
}
friend NumValid<T> operator/(const NumValid<T> &left, const int right) { return left / (lli) right; }
friend NumValid<T> operator%(const NumValid<T> &left, const lli right) {
return NumValid<T>(left.testVal % right);
}
friend NumValid<T> operator%(const NumValid<T> &left, const int right) { return left % (lli) right; }
friend NumValid<T> operator&(const NumValid<T> &left, const lli right) {
return NumValid<T>(left.testVal & right);
}
friend NumValid<T> operator&(const NumValid<T> &left, const int right) { return left & (lli) right; }
friend NumValid<T> operator|(const NumValid<T> &left, const lli right) {
return NumValid<T>(left.testVal | right);
}
friend NumValid<T> operator|(const NumValid<T> &left, const int right) { return left | (lli) right; }
friend NumValid<T> operator^(const NumValid<T> &left, const lli right) {
return NumValid<T>(left.testVal ^ right);
}
friend NumValid<T> operator^(const NumValid<T> &left, const int right) { return left ^ (lli) right; }
friend bool operator<(const NumValid<T> &left, const lli right) { return left.testVal < right; }
friend bool operator<(const NumValid<T> &left, const int right) { return left< (lli) right; }
friend bool operator<(const lli left, const NumValid<T> &right) { return left < right.testVal; }
friend bool operator<(const int left, const NumValid<T> &right) { return (lli) left < right; }
friend bool operator>(const NumValid<T> &left, const lli right) { return left.testVal > right; }
friend bool operator>(const NumValid<T> &left, const int right) { return left> (lli) right; }
friend bool operator>(const lli left, const NumValid<T> &right) { return left > right.testVal; }
friend bool operator>(const int left, const NumValid<T> &right) { return (lli) left > right; }
friend bool operator==(const NumValid<T> &left, const lli right) { return left.testVal == right; }
friend bool operator==(const NumValid<T> &left, const int right) { return left == (lli) right; }
friend bool operator==(const lli left, const NumValid<T> &right) { return left == right.testVal; }
friend bool operator==(const int left, const NumValid<T> &right) { return (lli) left == right; }
friend bool operator==(const NumValid<T> &left, const NumValid<T> &right) { return left.testVal == right.testVal; }
friend NumValid<T> operator+(const NumValid<T> &left, const NumValid<T> &right) {
if(left.testVal + right.testVal != left.val128 + right.val128) {
cout << "overflowed!! (" << left.testVal << " + " << right.testVal << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal + right.testVal);
}
friend NumValid<T> operator-(const NumValid<T> &left, const NumValid<T> &right) {
if(left.testVal - right.testVal != left.val128 - right.val128) {
cout << "overflowed!! (" << left.testVal << " - " << right.testVal << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal - right.testVal);
}
friend NumValid<T> operator*(const NumValid<T> &left, const NumValid<T> &right) {
if(left.testVal * right.testVal != left.val128 * right.val128) {
cout << "overflowed!! (" << left.testVal << " * " << right.testVal << ")" << endl;
assert(0);
}
return NumValid<T>(left.testVal * right.testVal);
}
friend NumValid<T> operator/(const NumValid<T> &left, const NumValid<T> &right) {
return NumValid<T>(left.testVal / right.testVal);
}
friend NumValid<T> operator%(const NumValid<T> &left, const NumValid<T> &right) {
return NumValid<T>(left.testVal % right.testVal);
}
friend istream& operator>> (istream &in, NumValid<T> &num) {
lli val;
in >> val;
num = val;
return in;
}
friend ostream& operator<< (ostream &out, NumValid<T> &num) {
out << num.testVal;
return out;
}
};
typedef NumValid<long long int> ll;
// for hash-table
namespace std {
template<class T> struct hash<NumValid<T> > {
std::size_t operator()(const NumValid<T> &key) const {
return std::hash<T>{}(key.get());
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment