Numpy boolean & Python integer with 1<<62

Finding very unique setup in Python motivates me to write in Qiita.

注：この投稿はAkito D. Kawamura (@aDAVISk) の名前で、クリエイティブコモンズBYで公開しています。

Problem　問題

The critical code (Python 3.6) is the following:
これが問題のコード（Python 3.6）です:

bitshiftMagic.py
```import numpy as np
cc = np.array([True])
vv = 1 << 62
for ii in range(3):
vv = vv << 1 | cc[0]
print(bin(vv))
```

then I get the error message as
すると以下のようなエラーメッセージ出てきます。

Output1
```0b1000000000000000000000000000000000000000000000000000000000000001
Traceback (most recent call last):
File "bitshiftMagic.py", line 5 in <module>
vv = vv << 1 | cc[0]
TypeError: ufunc 'left_shift' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
```

Note the first line is a correct. It fails at the second time in the for loop.

Some trials いくつかの試行

If I set `cc = [True]` instead of line 2 then everything is fine.
2行目を`cc = [True]`とすると何ら問題なく動きます。

Output2
```0b1000000000000000000000000000000000000000000000000000000000000001
0b10000000000000000000000000000000000000000000000000000000000000011
0b100000000000000000000000000000000000000000000000000000000000000111
```

If I set `vv = 1 << 61` at line 3 then bit overflow is happening.
3行目を`vv = 1 << 61`とすると、ビットがオーバーフローします。

Output3
```0b100000000000000000000000000000000000000000000000000000000000001
-0b111111111111111111111111111111111111111111111111111111111111101
0b111
```

The problem can be solved with `vv = 1 << 63` at line 3.
この問題は、3行目を`vv = 1 << 63`とすれば回避できます。

Output4
```0b10000000000000000000000000000000000000000000000000000000000000001
0b100000000000000000000000000000000000000000000000000000000000000011
0b1000000000000000000000000000000000000000000000000000000000000000111
```

Solution 解決策

Here I give a sample code to store arbitrary length of random numpy boolean array into a stream of bits or an integer.

bitshiftMagic2.py
```import numpy as np
nn = 3 # try with a different number e.g. 70
arr = np.random.rand(nn) >= 0.5
vv = 1 << 63
for cc in arr:
vv = vv << 1 | cc
vv = vv & 2**nn-1
print(bin(vv))
```

Personal view 個人的見解

I think this problem is related to the type setting of Python, but I also confused in some detail. `vv` is set to 'int' at line 3 of bitshiftMagic.py with the highest number bit (for 2^62) 1, then left-shifted. Thus, the set bit is going to the sign bit, but it still gives a large positive number back (I'm confused here). The error is triggered at the second left-shift; I understand this time the bit is overflowed. But how about the other cases?

In case of `vv = 1 << 61`, `vv` is definitely a 64bit integer, and a bit-overflow is observed and then gives a small positive number. This is a textbook example of bit-overflow.

In case of `vv = 1 << 63`, `vv` is an integer of unlimited length. Hence, I can make numberless left-shift until RAM eaten up.

Overall, the key is the magic number `62`, where the integer is at a tip to overflow and will be left-shifted. Watch out at this border!

この問題の根幹はPythonの型設定にあるような気がしてますが、一部まだ理解できていない部分があります。bitshiftMagic.pyの3行目で`vv`は'int'で、その最も大きなビット（2の62乗のビット）に1が入ってます。そしてleft-shiftしますが、この時まだ大きな正の整数を返してきます（ここの理由がわからない）。2度目のleft-shiftでエラーが返りますが、これはbitがオーバーフローするのでまあ解ります。その他のケースも見てみます

`vv = 1 << 61`とした場合は、`vv`は明らかに64ビットの整数型です。ビットがオーバーフローして、そして小さな正の整数を返します。教科書通りのビットのオーバーフローです。

`vv = 1 << 63`とした場合は、`vv`は無限長の整数型になってます。よって、RAMを食い尽くすまでleft-shiftが出来ます。

まとめると、全ての問題は`62`というマジックナンバーにあるようです。整数型があふれんばかりになっていて、それをleft-shiftすると壊れると。この境界で作業される際にはご注意を！

See more　もっと詳しく

Please check my BitGraphics library at Git.
Gitの私のBitGraphicsライブラリーを参考にしてください。