Algebraic Foundations ( Arithmetic and Algebra) CGAL 4.13 -User Manual
理解:
本节主要介绍CGAL的代数结构和概念之间的互操作。与传统数论不同,CGAL的代数结构关注于实数轴的“可嵌入”特征。它没有将所有传统数的集合映射到自己的代数结构概念中,避免使用“数的类型”这一术语,由整数入手,逐步提炼,由简入繁,形成一个概念体系。最上层结构是不考虑除法的整数(IntegralDomainWithoutDivision
),它适应了所有“类型都可以由整数生成”的要求。然后向下精炼形成IntegralDomain(这一概念可能就引入了除法)。IntegralDomain向下分为两支(分支依据可能是除法),即对于Field(域),而对于Domain则主要用于GCD、因式分解等的余数相关计算。Field(域)下面精炼出平方根、n次方根和多项式根等结构(其精炼目的还不是特别清晰)。而Domain这一支则精炼出UniqueFactorizationDomain
, EuclideanRing
结构。前一个可能与因式分解相关,后一个则是欧几里德环。(当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
来得到强制类型的能力。
1 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类型,这一类型允许显式地控制混合的操作。
2 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. IntegralDomain
, UniqueFactorizationDomain
, EuclideanRing
and Field
correspond to the algebraic structures with the same name. FieldWithSqrt
, FieldWithKthRoot
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 Field
s. 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 Assignable
, CopyConstructible
, DefaultConstructible
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 AS
, Algebraic_structure_traits<AS>
provides several tags. The most important tag is the Algebraic_category
tag, which indicates the most refined algebraic concept the type AS
fulfills. The tag is one of; Integral_domain_without_division_tag
, Integral_domain_tag
, Field_tag
, Field_with_sqrt_tag
, Field_with_kth_root_tag
, Field_with_root_of_tag
, Unique_factorization_domain_tag
, Euclidean_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_tag
, Integral_domain_tag
, Field_tag
, Field_with_sqrt_tag
, Field_with_kth_root_tag
, Field_with_root_of_tag
, Unique_factorization_domain_tag
, Euclidean_ring_tag 或Null_tag(当类型不是一个代数结构概念时)。标签是由相互继承产生的,所以它们反应了代数结构概念的层次关系,如Field_with_sqrt_tag是派生于Field_tag。
File Algebraic_foundations/algebraic_structure_dispatch.cpp
3 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. sign, to_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概念AdaptableUnaryFunction
和AdaptableBinaryFunction
的模型,并在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
概念的模型时,它是有理数的一个超集。
4 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 的列出。
5 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 ExplicitInteroperable
. ExplicitInteroperable
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
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
6 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 Quotient
, Gmpq
, mpq_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)。这不仅Quotient
, Gmpq
, mpq_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
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
7 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.