现充|junyu33

Rathee 三部曲:CrypTFlow2,SIRNN 与 SecFloat

Background

Notation: 记安全参数为 λ, 秘密共享的整数长度为 l-bit.

MPC 方面,假设我们拥有以下基础知识:

在浮点数储存方面,我们使用 IEEE 754 Float32(单精度标准):

IEEE 754 加法

不失一般性,设 x≥y,为了计算 z=x+y,其中:

x=(−1)Sx⋅(1.Mx)⋅2Ex,y=(−1)Sy⋅(1.My)⋅2Ey

则步骤如下:

  1. 指数对齐。若 Ex > Ey,将 y 的尾数右移: My←1.My2Ex−Ey,E←Ex,Mx←(1.Mx).
  2. 尾数相加。考虑Sx,Sy的符号情况。若同号,则计算 M=Mx+My。若异号,则用大者减小者得到差的绝对值M=|Mx−My|,并附上正确的符号S。
  3. 规范化。显然 max{Mx+My,|Mx−My|}<4,故M右移最多只需一次(对应指数E加1即可)。若 M=0,则直接跳到第四步。其余情况反复左移并自减E,直到M∈[1,2) 时停止。
  4. 写入结果。最后将 M 的首位 1 剔除,将最后的 S,E,M 重新作为新的 32 位浮点结果。
  5. 在 My←1.My2Ex−Ey、M=Mx+My、M=|Mx−My|以及对M右移一位这四个步骤中,会涉及到舍入问题。

IEEE 754 乘法

乘法由于不涉及数的大小比较,因此步骤相对比较简单。

  1. 符号位异或。S=Sx⊕Sy.
  2. 指数相加。E=Ex+Ey−bias.
  3. 尾数相乘。M=(1.Mx)⋅(1.My),结果在 [1,4) 范围内。
  4. 规范化。如果结果 ≥2,将 E 自增并将 M 右移一位,最后剔除 M 最高位的 1.
  5. 在 M=(1.Mx)⋅(1.My) 与 M 右移一位这两步涉及到舍入操作。

舍入方法

我们令 d,g,f 分别为 M 的最低位(decision bit),被丢弃的最高位(guard bit)和被丢弃的剩余位(sticky bit)。则“四舍六入五成双”的规则可以形式化表述为如下公式:

c=g∧(d∨f)

简单的解释一下,就是只有当 g=1 时才可能进位。此时如果 f=1(肯定大于0.5)或者 d=1(刚好0.5但要是偶数),则进位(c=1)。

注意舍入之后有可能需要再次规范化。

Building Blocks

下面用自底向上的方式,讲清楚整个协议是如何构建的。

FMUX

我们需要实现的理想功能是,MUX(b,x)=(b==1?x:0)。即对于布尔 secret share [c]=(c0,c1),ci∈{0,1} 和算术 secret share [a]=(a0,a1),a∈Zn,输出 [a⋅c]。步骤如下:

SETUP: P0 持有 a0,c0,P1 持有 a1,c1。

我们列举出四种可能的 (c0,c1) 情况:

(s0,s1)=(−r0+c0a0,−r0+a0(1−c0)),(t0,t1)=(−r1+c1a1,−r1+a1(1−c1))

x0=tc0,x1=sc1

c0 c1 x0 x1 (r0+r1)+(x0+x1)
0 0 −r1+c1a1 −r0+c0a0 0
0 1 −r1+c1a1 −r0+a0(1−c0) a
1 0 −r1+a1(1−c1) −r0+c0a0 a
1 1 −r1+a1(1−c1) −r0+a0(1−c0) 0

结果刚好等于 [a⋅c],因此协议正确。

通信量为两轮 IKNP-OT 的开销,也就是 2(λ+2l)=2λ+4l。但 CryptoFlow2 的 3.1.1 节可以将通信开销优化到 2λ+2l。

FAND

