1. 程式人生 > >Modular Arithmetic ( Arithmetic and Algebra) CGAL 4.13 -User Manual

Modular Arithmetic ( Arithmetic and Algebra) CGAL 4.13 -User Manual

spec called gad .org cal necessary epp 完成 general

1 Introduction

Modular arithmetic is a fundamental tool in modern algebra systems. In conjunction with the Chinese remainder theorem it serves as the workhorse in several algorithms computing the gcd, resultant etc. Moreover, it can serve as a very efficient filter, since it is often possible to exclude that some value is zero by computing its modular correspondent with respect to one prime only.

模運算是現代代數系統的基本工具。與中國余數定理(Chinese remainder theorem)結合,是若幹計算GCD和合矢量(resultant )算法的核心。另外,它能夠作為一個十分高效的工具,原因在於它常常可能排除計算一個素數( since it is often possible to exclude that some value is zero by computing its modular correspondent with respect to one prime only.)

2 Residue and Modularizable

First of all, this package introduces a type Residue

. It represents Z/pZ for some prime p. The prime number p is stored in a static member variable. The class provides static member functions to change this value.

Changing the prime invalidates already existing objects of this type. However, already existing objects do not lose their value with respect to the old prime and can be reused after restoring the old prime. Since the type is based on double arithmetic the prime is restricted to values less than 226

. The initial value of p is 67108859.

Moreover, the package introduces the concept Modularizable. An algebraic structure T is considered as Modularizable if there is a mapping from T into an algebraic structure that is based on the type Residue. For scalar types, e.g. Integers, this mapping is just the canonical homomorphism into Z/pZ represented by Residue. For compound types, e.g. Polynomials, the mapping is applied to the coefficients of the compound type. The mapping is provided by the class Modular_traits<T>. The class Modular_traits<T> is designed such that the concept Modularizable can be considered as optional, i.e., Modular_traits<T> provides a tag that can be used for dispatching.

首先,本包引入了Residue類型。它表示某素數p的乘法群(Z/pZ );素數(prime)p是保存在一個靜態成員變量。一個類提供的靜態函數用來改變這個值。(數學上,同余(英語:congruence modulo,符號:≡)是數論中的一種等價關系。當兩個整數除以同一個正整數,若得相同余數,則二整數同余。同余是抽象代數中的同余關系的原型。在同余理論中,模 n 的互質同余類組成一個乘法群,稱為整數模 n 乘法群,也稱為模 n 既約剩余類。在環理論中,一個抽象代數的分支,也稱這個群為整數模 n 的環的單位群(單位是指乘法可逆元)。這個群是數論的基石,在密碼學、整數分解和素性測試均有運用。例如,關於這個群的階(即群的“大小”),我們可以確定如果 n 是質數當且僅當階數為 n-1。)

改變素數的值使現存的這個類的對象非法。但現存的對象不會丟失該值,通過恢復舊的素數就可以重用。因該類型基於雙精度算術運算,素數被限制在小於226,初始p的值是67108859。

另外,本包引入了“可余的”或可模的 Modularizable概念。如果一個代數結構T與一個基於Residue的結構存在一個映射(mapping ),則T被認為是Modularizable。對於標量,即整數,映射僅僅是Z/pZ(乘法群)中Residue表示的典型同態(canonical homomorphism);對於復合類型,即多項式,映射運用於復合類型的系數。映射由類 Modular_traits<T>提供。類 Modular_traits<T>的設計可以將概念Modularizable 作為可選的,即 Modular_traits<T> 提供了一個標簽用於調度。

2.1 Example

In the following example modular arithmetic is used as a filter on order to avoid unnecessary gcd computations of polynomials. A gcd computation can be very costly due to coefficient growth within the Euclidean algorithm.

The general idea is that firstly the gcd is computed with respect to one prime only. If this modular gcd is constant we can (in most cases) conclude that the actual gcd is constant as well.

For this purpose the example introduces the function may_have_common_factor(). Note that there are two versions of this function, namely for the case that the coefficient type is Modularizable and that it is not. If the type is not Modularizable the filter is just not applied and the function returns true.

Further note that the implementation of class Residue requires a mantissa precision according to the IEEE Standard for Floating-Point Arithmetic (IEEE 754). However, on some processors the traditional FPU uses an extended precision. Hence, it is indispensable that the proper mantissa length is enforced before performing any arithmetic operations. Moreover, it is required that numbers are rounded to the next nearest value. This can be ensured using Protect_FPU_rounding with CGAL_FE_TONEAREST, which also enforces the required precision as a side effect.

下面的例子中,求余的運算用於過濾,避免多項式中不必須的GCD計算。GCD計算十分耗時,由於歐幾裏德算法(Euclidean algorithm)中的系數的增長。

