多精度里FNT和SSA的点滴

多精度里FNT和SSA的点滴.

Karatsuba,TOOM3,4.5...Toom-Cook
可以看成是插值算法的逐步扩展.

比如TOOM3,

对Q(x),x=取5个不同值,即可一矩阵(行列式)

通过解上面矩阵既可以得到A,B,C,D,E,即Q(x)多项式系数.

这个推广后即是Toom-Cook算法.

FFT则是Toom-Cook对取值的一个特化.

对于长度为N的FFT,其取值为复数域内N次方根,

就是一个范德蒙德(Vandermonde)矩阵.

其求解只需要nlogn就可以了.具体的解法随便一本关于傅里叶变换的书都会有介绍.

题外话:FFT还有一个特性就是变换后,频域和时域相互映射起来,这个在工程某些方面这个特性是很有用的.比如滤波,信号处理,数据压缩等等多个方面.有很大的作用(其他如余弦变换,小波变换也有类似的功能,但在有限域内这个特性一般都没有了),在高精度计算里,这个特性并没有用上.略过不表.

FNT,一般指代的是快速数论变换(也有人指FNT是指快速数论变换里面的费马变换,但是由于费马素数太少,实际的应用只存在特定领域),

这里基于代码简单化起见,特指是基2的快速数论变换,但要说明的是,FNT不仅仅包含基2的快速数论变换.

FNT实际只是FFT在有限域的一种表现形式.类比说就是FFT其插值是取复数域内的N次方根,FNT其插值是取某个剩余系内的N次方根.其余的运算和FFT基本一致.

FNT额外的好处就是由于在有限域下计算,只要数据不产生溢出,里面的精度是不会丢失的.这个要比FFT要好.

FNT里面的相关参数主要有M,N,α(或记作r),M为模,N为变换长度, α(r)为N次方根(MOD M下),只要选取的M存在N次方根,这个选取M就是可用的.就这点来说,这个选取还是比较宽松的,如果还需要考虑计算的效率问题(主要是a * b % M这个过程),选取的M则需要好好考虑.

选择M基于下面一些考虑.

变换长度为N,则必须存在N次方根(这个是FNT的内在要求)

高精度计算里,卷积的结果范围为,则必须 (R为进制)

计算尽可能简单.(这个是高精度要求,也可以算是卷积要求)

附:计算尽可能简单不等于尽可能小.比如这个的计算就都比M = 123456789要简单.(实际运行效率要求)

显然,这里没有要求M必须是素数.这就留出了较大的优化空间.

优化方向,主要是选取M方面着手.

1.        M尽可能小

2.        CRT(中国剩余定理),

3.        MOD M尽可能简单

4.        选取比较特殊的M,

1:这个略过(感觉废话),

2:这个主要是aploat主要干的事,(我的代码主要也是基于这个)

3:这个主要是GMP的优化方向,(不是太旧的版本是这样,4.x之前的据说不是)

4: Fürer‘s algorithm似乎就是基于这个方向,但是没有看懂原理

比如M = 65537(),在十进制下其变换长度最大为 65536/81 > 512,即10进制下最大变换长度为512,

比如1649267441665()/ 81 > ,在10000进制下,

如果M不是素数,,就实际应用效率而言,一般取M为3个接近自然位长(32位,64位机类似去接近64位)素数乘积.且每个素数都存在N次方根.即可.

比如 apfloat里面使用的3个素数就是2113929217, 2013265921, 1811939329,(源代码为2.41版本)

这里考虑加减法上的优化,都没有使用超过2^31的数.

自身代码的选择则是2013265921, 1811939329,1711276033,实际选取的原则其实并没有什么不同.