这是显然的,直接使用 beaver triple 实现,通信量为 (λ+16)+4。(见 CryptoFlow2 的附录 A1 节)

FOR

我们有 [x∨y]=[x⊕y]⊕[x∧y]。因此令 [x∧y]=(z0,z1),因此每一方直接计算 xi⊕yi⊕zi 即可。通信量与 FAND 相同,也为 λ+20。

FEQ

我们将 x,y 按照 m-bit 进行分块。考虑对某个块 xj,yj 进行比较。我们使用 1-out-of-2m OT:

我们可以通过树状结构与 FAND,计算 (eq1,j)i=(eq0,j)i∧(eq0,j+m)i,将 m-bit 比较拓展到 2m-bit,最后完成整个长度的比较。通信量为 ⌈lm⌉(2λ+2m)+⌈lm⌉(λ+20),轮数为 log⁡l.

FGT/LT

仍然是分块的思路,首先计算块长度为 m 的结果 1{xj<yj},还是可以使用 1-out-of-2m OT 完成。P0 只需随机生成 (lt0,j)0, 并准备 2m 个消息 tj,k=(lt0,j)0⊕1{xj<k}.

然后合并的时候高位优先,1{x<y}=1{xH<yH}⊕(1{xH=yH}∧1{xL<yL}).

通信成本小于 λ(4q)+2m(2q)+22q,取 m=4,q=l/4 时为 λl+13.5l ,轮数 log⁡l.

FLUT

假设 LUT 有 2m 项,每一项有 n-bit.

SETUP: P0 随机取索引 r∈{0,1}m,和 LUT L 混淆后的 share T0[i]∈Z2n,∀i∈{0,1}m.

FWrap

如果我们要计算 1{a+b>2n−1},这等同于计算 1{2n−1−a<b}。因此直接使用 FGT/LT 即可。

FB2A

P0,P1 分别持有布尔共享的一位 c=c0⊕c1,c∈{0,1},并最后得到 d=d0+d1(mod2n) 且 d=c。

验证一下结果,d0+d1=c0+c1−2(y0+y1)。

通信开销为一次 1-out-of-2 COTn,成本为 λ+n.

FZExt

我们有了前面的 FWrap 和 FB2A,构造 FZExt 便是自然的事情。对于 m-bit 的加法共享,我们尝试将其零扩展到 n-bit (n>m)。首先,我们要 check 这两个 share 是否有进位(使用 FWrap),然后将得到的布尔进位 w 使用 FB2A 转为 Z2n−m 的算术值。

但我们只是做零扩展操作,两个 share 相加,不能在第 m 位产生进位,因此双方要在 Z2n 减掉一个 2m 的 share,由于 m 公开,可以直接本地完成。

成本为 Comm(FWrap+FB2A)=λm+14m+λ+(n−m)=λ(m+1)+13m+n.

FTR

既然我们有了从小到大的 FZExt,那自然也有反过来的 FTR。我们假设从 l-bit 截断低位的 s-bit,并输出最终的高位 l−s-bit(这本质上也等同于 x >> s):

SETUP: Pb 将原来的 share xb 拆成 ub||vb,前者为 l−s 位,后者为 s 位,可以证明:

TR(x,s)=u0+u1+Wrap(v0,v1,s)

开销为 Comm(FWrap+FB2A)=(λs+14s)+(λ+(l−s))=λ(s+1)+13s+l.

FCrossTerm

FCrossTerm 与用 beaver triple 的安全乘法比较相近,但区别是后者 P0 和 P1 都知道 x 和 y 的一部分 share。而 FCrossTerm 的适用条件是 P0 独占 x,P1 独占 y,最后各自获得长度 l=m+n 的 x∗y 的 share.

总通信成本为 ∑i=0m−1(λ+(l−i))=mλ+ml−m(m−1)2=O(mλ+mn).

FUMult

语义是双方持有 x=x0+x1(mod2m),y=y0+y1(mod2n),目标是计算 z=x⋅y∈Z2m+n.

