最近在尝试密码数学挑战赛,选的是子集和问题。看到题目中说相关的LLL算法、BKZ在NTL这个库中实现了,那想省点事儿,就去装这个库好了。结果这个库也得弄半天,emmm,环境配置不好弄啊。网上相关问题都不完全适用于我的情况,就想记录下自己的过程。
介绍
NTL(Number Thery Library),是一个高性能的、可移植的c++库,提供任意长度整数的数据结构和算法,适用于整数和有限域上的向量、矩阵和多项式,并可用于任意精度的浮点运算。
NTL其实就是一个数论库,实现了许多数论的概念方法,用来处理和数论有关的问题,就像python的gmpy2库。NTL使得C++也能方便的处理大整数,香得很。
安装
我们先去NTL官网下载,在下载页面选择最新的库,这里是Unix版本的。
下载完成后,打开下载文件所在目录,在终端依次输入以下命令
gunzip ntl-xxx.tar.gz #xxx为自己所下文件版本号
tar xf ntl-xxx.tar
cd ntl-xxx/src
#刚开始,我安装的时候并没有加上PREFIX=$HOME/NTL NTL_GMP_LIP=off,结果会因为电脑上没有GMP这个东西而爆出一系列错误,这些错误也没处理好。
#后来就加上这个选项,之后不会报错,只是执行的时间长了一点。
#现在想一下,可以通过brew install gmp安装gmp,从而不加这个选项,只不过并没有实际测试,不保证正确
./configure PREFIX=$HOME/NTL NTL_GMP_LIP=off
make
make check
sudo make install
有一点值得说的是,上述1,2行的代码可以不用打。直接点击下载好那个ntl-xxx.tar.gzz文件,文件就解压好了,MAC自带的归档程序处理结果。
等这几条命令都执行完,NTL库就被安装到电脑上了。只是这里NTL安装的路径不太对,想编译源代码时,会提示找不到NTL的相关头文件。
这是因为gcc在编译时,会默认到/usr/local/include文件夹中寻找所需要的头文件。而这里安装的路径并不对,程序给我安装到当前用户的主目录下面。在/usr/local/include中找不到NTL,自然会报错:找不到头文件。
下来移动文件到正确位置。在/Users/crownz/NTL中,有三个文件夹include,lib和share,在/usr/local也有include,lib和share,将里面内容分别到对应文件夹移动即可。
用命令行就是下面那样,就是简单地文件移动操作,自己分别打开两个文件夹,对照着一看就懂了。
测试
装完了,咱们还要验证一下究竟能不能用。写一个简单的程序如下:
#include < NTL/ZZ.h > //NTL中的ZZ类,可处理任意长度的整数,还有一些其他数论函数
#include < iostream > //这俩头文件尖括号内部的空格要去掉,这里是因为博客代码展示问题,不得不加上的
using namespace std;
using namespace NTL; //使用NTL必须加的命名空间
int main()
{
ZZ a, b, c; //定义三个ZZ类型的数
cin>>a;
cin>>b;
c=(a+1)*(b+1);
cout<< c <<"\n";
return 0;
}
功能很简单,输入两个数分别加1,再计算乘积输出。写好的程序,还需要通过g++编译,方法如下(test.cpp和test分别为源代码和输出程序):
g++ -g -O2 -std=c++11 -pthread -march=native test.cpp -o test -lntl -lgmp -lm
- 解释
- 默认情况下,NTL是在c++ 11模式下构建的,需要确保编译器配置能够接受c++11。
- 默认情况下,NTL是在启用了多线程的情况下构建的,因此,可能需要将-pthread选项传递给GCC。
- 要获得针对特定x86体系结构的代码的最佳性能,-march=native选项通常是一个好方法。
- 可以在文件/usr/local/ include/ntl/config中查看,NTL的配置脚本除了-g -O2之外还选择了哪些选项。
- 如果使用gf2x构建NTL,只需在-lgmp之后添加-lgf2x选项即可。而如果NTL构建为共享库,则可能没有必要这样做。
官网给的例子是就是g++的,我尝试用gcc编译爆了一堆错,也不解决了,就用g++好了。
看到程序顺畅地输出结果。
有了NTL库,我们就可以像python那样方便地处理大数,还能有一堆实现好的数论方法,还具有python所没有的速度,完美。
参考