Documentation ¶
Index ¶
- Constants
- func ConfigureLogger(file bool, fileLevel logging.Level, terminal bool, terminalLevel logging.Level)
- func GenU2(R *RieselNumber, v1 int64) (*big.Int, error)
- func GenUN(R *RieselNumber, u *big.Int) (*big.Int, error)
- func GenV1(R *RieselNumber, method uint8) (int64, error)
- func IsPrime(R *RieselNumber) (bool, error)
- type RieselNumber
Constants ¶
const ( RIESEL uint8 = iota RODSETH PENNE )
GenV1 available algorithms
Variables ¶
This section is empty.
Functions ¶
func ConfigureLogger ¶
func ConfigureLogger(file bool, fileLevel logging.Level, terminal bool, terminalLevel logging.Level)
ConfigureLogger allows to enable file and terminal outputs for the log messages The available logging levels are:
DEBUG < INFO < NOTICE < WARNING < ERROR < CRITICAL
It is not recommended to set the level of any backend to DEBUG unless for very specific debugging reasons. If you do so, expect a lot of logs and a considerable slowing down in performance.
func GenU2 ¶
func GenU2(R *RieselNumber, v1 int64) (*big.Int, error)
GenU2 computes U(2) for the given Riesel candidate, where:
U(2) = V(h)
This function requires:
a) n >= 2 b) h >= 1 c) h mod 2 == 1 d) v1 >= 3
We calculate any V(x) as follows: (Ref1, top of page 873)
V(0) = alpha^0 + alpha^(-0) = 2 V(1) = alpha^1 + alpha^(-1) = GenV1(h,n) V(x+2) = V(1)*V(x+1) - V(x)
It can be shown that the following are true:
V(2*x) = V(x)^2 - 2 V(2*x+1) = V(x+1) * V(x) - V(1)
To prevent V(x) from growing too large, we will replace all V(x) with (V(x) mod N).
func GenUN ¶
GenUN computes U(n) for the given Riesel candidate.
This function requires:
a) n >= 2 b) h >= 1 c) h mod 2 == 1 d) u >= 3
We calculate each term of the Lucas sequence sequentially as follows: (Ref1, page 871)
U(x+1) = U(x)^2 - 2
To prevent U(x) from growing too large, we will replace all U(x) with (U(x) mod N).
func GenV1 ¶
func GenV1(R *RieselNumber, method uint8) (int64, error)
GenV1 computes a valid V(1) value for the given Riesel candidate.
This function assumes:
a) n >= 2 b) h >= 1 c) h mod 2 == 1
The generation of V(1) depends on the value of h. There are two cases to consider:
- h mod 3 != 0
- h mod 3 == 0
CASE 1: (h mod 3 != 0)
This case is easy. In [Ref1], page 869, one finds that if:
a) h mod 6 == +/-1 b) N mod 3 != 0
which translates, given that we assumed odd h, into the condition:
c) h mod 3 != 0
if this case condition is true then (also page 869):
U(2) = (2 + sqrt(3))^h + (2 - sqrt(3))^h = = (2 + sqrt(3))^h + (2 + sqrt(3))^(-h)
[ this is because it is easy to show that: (2 - sqrt(3)) = (2 + sqrt(3))^(-1) ]
Since [Ref1] states:
V(i) = alpha^i + alpha^(-i)
and since U(2) = V(h), we can simply let:
alpha = (2 + sqrt(3))
thus, in case 1, we return:
V(1) = alpha^1 + alpha^(-1) = = (2 + sqrt(3)) - ((2 - sqrt(3)) = 4
CASE 2: (h mod 3 == 0):
This case is more complicated and its explanation depends on the algorithm chosen (Riesel, Rodseth or Penne).
NOTE: Even though CASE 2 could work for any h, we use it only when h mod 3 == 0, because CASE 1 is faster and thus we prefer to use that when h mod 3 != 0.
func IsPrime ¶
func IsPrime(R *RieselNumber) (bool, error)
IsPrime performs a full Lucas-Lehmer-Riesel primality test on the given Riesel number R = h * 2^n - 1, and returns true if the number is prime.
The test works as follows:
- Generate V(1)
- From V(1) generate U(2) = V(h)
- From U(2) generate U(n)
- N is prime is U(n) == 0 (mod N)
The following conditions must be true for the test to work:
a) n >= 2 b) h >= 1
Types ¶
type RieselNumber ¶
A RieselNumber represents a number in the form h*2^n-1
QUESTION: Will it ever be the case that h > 2^63 - 1?
func NewRieselNumber ¶
func NewRieselNumber(h, n int64) (*RieselNumber, error)
NewRieselNumber constructs a new RieselNumber instance with the given h and n
This function requires:
a) h >= 1 b) n >= 2
When h is even, we will reduce it to odd and add number of times we had to divide it by two to n.
func (*RieselNumber) String ¶
func (R *RieselNumber) String() string
Custom "toString" functionality to print instances of RieselNumber as h*2^n-1