这里还是不能直接做 beaver triple,因为它是 ring agnostic 的,可能会带来未知的 wrap 问题。当然一个办法是将 x,y 都扩展到足够大的环,做安全乘法后又截断回去。当然这里有两个问题,一是 FTR 是高位截断而不是低位截断,协议需要稍微改一改;二是这种办法运算成本较高,不如接下来介绍的专用 FUMult 协议。

我们现在要计算(x0+x1)(y0+y1)=x0y0+x1y1+x0y1+x1y0,前两者可以分别由 P0,P1 离线完成。而后两者就涉及到刚才的 FCrossTerm 了。总之,我们有了在 P0 存储的完整 x0y0,P1 存储的 x1y1,以及双方都拥有的 ⟨x0y1⟩,⟨x1y0⟩ 的一部分。FUMult 的作用就是把这 4 项安全地拼起来,并且处理 wrap 的问题。

尝试把两个 share 加起来看看:∑b(xbyb+⟨x0y1⟩b+⟨x1y0⟩)=(x0+x1)(y0+y1)

而 ∑b(−2n⟨g⟩b−2m⟨h⟩b)=−2ng−2mh=−2n(wy⋅x)−2m(wx⋅y)

合在一起,z=(x0+x1)(y0+y1)−wy⋅(x⋅2n)−wx⋅(y⋅2m)

=(x+wx2m)(y+wy2n)−wy⋅(x⋅2n)−wx⋅(y⋅2m)=xy,刚好抵消。

设ν=max(m,n),l=m+n,论文给出了具体的开销,数量级为 O(λν+ν2)。相比于 beaver triple 做法(含生成乘法三元组)的 O(λl+l2) 数量级相同,但论文声称 FUMult 通信少 1.5×.

FSMult 与 FUMult 原理类似,通信量完全相同,这里就略过了。

FDigDec

作用是将一个 l-bit 的 share ⟨x⟩,按 d-bit 分块,拆分成 c=⌈ld⌉ 个 {⟨zi⟩}i=0c−1,其中 x=zc−1||zc−2||⋯||z0. 显然,本地进行这个操作会导致 wrap 问题。

当然解决这个问题的思路也容易想到,首先使用 Fwrap 判断 ⟨x[0,d−1]⟩ 的两个 share 是否溢出,并得到溢出结果的 share ⟨c0⟩,令 ⟨z0⟩=⟨x[0,d−1]⟩−2d⟨c0⟩,并将目前双方的高位 ⟨x[d,l−1]⟩ 加上 ⟨c0⟩,最后递归执行这一过程即可。

复杂度相当于 (c−1) 次 Fwrap 的成本,也就是 (c−1)(λd+14d).

FMSNZB−P

检测第 i 个 d-bit 分块中最高非零位对应的全局 index,也可以理解成 ⌊log2⁡(zi)⌋+i⋅d,这里的具体实现方法是直接 FLUT 解决。但有一个问题是当 zi=0 时右边这个式子与左边实现的语义并不相同,作者这里选择让 zi=0 的结果未定义,交给上层协议来解决。

这一点我不是很理解,zi=0 的情况也可以在 FLUT 的情况直接解决啊,又不会增加通信成本。

总之,通信量等价于一个 1-out-of-2d OT⌈log2⁡l⌉ 实现,因此通信量为 2λ+2d⌈log2⁡l⌉.

FZeros,FOneHot

前者的意思是判断一个长度为 d 的向量(或者 d-bit 数)是否为零。而后者是将一个 ⟨k⟩∈[0,l−1] 的 share,转化为一个长度为 l 的向量 share,满足和为 (0,0,⋯,1,⋯,0),其中仅有第 k 个向量为 1.

这两个分别可以用 1-out-of-2d OT 和 1-out-of-l OTl 实现,成本分别为 2λ+2d 和 2λ+l2。虽然后者成本较高,但只在父协议 FMSNZB 的最后调用一次,因此总成本还能接受。

