这是按照从低到高排列的快速约减矩阵
|===|===|===|===|===|===|===|===|
|c00|c01|c02|c03|c04|c05|c06|c07|
|===|===|===|===|===|===|===|===|
|a00|a01|a02|a03|a04|a05|a06|a07|(=)
|---|---|---|---|---|---|---|---|
| | | |a11|a12|a13|a14|a15|(+)
| | | |a11|a12|a13|a14|a15|(+)
|---|---|---|---|---|---|---|---|
| | | |a12|a13|a14|a15| |(+)
| | | |a12|a13|a14|a15| |(+)
|---|---|---|---|---|---|---|---|
|a08|a09|a10| | | |a14|a15|(+)
|a09|a10|a11|a13|a14|a15|a13|a08|(+)
|---|---|---|---|---|---|---|---|
|a11|a12|a13| | | |a08|a10|(-)
|a12|a13|a14|a15| | |a09|a11|(-)
|a13|a14|a15|a08|a09|a10| |a12|(-)
|a14|a15| |a09|a10|a11| |a13|(-)
|===|===|===|===|===|===|===|===|
说老实话,虽然最先接触的素域椭圆曲线就是这个,但是最先产生代码的反而是国密SM2的快速约减算法,原因无它,太不顺眼了,最初是想按照NIST建议的方式按行进行加减运算,没想到写起代码来要多别扭有多别扭,直到有一天接触到FPGA编程才发现这个算法实现方案根本就不是给通用x64处理器用的,它最适合的硬件是具备36位加法器的DSP或是直接搭建260位加法器的FPGA,要在通用x64处理器上实现,做一点等效变换是必要的。
构造如下6个组合数值,其值分别为:
K00 = a11 + a12 + a13
K01 = a12 + a13 + a14
K02 = a13 + a14 + a15
N00 = a08 + a09
N01 = a09 + a10
N02 = a10 + a11
用这6个组合数值再加上a14和a15这两个独立32位数值,重构快速约减矩阵如下:
|===|===|===|===|===|===|===|===|
|c00|c01|c02|c03|c04|c05|c06|c07|
|===|===|===|===|===|===|===|===|
|a00|a01|a02|a03|a04|a05|a06|a07|(=)
|---|---|---|---|---|---|---|---|
| | | |K00|K01|K02|a14|a15|(+)
| | | |K00|K01|K02|a14|a15|(+)
| | | |a14| | | |a15|(+)
|N00|N01|N02| | | |K02|N00|(+)
| | | | | | | |a15|(+)
|---|---|---|---|---|---|---|---|
|K00|K01|K02|K02|a14|a15|N00|N01|(-)
|a14|a15| |N00|N01|N02| |K00|(-)
|===|===|===|===|===|===|===|===|
总算顺眼了。顺便安排8个64位通用寄存器来存储这些数值:
r15 = a15
r14 = a14
r13 = a13 + a14 + a15
r12 = a12 + a13 + a14
r11 = a11 + a12 + a13
r10 = a10 + a11
r9 = a09 + a10
r8 = a08 + a09
从而得到最终的寄存器缓存数值优化方案,如果完全不考虑优化问题,其寄存器缓存数值本该如下:
r15 = a15
r14 = a14
r13 = a13
r12 = a12
r11 = a11
r10 = a10
r9 = a09
r8 = a08
由x64加法器的特性可知,即使是无优化的按列运算方案,也是优于按行运算方案的,这和384位NIST素域椭圆曲线快速约减算法的实现完全不同,后者按列运算是无论怎么优化也比不了按行运算快捷的,顺带猜测国密SM2素域椭圆曲线参数的设计者应该是主攻DSP和ASIC解决方案的,那个在通用x64处理器上也是按列运算胜出。