如不考虑乘法复杂度就乘法次数而言,直接MOD M运算的乘法次数要小于分三段,由于M超出了自然位长(80+位,接近3个自然位长,因此分三段最后再用CRT合并,这个中途都是32位长,只有最后CRT时才是3个自然位长长度,这样可能会比直接一次3个自然位长的FNT更好的效率.

较为细致较为精确的复杂度后面(可能)会进行补充说明.

GMP应用的是SSA,我的理解是M为,r = 2,的FNT的一个特化.

上面这个的流程可以算是说得比较清楚的了.

取一个适合大的简单的模M(2次幂加1),根也是2的幂.因此当中的计算应该算是简单的.

上面的流程写成递归的形式比较方便.

另外还有一个优化方法是选取的M是某个小素数的幂.但这个了解不多.

关于FNT,一些比较细致的常熟级复杂度优化会在后面进行补充说明

我的代码已经全部放上了github上了.另外也在51nod上的大数乘法里使用有关于FNT的具体代码AC通过了.

至于GMP和Apfloat库源代码可以在其官方上下载.

看不到公式的请查看附件

时间: 2024-10-03 02:41:22

多精度里FNT和SSA的点滴的相关文章

Erlang点滴--try语句里的尾递归

像Erlang这种函数式编程语言,尾递归的使用对于减少栈开销是很重要的.尽管Erlang并不提倡防御式编程,但仍然提供了 try ... of ... catch ... after ... end 语句.这里有个需要注意的地方:try 语句模块里面的函数调用有可能无法形成尾递归. 下面是一个小实验: 1 -module(test). 2 -compile(export_all). 3 4 -define(LOOP_CNT, 10000000). 5 6 start_loop() -> 7 ti

多精度计算备忘录之乘法 ------ 复杂度分析

多精度计算里,多精度乘法是其中最重要的运算之一,编写的多精度库(类)的其中一个重要效率标识就是其乘法的速度. 根据曾经写的大数类的记忆,简单记录下其中的一些技巧,以备查询. 一般的算法有如: 多精度乘法,所知的几个主要的优化方法有: 1:直接乘法. 2:comba乘法 3:Karatsuba乘法 4:toom_cook乘法 5:FFT乘法 6:FNT算法,或其他类似的有限域上对应类似的FFT算法 7:自己未曾理解的算法. 8:改进技巧, 1:直接乘法. a   b    c *         

测试不同格式下depth buffer的精度

这篇文章主要是参考MJP的"Attack of The Depth Buffer",测试不同格式下depth buffer的精度. 测试的depth buffer包含两类: 一是非线性的depth buffer,存储着perspective z(也就是最常用的,透视投影后归一化的z/w的buffer),二是线性的depth buffer,存储着view space z(这里的线性指的是在view space 中是否线性).测试的格式包括16位浮点数,32位浮点数,16位定点数,还有最常

计算几何中的精度问题

转自:北岛知寒 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直"画龙点睛".这些年的题目基本是朝着越来越不卡精度的方向发展了,但是也不乏一些奇怪的题,另外有些常识不管题目卡不卡,都是应该知道的.今天我就开膛回顾下见过且还有印象的精度问题,由于本人见识和记忆均有限,望各位大神瞄过后不吝补充.另外,为了弥补我匮乏的文思,我可能乱扯些不太相关或者尽人皆知的东西凑数.那么,现在开始.

OJ提交题目中的语言选项里G++与C++的区别(转载)

原文链接:http://blog.polossk.com/201405/c-plus-plus-g-plus-plus G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已. 那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式.准确地说,选择C++的话,意味着你将使用的是最标准的编译方式,也就是ANSI C++编译.如果你使用的是G++的话,意味着你将使用GNU项目中最平凡适用人群最多的编译器(其实也就是

图像分类中混淆矩阵精度验证法中的几个指标说明

ToolBox->Classification->PostClassification->Confusion Matrix->Using Ground Truth ROIs,可以得到如下的分类精度验证的混淆矩阵. 要看懂这个精度验证结果,需要了解几个混淆矩阵中的几项评价指标: 1.总体分类精度(Overall Accuracy) 等于被正确分类的像元总和除以总像元数.被正确分类的像元数目沿着混淆矩阵的对角线分布,总像元数等于所有真实参考源的像元总数,如本次精度分类精度表中的Over

poj 百练 2765 八进制小数(精度问题)

2765:八进制小数 查看 提交 统计 提示 提问 总时间限制:  1000ms  内存限制:  65536kB 描述 八进制小数可以用十进制小数精确的表示.比如,八进制里面的0.75等于十进制里面的0.963125 (7/8 + 5/64).所有小数点后位数为n的八进制小数都可以表示成小数点后位数不多于3n的十进制小数. 你的任务是写一个程序,把(0, 1)中的八进制小数转化成十进制小数. 输入 输入包括若干八进制小数,每个小数占用一行.每个小数的形式是0.d1d2d3 ... dk,这里di

[工作积累] UE4 TAA ReProjection的精度处理

先贴一个UE4 TAA的slidehttps://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf 里面细节问题很多,先记录一下目前想到和遇到的问题,便于备忘,后面有空的话再记录. TAA用到的Velocity和抖动对精度要求比较高, 特别是大场景下误差容易比较大,UE4做了一系列的处理来保持精度. 投影矩阵的精度 1 static const FMatrix InvertProjectionMa

cout输出控制——位数和精度控制

刷到一道需要控制输出精度和位数的题目 刚开始以为单纯使用 iomanip 函数库里的 setprecision 就可以,但 OJ 给我判了答案错误,后来一想这样输出并不能限制位数只能限制有效位数. 比如说 0.000101000110 用 setprecision(4) 答案是 0.000101 这里甚至把最后一位的有效数字 0 省略了!! 后来了解到 fixed 关键字 那么在这里若要控制小数点后 N 位 只要写成 cout << fixed << setprecision(N)