FMSNZB

含义是给定一个输入 ⟨x⟩l,计算出 l 的最高零位的值 k,输出向量 share 满足和为 (0,0,⋯,1,⋯,0),其中仅有第 k 个向量为 1。 为了简单起见,这里我假设 FMSNZB−P 是定义良好的(也就是处理了 zi=0 的情况)。令 ι=⌈log2⁡l⌉:

总结

原语 依赖的原语 功能 通信开销
FMUX (21)−OTl 长度l位的三目运算符 2λ+2l
FOR FAND, i.e. beaver triple 逻辑或 λ+20
FEQ (2m1)−OT,FAND 长度l位的算术相等 <34λl+9l
FLT/GT (2m1)−OT,FAND 长度l位的算术比较 <λl+14l
FLUT (2m1)−OTn 长度m位,结果 n 位的查找表 2λ+2mn
FZExt FWrap,FB2A m 位零扩展到 n 位 λ(m+1)+13m+n
FTR FWrap,FB2A l 位截取高 l−s 位 λ(s+1)+l+13s
FUMult,FSMult FCrossTerm,FWrap,FMUX 长度m,n位的无/有符号乘 O(λl+l2)
FMSNZB FDigDec,FMSNZB−P,FOneHot等 长度l位的最高非零位index ≤λ(5l−4)+l2

Primitives

我们终于构建了 secfloat 论文对应的所有基础协议,现在我们转入本篇论文构造的重要原语。

FFPcheckp,q

用来检查浮点数在浮点参数为 p,q(IEEE754 默认 p=8,q=23)的情况下是否上溢或者下溢。这是本文的一个创新点,就是可以自己选取浮点参数,不一定遵照 IEEE754 的格式。

α = (z, s, e, m)
if 1{e > 2^{p-1} - 1} then
   m = 2^q; e = 2^{p-1}
if 1{z = 1} ∨ 1{e < 2 - 2^{p-1}} then
   m = 0; e = 1 - 2^{p-1}; z = 1
Return (z, s, e, m)

这个逻辑符合论文对溢出的处理方式,这里大概描述一下协议是怎么跑的:

FTRSl,s

FTRS 在 FTR 的基础上,增加了对浮点数粘滞位 S 的进位判定。当被舍去的低 s 位只要有任意一位为 1,且 LSB(x)=0,则执行进位操作。其功能等同于 (x >> s) | (x & (2**s - 1) != 0)。右移还是用 FTR 搞定(或者说是结合 FWrap 与 FB2A),但之后还要做一个 FZeros 的操作,成本较高。

由于 FZeros 也等价于判断两个 share 的和是否为 2s,或者两者都为0,因此其本质也是比较操作(或者 FWrap 操作)。因此作者选择将 FWrap 和 FZeros 捆绑实现成 FWrap&All0s,成本仅仅相当于一个比较操作和一个 FAND 的成本(这里论文有 typo,不是两个 FAND 的成本)。

FRNTEl

FRNTE 等价于带舍入的右移 x≫Rr。在前文中我们讲过 IEEE 的舍入逻辑如下:

c=g∧(d∨f)

我们首先用 TRS(x, r-2) 确认 f 后面的位是否为 1,如果是就加回来以确保粘滞位判定逻辑正确。此时 x 的后三位就分别是d,g,f。然后用 FLUT 将这个 8-bit 的舍入逻辑硬编码到结果 c 中。最后再调用 TR(x, 2) 并加上舍入结果 c 即可。

FRound∗p,q,Q

给出浮点数 α=(z,s,e,m) 中的 (e,m),将已规格化的尾数 m 从 Q 位精度舍入到 q 位精度,并处理舍入导致的进位溢出。注意这里 m 采用了定点数形式,也就是尾数 1.M 对应定点数 m=(1.M)×2Q。因此 m 的取值范围是 [2Q,2Q+1)。协议逻辑如下所示:

