GF(2) 数値型のクラスを作ってみた

数値型の派生として GF(2) 用のクラスをざっくりと作ってみた。

修正した方がいいところが多少あると思います。

```python:GF2.py
import numbers


class GF2(numbers.Integral):
    # int 値を取得

    @staticmethod
    def ToInt(other):
        if type(other) == int:
            return other
        if type(other) == GF2:
            return other.value
        if type(other) == str:
            return int(other, 2)
        raise NotImplemented

    # 初期化

    def __init__(self, value):
        self.value = GF2.ToInt(value)

    # 変換

    def __int__(self): return self.value
    def __repr__(self): return bin(self.value)[2:]
    def __str__(self): return bin(self.value)[2:]

    # 比較

    def __eq__(self, other): return self.value == GF2.ToInt(other)
    def __lt__(self, other): raise NotImplemented
    def __le__(self, other): raise NotImplemented

    # 単項演算

    def __neg__(self): return GF2(self)
    def __pos__(self): return GF2(self)
    def __invert__(self): return GF2(self)

    # 二項演算：算術

    def __add__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __sub__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __mul__(self, other): return GF2(self.mul(other))
    def __pow__(self, other): return GF2(self.pow(other))
    def __divmod__(self, other): return tuple([GF2(v) for v in self.divmod(other)])
    def __truediv__(self, other): return GF2(self.div(other))
    def __floordiv__(self, other): return GF2(self.div(other))
    def __mod__(self, other): return GF2(self.mod(other))

    # 二項演算：論理

    def __and__(self, other): return GF2(self.value & GF2.ToInt(other))
    def __xor__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __or__(self, other): return GF2(self.value | GF2.ToInt(other))

    def __lshift__(self, other): return GF2(self.value << GF2.ToInt(other))
    def __rshift__(self, other): return GF2(self.value << GF2.ToInt(other))

    # 二項演算：右項

    def __radd__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __rsub__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __rmul__(self, other): return GF2(other) * self
    def __rmod__(self, other): return GF2(other) % self
    def __rtruediv__(self, other): return GF2(other) / self
    def __rfloordiv__(self, other): return GF2(other) // self
    def __rpow__(self, other): return GF2(other) ** self

    def __rand__(self, other): return GF2(self.value & GF2.ToInt(other))
    def __rxor__(self, other): return GF2(self.value ^ GF2.ToInt(other))
    def __ror__(self, other): return GF2(self.value | GF2.ToInt(other))

    def __rlshift__(self, other): return GF2(GF2.ToInt(other) << self.value)
    def __rrshift__(self, other): return GF2(GF2.ToInt(other) << self.value)

    # 二項演算：更新

    def __iadd__(self, other):
        self.value ^= GF2.ToInt(other)
        return self

    def __isub__(self, other):
        self.value ^= GF2.ToInt(other)
        return self

    def __imul__(self, other):
        self.value = self.mul(other)
        return self

    def __itruediv__(self, other):
        self.value = self.div(other)
        return self

    def __imod__(self, other):
        self.value = self.mod(other)
        return self

    # 組み込み

    def __abs__(self): return GF2(self)
    def __ceil__(self): return GF2(self)
    def __floor__(self): return GF2(self)
    def __round__(self): return GF2(self)
    def __trunc__(self): return GF2(self)

    # 積

    def mul(self, other):
        a = self.value
        b = GF2.ToInt(other)
        r = 0
        while b != 0:
            if (b & 1) != 0:
                r ^= a
            a <<= 1
            b >>= 1
        return r

    # 商

    def divmod(self, other):
        a = self.value
        b = GF2.ToInt(other)
        alen = a.bit_length()
        blen = b.bit_length()
        rlen = alen - blen
        if rlen < 0:
            return (0, a)
        b <<= rlen
        c = (1 << (alen - 1))
        r = 0
        for n in range(rlen + 1):
            r <<= 1
            if (a & c) != 0:
                a ^= b
                r |= 1
            b >>= 1
            c >>= 1
        return (r, a)

    def div(self, other):
        return self.divmod(other)[0]

    def mod(self, other):
        return self.divmod(other)[1]

    # 冪

    def pow(self, other):
        a = self.value
        b = GF2.ToInt(other)
        r = GF2(a)
        for n in range(b - 1):
            r *= a
        return r
```

```python:テスト
>>> a = GF2(0b100011101)
>>> print(a + a)
0
>>> print(a - a)
0
>>> print(a * a)
10000000101010001
>>> print(a / a)
1
>>> print(a // a)
1
>>> print(a % a)
0
>>> print(a ** 2)
10000000101010001
>>> 
>>> print(0 + a)
100011101
>>> print(0b11101 - a)
100000000
>>> print(0b11101 * a)
1110001010001
>>> print(0b11101 / a)
0
>>> print(0b11101 // a)
0
>>> print(0b11101 % a)
11101
>>> print(0b1100011101 / a)
11
>>> print(0b1100011101 % a)
111010
```