rational_factorization class for factoring rational numbers and representing factorizations
rational_factorization is a class for factoring non zero rational numbers and holding factorizations. At the moment trial division (TD) and the elliptic curve method (ECM) (see [29]) are supported. Depending on the size of the number to be factored different combinations of TD and ECM are chosen. In addition it is possible to use own strategies by changing various parameters of these two methods.
The factorization of a rational number is internally represented by
an int variable sign and a vector of pairs
, where base is of type bigint
and
exp of type int.
Let in the following
denote the i-th vector component and l the
length of the vector. The length of a rational_factorization
is
defined as length of ``its vector''. Then this rational_factorization
represents the rational number
The value of sign is either 1 or -1; the values of
the bases are always positive.
The vector is sorted according to the
size of the value of the base component.
Note that the rational
number 0 can not be represented by a rational_factorization
.
Different bases
,
of the
vector are not equal, but not necessarily coprime. In particular, a
rational_factorization
does in general not represent the prime
factorization of a rational number.
Constructors/Destructor
All constructors invoke the error_handler if the value of the input variable is 0.
rational_factorization()
initializes the variable with 1.
rational_factorization(int)
rational_factorization(unsigned int)
rational_factorization(long)
rational_factorization(unsigned long)
rational_factorization(const bigint &)
rational_factorization(const bigrational &)
rational_factorization(const rational_factorization &)
rational_factorization()
Assignments
Let a be of type rational_factorization . The operator =
is overloaded and the following assignment functions exist. If you try to assign 0 to a variable of type rational_factorization , the error_handler will be invoked.
void a.assign(long i)
a = i.
void a.assign(const bigint & I)
a = I.
void a.assign(const bigrational & J)
a = J.
void a.assign(const rational_factorization & F)
a = F.
Access Functions
int a.no_of_comp() returns the number of components of the rational_factorization
a, which is the number of different -pairs.
int a.sign()
returns the sign of the
rational number represented by a.
bigint a.base(int i)
returns .
If i<0 or if i is greater or equal than the number of
components of a, the error_handler
will be invoked.
int a.exponent(int i)
returns .
If i<0 or if i is greater or equal than the number of
components of a, the error_handler
will be invoked.
Arithmetical Operations
The following operators are overloaded and can be used in exactly the same way as for machine types in C (e.g. int) :
(binary) *, /
Let a be of type rational_factorization .
To avoid copying, these operations can also be performed by the following functions:
void multiply(rational_factorization & c, const rational_factorization & a, const rational_factorization & b)
.
void a.square()
void square(rational_factorization & c,
const
rational_factorization & a)
.
void divide(rational_factorization & c, const rational_factorization & a, const rational_factorization & b)
.
void a.invert()
void invert(rational_factorization & c,
const
rational_factorization & a)
.
Comparisons
The binary operators == and != are overloaded and can be used in exactly the same way as for machine types in C (e.g. int). Let a be an instance of type rational_factorization .
int a.compare(const rational_factorization & b)
returns
1
if a = b, 0
otherwise.
High-Level Functions
General High-Level Functions
void a.verbose(int state)
sets the amount of information which
is printed during computations. If state = 1 then the
factorization functions print information about the strategy, for
state = 0 there is no such output. The predefined value is state = 0.
int a.is_prime_factor(int i)
returns 1
, if
is probably a prime number, otherwise 0
. For checking
primality the bigint
function is_prime
is used, which
uses a probabilistic primality test.
int a.is_prime_factorization()
returns 1
, if
a is probably a prime factorization of a rational number,
0
otherwise. For checking primality the bigint
function
is_prime
, which uses a probabilistic primality test
on each base element of a, is used.
void a.refine()
refine the factorization a such that the
bases of a are pairwise coprime.
void a.refine_comp(int i,
const bigint & x)
refine the factorization a by dividing factor x out of
. If x is no divisor of
, the
error_handler
will be invoked.
void a.refine(const bigint & x) refine the factorization a by dividing x out of all bases of a. If x does not divide any base of a, the error_handler
will be invoked.
void a.factor_comp(int i,
int upper_bound = 34)
tries to find factors of with decimal length at
most
. A combination of TD
and ECM is used. The i-th component of
a is erased, found factors (with appropriate exponents) are
added to the vector of a and the
vector is resorted.
void a.factor(int upper_bound = 34)
tries to find factors with decimal
length at most in all base
elements of a with a combination of TD and ECM
and changes a appropriately. If you are sure, that there are no
prime factors smaller than
in any base of a you may get
the results more efficiently by using the function a.ecm()
.
(See below.)
Special High-Level Functions
void a.trialdiv_comp(int i,
unsigned int upper_bound =
,
unsigned int lower_bound = 1)
tries to factor
of a by using TD with all primes
p with lower_bound< p < upper_bound. The i-th
component of a is erased, found factors (with
appropriate exponents) are added to the vector of a and the
vector is resorted.
void a.trialdiv(unsigned int upper_bound =
,
unsigned int lower_bound = 1)
tries to factor
all base elements of a with TD using all primes
p with lower_bound< p < upper_bound. The vector of
a is changed
according to the rules used in a.trialdiv_comp
.
The following function require some understanding of the underlying
strategy of ECM.
A detailed description of the
implementation of TD and ECM can be found in [3]
and [33].
ECM uses the following strategy, which is parametrized by the
int variables ,
and step. These
variables can be chosen by the user. It starts to look for factors
with
decimal digits. After having tried a ``few''
curves and not having found a factor the parameters of ECM are
changed and we try to find
-digit factors,
-digit factors and so on, until the decimal
size of the factors we are looking for exceeds
. The
number of curves which is used for finding a d-digit factor is
chosen such that we find a d-digit factor with probability at least
if it exists. Note that found factors can be composite. The
built-in default values are
and
is set to half the decimal length of the number to be
factored. The bounds
and
are limited because we have only precomputed parameters for ECM
for factors of that size.
A detailed description of the
implementation of TD and ECM can be found in [3]
and [33].
void a.ecm_comp(int i,
int upper_bound =
34,
int lower_bound = 6,
int step =
3)
tries to find factors of with decimal
length k,
, by means of
ECM according to the strategy explained above.
Note that found factors of
can be composite. If the
value of
is 34, then
is set to
.
The vector of
a is changed appropriately. Unreasonable input (
,
or
out of range etc.) leads to a
call of the error_handler
.
void a.ecm(int upper_bound = 34,
int
lower_bound = 6,
int step = 3)
tries to factor all
base elements of a with ECM using the strategy
described in a.ecm_comp
and
changes a appropriately. Note that the result is not necessarily a
prime factorization.
Input/Output
The istream
operator >>
and the ostream
operator
<<
are overloaded. The istream
operator >>
expects the
input of a rational_factorization
in the following format:
.
In the input
is allowed to be an arbitrary non-zero rational
integer (i.e., of type bigint
). The input function computes the
internal format which was explained in the beginning.
bigint , bigrational
ECM fails to factor rational numbers, that only consist of prime factors smaller than 1000. Therefore it is strongly recommended to use the function factor or to ensure with the function trialdiv , that there are no such small prime factors left before calling functions which use ECM.
The methods for factoring internally use variables of type int. If the data type int does not consist of 32 bits on your computer, the factoring methods cannot be used on your computer. In this case calls of them would lead to wrong results.
#include <LiDIA/rational_factorization.h> int main() { rational_factorization f; bigint n; cout << "enter an integer n: "; cin >> n; // input n f.assign(n); // assign n as trivial factorization to f f.verbose(1); // we want a lot of informations f.factor(); // calculate prime factorization cout << f; // output f }
Franz-Dieter Berger, Thomas F. Denny, Andreas Müller, Volker Müller
Copyright 1995 by the
LiDIA -Group, Universität des Saarlandes