if 1{m >= 2^{Q+1} − 2^{Q−q−1}} then
   Return (e+1, 2^q)
else
   Return (e, m >>R (Q−q))

以下对该代码逻辑的正确性进行说明。尾数分为两种情况:

FFPAddp,q

在前置知识一节,我们已经概括了普通浮点加法的办法。下面我们将该方法与伪代码对应:

  1. 指数对齐。若 Ex > Ey,将 x 的尾数左移: Mx←(1.Mx)2Ex−Ey,E←Ey.
  1. 尾数相加。考虑Sx,Sy的符号情况。若同号,则计算 M=Mx+My。若异号,则用大者减小者得到差的绝对值M=|Mx−My|,并附上正确的符号S。

这里考虑同号与异号的情况。同号时,β1 与 β2 的符号位异或为 0,否则为 1。因此当 β1.s⊕β2.s=1 时,将 m2 变号完成相减操作。

  1. 规范化。这里我们找到加法结果 m 中最高有效位,为了保证有足够的空间舍入,协议在第一步时将精度为 q 的 m1,m2 零扩展为 2q+2 位(但注意精度是 2q+1)。假设 MSNZB 的结果为 k,要将高位的1规范化(也就是对齐后面 Round* 协议的 2q+1 位)需要左移 2q+1−k 位,对应乘 K=22q+1−k。

至于指数位的计算,由于先左移了 2q+1−k 位,同时又因为精度变化又增加 q+1,因此 e=e−(2q+1−k)+(q+1)=e+k−q。

  1. 写入结果。最后做一轮 FRound∗p,q,2q+1 的舍入,由于 |m1|>|m2|,符号位一定由 β1.s 决定。最后检查规范化的结果是否在浮点数有效范围内。

FFPMulp,q

  1. 符号位异或。S=Sx⊕Sy.(第7行)
  2. 指数相加。E=Ex+Ey−bias.(第1行,论文这里令 bias=0)
  3. 尾数相乘。M=Mx⋅My,结果在 [22q,22q+2) 范围内。(第2行)
  4. 规范化。如果结果 ≥22q+1,将 E 自增并将 M 右移一位,最后剔除 M 最高位的 1.

结果 ≥22q+1 走第 6 行 else 分支,否则走第四行 if 分支。

  1. 在 M=Mx⋅My 与 M 右移一位这两步涉及到舍入操作。(也就是第4、6行的 FRNTEl)

Math Functions

在《学数学,就这么简单》这本书中,有这样一个桥段:

FFPsin⁡π8,23

基于这样的思路,我们实际上可以细化出计算机是如何计算 sin⁡x 的。

  1. 首先利用三角函数诱导公式,将 x 的范围缩减到 [0,π/2]. (Range reduction)

这是论文的做法,但实际上舍入到 [−π/4,π/4] 再利用二倍角公式,误差会小一个数量级。

  1. 使用泰勒展开进行近似,例如 sin⁡x≈x−16x3+1120x5. (Polynomial Evaluation)
  2. 使用秦九韶算法 x−16x3+1120x5=((1120x2−16)x2+1)x,减少乘法次数并降低误差。

这些运算就只需要浮点加法和乘法可以搞定,至于多项式的系数由于相对固定,可以通过查表解决。

我们现在对应到具体的原语 FFPsin⁡π8,23 上,也就是计算 sin⁡πx。步骤如下:

  1. 首先处理特殊情况:当 |x|>223 时,由于 q=23,超过了尾数的精度,因此 x 一定是整数。sin⁡πx=0。另一种特殊情况是当 |x|<2−14 时,sin⁡πx≈πx,其误差在 x 本身浮点表示的误差以内。
  1. range reduction 步骤:目的是从输入 α 算出奇偶位 a∈{0,1} 以及区间 δ。令 |α|=2K+a+n,若 n<0.5,则 δ=n,否则 δ=1−n。故 sin⁡πα=(−1)a⊕1{α<0}sin⁡πδ.
