zoukankan      html  css  js  c++  java
  • Algebraic Foundations ( Arithmetic and Algebra) CGAL 4.13 -User Manual

    理解:

    本节主要介绍CGAL的代数结构和概念之间的互操作。与传统数论不同,CGAL的代数结构关注于实数轴的“可嵌入”特征。它没有将所有传统数的集合映射到自己的代数结构概念中,避免使用“数的类型”这一术语,由整数入手,逐步提炼,由简入繁,形成一个概念体系。最上层结构是不考虑除法的整数(IntegralDomainWithoutDivision ),它适应了所有“类型都可以由整数生成”的要求。然后向下精炼形成IntegralDomain(这一概念可能就引入了除法)。IntegralDomain向下分为两支(分支依据可能是除法),即对于Field(域),而对于Domain则主要用于GCD、因式分解等的余数相关计算。Field(域)下面精炼出平方根、n次方根和多项式根等结构(其精炼目的还不是特别清晰)。而Domain这一支则精炼出UniqueFactorizationDomainEuclideanRing 结构。前一个可能与因式分解相关,后一个则是欧几里德环。(当Cartesian kernels时,采用 FieldNumberType ,当Homogeneous kernels时采用RingNumberType 。这里可以看出齐次坐标表示时不需要除法,所以用环类型,而笛卡尔坐标需要除法,必须用Field类型

    CGAL将所有结构相关的功能全部集成在了Traits里,Traits中包含了相关标签(tag)Algebraic_Catagory来进行判定和调度。

    RealEmbedable概念的意思是:所有结构都能够在实数轴上找到其位置,并且可以排序(比较大小)。RealEmbedable由一个Traits类实现,要求运算符被重载。

    当类型是 Field 并 RealEmbeddable 概念的模型时,它是有理数的一个超集。

    当类型是 IntegralDomainWithoutDivision 并 RealEmbeddable 概念的模型时,这个类的对象表达的数在算术和比较上是一样的(the number represented by an object of this type is the same for arithmetic and comparison)。可推知这个类型表示的“环”是整数的一个超集,实数的一个子集,因而具有特征0(characteristic zero)。

    每个CGAL Kernel来自两种实数类型(能够嵌入实数的数据类型)。其中一个Kernel是 FieldNumberType,另一个是RingNumberType 。基本的Kernel坐标对象(points,vectors等)来自于这两个类中的一个。当Cartesian kernels时,采用 FieldNumberType ,当Homogeneous kernels时采用RingNumberType 。(这里可以看出齐次坐标表示时不需要除法,所以用环类型,而笛卡尔坐标需要除法,必须用Field类型)

    FieldNumberType概念合并了Field 和 RealEmbeddable两个概念,RingNumberType 则综合了 IntegralDomainWithoutDivision 和 RealEmbeddable两个概念。代数观点出发,实数类型不形成显著的概念,所以不在图1 的列出。

    两个类型进行计算时可能发生类型转换,存在隐式转换和显式转换,隐式转换类似于普通C++的隐式转换,包中引入的Coercion_traits可给予两个可互操作的类型A和B通过Coercion_traits<A,B>::Type来得到强制类型的能力。

    Introduction

    CGAL is targeting towards exact computation with non-linear objects, in particular objects defined on algebraic curves and surfaces. As a consequence types representing polynomials, algebraic extensions and finite fields play a more important role in related implementations. This package has been introduced to stay abreast of these changes. Since in particular polynomials must be supported by the introduced framework the package avoids the term number type. Instead the package distinguishes between the algebraic structure of a type and whether a type is embeddable on the real axis, or real embeddable for short. Moreover, the package introduces the notion of interoperable types which allows an explicit handling of mixed operations.

    CGAL的目标是面向非线性对象的精确计算,特别是定义代数曲线和曲面的对象。

    表示多项式、代数扩展和有限域(fiinite fields)的类型在相关实现中越来越重要。因为多项式必须被所介绍的架构所支持,本包避免使用术语“数的类型”(Number Type),而是在一个类型的代数结构(algebraic structure)和一个类是否在实数轴上是“可嵌入的”(embeddable),即real embeddable。另外,包还引入了interoperable类型,这一类型允许显式地控制混合的操作。

    Algebraic Structures

    The algebraic structure concepts introduced within this section are motivated by their well known counterparts in traditional algebra, but we also had to pay tribute to existing types and their restrictions. To keep the interface minimal, it was not desirable to cover all known algebraic structures, e.g., we did not introduce concepts for such basic structures as groups or exceptional structures as skew fields.

    本节介绍的代数结构概念由其传统对应代数概念引起。但我们不得不注意现有的类型和它们的约束。为了保持接口最小,将所有已知代数结构全覆盖将是不合适的,我们将不引入类似“组”(group)或象“反称域”(skew field)一样的异常结构。

     

    Figure 1.1 Concept Hierarchy of Algebraic Structures

     Figure 1.1 shows the refinement relationship of the algebraic structure concepts. IntegralDomainUniqueFactorizationDomainEuclideanRing and Field correspond to the algebraic structures with the same name. FieldWithSqrtFieldWithKthRoot and FieldWithRootOf are fields that in addition are closed under the operations 'sqrt', 'k-th root' and 'real root of a polynomial', respectively. The concept IntegralDomainWithoutDivision also corresponds to integral domains in the algebraic sense, the distinction results from the fact that some implementations of integral domains lack the (algebraically always well defined) integral division. Note that Field refines IntegralDomain. This is because most ring-theoretic notions like greatest common divisors become trivial for Fields. Hence we see Field as a refinement of IntegralDomain and not as a refinement of one of the more advanced ring concepts. If an algorithm wants to rely on gcd or remainder computation, it is trying to do things it should not do with a Field in the first place.

    图1.1是经提炼后的代数结构概念之间的关系图。IntegeralDomain, UniqueFactorizationDomain,EuclideanRing和Field(域)与同名的代数结构含义相同。FieldWithSqrt,FieldWithKthRoot和FieldWithRootOf是分别对于“平方根”、“K次方根”和“多项式的实根“封闭(close)的fields(域)。概念IntegralDomainWithoutDivision同样对应于代数中的没有整数除法(Integral division)运算的整数概念。注意Field(域)由IntegralDomain中提炼出来,这是因为大多数如GCD这样的环理论概念(ring-theoretic notion)在Filed中来讲变得不再重要所以我们将Field(域)看作是IntegralDomain而不是其他更加高级环概念的精炼。如果一个算法想依赖GCD或余数计算,它做的事首先与Field(域)没有关系。(从上图中可以看出环计算和方根计算是分为两个类)

    The main properties of an algebraic structure are collected in the class Algebraic_structure_traits. In particular the (most refined) concept each concrete model AS fulfills is encoded in the tag Algebraic_structure_traits<AS>::Algebraic_category . An algebraic structure is at least AssignableCopyConstructibleDefaultConstructible and EqualityComparable. Moreover, we require that it is constructible from int. For ease of use and since their semantic is sufficiently standard to presume their existence, the usual arithmetic and comparison operators are required to be realized via C++ operator overloading. The division operator is reserved for division in fields. All other unary (e.g., sqrt) and binary functions (e.g., gcd, div) must be models of the well known STL-concepts AdaptableUnaryFunction or AdaptableBinaryFunction concept and local to the traits class (e.g., Algebraic_structure_traits<AS>::Sqrt()(x) ). This design allows us to profit from all parts in the STL and its programming style and avoids the name-lookup and two-pass template compilation problems experienced with the old design using overloaded functions. However, for ease of use and backward compatibility all functionality is also accessible through global functions defined within namespace CGAL, e.g., CGAL::sqrt(x) . This is realized via function templates using the according functor of the traits class. For an overview see Section Algebraic Foundations Reference in the reference manual.

    一个代数结构中的主要性质收集于类 Algebraic_structure_traits中。特别对于(最精炼的)概念的每个具体的模型AS实现,都用标签Algebraic_structure_traits<AS>::Algebraic_category编码表达。一个代数结构最起码具有“可赋值”“可拷贝构造”“可缺省构造”和“可相等比较”(Assignable,CopyConstructible,DefaultConstructible and EqualityComparable.)等特性。另外,我们要求它能够“由整数创建”(constructible from int)。为了便于使用和足够的语义来确定他们的存在,通用的算术和比较运算符要求用C++运算符重载(overload)。除法运行符是为field中的除法保留的。所有其他一元(sqrt)和二元函数(GCD,div)必须为STL概念AdaptableUnaryFunction 或 AdaptableBinaryFunction的模型并且在trait类( Algebraic_structure_traits<AS>::Sqrt()(x) )的本地实现。这一设计利用了STL的所有优势,避免了重载成员函数名称查找、两次模板编译(two-pass template compilation)等问题。但为了易用和向后兼容,所有的功能可通过定义在CGAL命名空间的全局函数调用(如:CGAL::sqrt(x))。这是用相应trait的函子(functor)通过函数模板实现的。

    2.1 Tags in Algebraic Structure Traits

    2.2 Algebraic Category

    For a type ASAlgebraic_structure_traits<AS> provides several tags. The most important tag is the Algebraic_category tag, which indicates the most refined algebraic concept the type ASfulfills. The tag is one of; Integral_domain_without_division_tagIntegral_domain_tagField_tagField_with_sqrt_tagField_with_kth_root_tagField_with_root_of_tagUnique_factorization_domain_tagEuclidean_ring_tag, or even Null_tag in case the type is not a model of an algebraic structure concept. The tags are derived from each other such that they reflect the hierarchy of the algebraic structure concept, e.g., Field_with_sqrt_tag is derived from Field_tag.

    对于一个类型AS,Algebraic_structure_traits<AS>提供若干标签(tag)。最重要的标签是 Algebraic_category 标签。它指定了类型AS实现的最精炼的代数概念。这个标签是下面中的一个:

    Integral_domain_without_division_tagIntegral_domain_tagField_tagField_with_sqrt_tagField_with_kth_root_tagField_with_root_of_tagUnique_factorization_domain_tagEuclidean_ring_tag 或Null_tag(当类型不是一个代数结构概念时)。标签是由相互继承产生的,所以它们反应了代数结构概念的层次关系,如Field_with_sqrt_tag是派生于Field_tag。

    File Algebraic_foundations/algebraic_structure_dispatch.cpp

    #include <CGAL/basic.h>
    #include <CGAL/IO/io.h>
    #include <CGAL/Algebraic_structure_traits.h>
     
    template< typename NT > NT unit_part(const NT& x);
    template< typename NT >
    NT unit_part_(const NT& x, CGAL::Field_tag);
    template< typename NT >
    NT unit_part_(const NT& x, CGAL::Integral_domain_without_division_tag);
     
    template< typename NT >
    NT unit_part(const NT& x){
    // the unit part of 0 is defined as 1.
    if (x == 0 ) return NT(1);
     
    typedef typename AST::Algebraic_category Algebraic_category;
    return unit_part_(x,Algebraic_category());
    }
     
    template< typename NT >
    NT unit_part_(const NT& x, CGAL::Integral_domain_without_division_tag){
    // For many other types the only units are just -1 and +1.
    return NT(int(CGAL::sign(x)));
    }
     
    template< typename NT >
    NT unit_part_(const NT& x, CGAL::Field_tag){
    // For Fields every x != 0 is a unit.
    // Therefore, every x != 0 is its own unit part.
    return x;
    }
     
    int main(){
    // Function call for a model of EuclideanRing, i.e. int.
    std::cout<< "int: unit_part(-3 ): " << unit_part(-3 ) << std::endl;
    // Function call for a model of FieldWithSqrt, i.e. double
    std::cout<< "double: unit_part(-3.0): " << unit_part(-3.0) << std::endl;
    return 0;
    }
     

    Real Embeddable

    Most number types represent some subset of the real numbers. From those types we expect functionality to compute the sign, absolute value or double approximations. In particular we can expect an order on such a type that reflects the order along the real axis. All these properties are gathered in the concept RealEmbeddable. The concept is orthogonal to the algebraic structure concepts, i.e., it is possible that a type is a model of RealEmbeddable only, since the type may just represent values on the real axis but does not provide any arithmetic operations.

    As for algebraic structures this concept is also traits class oriented. The main functionality related to RealEmbeddable is gathered in the class Real_embeddable_traits. In particular, it porivdes the boolean tag Is_real_embeddable indicating whether a type is a model of RealEmbeddable. The comparison operators are required to be realized via C++ operator overloading. All unary functions (e.g. signto_double) and binary functions (e.g. compare ) are models of the STL-concepts AdaptableUnaryFunction and AdaptableBinaryFunction and are local to Real_embeddable_traits.

    In case a type is a model of IntegralDomainWithoutDivision and RealEmbeddable the number represented by an object of this type is the same for arithmetic and comparison. It follows that the ring represented by this type is a superset of the integers and a subset of the real numbers and hence has characteristic zero.

    In case the type is a model of Field and RealEmbeddable it is a superset of the rational numbers.

    大部分数的类型表示实数的一个子集。从这些类中我们期望其具备计算符号、绝对值或双精度近似值(double approximations)功能。特别地,我们期望其能够在实数轴上排序。所有这些性质都收集在RealEmbeddable概念中。这个概念是与代数结构的概念们是正交的,即一个类可能仅仅是 RealEmbeddable 的模型,因为这个类型可以只表示实数轴上的一个值但不提供任何算法操作。

    对于代数结构而言,这个概念也是traits类。 RealEmbeddable 相关的主功能由Real_embeddable_traits收集。它提供了一个布尔标签Is_real_embeddable来指示其是否一个RealEmbeddable 的模型。其比较符号要求通过C++操作符重载来实现。所有的一元函数(如to_double)或二元函数(如compare)是STL概念AdaptableUnaryFunctionAdaptableBinaryFunction的模型,并在Real_embeddable_traits本地实现。

    当类型是 IntegralDomainWithoutDivision 并 RealEmbeddable 概念的模型时,这个类的对象表达的数在算术和比较上是一样的(the number represented by an object of this type is the same for arithmetic and comparison)。可推知这个类型表示的“环”是整数的一个超集,实数的一个子集,因而具有特征0(characteristic zero)。

    当类型是 Field 并 RealEmbeddable 概念的模型时,它是有理数的一个超集。

    Real Number Types

    Every CGAL Kernel comes with two real number types (number types embeddable into the real numbers). One of them is a FieldNumberType, and the other a RingNumberType. The coordinates of the basic kernel objects (points, vectors, etc.) come from one of these types (the FieldNumberType in case of Cartesian kernels, and the RingNumberType for Homogeneous kernels).

    The concept FieldNumberType combines the requirements of the concepts Field and RealEmbeddable, while RingNumberType combines IntegralDomainWithoutDivision and RealEmbeddable. Algebraically, the real number types do not form distinct structures and are therefore not listed in the concept hierarchy of Figure 1.1.

    每个CGAL Kernel来自两种实数类型(能够嵌入实数的数据类型)。其中一个Kernel是 FieldNumberType,另一个是RingNumberType 。基本的Kernel坐标对象(points,vectors等)来自于这两个类中的一个。当Cartesian kernels时,采用 FieldNumberType ,当Homogeneous kernels时采用RingNumberType 。(这里可以看出齐次坐标表示时不需要除法,所以用环类型,而笛卡尔坐标需要除法,必须用Field类型)

    FieldNumberType概念合并了Field 和 RealEmbeddable两个概念,RingNumberType 则综合了 IntegralDomainWithoutDivision 和 RealEmbeddable两个概念。代数观点出发,实数类型不形成显著的概念,所以不在图1 的列出。

    Interoperability

    This section introduces two concepts for interoperability of types, namely ImplicitInteroperable and ExplicitInteroperable. While ExplicitInteroperable is the base concept, we start with ImplicitInteroperable since it is the more intuitive one.

    In general mixed operations are provided by overloaded operators and functions or just via implicit constructor calls. This level of interoperability is reflected by the concept ImplicitInteroperable. However, within template code the result type, or so called coercion type, of a mixed arithmetic operation may be unclear. Therefore, the package introduces Coercion_traits giving access to the coercion type via Coercion_traits<A,B>::Type for two interoperable types A and B.

    Some trivial example are int and double with coercion type double or Gmpz and Gmpq with coercion type Gmpq. However, the coercion type is not necessarily one of the input types, e.g. the coercion type of a polynomial with integer coefficients that is multiplied by a rational type is supposed to be a polynomial with rational coefficients.

    Coercion_traits is also required to provide a functor Coercion_traits<A,B>::Cast() , that converts from an input type into the coercion type. This is in fact the core of the more basic concept ExplicitInteroperableExplicitInteroperable has been introduced to cover more complex cases for which it is hard or impossible to guarantee implicit interoperability. Note that this functor can be useful for ImplicitInteroperable types as well, since it can be used to void redundant type conversions.

    In case two types A and B are ExplicitInteroperable with coercion type C they are valid argument types for all binary functors provided by Algebraic_structure_traits and Real_embeddable_traits of C. This is also true for the according global functions.

    本节介绍了两个类型之间交互的概念,即ImplicitInteroperable 和ExplicitInteroperable 。概念 ExplicitInteroperable 是基概念,我们先从ImplicitInteroperable 概念入手,因其相对直观一点。

    总的来说,混合操作由重载的操作符和函数或仅通过调用隐式构造函数来提供。这一层的交互反应在 ImplicitInteroperable概念中。但在模板代码中混合操作结果类型或强制类型(coercion type)可能会不清楚。所以,包中引入的Coercion_traits可给予两个可互操作的类型A和B通过Coercion_traits<A,B>::Type来得到强制类型的能力。

    一些小例子包括:int和double与强制类型(coercion type)double,Gmpz和Gmpq与强制类型Gmpq。但强制类型不一定是一种输入类型,即一个整数系数与有理数相乘的多项式的强制类型将被推定为具有有理数的多项式。

    Coercion_traits也要求提供一个函子(functor)Coercion_traits<A,B>::Cast() 。其作用是将一个输入类型转换成强制类型。这实际就是显式交互(ExplicitInteroperable)的核心。ExplicitInteroperable的引入可以涵盖更复杂的情况,这些情况下保证隐式交互( implicit interoperability)是困难甚至是不可能的。这一functor对于隐式交互(ImplicitInteroperable)也是有用的,因它能够用于取消冗余的类型转换。

    当两种类型A和B与强制类型C是能够显式交互(ExplicitInteroperable)时,它们是Algebraic_structure_traits 和 Real_embeddable_traits提供的二元函子的合法参数类型。对于相应的全局函数也是如此。

    5.1 Examples

    The following example illustrates how two write code for ExplicitInteroperable types.

    下面的例子展示了如何使用ExplicitInteroperable 。
    File Algebraic_foundations/interoperable.cpp

    #include <CGAL/basic.h>
    #include <CGAL/Coercion_traits.h>
    #include <CGAL/IO/io.h>
     
    // this is an implementation for ExplicitInteroperable types
    // the result type is determined via Coercion_traits<A,B>
    template <typename A, typename B>
    binary_func(const A& a , const B& b){
     
    // check for explicit interoperability
    CGAL_static_assertion((CT::Are_explicit_interoperable::value));
     
    // CT::Cast is used to to convert both types into the coercion type
    typename CT::Cast cast;
    // all operations are performed in the coercion type
    return cast(a)*cast(b);
    }
     
    int main(){
    // Function call for the interoperable types
    std::cout<< binary_func(double(3), int(5)) << std::endl;
    // Note that Coercion_traits is symmetric
    std::cout<< binary_func(int(3), double(5)) << std::endl;
    return 0;
    }

    The following example illustrates a dispatch for ImplicitInteroperable and ExplicitInteroperable types. The binary function (that just multiplies its two arguments) is supposed to take two ExplicitInteroperable arguments. For ImplicitInteroperable types a variant that avoids the explicit cast is selected.

    下面的例子展示了对的 ImplicitInteroperable 和ExplicitInteroperable调度(dispatch)。二元函数意味着有两个显式交互的参数。对于隐式交互(ImplicitInteroperable )类型,选择了一种避免显式转换的变体。
    File Algebraic_foundations/implicit_interoperable_dispatch.cpp

    #include <CGAL/basic.h>
    #include <CGAL/Coercion_traits.h>
    #include <CGAL/Quotient.h>
    #include <CGAL/IO/io.h>
     
    // this is the implementation for ExplicitInteroperable types
    template <typename A, typename B>
    binary_function_(const A& a , const B& b, CGAL::Tag_false){
    std::cout << "Call for ExplicitInteroperable types: " << std::endl;
    typename CT::Cast cast;
    return cast(a)*cast(b);
    }
     
    // this is the implementation for ImplicitInteroperable types
    template <typename A, typename B>
    binary_function_(const A& a , const B& b, CGAL::Tag_true){
    std::cout << "Call for ImpicitInteroperable types: " << std::endl;
    return a*b;
    }
     
    // this function selects the correct implementation
    template <typename A, typename B>
    binary_func(const A& a , const B& b){
    typedef typename CT::Are_implicit_interoperable Are_implicit_interoperable;
    return binary_function_(a,b,Are_implicit_interoperable());
    }
     
    int main(){
    CGAL::set_pretty_mode(std::cout);
     
    // Function call for ImplicitInteroperable types
    std::cout<< binary_func(double(3), int(5)) << std::endl;
     
    // Function call for ExplicitInteroperable types
    CGAL::Quotient<int> rational(1,3); // == 1/3
    CGAL::Sqrt_extension<int,int> extension(1,2,3); // == 1+2*sqrt(3)
    CGAL::Sqrt_extension<CGAL::Quotient<int>,int> result = binary_func(rational, extension);
    std::cout<< result << std::endl;
     
    return 0;
    }
     

    Fractions

    Beyond the need for performing algebraic operations on objects as a whole, there are also number types which one would like to decompose into numerator and denominator. This does not only hold for rational numbers as QuotientGmpqmpq_class or leda_rational, but also for compound objects as Sqrt_extension or Polynomial which may decompose into a (scalar) denominator and a compound numerator with a simpler coefficient type (e.g. integer instead of rational). Often operations can be performed faster on these denominator-free multiples. In case a type is a Fraction the relevant functionality as well as the numerator and denominator type are provided by Fraction_traits. In particular Fraction_traits provides a tag Is_fraction that can be used for dispatching.

    A related class is Rational_traits which has been kept for backward compatibility reasons. However, we recommend to use Fraction_traits since it is more general and offers dispatching functionality.

    除了需要作为整体在对象之间进行代数运算外,还存在数字类型需要将其分解为分子(numerator)和分母(denominator)。这不仅QuotientGmpqmpq_class 和leda_rational的需要,也是Sqrt_extension或多项式等复合对象的需要,这些对象可以分解为一个标量(scalar)的分母和具有较简单系数类型的复合的分子。这种没有分母参与的乘法操作经常会更快。当类型是一个分数时(Fraction),相关的功能和分子及分母由Fraction_traits提供。特别是,Fraction_traits提供了一个Is_fraction标签用于调度。

    一个相关的类是Rational_traits ,它是因为向后兼容的原因而保留。但是我们推荐使用Fraction_traits,因它更加通用并提供了调度功能。

    6.1 Examples

    The following example show a simple use of Fraction_traits
    File Algebraic_foundations/fraction_traits.cpp

    #include <CGAL/basic.h>
    #include <CGAL/Fraction_traits.h>
    #include <CGAL/IO/io.h>
     
    #ifdef CGAL_USE_GMP
    #include <CGAL/Gmpz.h>
    #include <CGAL/Gmpq.h>
    int main(){
    typedef FT::Numerator_type Numerator_type;
    typedef FT::Denominator_type Denominator_type;
     
    CGAL_static_assertion((boost::is_same<Numerator_type,CGAL::Gmpz>::value));
    CGAL_static_assertion((boost::is_same<Denominator_type,CGAL::Gmpz>::value));
     
    Numerator_type numerator;
    Denominator_type denominator;
    CGAL::Gmpq fraction(4,5);
    FT::Decompose()(fraction,numerator,denominator);
     
    CGAL::set_pretty_mode(std::cout);
    std::cout << "decompose fraction: "<< std::endl;
    std::cout << "fraction : " << fraction << std::endl;
    std::cout << "numerator : " << numerator<< std::endl;
    std::cout << "denominator: " << denominator << std::endl;
     
    std::cout << "re-compose fraction: "<< std::endl;
    fraction = FT::Compose()(numerator,denominator);
    std::cout << "fraction : " << fraction << std::endl;
    }
    #else
    int main(){ std::cout << "This examples needs GMP" << std::endl; }
    #endif

    The following example illustrates the integralization of a vector, i.e., the coefficient vector of a polynomial. Note that for minimizing coefficient growth Fraction_traits<Type>::Common_factor is used to compute the least common multiple of the denominators.


    File Algebraic_foundations/integralize.cpp

    #include <CGAL/basic.h>
    #include <CGAL/Fraction_traits.h>
    #include <CGAL/IO/io.h>
    #include <vector>
     
    template <class Fraction>
    std::vector<typename CGAL::Fraction_traits<Fraction>::Numerator_type >
    integralize(
    const std::vector<Fraction>& vec,
    ) {
    typedef typename FT::Numerator_type Numerator_type;
    typedef typename FT::Denominator_type Denominator_type;
    typename FT::Decompose decompose;
     
    std::vector<Numerator_type> num(vec.size());
    std::vector<Denominator_type> den(vec.size());
     
    // decompose each coefficient into integral part and denominator
    for (unsigned int i = 0; i < vec.size(); i++) {
    decompose(vec[i], num[i], den[i]);
    }
     
    // compute 'least' common multiple of all denominator
    // We would like to use gcd, so let's think of Common_factor as gcd.
    typename FT::Common_factor gcd;
    d = 1;
    for (unsigned int i = 0; i < vec.size(); i++) {
    d *= CGAL::integral_division(den[i], gcd(d, den[i]));
    }
     
    // expand each (numerator, denominator) pair to common denominator
    for (unsigned int i = 0; i < vec.size(); i++) {
    // For simplicity ImplicitInteroperability is expected in this example
    num[i] *= CGAL::integral_division(d, den[i]);
    }
    return num;
    }
     
    #ifdef CGAL_USE_GMP
     
    #include <CGAL/Gmpz.h>
    #include <CGAL/Gmpq.h>
     
    int main(){
    std::vector<CGAL::Gmpq> vec(3);
    vec[0]=CGAL::Gmpq(1,4);
    vec[1]=CGAL::Gmpq(1,6);
    vec[2]=CGAL::Gmpq(1,10);
    std::cout<< "compute an integralized vector" << std::endl;
    std::cout<<"input vector: ["
    << vec[0] << "," << vec[1] << "," << vec[2] << "]" << std::endl;
    std::vector<CGAL::Gmpz> integral_vec = integralize(vec,d);
    std::cout<<"output vector: ["
    << integral_vec[0] << ","
    << integral_vec[1] << ","
    << integral_vec[2] << "]" << std::endl;
    std::cout<<"denominator : "<< d <<std::endl;
    }
    #else
    int main(){ std::cout << "This examples needs GMP" << std::endl; }
    #endif

    Design and Implementation History

    The package is part of CGAL since release 3.3. Of course the package is based on the former Number type support of CGAL. This goes back to Stefan Schirra and Andreas Fabri. But on the other hand the package is to a large extend influenced by the experience with the number type support in Exacus [1], which in the main goes back to Lutz Kettner, Susan Hert, Arno Eigenwillig and Michael Hemmer. However, the package abstracts from the pure support for number types that are embedded on the real axis which allows the support of polynomials, finite fields, and algebraic extensions as well. See also related subsequent chapters.

  • 相关阅读:
    Django01
    WEB框架介绍
    前端插件介绍
    JQuery
    DOM
    js
    css
    HTML
    图片懒加载
    js中style,currentStyle和getComputedStyle的区别
  • 原文地址:https://www.cnblogs.com/myboat/p/9945858.html
Copyright © 2011-2022 走看看