什么是bignum图书馆的便利基础&素性测试算法?

时间:2010-04-18 22:21:52

标签: c algorithm primes bignum

我将编写RSA原始论文中提出的Solovay-Strassen素性测试。

此外,我需要编写一个小的bignum库,因此在搜索bignum的方便表示时,我遇到了specification

struct {
  int sign;
  int size;
  int *tab;
} bignum;

我还将使用Karatsuba方法编写乘法例程。

所以,对于我的问题:

在bignum结构中存储整数数据的基础是什么?

注意:我不允许使用第二方或内置的bignum实现,例如GMP。

谢谢。

4 个答案:

答案 0 :(得分:3)

2的力量。

对于一个简单的实现,可能是机器上一个单词大小的一半,这样就可以将两位数相乘而不会溢出。所以65536或4294967296.或者可能是最大整数类型的一半,原因相同但可能性能更好。

但是我从来没有真正实现过这样的库:如果你使用的是最知名的算法,那么你就不会进行学校式的长乘法。 Karatsuba乘法(以及你使用的其他任何聪明的技巧)可能会受益于一个超过数字大小两倍的整数,我真的不知道性能是如何运作的。如果是这样,那么你最好使用256和32位算术,或65536和64位算术。

在任何情况下,如果您的表示是二进制的,那么您可以选择较大的二次幂基数,以方便每个操作。例如,您可以将数据视为基数2 ^ 16进行乘法,但基数为2 ^ 32进行加法。只要您对尾数有所了解,这一切都是一样的。我可能从base 2 ^ 16开始(因为这迫使我开始使用endian-ness,而2 ^ 8不会),并且看看我如何继续 - 因为每个操作都被优化,部分优化是确定最佳基础。

使用不是字节倍数的大小是可能的,但是你必须对所有内容使用相同的基数,因为根据基数在特定位置存储中存在未使用的位。

答案 1 :(得分:2)

您将完成以下操作:

B + C d ...;

要么选择最大字长的1/4,要么选择1/2最大字大小一两个。对于64位系统,这将是2 ^ 16或2 ^ 30,对于32位系统,这将是2 ^ 8或2 ^ 14。使用编译器支持的最大大小,而不是硬件。

如果在64位系统上选择2 ^ 31,则表示可以添加4个没有溢出的产品。如果您选择2 ^ 30,那么您可以添加16个产品而不会溢出。您可以添加的越多,没有溢出,您可以使用更大的临时块。

如果您选择字数的1/4,您仍然会有原生类型,因此更容易将结果存回。你也可以忽略溢出。这基本上可以使编写代码更快,更不容易出错,并且内存效率稍高。除非你喜欢大量的数学操作,否则我会推荐这个。

选择更大的基数将使大O数看起来更好。在实践中,虽然拥有更大的底座可能会更快,但它不会是您希望的4倍速度。

答案 2 :(得分:1)

你使用的基数应该是2的幂。由于看起来你要单独跟踪符号,你可以使用无符号整数来存储数字本身。你需要能够一次增加这些数字的2个/数字/单位,所以大小必须不超过你可用的单词大小的一半。即在x86上,unsigned int是32位,所以你希望你的数字不超过16位。对于无符号整数的乘积的中间结果,您也可以使用“long long”。然后你看着2 ^ 32为你的基地。最后要考虑的是你可能想要添加产品的总和,除非你使用更少的位,否则它们会溢出。

如果性能不是主要问题,我只需使用base 256并将其称为一天。您可能希望使用typedef和已定义的常量,以便以后可以轻松更改这些参数。

答案 3 :(得分:1)

选项卡数组中的整数应该是无符号的。它们应该是最大可能的尺寸(基础),您可以倍增并仍然代表产品。例如,如果编译器/处理器支持64位无符号long long,则可以将uint32_t用于“digits”数组。如果您的编译器/处理器只能本机生成32位产品,则应使用uint16_t。

当你对两个数组求和时,你需要处理溢出;在装配中这很容易。在C中,您可以选择使用少一位(31或15)来使溢出检测更容易。

还要考虑endianess,以及它和算法对缓存行为的影响。