m = α.m * 2^{α.e + 14}
a = TR(m, q+14); n = m mod 2^{q+14}

将 α 变成一个整数。由于 |α|=2α.e⋅α.m2q,故 m=α.m⋅2α.e+14≈|α|⋅2q+14. 则 a 为 |α| 的整数部分, n 为 |α| 的小数部分。

f = (n > 2^{q+13} ? 2^{q+14} - n : n)
k,K = MSNZB(f); f = f * K
z = 1{f=0}; e = (z ? -2^{p-1}+1 : k - q - 14)

第一行保证 f=δ⋅2q+14。第二行找到 f 的最高有效位,从而将 f 规范化,并在第三行设定正确的指数位 e。

当 f=0 时,sin⁡πα=0。将零位 z 设为 1,并按照论文约定将指数位 e 设为 −2p−1+1.

δ = (z, 0, e, TR(f, q+14−Q))

最后重新将定点数 f 以 Q 位精度存储,与其他参数合并成浮点数 δ。

  1. polynomial evaluation 步骤,注意论文使用了 Remez 等精度更高的逼近方法,而不是泰勒展开:
if 1{δ.e < −14} then
   µ = Float_{p,Q}(π) ⊗_{p,Q} δ

先前 |δ|≤2−14 时的特殊情况,sin⁡πx≈πx.

if 1{δ.e < −5} then
   idx1 = δ.e + 14 mod 2^4
   (θ1, θ3, θ5) = GetC_{4,9,5,p,Q}(idx1, Θ1_sin, K1_sin)

考虑 2−14<|δ|<2−5 时的情况,这里 GetC 函数提供了一个查表操作,通过选取 K1_sin 这一常数类,在 Θ1_sin 这个表中,通过 index idx1(也就是 δ.e+14 的低4位)获取对应的参数 (θ1, θ3, θ5)。

4 是表的 bit 数,9 是 spline(系数对)的个数,5 是拟合的多项式的次数。

idx2 = 32 · (δ.e + 5 mod 27)
idx2 = idx2 + ZXt(TR(δ.m, Q−5) mod 32, 7)
idx2 = 1{δ.e = −1} ? 127 : idx2
(θ1, θ3, θ5) = GetC_{7,34,5,p,Q}(idx2, Θ2_sin, K2_sin)

在 2−5≤|δ|<0.5 这个区间,用δ.e + 5的低2位和δ.m的高5位进行查表的区分(这是论文的第二个创新点:分段索引),来调用对应误差最小的 (θ1, θ3, θ5)。对 |δ|=0.5 的区间,进行特判。

  1. 使用秦九韶算法求出对应的浮点值:
Δ = δ ⊗_{p,Q} δ
µ = ((θ5 ⊗ Δ) ⊞* θ3) ⊗ Δ
µ = (µ ⊞* θ1) ⊗ δ
Return (µ.z, a ⊕ α.s, Round*(µ.e,µ.m))

Δ=δ2

μ=(θ5Δ+θ3)Δ=θ5δ4+θ3δ2

μ=(μ+θ1)δ=θ5δ5+θ3δ3+θ1δ≈sin⁡πδ

前文说过:sin⁡πα=(−1)a⊕1{α<0}sin⁡πδ,故 a ⊕ α.s 确定符号位,最后舍入即可得到最终结果。

大概总结一下,FFPsin⁡π8,23 先对输入做范围归约,把问题化到0到0.5的小区间并记录符号补偿;对极大或极小输入走快速分支。随后按指数和尾数位确定分段,用查表选出对应多项式系数,采用秦九韶算法计算近似值,最后做符号恢复并舍入到单精度输出。

这个方法一个潜在的缺点是,这个 GetC 函数用的表是 ad-hoc 的,与前面浮点四则运算的协议不同,如果想要任意指定p,q,或者迁移到 SecDouble,这个系数表需要进行重新计算才能使得误差小于 1ULP。论文为了追求性能与准确度,牺牲了算法的灵活性。

