128ビット整数をいい感じに使えるライブラリを作ってみた(C++)

作ってみたとは書いたものの、肝心の入出力の部分はこちらの記事のコードをがっつりコピペをさせていただきました。

kenkoooo.hatenablog.com

この場で感謝します。感謝。

さて、では何を作ったのかというと、入出力に加えて四則演算と剰余を行えるようにしてみました。

それ元々できるよって言われたら実は返す言葉がありません。
なぜ作ったのかというと、structclassにしたかったという曖昧な動機なので特に深い理由はないです。

#include <bits/stdc++.h>
using namespace std;

class i128 {
private:
  __int128_t v;

public:
  i128() {}
  i128(const long long &a) { v = a; }
  i128(const string &s) { parse(s); }

  long long long_val() { return (long long)v; }
  __int128_t val() { return v; }
  __int128_t abs() { return v < 0 ? -v : v; }

  void set(const long long &a) { v = a; }

  void parse(const string &s) {
    v = 0;
    for ( char c : s ) {
      if ( isdigit(c) ) v = v * 10 + (c - '0');
    }
    if ( s[0] == '-' ) v *= -1;
  }

  // clang-format off
  i128 operator+(const i128 &a) { return v + a.v; }
  i128 operator-(const i128 &a) { return v - a.v; }
  i128 operator*(const i128 &a) { return v * a.v; }
  i128 operator/(const i128 &a) { return v / a.v; }
  i128 operator%(const i128 &a) { return v % a.v; }
  void operator+=(const i128 &a) { v += a.v; }
  void operator-=(const i128 &a) { v -= a.v; }
  void operator*=(const i128 &a) { v *= a.v; }
  void operator/=(const i128 &a) { v /= a.v; }
  void operator%=(const i128 &a) { v %= a.v; }

  template <typename T> i128 operator+(const T &a) { i128 res = *this; res.v += a; return res; }
  template <typename T> i128 operator-(const T &a) { i128 res = *this; res.v -= a; return res; }
  template <typename T> i128 operator*(const T &a) { i128 res = *this; res.v *= a; return res; }
  template <typename T> i128 operator/(const T &a) { i128 res = *this; res.v /= a; return res; }
  template <typename T> i128 operator%(const T &a) { i128 res = *this; res.v %= a; return res; }
  template <typename T> void operator+=(const T &a) { v += a; }
  template <typename T> void operator-=(const T &a) { v -= a; }
  template <typename T> void operator*=(const T &a) { v *= a; }
  template <typename T> void operator/=(const T &a) { v /= a; }
  template <typename T> void operator%=(const T &a) { v %= a; }

  template <typename T> i128 operator-() { i128 res = *this; res.v *= -1; return res; }

  bool operator<(const i128 &a) { return v < a.v; }
  bool operator>(const i128 &a) { return v > a.v; }
  bool operator<=(const i128 &a) { return v <= a.v; }
  bool operator>=(const i128 &a) { return v >= a.v; }
  bool operator==(const i128 &a) { return v == a.v; }
  bool operator!=(const i128 &a) { return v != a.v; }

  template <typename T> bool operator<(const T &a) { return v < a; }
  template <typename T> bool operator>(const T &a) { return v > a; }
  template <typename T> bool operator<=(const T &a) { return v <= a; }
  template <typename T> bool operator>=(const T &a) { return v >= a; }
  template <typename T> bool operator==(const T &a) { return v == a; }
  template <typename T> bool operator!=(const T &a) { return v != a; }
  // clang-format on

  friend istream &operator>>(istream &is, i128 &v) {
    string s;
    is >> s;
    v.parse(s);
    return is;
  }

  friend ostream &operator<<(ostream &os, const i128 &v) {
    if ( !ostream::sentry(os) ) return os;
    char buf[64];
    char *d = end(buf);
    __uint128_t tmp = (v.v < 0 ? -v.v : v.v);

    do {
      d--;
      *d = char(tmp % 10 + '0');
      tmp /= 10;
    } while ( tmp );
    if ( v.v < 0 ) {
      d--;
      *d = '-';
    }
    int len = end(buf) - d;
    if ( os.rdbuf()->sputn(d, len) != len ) { os.setstate(ios_base::badbit); }
    return os;
  }
};
int main() {
  i128 n;
  cin >> n;
  n *= 100100100100;
  cout << n << endl;
}
int main() {
  string s = "100100100100100";
  i128 n(s);
  cout << n * 102010 << endl;
}

あとがき

冷静になって考えてみると、やっぱり使い道がないような...?
入出力の部分だけべた貼りすればよい気がしてきたけど気にしない。