0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-12-22

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

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

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
テスト
>>> 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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0