FFPlog28,23

令 α=m⋅2N,m∈[1,2),N=α.e,令 a=1{N=−1},则分为两种情况:

log2⁡(α)={N+log2⁡(1+δ)a=0,log2⁡(1−δ′)a=1.

然后,分别按照 a=0 与 a=1 构造两组近似多项式 (θ0a,θ1a,θ2a,θ3a),(θ0b,θ1b,θ2b,θ3b),还是按照分段索引法对指定范围的 δ.e 与 δ.m 进行查表。

然后通过秦九韶算法(Horner's method)计算出 log2⁡(1+⋅) 的值。对于最后加 N 的计算,首先通过查表方式将 N 转化为浮点数,再调用 FFPAddp,q 协议即可。

  1. range reduction 步骤:
a = 1{N = −1}
f = a ? (2^{q+1} − α.m) : (α.m − 2^q)
k,K = MSNZB(f); f = f *_{q+1} K
e = a ? (k − q − 1) : (k − q)

当 N=−1 时(此时 a=1),f=1−m/2,否则(此时 a=0)f=m−1,并将 f 规范化。

z = 1{f = 0}; e = (z ? −2^{p−1}+1 : e); 
N = α.e; δ = (z,0,e, f *_{Q+1} 2^{Q−q})

通过 f 构造出浮点数 δ,并将精度从 q=23 位提高到 Q=27 位,为后文 evaluation 准备。

  1. polynomial evaluation 步骤
if 1{δ.z} then
   µ = Float_{p,Q}(0)

当 δ=0 时,log2⁡(1+⋅)=log2⁡1=0,故返回 μ=0。

if 1{δ.e < −5} then
   idx1 = (δ.e + 24) mod 2^5
   (θa0,θa1,θa2,θa3) = GetC_{5,19,4,p,Q}(idx1, Θ1_log, K1_log)
   (θb0,θb1,θb2,θb3) = GetC_{5,18,4,p,Q}(idx1, Θ3_log, K3_log)

当 2−24≤δ<2−5 时,使用 δ.e + 24 的低5位作为 index,对 a=1 的情况查表 Θ1_log,对 a=0 的情况查表 Θ3_log,这里为了避免数据依赖必须两个都做。

else
   idx2 = 16 · (δ.e + 5 mod 2^7)
   idx2 = idx2 + ZXt(TR(δ.m, Q−4) mod 16, 7)
   (θa0,θa1,θa2,θa3) = GetC_{7,20,4,p,Q}(idx2, Θ2_log, K2_log)
   (θb0,θb1,θb2,θb3) = GetC_{7,32,4,p,Q}(idx2, Θ4_log, K4_log)

当 2−5≤δ<1 时,使用 δ.e + 5 的低3位与 δ.m 的高4位作为 index,对 a=1 的情况查表 Θ2_log,对 a=0 的情况查表 Θ4_log。

(θ0,θ1,θ2,θ3) = a ? (θa0,θa1,θa2,θa3) : (θb0,θb1,θb2,θb3)

根据前文对 a 值的分类讨论,选择最终的多项式系数。

  1. 秦九韶算法(Horner)步骤及最后加N
µ = ((θ3 ⊗ δ) ⊞* θ2) ⊗ δ
µ = ((µ ⊞* θ1) ⊗ δ) ⊞* θ0

计算出三次多项式 μ=θ3δ3+θ2δ2+θ1δ+θ0=log2⁡(1+⋅) 的值。

β = LInt2Float(N)
β′ = (β.z,β.s,β.e, β.m *_{Q+1} 2^{Q-6})

将 N 使用小 LUT,将 N 转化为低精度(尾数为6位)的浮点形式 β,再转化为高精度 Q 的形式 β′。

γ = a ? µ : (µ ⊞* β′)
Return (γ.z, γ.s, Round*(γ.e, γ.m))

最后执行浮点加法:

最终对 γ 舍入得到协议结果。