Decomposition(a[X])
offset = 0 //各桁にBg/2を足すための定数をつくる
for i form 1 to l
offset += Bg / 2 * (1 << (32 - i * Bgbit))
for i form 0 to N-1
ãᵢ = aᵢ+offset //ここで繰り上がりがあるからoffsetをつくる
for i from 1 to l
for j from 0 to N-1
//2進でBgbit桁(最大Bg-1)を取り出してBg/2を引く
āᵢⱼ=((ãⱼ>>(32-Bgbit*i))&(Bg-1))-Bg/2 //&はbit演算のAND
return 𝐚̄[X]
offsetでうまく行くことの証明(方針)
offsetを桁の数だけ作らずにひとつだけでいいことは直感的でない
前提としてもし各桁を[0,Bg)の範囲で取るならmaskだけで良い
a^ij=((aᵢ>>(32−Bgbit∗i))&(Bg−1))としよう
a[X]からa^[X]を経由したaˉ[X]への変換を考える
これが結局前の疑似コードと一致することを示す
offsetでうまく行くことの証明(基本的アイデア)
a^ij={Bg+aˉijifa^ij≥2Bgaˉijotherwise
となるようにaˉijを決めることができる(要は桁上がりをしている)
offsetでうまく行くことの証明(疑似コード)
このアイデアをナイーブに実装した場合の疑似コードを示そう
Decompositionhat(a[X])
for i from 1 to l
for j from 0 to N-1
âᵢⱼ=((aⱼ>>(32-Bgbit*i))&(Bg-1))
for i from l to 1
for j from 0 to N-1
if âᵢⱼ ≥ Bg/2
āᵢⱼ = âᵢⱼ - Bg
â₍ᵢ₋₁₎ⱼ += 1
else
āᵢⱼ = âᵢⱼ
return 𝐚̄[X]
offsetでうまく行くことの証明(ちょっと最適化)
前のスライドのコードをbit演算でちょっと最適化すると以下のようになる
これを見るとBg/2を足してBg以上になったら上の桁に繰り上がっている
この繰り上がり処理を加算器に任せようと思うとoffsetになる
Decompositionhatopt(a[X])
for i from 1 to l
for j from 0 to N-1
âᵢⱼ=((aᵢ>>(32-Bgbit*i))&(Bg-1))
for i from l to 1
for j from 0 to N-1
temp = âᵢⱼ + Bg/2
â₍ᵢ₋₁₎ⱼ += temp>>Bgbit //temp > Bgなら1
āᵢⱼ = (temp & (Bg-1)) - Bg/2 //マスクからはみ出たところは上の桁に行っている
return 𝐚̄[X]