39. 実装例(F#)
• ビット順序を反転する関数を定義
let rev (v:uint32) =
let mutable ret = 0u
for i = 0 to 31 do
if v &&& (1u <<< i) <> 0u then
ret <- ret ||| (1u <<< (31 - i))
ret
printfn "%x" (rev 1u) // 80000000
• 破壊的代入に突っ込まないでください・・・
40. 実装例(F#)
• データが1バイトの場合
let crc32_1 (b:byte) =
let b' = uint32 b
let mutable 被除数 = uint64(~~~(rev b')) <<< 8
let 除数 = 0x104c11db7UL
let 最上位 = 0x100000000UL
for i = 7 downto 0 do
if 被除数 &&& (最上位 <<< i) <> 0UL then
被除数 <- 被除数 ^^^ (除数 <<< i)
rev(~~~(uint32 被除数))
printf "%x" (crc32_1(byte 'a'))
// e8b7be43
41. 実装例(F#)
• データが4バイトの場合
let crc32_4 (buf:byte[]) =
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = uint64(~~~(rev buf')) <<< 32
let 除数 = 0x104c11db7UL
let 最上位 = 0x100000000UL
for i = 31 downto 0 do
if 被除数 &&& (最上位 <<< i) <> 0UL then
被除数 <- 被除数 ^^^ (除数 <<< i)
rev(~~~(uint32 被除数))
let bytes = Encoding.ASCII.GetBytes "abcd"
printf "%x" (crc32_4 bytes)
// ed82cd11
49. 実装例(F#)
let crc32_4 (buf:byte[]) =
除数が33bit
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = uint64(~~~(rev buf'))
let 除数 = 0x104c11db7UL
let 最上位 = 0x100000000UL
for i = 0 to 31 do
被除数 <- (if 被除数 &&& 最上位 = 0UL
then 被除数 else (被除数 ^^^ 除数)) <<< 1
rev(~~~(uint32 被除数))
let crc32_4 (buf:byte[]) =
計算を32bit化
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = ~~~(rev buf')
let 除数 = 0x04c11db7u // Wikipediaに出てきた値(標準)
let 最上位 = 0x80000000u
for i = 0 to 31 do
let 被除数' = 被除数 <<< 1
被除数 <- if 被除数 &&& 最上位 = 0u
then 被除数' else 被除数' ^^^ 除数
rev(~~~被除数)
52. 実装例(F#)
let crc32_4 (buf:byte[]) =
標準
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = ~~~(rev buf')
let 除数 = 0x04c11db7u // Wikipediaに出てきた値(標準)
let 最上位 = 0x80000000u
for i = 0 to 31 do
let 被除数' = 被除数 <<< 1
被除数 <- if 被除数 &&& 最上位 = 0u
then 被除数' else 被除数' ^^^ 除数
rev(~~~被除数)
let crc32_4 (buf:byte[]) =
反転
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = ~~~buf'
let 除数 = 0xedb88320u // Wikipediaに出てきた値(反転)
for i = 0 to 31 do
let 被除数' = 被除数 >>> 1
被除数 <- if 被除数 &&& 1u = 0u
then 被除数' else 被除数' ^^^ 除数
~~~被除数
57. 実装例(F#)
let crc32_4 (buf:byte[]) =
一気に用意
let buf' = BitConverter.ToUInt32(buf, 0)
let mutable 被除数 = ~~~buf'
let 除数 = 0xedb88320u
for i = 0 to 31 do
let 被除数' = 被除数 >>> 1
被除数 <- if 被除数 &&& 1u = 0u
then 被除数' else 被除数' ^^^ 除数
~~~被除数
let crc32 (buf:byte[]) =
逐次投入により任意長対応
let mutable 被除数 = ~~~0u
let 除数 = 0xedb88320u
for b in buf do
被除数 <- 被除数 ^^^ uint32(b)
for j = 0 to 7 do
let 被除数' = 被除数 >>> 1
被除数 <- if 被除数 &&& 1u = 0u
then 被除数' else 被除数' ^^^ 除数
~~~被除数
59. 実装例(F#)
let crc32_table =
[| for i in 0..255 ->
let mutable reg = uint32 i
for j = 0 to 7 do
let reg' = reg >>> 1
reg <- if reg &&& 1u = 0u
then reg' else reg' ^^^ 0xedb88320u
reg |]
let crc32 (buf:byte[]) =
let mutable reg = ~~~0u
for b in buf do
reg <- reg ^^^ (uint32 b)
let t = crc32_table.[int(reg) &&& 0xff]
reg <- (reg >>> 8) ^^^ t
~~~reg
• 大抵のサンプル実装は似たようなコード