通用的思路是,首先GCD計算只涉及一個素數。如果這個模GCD(modular gcd )是一個常數,我們可以推測大多數情況下實際的GCD也是一個常數。

出於這個目的,例子中引入了一個函數may_have_common_factor()。這個函數有兩個版本,分別用於系數類型是Modularizable和非Modularizable時。如果是後者,則過濾器則不會被使用,函數返回true.

另外,根據IEEE浮點運算標準(IEEE754)Residue類的實現要求尾數的精度。但在有些處理器中傳統的FPU使用一個擴展的精度,所以必須在進行任何算法運算前將尾數精度進行適當設置。同是,要求將數舍入到最近的值,這個要求可通過帶CGAL_FE_TONEAREST參數的Protect_FPU_rounding 來完成,它也同時將尾數精度進行了適當設置。

File Modular_arithmetic/modular_filter.cpp

#include <CGAL/basic.h> #ifdef CGAL_USE_GMP #include <CGAL/Gmpz.h> #include <CGAL/Polynomial.h> // Function in case Polynomial is Modularizable template< typename Polynomial > bool may_have_common_factor( const Polynomial& p1, const Polynomial& p2, CGAL::Tag_true) { std::cout<< "The type is modularizable" << std::endl; // Enforce IEEE double precision and rounding mode to nearest // before useing modular arithmetic CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST); // Use Modular_traits to convert to polynomials with modular coefficients typedef CGAL::Modular_traits<Polynomial> MT; typedef typename MT::Residue_type MPolynomial; typedef typename MT::Modular_image Modular_image; MPolynomial mp1 = Modular_image()(p1); MPolynomial mp2 = Modular_image()(p2); // check for unlucky primes, the polynomials should not lose a degree typename CGAL::Polynomial_traits_d<Polynomial>::Degree degree; typename CGAL::Polynomial_traits_d<MPolynomial>::Degree mdegree; if ( degree(p1) != mdegree(mp1)) return true; if ( degree(p2) != mdegree(mp2)) return true; // compute gcd for modular images MPolynomial mg = CGAL::gcd(mp1,mp2); // if the modular gcd is not trivial: return true if ( mdegree(mg) > 0 ){ std::cout << "The gcd may be non trivial" << std::endl; return true; }else{ std::cout << "The gcd is trivial" << std::endl; return false; } } // This function returns true, since the filter is not applicable template< typename Polynomial > bool may_have_common_factor( const Polynomial&, const Polynomial&, CGAL::Tag_false){ std::cout<< "The type is not modularizable" << std::endl; return true; } template< typename Polynomial > Polynomial modular_filtered_gcd(const Polynomial& p1, const Polynomial& p2){ typedef CGAL::Modular_traits<Polynomial> MT; typedef typename MT::Is_modularizable Is_modularizable; // Try to avoid actual gcd computation if (may_have_common_factor(p1,p2, Is_modularizable())){ // Compute gcd, since the filter indicates a common factor return CGAL::gcd(p1,p2); }else{ typename CGAL::Polynomial_traits_d<Polynomial>::Univariate_content content; typename CGAL::Polynomial_traits_d<Polynomial>::Construct_polynomial construct; return construct(CGAL::gcd(content(p1),content(p2))); // return trivial gcd } } int main(){ CGAL::set_pretty_mode(std::cout); typedef CGAL::Gmpz NT; typedef CGAL::Polynomial<NT> Poly; CGAL::Polynomial_traits_d<Poly>::Construct_polynomial construct; Poly f1=construct(NT(2), NT(6), NT(4)); Poly f2=construct(NT(12), NT(4), NT(8)); Poly f3=construct(NT(3), NT(4)); std::cout << "f1 : " << f1 << std::endl; std::cout << "f2 : " << f2 << std::endl; std::cout << "compute modular filtered gcd(f1,f2): " << std::endl; Poly g1 = modular_filtered_gcd(f1,f2); std::cout << "gcd(f1,f2): " << g1 << std::endl; std::cout << std::endl; Poly p1 = f1*f3; Poly p2 = f2*f3; std::cout << "f3 : " << f3 << std::endl; std::cout << "p1=f1*f3 : " << p1 << std::endl; std::cout << "p2=f2*f3 : " << p2 << std::endl; std::cout << "compute modular filtered gcd(p1,p2): " << std::endl; Poly g2 = modular_filtered_gcd(p1,p2); std::cout << "gcd(p1,p2): " << g2 << std::endl; } #else int main (){ std::cout << " This examples needs GMP! " << std::endl; } #endif

3 Design and Implementation History

The class Residue is based on the C-code of Sylvain Pion et. al. as it was presented in [2].

The remaining part of the package is the result of the integration process of the NumeriX library of Exacus [1] into CGAL.

Modular Arithmetic ( Arithmetic and Algebra) CGAL 4.13 -User Manual