]>
Axiom provides two kinds of floating point numbers. The domain Float (abbreviation FLOAT) implements a model of arbitrary precision floating point numbers. The domain DoubleFloat (abbreviation DFLOAT) is intended to make available hardware floating point arithmetic in Axiom. The actual model of floating point that DoubleFloat provides is system-dependent. For example, on the IBM system 370 Axiom uses IBM double precision which has fourteen hexadecimal digits of precision or roughly sixteen decimal digits. Arbitrary precision floats allow the user to specify the precision at which arithmetic operations are computed. Although this is an attractive facility, it comes at a cost. Arbitrary-precision floating-point arithmetic typically takes twenty to two hundred times more time than hardware floating point.
For more information about Axiom's numeric and graphic facilities, see ugGraphPage in Section ugGraphNumber , ugProblemNumeric , and DoubleFloatXmpPage .
Scientific notation is supported for input and output of floating point numbers. A floating point number is written as a string of digits containing a decimal point optionally followed by the letter ``E'', and then the exponent.
We begin by doing some calculations using arbitrary precision floats. The default precision is twenty decimal digits.
A decimal base for the exponent is assumed, so the number 1.234E2 denotes .
The normal arithmetic operations are available for floating point numbers.
You can use conversion (ugTypesConvertPage in Section ugTypesConvertNumber ) to go back and forth between Integer, Fraction Integer and Float, as appropriate.
Since you are explicitly asking for a conversion, you must take responsibility for any loss of exactness.
This conversion cannot be performed: use truncatetruncateFloat or roundroundFloat if that is what you intend.
The operations truncatetruncateFloat and roundroundFloat truncate ...
and round to the nearest integral Float respectively.
The operation fractionPartfractionPartFloat computes the fractional part of x, that is, x - truncate x.
The operation digitsdigitsFloat allows the user to set the precision. It returns the previous value it was using.
The precision is only limited by the computer memory available. Calculations at 500 or more digits of precision are not difficult.
Reset digitsdigitsFloat to its default value.
Numbers of type Float are represented as a record of two integers, namely, the mantissa and the exponent where the base of the exponent is binary. That is, the floating point number (m,e) represents the number . A consequence of using a binary base is that decimal numbers can not, in general, be represented exactly.
A number of operations exist for specifying how numbers of type Float are to be displayed. By default, spaces are inserted every ten digits in the output for readability.Note that you cannot include spaces in the input form of a floating point number, though you can use underscores.
Output spacing can be modified with the outputSpacingoutputSpacingFloat operation. This inserts no spaces and then displays the value of x.
Issue this to have the spaces inserted every 5 digits.
By default, the system displays floats in either fixed format or scientific format, depending on the magnitude of the number.
A particular format may be requested with the operations outputFloatingoutputFloatingFloat and outputFixedoutputFixedFloat.
Additionally, you can ask for n digits to be displayed after the decimal point.
This resets the output printing to the default behavior.
Consider the problem of computing the determinant of a 10 by 10 Hilbert matrix. The -th entry of a Hilbert matrix is given by 1/(i+j+1).
First do the computation using rational numbers to obtain the exact result.
This version of determinantdeterminantMatrix uses Gaussian elimination.
Now use hardware floats. Note that a semicolon (;) is used to prevent the display of the matrix.
The result given by hardware floats is correct only to four significant digits of precision. In the jargon of numerical analysis, the Hilbert matrix is said to be ``ill-conditioned.''
Now repeat the computation at a higher precision using Float.
Reset digitsdigitsFloat to its default value.
The Fraction domain implements quotients. The elements must belong to a domain of category IntegralDomain: multiplication must be commutative and the product of two non-zero elements must not be zero. This allows you to make fractions of most things you would think of, but don't expect to create a fraction of two matrices! The abbreviation for Fraction is FRAC.
Use / to create a fraction.
The standard arithmetic operations are available.
Extract the numerator and denominator by using numernumerFraction and denomdenomFraction, respectively.
Operations like maxmaxFraction, minminFraction, negative?negative?Fraction, positive?positive?Fraction and zero?zero?Fraction are all available if they are provided for the numerators and denominators. See IntegerXmpPage for examples.
Don't expect a useful answer from factorfactorFraction, gcdgcdFraction or lcmlcmFraction if you apply them to fractions.
Since all non-zero fractions are invertible, these operations have trivial definitions.
Use mapmapFraction to apply factorfactorFraction to the numerator and denominator, which is probably what you mean.
Other forms of fractions are available. Use continuedFraction to create a continued fraction.
Use partialFraction to create a partial fraction. See ContinuedFractionXmpPage and PartialFractionXmpPage for additional information and examples.
Use conversion to create alternative views of fractions with objects moved in and out of the numerator and denominator.
Conversion is discussed in detail in Section ugTypesConvertPage .
The domain FullPartialFractionExpansion implements factor-free conversion of quotients to full partial fractions.
Our examples will all involve quotients of univariate polynomials with rational number coefficients.
Here is a simple-looking rational function.
We use fullPartialFractionfullPartialFractionFullPartialFractionExpansion to convert it to an object of type FullPartialFractionExpansion.
Use a coercion to change it back into a quotient.
Full partial fractions differentiate faster than rational functions.
We can check that the two forms represent the same function.
Here are some examples that are more complicated.
This verification takes much longer than the conversion to partial fractions.
For more information, see the paper: Bronstein, M and Salvy, B. ``Full Partial Fraction Decomposition of Rational Functions,'' Proceedings of ISSAC'93, Kiev, ACM Press. All see PartialFractionXmpPage for standard partial fraction decompositions.
Sometimes when working with tables there is a natural value to use as the entry in all but a few cases. The GeneralSparseTable constructor can be used to provide any table type with a default value for entries. See TableXmpPage for general information about tables.
Suppose we launched a fund-raising campaign to raise fifty thousand dollars. To record the contributions, we want a table with strings as keys (for the names) and integer entries (for the amount). In a data base of cash contributions, unless someone has been explicitly entered, it is reasonable to assume they have made a zero dollar contribution.
This creates a keyed access file with default entry 0.
Now patrons can be used just as any other table. Here we record two gifts.
Now let us look up the size of the contributions from Jones and Stingy.
Have we met our seventy thousand dollar goal?
So the project is cancelled and we can delete the data base:
Solving systems of polynomial equations with the Gröbner basis algorithm can often be very time consuming because, in general, the algorithm has exponential run-time. These systems, which often come from concrete applications, frequently have symmetries which are not taken advantage of by the algorithm. However, it often happens in this case that the polynomials which occur during the Gröbner calculations are reducible. Since Axiom has an excellent polynomial factorization algorithm, it is very natural to combine the Gröbner and factorization algorithms.
GroebnerFactorizationPackage exports the groebnerFactorizegroebnerFactorizeGroebnerFactorizationPackage operation which implements a modified Gröbner basis algorithm. In this algorithm, each polynomial that is to be put into the partial list of the basis is first factored. The remaining calculation is split into as many parts as there are irreducible factors. Call these factors In the branches corresponding to the factor can be divided out, and so on. This package also contains operations that allow you to specify the polynomials that are not zero on the common roots of the final Gröbner basis.
Here is an example from chemistry. In a theoretical model of cyclohexane, , the six carbon atoms each sit in the center of gravity of a tetrahedron that has two hydrogen atoms and two carbon atoms at its corners. We first normalize and set the length of each edge to 1. Hence, the distances of one fixed carbon atom to each of its immediate neighbours is 1. We will denote the distances to the other three carbon atoms by , and .
A. Dress developed a theory to decide whether a set of points and distances between them can be realized in an -dimensional space. Here, of course, we have .
For cyclohexane the distances have to satisfy this equation.
They also must satisfy the equations given by cyclic shifts of the indeterminates.
The union of the solutions of this list is the solution of our original problem. If we impose positivity conditions, we get two relevant ideals. One ideal is zero-dimensional, namely , and this determines the ``boat'' form of cyclohexane. The other ideal is one-dimensional, which means that we have a solution space given by one parameter. This gives the ``chair'' form of cyclohexane. The parameter describes the angle of the ``back of the chair.''
groebnerFactorizegroebnerFactorizeGroebnerFactorizationPackage has an optional Boolean-valued second argument. When it is true partial results are displayed, since it may happen that the calculation does not terminate in a reasonable time. See the source code for GroebnerFactorizationPackage in groebf.input for more details about the algorithms used.
The domain Heap(S) implements a priority queue of objects of type S such that the operation extract! removes and returns the maximum element. The implementation represents heaps as flexible arrays (see FlexibleArrayXmpPage ). The representation and algorithms give complexity of for insertion and extractions, and for construction.
Create a heap of six elements.
Use insert! to add an element.
The operation extract! removes and returns the maximum element.
The internal structure of h has been appropriately adjusted.
Now extract! elements repeatedly until none are left, collecting the elements in a list.
Another way to produce the same result is by defining a heapsort function.
Create another sample heap.
Apply heapsort to present elements in order.
All rationals have repeating hexadecimal expansions. The operation hexhexHexadecimalExpansion returns these expansions of type HexadecimalExpansion. Operations to access the individual numerals of a hexadecimal expansion can be obtained by converting the value to RadixExpansion(16). More examples of expansions are available in the DecimalExpansionXmpPage , BinaryExpansionXmpPage , and RadixExpansionXmpPage .
This is a hexadecimal expansion of a rational number.
Arithmetic is exact.
The period of the expansion can be short or long ...
or very long!
These numbers are bona fide algebraic objects.
Axiom provides many operations for manipulating arbitrary precision integers. In this section we will show some of those that come from Integer itself plus some that are implemented in other packages. More examples of using integers are in the following sections: ugIntroNumbersPage in section ugIntroNumbersNumber IntegerNumberTheoryFunctionsXmpPage , DecimalExpansionXmpPage , BinaryExpansionXmpPage , HexadecimalExpansionXmpPage , and RadixExpansionXmpPage .
The size of an integer in Axiom is only limited by the amount of computer storage you have available. The usual arithmetic operations are available.
There are a number of ways of working with the sign of an integer. Let's use this x as an example.
First of all, there is the absolute value function.
The signsignInteger operation returns -1 if its argument is negative, 0 if zero and 1 if positive.
You can determine if an integer is negative in several other ways.
Similarly, you can find out if it is positive.
This is the recommended way of determining whether an integer is zero.
Use the zero?zero?Integer operation whenever you are
testing any mathematical object for equality with zero. This is
usually more efficient that using = (think of matrices: it is
easier to tell if a matrix is zero by just checking term by term than
constructing another ``zero'' matrix and comparing the two matrices
term by term) and also avoids the problem that = is usually used
for creating equations.
This is the recommended way of determining whether an integer is equal to one.
This syntax is used to test equality using =. It says that you want a Boolean (true or false) answer rather than an equation.
The operations odd?odd?Integer and even?even?Integer determine whether an integer is odd or even, respectively. They each return a Boolean object.
The operation gcdgcdInteger computes the greatest common divisor of two integers.
The operation lcmlcmInteger computes their least common multiple.
To determine the maximum of two integers, use maxmaxInteger.
To determine the minimum, use minminInteger.
The reduce operation is used to extend binary operations to more than two arguments. For example, you can use reduce to find the maximum integer in a list or compute the least common multiple of all integers in the list.
The infix operator ``/'' is not used to compute the quotient of integers. Rather, it is used to create rational numbers as described in FractionXmpPage .
The infix operation quoquoInteger computes the integer quotient.
The infix operation remremInteger computes the integer remainder.
One integer is evenly divisible by another if the remainder is zero. The operation exquoexquoInteger can also be used. See ugTypesUnionsPage in Section ugTypesUnionsNumber for an example.
The operation dividedivideInteger returns a record of the quotient and remainder and thus is more efficient when both are needed.
Records are discussed in detail in Section ugTypesRecords .
Use the operation factorfactorInteger to factor integers. It returns an object of type Factored Integer. See FactoredXmpPage for a discussion of the manipulation of factored objects.
The operation prime?prime?Integer returns true or false depending on whether its argument is a prime.
The operation nextPrimenextPrimeIntegerPrimesPackage returns the least prime number greater than its argument.
The operation prevPrimeprevPrimeIntegerPrimesPackage returns the greatest prime number less than its argument.
To compute all primes between two integers (inclusively), use the operation primesprimesIntegerPrimesPackage.
You might sometimes want to see the factorization of an integer when it is considered a Gaussian integer. See ComplexXmpPage for more details.
Axiom provides several number theoretic operations for integers. More examples are in IntegerNumberTheoryFunctionsXmpPage .
The operation fibonaccifibonacciIntegerNumberTheoryFunctions computes the Fibonacci numbers. The algorithm has running time for argument n.
The operation legendrelegendreIntegerNumberTheoryFunctions computes the Legendre symbol for its two integer arguments where the second one is prime. If you know the second argument to be prime, use jacobijacobiIntegerNumberTheoryFunctions instead where no check is made.
The operation jacobijacobiIntegerNumberTheoryFunctions computes the Jacobi symbol for its two integer arguments. By convention, 0 is returned if the greatest common divisor of the numerator and denominator is not 1.
The operation eulerPhieulerPhiIntegerNumberTheoryFunctions computes the values of Euler's -function where equals the number of positive integers less than or equal to n that are relatively prime to the positive integer n.
The operation moebiusMumoebiusMuIntegerNumberTheoryFunctions computes the Möbius function.
Although they have somewhat limited utility, Axiom provides Roman numerals.
The elements of a module M over a ring R are said to be linearly dependent over R if there exist in R, not all , such that . If such 's exist, they form what is called a linear dependence relation over R for the 's.
The package IntegerLinearDependence provides functions for testing whether some elements of a module over the integers are linearly dependent over the integers, and to find the linear dependence relations, if any.
Consider the domain of two by two square matrices with integer entries.
Now create three such matrices.
This tells you whether m1, m2 and m3 are linearly dependent over the integers.
Since they are linearly dependent, you can ask for the dependence relation.
This means that the following linear combination should be 0.
When a given set of elements are linearly dependent over R, this also means that at least one of them can be rewritten as a linear combination of the others with coefficients in the quotient field of R.
To express a given element in terms of other elements, use the operation solveLinearlyOverQsolveLinearlyOverQIntegerLinearDependence.
The IntegerNumberTheoryFunctions package contains a variety of operations of interest to number theorists. Many of these operations deal with divisibility properties of integers. (Recall that an integer a divides an integer b if there is an integer c such that b = a * c.)
The operation divisorsdivisorsIntegerNumberTheoryFunctions returns a list of the divisors of an integer.
You can now compute the number of divisors of 144 and the sum of the divisors of 144 by counting and summing the elements of the list we just created.
Of course, you can compute the number of divisors of an integer n, usually denoted d(n), and the sum of the divisors of an integer n, usually denoted (n), without ever listing the divisors of n.
In Axiom, you can simply call the operations numberOfDivisorsnumberOfDivisorsIntegerNumberTheoryFunctions and sumOfDivisorssumOfDivisorsIntegerNumberTheoryFunctions.
The key is that d(n) and (n) are ``multiplicative functions.'' This means that when n and m are relatively prime, that is, when n and m have no prime factor in common, then d(nm) = d(n) d(m) and (nm) = (n) (m). Note that these functions are trivial to compute when n is a prime power and are computed for general n from the prime factorization of n. Other examples of multiplicative functions are (n), the sum of the -th powers of the divisors of n and , the number of integers between 1 and n which are prime to n. The corresponding Axiom operations are called sumOfKthPowerDivisorssumOfKthPowerDivisorsIntegerNumberTheoryFunctions and eulerPhieulerPhiIntegerNumberTheoryFunctions.
An interesting function is (n), the Möbius function, defined as follows: (1) = 1, (n) = 0, when n is divisible by a square, and , when n is the product of k distinct primes. The corresponding Axiom operation is moebiusMumoebiusMuIntegerNumberTheoryFunctions. This function occurs in the following theorem:
Theorem (Möbius Inversion Formula):
Let f(n)
be a function on the positive integers and let F(n) be defined
by sum of f(n) over
d | n where the sum is taken over the positive divisors of
n. Then the values of f(n) can be recovered from the values of
F(n):
where again the sum is taken over the positive divisors of n.
When f(n) = 1, then F(n) = d(n). Thus, if you sum over the positive divisors d of n, you should always get 1.
Similarly, when f(n) = n, then F(n) = (n). Thus, if you sum (d) (n/d) over the positive divisors d of n, you should always get n.
The Fibonacci numbers are defined by and for .
The operation fibonaccifibonacciIntegerNumberTheoryFunctions computes the -th Fibonacci number.
Fibonacci numbers can also be expressed as sums of binomial coefficients.
Quadratic symbols can be computed with the operations legendrelegendreIntegerNumberTheoryFunctions and jacobijacobiIntegerNumberTheoryFunctions. The Legendre symbol is defined for integers and with an odd prime number. By definition, = +1, when is a square , = -1, when is not a square , and = 0, when is divisible by .
You compute via the command legendre(a,p).
The Jacobi symbol is the usual extension of the Legendre symbol, where n is an arbitrary integer. The most important property of the Jacobi symbol is the following: if K is a quadratic field with discriminant d and quadratic character , then . Thus, you can use the Jacobi symbol to compute, say, the class numbers of imaginary quadratic fields from a standard class number formula.
This function computes the class number of the imaginary quadratic field with discriminant d.
A kernel is a symbolic function application (such as sin(x+ y)) or a symbol (such as x). More precisely, a non-symbol kernel over a set S is an operator applied to a given list of arguments from S. The operator has type BasicOperator (see BasicOperatorXmpPage ) and the kernel object is usually part of an expression object (see ExpressionXmpPage ).
Kernels are created implicitly for you when you create expressions.
You can directly create a ``symbol'' kernel by using the kernelkernelKernel operation.
This expression has two different kernels.
The operator kernelskernelsExpression returns a list of the kernels in an object of type Expression.
This expression also has two different kernels.
The sin(x) kernel is used twice.
An expression need not contain any kernels.
If one or more kernels are present, one of them is designated the main kernel.
Kernels can be nested. Use heightheightKernel to determine the nesting depth.
This has height 2 because the x has height 1 and then we apply an operator to that.
Use the operatoroperatorKernel operation to extract the operator component of the kernel. The operator has type BasicOperator.
Use the namenameKernel operation to extract the name of the operator component of the kernel. The name has type Symbol. This is really just a shortcut for a two-step process of extracting the operator and then calling namenameBasicOperator on the operator.
Axiom knows about functions such as sin, cos and so on and can make kernels and then expressions using them. To create a kernel and expression using an arbitrary operator, use operatoroperatorBasicOperator.
Now f can be used to create symbolic function applications.
Use the is?is?Kernel operation to learn if the operator component of a kernel is equal to a given operator.
You can also use a symbol or a string as the second argument to is?is?Kernel.
Use the argumentargumentKernel operation to get a list containing the argument component of a kernel.
Conceptually, an object of type Expression can be thought of a quotient of multivariate polynomials, where the ``variables'' are kernels. The arguments of the kernels are again expressions and so the structure recurses. See ExpressionXmpPage for examples of using kernels to take apart expression objects.