=================================================== = Major New Features in Mathematica Version 2.2 = =================================================== Summaries of New Features - -------------------------- This listing contains brief summaries of some of the enhancements to Mathematica between Version 2.1 and Version 2.2. Some of these enhancements are explained at greater length in subsequent sections. Particularly important changes are indicated by outlined bullets: o. Incompatibilities between Versions 2.1 and 2.2 are indicated below by crossed bullets: x. Algebra ======= o Symbolic definite integration now includes tests for non-integrable singularities, and corrections for branch cuts in the range of integration. o There is a new Method option for specifying the row reduction algorithm used by the linear algebra functions Inverse, LinearSolve, NullSpace, and RowReduce. Possible values for Method are CofactorExpansion, DivisionFreeRowReduction, OneStepRowReduction, and Automatic, which uses an internal heuristic for selecting an algorithm. - - The default value of the VerifySolutions option in Solve has been changed from False to Automatic. With VerifySolutions -> Automatic, solutions involving multiple-valued functions are tested by substituting them back into the original equation. For example, the solution {x -> (-1)^(2/3)} for the equation Solve[x^(3/2) == 1, x] is rejected upon testing. - - There is a new value, Automatic, for the ZeroTest option in the linear algebra functions Inverse, LinearSolve, NullSpace, RowReduce, Eigenvectors, and Eigensystem. ZeroTest->Automatic applies various transformations, including numerical approximations, to determine whether an expression is zero. - - The code used by Solve for handling equations with nontrivial powers has been revised and extended. Equations such as Solve[Exp[x+1] == Exp[2 x], x] and Solve[y^(1+a) == 1, y] will now be solved. - - Transcendental dependency checking in Eliminate and related functions has been improved so that it no longer rejects soluble transcendental dependencies. For example, Eliminate[{x^(a b) == f, b == E^(x y)}, b] will now correctly eliminate the parameter b. - - Equations involving repeated roots are now solved much more quickly, typically by a factor equal to the multiplicity of the root. - - The speed of Roots for equations that can be factored or decomposed has been improved. - - The form of results from Solve has been simplified, especially for polynomial equations involving roots. - - The behavior of Roots for nonpolynomial equations and other invalid inputs has been improved, as well as the ability to recognize inputs that are not explicitly polynomial equations. - - A shortcoming in handling of equations that are soluble by simple elimination of variables has been corrected. For example, Solve[b/(a x) == 1 && a == 1 && b == Sqrt[2], x] formerly gave no solution. - - Automatic recognition of linear equations has been improved. Formerly, Solve and related functions sometimes failed to recognize linear equations, and would compute solutions using methods designed for more general equations. - - Solve and Roots handle cubic and quartic equations faster, and give more concise output. - - There is a new function HermiteNormalForm that computes the Hermite normal form of a matrix of integers. - - LatticeReduce now handles integer matrices of deficient row rank. - - AlgebraicRules now returns an AlgebraicRulesData object rather than {{}} for the degenerate case AlgebraicRules[{},{}]. - - The speed of Solve for equations with several variables has been greatly improved, in part through the use of an improved algorithm for variable ordering. - - The function Det has been speeded up for all exact matrices. - - LUDecomposition now works for exact matrices. - - An infinite loop in multivariate factorization has been corrected. - - Dt[f, {x, n}] will now return unchanged for symbolic values of n. - - The NonConstants option in Dt now works for parameters within unrecognized functions. - - A number of simplifications for trigonometric functions of inverse trigonometric functions are now automatic. For example, Cos[ArcSin[z]] becomes Sqrt[1 z^2] and Cos[ArcTan[z]] becomes 1/Sqrt[1 + x^2]. - - The behavior of trigonometric and inverse trigonometric functions at infinity has been made more consistent. For example, Tan[Infinity] evaluates to Indeterminate rather than RealInterval[{-Infinity, Infinity}], and ArcSin[-Infinity] now evaluates to I Infinity. - - The function Beta[x, y] will now simplify automatically when x + y is an integer. - - Indefinite integration preserves the form of radicals in results when possible, thereby improving behavior with respect to branch cuts. For example, the results of Integrate[1/Sqrt[a-b x^2],x] and Integrate[Sqrt[-1-x^2], x] are now given in terms of the roots in the integrands. - - Indefinite integration preserves logarithmic branch cuts when possible, thereby improving consistency between constants of integration. For example, Integrate[Log[1 - a t], t] now gives an answer in terms of the Log[1 - a t] rather than Log[a t - 1]. - - ComplexExpand is 10--20% faster for typical examples. - - Limit and Residue now include support for the functions Csch, Sech, Coth, Rational, Zeta, Gamma, and Beta. Limit will also now handle the functions ArcCsch, ArcSech, ArcTanh, and ArcCoth. - - The ability of Integrate to handle integrands involving unknown functions has been extended. Example: Integrate[D[(E^b[x]*a[x]+E^d[x]*c[x])*Log[Log[x]],x],x]. - - The minus sign from a rational number with a numerator of 1 is distributed over Plus. For example, (-1/2) (-a-b) now returns (a + b)/2. - - An error in simplification of certain products of roots and rational numbers has been corrected to prevent infinite recursion. Example: (1/5) (Pi/2)^(3/2). - - Differentiation of SphericalHarmonicY[l, m, theta, phi] with respect to theta has been added. - - A rule for differentiation of LogGamma has been added. - - Series involving hyperbolic functions are now expressed in terms of hyperbolic functions rather than exponentials. Results both from Series and from functions such as Limit that use series expansions internally are improved. - - Limits involving the two argument form of Erf can now be computed. - - Directional limits are used when definite integrals are evaluated by computing limits of the corresponding indefinite integral. - - Series expansions for Hypergeometric0F1 with constant arguments are now handled correctly. - - Series expansions of Erf, Erfc, and Erfi are now supported. Asymptotic expansions have also been added for SinIntegral, CosIntegral, SinhIntegral, CoshIntegral, FresnelC, and FresnelS. - - The behavior of Apart and Factor for certain expressions containing roots and complex numbers has been improved. For example, the result of Apart[1/(1 - c ((-1 - I) x^3)^(3/2))^3] is now correct for all values of c and x. - - The behavior of Factor for polynomials containing inexact coefficients has been improved. For example, Factor[0.511547 + z^2] no longer returns a polynomial with a small linear term. - - An error in Expand for certain expressions with complex exponents has been corrected. Example: Expand[(x^3)^(1/2 + 2*I)] is now correct. - - Automatically simplified forms for Hypergeometric2F1 have been improved. - - A number of formerly incorrect results from definite integration have been corrected, including results for Gaussian definite integrals. x Unique integration variables are now generated when necessary in symbolic integration to prevent interaction between integration variables in nested integrals. x Automatic simplifications involving roots of integers have been changed and made more consistent. For example, Sqrt[2^3] now factors out even powers and returns 2 Sqrt[2]. x The behavior of LinearSolve[m, b] has been changed when b is a matrix. The result now satisfies the relation b == m.LinearSolve[m, b] rather than the transpose. Corresponding changes have been made in LUDecomposition and LUBackSubstitution. Numerics ======== o There is a new global variable $RandomState that gives an integer representing the internal state of the random number generator. o Optimized code has been added for solving sparse numerical systems of linear equations. Solve automatically applies this code to such equations. - - Normalization and ordering of the vectors returned by Eigenvectors is now independent of numerical precision. - - The functions Dot and MatrixPower have been rewritten for inexact numerical matrices, and are now faster. - - The function NDSolve now has an option MaxStepSize for controlling the maximum step size used in solving differential equations. - - The function NDSolve now accepts multiple segments of domains: for example, NDSolve[ {y'[x]==x, y[1]==1}, y[x], {x, 1, 2, 3, 4} ]. - - The function SchurDecomposition now has an option RealBlockForm->False. The option setting RealBlockForm->True reproduces the behavior of previous versions, which was to give 2 X 2 real blocks rather than complex numbers. - - The permutation matrix returned by SchurDecomposition is now a matrix of exact, rather than inexact, integers. - - An error in the treatment of the SingularityDepth option in NIntegrate for multi-dimensional integrals has been corrected. - - Det has been speeded up for complex numerical matrices and rational matrices. - - Inverse for matrices of machine real numbers or of integers has been speeded up. - - An error in NRoots related to automatic switching between machine arithmetic and extended precision arithmetic has been corrected. - - Fourier for multidimensional arrays has been speeded up. The initialization package Fourier.m is now obsolete. - - Log[Infinity] now evaluates to Infinity. Log[Indeterminate] now evaluates to Indeterminate. - - FindMinimum is now better able to handle functions which become large very rapidly away from the minimum. - - The behavior of JacobiAmplitude for exact numerical arguments has been corrected. Inputs such as JacobiAmplitude[2, 2] will return unchanged, rather than the result of an internal rule being returned. - - An inconsistency in numerical evaluation of Hypergeometric2F1 across the branch cut has been corrected. - - An error in numerical evaluation of Erfc along the imaginary axis has been corrected. - - Control of precision in numerical evaluation of trigonometric functions has been corrected. For example, iteration of x=ArcTan[Tan[x]] for inexact values of x will retain the original precision. - - Rounding used during conversion of high-precision numbers to machine-precision numbers has been improved. - - Numerical precision has been improved in computing square roots of complex numbers. x Canonical ordering for numbers has been changed and made more consistent. This change affects Sort and functions with the Orderless attribute. Numbers are now ordered first by real part, and if the real parts are equal, by the absolute value of the imaginary part. In particular, complex conjugate pairs will now be adjacent in sorted order. Numbers were formerly sorted first by real part and then by imaginary part. Input and Output ================ o The input \(char) can now be used to enter characters from an extended character set. For example \(Alpha) is recognized as the corresponding Greek character. Extended characters can be used in strings and in names for symbols. The InputForm of extended characters will display as \(char). Extended characters are encoded using the Unicode Standard. - - The value of the WordSeparators option can now be a pair of lists, as with RecordSeparators. - - FortranForm and CForm have been changed to display machine numbers at full machine precision. - - Handling of syntax errors involving the backquote (`) has been improved. - - Processing of octal character codes has been improved. For example, it is now possible to make a symbol whose name is an octal code. - - Comments contained in input are now written to the stream $Echo. - - The backquote character (`) can now appear in StringForm using \`, as in StringForm["aaa\`bbb `1` ccc", x]. - - Mathematica can now format more deeply nested expressions. - - Warning messages for incorrect parentheses in input have been improved. - - The number of input digits is now preserved when displaying negative machine numbers. - - An error in the TeXForm of Intersection has been fixed. - - Line breaking has been changed to prevent line breaks within multibyte characters, before punctuation marks, and within TeX tokens in the output of TeXForm. - - All file operation functions will now issue a warning message if the filename argument is an empty string. - - The speed of ReadList when reading multiline expressions has been greatly improved. - - An error has been corrected in the behavior of ReadList when the RecordLists -> True option is used and there are tabs or spaces at the end of a line. - - ReadList and related functions which read objects of type Number from a file can now accept numbers in which the exponent is specified with a D notation. For example, 1.D+8 will be read by ReadList as 1.0 * 10^8. - - The RecordLists option in ReadList will now work in the presence of a third argument specifying the number of objects to read. - - The RecordSeparators option in ReadList can now be used when reading Number format. x The display of numbers with zero precision has been changed to indicate the accuracy as an exponent: for example, 0. 10^99. x Parsing of nested SameQ is now left associative. SameQ[a, b] === SameQ[a, b] is now parsed as SameQ[SameQ[a, b], SameQ[a, b]] rather than SameQ[a, b, SameQ[a, b]]. x The input a != b == c is now equivalent to Inequality[a, Unequal, b, Equal, c] rather than Equal[Unequal[a, b], c], and the corresponding formatting rules have been added so Inequality[a, Unequal, b, Equal, c] is displayed as a != b == c. x The input a_:b/c is now treated as the pattern a_:(b/c) rather than the fraction (a_:b)/c. x The input x__:y is now treated as an optional pattern rather than a syntax error. Graphics and Sound ================== - - Support for additional PostScript operators (sqrt, etc.) has been added so that arrowheads and other objects can be drawn. - - The rendering of three-dimensional polygons viewed edge-on has been changed to show the polygon if it has visible edges. - - The rendering of shaded ContourGraphics objects is considerably faster, particularly when there is a large amount of small-scale structure in the output. Errors in processing of the ContourStyles and ContourLines options have also been corrected. - - The fourth element in the first argument of ParametricPlot3D can now be a list of graphics primitives. - - Coercion of Graphics3D objects to Graphics objects has been improved. - - Polygons in Graphics3D objects that lie outside the bounding box are now omitted from the display. - - An input argument checking error in ListPlay has been corrected. Machine-Specific Changes - - The X PostScript interpreters now support the use of visuals other than the default. This is particularly beneficial for users who have a 24-bit display in which the 24-bit visual is not the default visual. - - The X PostScript interpreters will now use Display PostScript if the necessary extensions are present on the X server. - - All X-based PostScript interpreter programs that use resource files will now run only if the proper resource file has been installed. This will help in repairing installation problems and enhance the reliability of these utilities. - - The X-based PostScript interpreters for Motif (motifps) and OPEN LOOK (olps) can now display rotated text. - - New output formats have been added to the PostScript interpreter rasterps to produce Portable BitMap (pbm), Portable PixMap (ppm), and Portable GrayMap (pgm) binary output files. Public domain libraries such as the PBMPlus package available on MathSource2pt exist to render this format into a wide variety of output types such as TIFF. (Note: rasterps does not exist on the Macintosh. The DOS version of rasterps is available on MathSource, but is not distributed on Windows.) System Features =============== o MathBook is now included. MathBook is an X-based program developed at Wolfram Research that provides a hypertext interface to navigate through documentation such as the Mathematica Reference Guide. Versions are available for Motif, OPEN LOOK, and Athena widget sets. - - Localization of variables in Module has been corrected for the case when variable initialization also involves a Module. - - A new option SameTest has been added to Union, Intersection, and Complement, for specifying the function to use when comparing expressions. As part of this change, Union and Intersection no longer have the attribute Orderless, but instead sort their arguments outside the main evaluator. - - The usage messages for options have been extended to include more complete information about possible values. MathLink (Not supported in the Windows or DOS versions of Mathematica) ======== o The kernel and the Notebook front end now communicate using MathLink. - - A new link protocol has been added for creating ``local'' link objects within MathLink source files for use in storing and manipulating Mathematica expressions. - - The C function MLTransferExpression has been added to the MathLink for copying an expression from one link to another. - - The C function MLDeviceInformation has been added for obtaining low-level device information. - - New C functions MLSetUserData and MLUserData have been added to the MathLink library for use in storing data in a link object. - - MathLink now supports the AppleTalk Data Stream Protocol. x The yield function interface has been changed. Now the first argument passed to the yield function is the link pointer. A slightly different implementation of the yield function feature was present but not documented in Version 2.1. Packages ======== (For more information, see Guide to Standard Mathematica Packages, Supplement V2.2.) o There is a new package Graphics`ContourPlot3D` for plotting implicit functions of three variables and constructing iso-surfaces of three-dimensional data sets. The package includes the function ContourPlot3D, for use with functions, and ListContourPlot3D, for use with lists of data. o There is a new package Calculus`PDSolve1` for symbolic solution of first-order partial differential equations. This package loads the package Calculus`DSolve` automatically as needed. - - The package Calculus`DSolve` now supports additional Ricatti equations and systems of nonlinear ordinary differential equations. - - DSolve has been speeded up for systems of linear equations with constant coefficients. Detection of degenerate solutions and rejection of invalid branches for valid solutions has been improved. Solutions have been added for inhomogeneous linear equations with constant coefficients. Additional classes of equations are solved by representing the result as an unevaluated definite integral (using Integrate) or as the solution of a nondifferential equation (using Solve). Certain classes of simultaneous equations and linear equations with variable coefficients have been added. Handling of equations with inexact coefficients has been improved. - - There is a new package Utilities`Package` that introduces functions for finding accessible Mathematica packages, and for getting documentation and summary information from standard package headers. - - A package NumericalMath`SplineFit` has been added. - - The package Graphics`Spline` has been modified to use the PostScript curveto operator so that splines corresponding to four-point Bezier curves are rendered more efficiently. The ability to render splines adaptively has also been added. - - There is a new package Graphics`Arrow` for generating pointers and arrowheads in graphical output. - - Option processing has been corrected and improved in a number of graphics packages, including Graphics`Graphics`, Graphics`Graphics3D`, and Graphics`PlotField3D`. Options are now supported in ErrorListPlot in the Graphics`Graphics` package. - - The functions Geodesate, Truncate, and OpenTruncate have been added in the Graphics`Polyhedra` package. - - Automatic numericalization in the packages Statistics`ContinuousDistributions`, Statistics`NormalDistribution`, and Statistics`DiscreteDistributions` has been made more consistent. Also, distributions defined in these packages will now return zero for parameters outside the domain of the distribution. - - There is a new package Calculus`VariationalMethods` for variational calculus. - - There is a new package Calculus`EllipticIntegrate` for handling standard classes of elliptic integrals. - - Handling of messages and error conditions in the package DiscreteMath`RSolve` has been improved. - - Extensive improvements and corrections have been made in the package Algebra`SymbolicSum`. Many finite sums of rational functions have been speeded up. - - The package NumericalMath`Butcher` has been modified. The number of steps in the method can now be symbolic. - - The package Calculus`FourierTransform` has been revised. An inconsistency in normalization of DiracDelta has been corrected. - - The package Calculus`LaplaceTransform` has been revised, with improved handling of multivariate transforms. - - The behavior of NLimit in NumericalMath`NLimit` has been improved for cases in which the algorithm fails. - - SimplifyGamma has been improved for generalized incomplete gamma functions. - - SimplifyPolyGamma has been improved for sums of PolyGamma functions, and an infinite recursion error has been corrected. - - There is a new package Miscellaneous`Music`. - - There is a new package Miscellaneous`Audio` that includes a variety of utilities for creating and manipulating sounds. - - A new package Statistics`Common`FitCommon` has been created for defining symbols common to the Statistics`LinearRegression` and Statistics`NonlinearFit` packages, and a package Graphics`Common`GraphicsCommon` for defining common symbols in graphics packages has been added. - - The behavior near singularities of PlotVectorField and related functions in the packages Graphics`PlotField` and Graphics`PlotField3D` has been improved. - - The precision of values used for colors in the Graphics`Colors` package has been increased to produce results more suitable for 24-bit displays. The package also includes specifications for 133 new colors. - - An error has been corrected in processing of the FrameTicks option for the logarithmic plotting functions (such as LogListPlot) in the Graphics`Graphics` package. - - Graphics created with FilledPlot in the Graphics`FilledPlot` package can now be easily combined with other graphics. This package now introduces an option to Graphics called AxesFront that allows the axes and grid lines to be drawn over the graphic. Also, a new function ListFilledPlot has been added. - - The ListShadowPlot3D function defined in the Graphics`Graphics3D` package can now be used with a nonsquare matrix of data. - - The package Obsolete.m provides equivalent code or warning messages for those Mathematica function usages that are no longer valid in Version 2.2. x The package PolynomialMod has been moved from the NumberTheory directory to the Algebra directory. The new package context is Algebra`PolynomialMod`. Symbolic Linear Algebra - ------------------------ Options in Linear Algebra Functions =================================== The algorithms used in Mathematica for working with symbolic matrices (matrices with exact or symbolic entries) and for solving linear equations with symbolic coefficients have been substantially extended for Version 2.2. The affected functions include Inverse, LinearSolve, NullSpace, RowReduce, Eigenvectors, and other functions (such as Solve and DSolve) that manipulate linear equations internally. The two most visible changes are the introduction of a Method option used to select an algorithm for row reduction, and the addition of ZeroTest->Automatic as a value for the ZeroTest option. Row reduction is described in the following sections. The ZeroTest option specifies a function to apply in determining whether a matrix element is zero. For complicated expressions, making this determination can be very time consuming, or even mathematically impossible. An expression involving transcendental functions, for example, may simplify to zero only through application of specialized identities. The ZeroTest option allows you to control the types of transformations that are used. The value ZeroTest->Automatic applies various transformations including numerical approximations in an effort to determine whether an expression is zero. This approach is particularly appropriate for matrices involving transcendental functions, algebraic numbers, or other complicated expressions. - -------------------------------------------------------------------------------- | | | ZeroTest->Automatic use built-in heuristics to decide whether an | | expression is zero | | | | ZeroTest->(# == 0 &) test only for expressions that are | | explicitly zero | | | | ZeroTest->(Together[#] == 0 &) | | apply the function Together to an | | expression before comparing it with zero | | | - -------------------------------------------------------------------------------- Values for the ZeroTest option in linear algebra functions. This matrix is singular. In[1]:= m = {{1, 2 Sin[x]^2}, {1, 1 - Cos[2 x]}} 2 Out[1]= {{1, 2 Sin[x] }, {1, 1 - Cos[2 x]}} With a trivial value for the ZeroTest option, Inverse does not detect that this matrix is singular. In[2]:= Inverse[m, ZeroTest -> (# == 0 &)] 1 - Cos[2 x] Out[2]= {{------------------------, 2 1 - Cos[2 x] - 2 Sin[x] 2 -2 Sin[x] ------------------------}, 2 1 - Cos[2 x] - 2 Sin[x] 1 {-(------------------------), 2 1 - Cos[2 x] - 2 Sin[x] 1 ------------------------}} 2 1 - Cos[2 x] - 2 Sin[x] Although ZeroTest -> Automatic requires slightly more time to evaluate, it does allow Inverse to determine that this matrix is singular. In[3]:= Inverse[m, ZeroTest -> Automatic] Inverse::sing: 2 Matrix {{1, 2 Sin[x] }, {1, 1 + <<1>>}} is singular. 2 Out[3]= Inverse[{{1, 2 Sin[x] }, {1, 1 - Cos[2 x]}}, ZeroTest -> Automatic] Row Reduction ============= Row reduction is the process of constructing linear combinations of rows of a matrix to obtain the reduced row echelon form of the matrix, in which all of the entries above and below the pivots are zero. If the matrix is thought of as a system of linear equations, row reduction corresponds to replacing a system of equations with an equivalent system consisting of linear combinations of the original equations. Here is the result from solving a pair of linear equations. In[4]:= Solve[{m11 x1 + m12 x2 == b1, m21 x1 + m22 x2 == b2}, {x1, x2}] b1 m12 (-(b2 m11) + b1 m21) Out[4]= {{x1 -> --- + --------------------------, m11 m11 (-(m12 m21) + m11 m22) -(b2 m11) + b1 m21 x2 -> -(--------------------)}} -(m12 m21) + m11 m22 These equations can be represented as the matrix equation m.x == b. In[5]:= m = {{m11, m12}, {m21, m22}}; b = {b1, b2} ; LinearSolve gives the solution to the matrix equation. This result is equivalent to the result obtained by Solve. In[6]:= LinearSolve[m, b] b1 m12 (b2 m11 - b1 m21) Out[6]= {--- - --------------------------, m11 m11 (-(m12 m21) + m11 m22) b2 m11 - b1 m21 --------------------} -(m12 m21) + m11 m22 Here is the row echelon form of the matrix of coefficients for this pair of equations. The solution can be obtained from the last column of the result. In[7]:= RowReduce[{{m11, m21, -b1}, {m12, m22, -b2}}] b1 Out[7]= {{1, 0, -(---) - m11 (-(b2 m11) + b1 m12) m21 --------------------------}, m11 (-(m12 m21) + m11 m22) -(b2 m11) + b1 m12 {0, 1, --------------------}} -(m12 m21) + m11 m22 Methods of Row Reduction In Version 2.2, the functions Inverse, LinearSolve, NullSpace, and RowReduce include a Method option for selecting an algorithm to use for row reduction. (A row reduction algorithm can also be specified for Solve, with the command SetOptions[RowReduce, Method -> method]). Although all values of the Method option give mathematically equivalent results, the complexity of the answer, and the time required to compute it, can differ significantly between methods. - -------------------------------------------------------------------------------- | | | Method->CofactorExpansion | | use cofactor expansion for row reduction | | | | Method->DivisionFreeRowReduction | | use the division-free algorithm for row | | reduction | | | | Method->OneStepRowReduction | | use the one-step algorithm for row reduction | | | | Method->Automatic select a row reduction algorithm automatically | | | - -------------------------------------------------------------------------------- Values for the Method option in linear algebra functions. Row reduction with Method->CofactorExpansion uses matrix cofactors to compute the inverse of the left-most square submatrix, and effectively multiplies by this inverse to get the row echelon form of the original matrix. This method is typically useful for small dense matrices. It will fail if the left-most square matrix is not invertible, or if there are more rows than columns, in which case the left-most square submatrix does not exist. If this method fails, the division-free algorithm is used. Both the division-free algorithm, selected using Method->DivisionFreeRowReduction, and the one-step algorithm, selected using Method -> OneStepRowReduction, obtain results using operations such as multiplying rows by constants, and adding one row of the matrix to another. As the name suggests, the division-free algorithm avoids division of matrix elements by pivots. The one-step algorithm does do exact divisions, and as a consequence will often give smaller intermediate and final results.The division-free and one-step algorithms are described in Erwin H. Bareiss, "Sylvester's Identity and Multistep Integer-Preserving Gaussian Elimination," Mathematical Computation 22, 103 (1968): 565--578. (Note that if the matrix contains approximate real numbers or radicals, Method -> OneStepRowReduction is ignored.) The default values of the Method option are chosen to give the preferred behavior for typical matrices. Although there is often a tradeoff between speed and complexity, this is not always the case. Sometimes the fastest method also gives the simplest results. You may want to experiment with different values for the Method option and select the method that seems most appropriate for your situation. Here is the default behavior for solving this set of linear equations. In[8]:= LinearSolve[{{x,y,0},{0,z,x},{y,x,0}}, {1,0,0}] 2 1 y y y z Out[8]= {- + -----------, -(-------), -----------} x 2 2 2 2 2 2 x (x - y ) x - y x (x - y ) Here is the solution obtained using Method >CofactorExpansion. This solution is mathematically equivalent to the previous solution, but may be given in a different form. In[9]:= LinearSolve[{{x,y,0},{0,z,x},{y,x,0}}, {1,0,0}, Method->CofactorExpansion] 2 x x y y z Out[9]= {-(----------), ----------, -(----------)} 3 2 3 2 3 2 -x + x y -x + x y -x + x y Here is the solution obtained using Method >DivisionFreeRowReduction. Again, both the time required for the computation and the size of the result may be different. In[10]:= LinearSolve[{{x,y,0},{0,z,x},{y,x,0}}, {1,0,0}, Method->DivisionFreeRowReduction] 2 1 y y y z Out[10]= {- + -----------, -(-------), -----------} x 2 2 2 2 2 2 x (x - y ) x - y x (x - y ) Other linear algebra functions, such as NullSpace, also have a Method option. In[11]:= NullSpace[{{x, 1, 3, 0}, {3 x, 0, 5, x}}, Method->OneStepRowReduction] 1 x -5 4 Out[11]= {{-(-), -, 0, 1}, {---, -(-), 1, 0}} 3 3 3 x 3 Random Number Generation - ------------------------- The functions SeedRandom[ ] and Random[ ] cause the internal state of the random number generator to change. Random[ ] returns a random number of the specified type and advances the random number generator to the next state so that the next call to Random[ ] will give you a different result. SeedRandom[ ] gives a completely new state that depends on the value of the seed specified. This lets you start the random number generator at the same place to get an identical sequence of random numbers, so you can, for example, repeat a simulated experiment. The global variable $RandomState allows you to save and restore the state of the random number generator. By saving its state, you can make other, unrelated calls to Random[ ], restore the state to what it was before the unrelated calls were made, and proceed as if those unrelated calls had never been made. This seeds the random number generator. In[1]:= SeedRandom[23]; This forms a table of random numbers. In[2]:= a = Table[Random[ ], {5}] Out[2]= {0.613023, 0.180991, 0.777741, 0.120589, 0.424956} This forms another table of random numbers. In[3]:= b = Table[Random[ ], {5}] Out[3]= {0.732973, 0.196755, 0.98667, 0.312975, 0.0609892} This reseeds the random number generator to the same initial state. In[4]:= SeedRandom[23]; You get the same random numbers as before. In[5]:= a == Table[Random[ ], {5}] Out[5]= True This saves the state of the random number generator in the variable savestate. In[6]:= savestate = $RandomState Out[6]= 5719829100760399981454893431860139940790300 9635798944922537314783898244824711380021450072991 4804102788634400420529694445087671496265568889367 4550095209321010238262197439701197574743526444609 3564127810430134664259030065716049623689870822495 2794067585775161966764581555216272246194708272492 9903373393832357719647189005481258347258401968165 2028508126110637841044993503256704014951433039886 8683344334190448841852859928837339683045086834879 7664126973441062108863413681785839989776553985455 9816325795628835230588320678529285283598436177670 2416322826697143753448517 This calls Random[ ] a few times. In[7]:= Table[Random[ ], {3}] Out[7]= {0.732973, 0.196755, 0.98667} This restores the state of the random number generator to what it was. In[8]:= $RandomState = savestate; You get the same random numbers as before. In[9]:= b == Table[Random[ ], {5}] Out[9]= True You do not need to explicitly save the value of $RandomState in a variable. This can be done for you automatically with a Block[ ] construct. You can define a function that saves and restores the random state. In[10]:= t := Block[{$RandomState = savestate}, Table[Random[ ], {3}]] This restores the state of the random number generator to what it was before b was formed. In[11]:= $RandomState = savestate; This calls Random[ ] from within a Block[ ] that saves the random state. In[12]:= t Out[12]= {0.732973, 0.196755, 0.98667} You get the same random numbers as before. In[13]:= b == Table[Random[ ], {5}] Out[13]= True Sparse Linear Systems - ---------------------- Mathematica provides the function Solve to solve systems of equations. When the system is linear in the variables, it can be represented and solved in a matrix form; this functionality is available from LinearSolve. This uses Solve to solve this system. In[1]:= Solve[ {3. x + 2. y == 5., 5. x + 3. y == 1.}, {x, y}] Out[1]= {{x -> -13., y -> 22.}} This uses LinearSolve to solve the same system represented as a matrix problem. In[2]:= LinearSolve[ {{3., 2.}, {5., 3.}}, {5., 1.}] Out[2]= {-13., 22.} Under appropriate conditions, Solve calls the same LU decomposition routines that LinearSolve uses. These conditions are that the set of equations is linear, and that the coefficients consist only of machine numbers. This technique for solving linear systems is suited to dense matrices where the number of zero entries is small. For these dense systems, the representation of the equations is more compact for LinearSolve than for Solve. Alternatively if the system is sparse, i.e., if it has a large number of zero entries, the Solve representation becomes much more efficient. Not only is there an efficient representation for these sparse systems, but there are specialized algorithms to solve them. Such algorithms have been added to Version 2.2, to be called automatically from Solve when the coefficients are real or complex machine numbers and the system is sparse. This sets up the equations. In[3]:= (n = 20; vars = Table[x[i], {i, n}]; eqns = Join[{-2. x[1] + x[2] == 1}, Table[x[i-1] - 2. x[i] + x[i+1] == i, {i, 2, n-1}], {x[n-1] - 2. x[n] == n}]; ) You won't want to see all the equations, but here are a few of them. In[4]:= Short[eqns, 4] Out[4]//Short= {-2. x[1] + x[2] == 1, x[1] - 2. x[2] + x[3] == 2, x[2] - 2. x[3] + x[4] == 3, <<2>>, <<2>>, <<13>>, x[18] - 2. x[19] + x[20] == 19, x[19] - 2. x[20] == 20} Solve will automatically call the sparse solver. This example runs many times faster in Version 2.2 than in Version 2.1. In[5]:= Solve[eqns, vars] Out[5]= {{x[1] -> -73.3333, x[2] -> -145.667, x[3] -> -216., x[4] -> -283.333, x[5] -> -346.667, x[6] -> -405., x[7] -> -457.333, x[8] -> -502.667, x[9] -> -540., x[10] -> -568.333, x[11] -> -586.667, x[12] -> -594., x[13] -> -589.333, x[14] -> -571.667, x[15] -> -540., x[16] -> -493.333, x[17] -> -430.667, x[18] -> -351., x[19] -> -253.333, x[20] -> -136.667}} Among the many uses for this functionality is the possibility of solving partial differential equations with finite difference methods. Interval Computation - --------------------- Introduction ============ An approximate number can be represented as an interval containing the exact value. Interval computation allows rigorous error analysis in calculations with approximate numbers. In versions of Mathematica prior to 2.2 the function RealInterval was available in the kernel for basic interval computations. The packages NumericalMath`IntervalArithmetic` and NumericalMath`IntervalAnalysis` provided some functionality that was not available in RealInterval. In Version 2.2, RealInterval has been extensively revised and renamed Interval (in anticipation of complex intervals to be supported in the future). The packages NumericalMath`IntervalArithmetic` and NumericalMath`IntervalAnalysis` are still included with Version 2.2, but the kernel function Interval is more powerful than the packages. Interval ======== - -------------------------------------------------------------------------------- | | | Interval[{a, b}] the real interval from a to b | | | | Interval[{a_1, b_1}, {a_2, b_2}, ... ] | | the union of the real intervals a_1 to b_1, | | a_2 to b_2, ... | | | - -------------------------------------------------------------------------------- Representations of real intervals. This is the interval from 1 to 4. In[1]:= Interval[{1, 4}] Out[1]= Interval[{1, 4}] An interval may be a single real number. In[2]:= Interval[4] Out[2]= Interval[{4, 4}] Several disjoint intervals may be part of a single Interval data object. In[3]:= Interval[{1, 3}, 4, {7, 9}] Out[3]= Interval[{1, 3}, {4, 4}, {7, 9}] Intersecting pieces are merged into single intervals. In[4]:= Interval[{1, 3}, {2, 4}] Out[4]= Interval[{1, 4}] Arithmetic can be done with intervals. In[5]:= Interval[{1, 4}] + Interval[{1, 2}, {10, 12}] Out[5]= Interval[{2, 6}, {11, 16}] Arithmetic with a mixture of numbers and intervals also works. In[6]:= Interval[{1, 5}] + 3 Out[6]= Interval[{4, 8}] With inexact numbers, directed rounding is used to ensure that the interval always contains the ``true'' value. In[7]:= Interval[3.] - 3 -16 -16 Out[7]= Interval[{-4.44089 10 , 4.44089 10 }] Division by an interval containing 0 results in two semi-infinite intervals. In[8]:= 1/Interval[{-2, 3}] 1 1 Out[8]= Interval[{-Infinity, -(-)}, {-, Infinity}] 2 3 Numerical evaluation is sometimes used to decide whether intervals intersect. In[9]:= Interval[{1, Pi}, {E, Sqrt[26]}, {4, 7}] Out[9]= Interval[{1, 7}] It should be noted that symbolic interval arithmetic is not supported. This is because combinatorial explosion of expressions involving Min and Max would quickly render any symbolic result useless. Set Theoretic Interval Functions ================================ The functions IntervalUnion, IntervalIntersection, and IntervalMemberQ provide set theoretic functionality. - -------------------------------------------------------------------------------- | | | IntervalUnion[int_1,int_2, ...] | | gives the set theoretic union of the intervals | | int_1, int_2, ... | | | | IntervalIntersection[int_1,int_2, ...] | | gives the set theoretic intersection of the | | intervals int_1, int_2, ... | | | | IntervalMemberQ[int,x] gives True if the number x is in the interval | | int and False otherwise | | | | IntervalMemberQ[int_1,int_2] | | gives True if the interval int_2 is contained | | within the interval int_1 and False otherwise | | | - -------------------------------------------------------------------------------- Set theoretic interval functions. This defines two intervals. In[10]:= (a = Interval[{1, 3}, 4, {7, 12}]; b = Interval[{2, 4}, {10, 20}];) This finds the union of the intervals. In[11]:= IntervalUnion[a, b] Out[11]= Interval[{1, 4}, {7, 20}] This finds the intersection of the intervals. In[12]:= IntervalIntersection[a, b] Out[12]= Interval[{2, 3}, {4, 4}, {10, 12}] The result may be an empty interval. In[13]:= IntervalIntersection[a, b, Interval[{-3, -2}]] Out[13]= Interval[] The number 10 is in the interval a. In[14]:= IntervalMemberQ[a, 10] Out[14]= True Numerical approximation is used when required. In[15]:= IntervalMemberQ[a, E] Out[15]= True The interval Interval[{8, 10}] is contained within the interval a. In[16]:= IntervalMemberQ[a, Interval[{8, 10}]] Out[16]= True Interval Comparisons ==================== In manipulating intervals, you often want to compare them or find their extrema. - -------------------------------------------------------------------------------- | | | Min[int] gives the greatest lower bound of the interval | | int | | | | Max[int] gives the least upper bound of the interval int | | | - -------------------------------------------------------------------------------- Extremal functions. - -------------------------------------------------------------------------------- | | | int_1 < int_2 gives True if every element in the interval | | int_1 is less than every element of int_2 | | | | int_1 <= int_2 gives True if every element in the interval | | int_1 is less than or equal to every element | | of int_2 | | | | int_1 > int_2 gives True if every element in the interval | | int_1 is greater than every element of | | int_2 | | | | int_1 >= int_2 gives True if every element in the interval | | int_1 is greater than or equal to every | | element of int_2 | | | - -------------------------------------------------------------------------------- Interval comparisons. The smallest number in this interval is 1. In[17]:= Min[Interval[{1, Infinity}]] Out[17]= 1 The smallest upper bound for this interval is Infinity. In[18]:= Max[Interval[]] Out[18]= -Infinity The number 3 is common to both intervals so the inequality is False. In[19]:= Interval[{1, 3}] < Interval[{3, 7}] Out[19]= False Only the number 4 is common to both intervals, so the inequality is True. In[20]:= Interval[{4, 7}] >= Interval[{1, 4}] Out[20]= True Elementary Functions on Intervals ================================= The basic arithmetic operations and the elementary functions are supported for interval arithmetic. In all cases directed rounding is used when inexact numbers are involved. Sin maps one interval onto another. In[21]:= Sin[Interval[{2, 4}]] Out[21]= Interval[{Sin[4], Sin[2]}] Intersecting intervals are merged. In[22]:= Sin[Interval[{-1, 1}, {2, 4}]] Out[22]= Interval[{-Sin[1], Sin[2]}] Interior extrema are dealt with properly. In[23]:= Cos[Interval[{3, 4}]] Out[23]= Interval[{-1, Cos[4]}] Abs maps intervals to intervals. In[24]:= Abs[Interval[{-5, -2}, {1, 3}]] Out[24]= Interval[{1, 5}] To get a bound on the magnitudes of the numbers in an interval use Max or Min in conjunction with Abs. In[25]:= Max[Abs[Interval[{-5, 3}]]] Out[25]= 5 Lists as Sets: Sameness of Elements - ------------------------------------ The default comparison test for the functions Union[ ], Intersection[ ], and Complement[ ] is based on canonical ordering: if canonical ordering distinguishes between two elements in a list, they are considered different. In many situations this notion of sameness is much too stringent. For this reason, the functions Union[ ], Intersection[ ], and Complement[ ] now have an option called SameTest. This creates a table of nearly equal values. In[1]:= a = Table[1.0 + 2^k $MachineEpsilon, {k, 0, 8}] Out[1]= {1., 1., 1., 1., 1., 1., 1., 1., 1.} With the default SameTest each of these numbers is different. In[2]:= Union[a] Out[2]= {1., 1., 1., 1., 1., 1., 1., 1., 1.} SameQ[ ] allows small differences to be ignored. In[3]:= Union[a, SameTest -> SameQ] Out[3]= {1., 1., 1., 1., 1., 1., 1., 1.} Equal[ ] allows slightly larger differences to be ignored. In[4]:= Union[a, SameTest -> Equal] Out[4]= {1., 1.} MathLink Programming - -------------------- New Features ============ Loopback Links MathLink now supports ``loopback'' link objects that use a new ``local'' link protocol. - -------------------------------------------------------------------------------- | | int argc = 2; char* argv[ ] = {"-linkmode", "loopback"}; MLINK locallink = MLOpen(argc, argv); | | - -------------------------------------------------------------------------------- Opening a loopback link. A ``loopback'' link object is created when a link is opened with the MLOpen argument sequence "-linkmode" "loopback". This link mode selection implies the choice of "local" as the link protocol. This provides a Mathematica expression type for the C programmer. Expressions are read back from a loopback link in the same order that they were written to that link. Local link objects are not available from within Mathematica. Echoing Expressions from One Link to Another The C function MLTransferExpression(MLINK dmlp, MLINK smlp) has been added to the MathLink library; it transfers an expression off of one link and onto another in one call. This function is particularly useful for copying an expression off of the ``main'' link to a loopback link for later use. Low-Level Device Information The C function MLDeviceInformation(MLINK, unsigned long, void *, long *) has been added to the MathLink library; it returns information on the low-level device that may be important to the MathLink programmer. Various kinds of information can be accessed, depending on the device involved. A selector argument to MLDeviceInformation determines what kind of information is returned. (The valid selectors are listed in the mathlink.h header file.) The arguments to MLDeviceInformation are a link pointer, a selector, a pointer to a buffer, and a pointer to a buffer length. - -------------------------------------------------------------------------------- | | extern void get_mathlink_data(MLINK mlp); ... int fd = -1; long len = sizeof(fd); ... if (MLDeviceInformation(mlp, SOCKET_FD, &fd, &len)) { XtAddInput(fd, XtInputReadMask, get_mathlink_data, mlp); }else{ /* [have to poll with MLReady] */ ... } | | - -------------------------------------------------------------------------------- A typical use of MLDeviceInformation for X Window System programmers. Storing User Data within Link Data Structure The C functions MLSetUserData(MLINK, void *userdat, void (*userfn)(MLINK)) and have been added to the MathLink library; they provide storage inside a link object for use by the MathLink programmer. These functions provide storage for two pieces of data, symbolized here by userdat and userfn. The userdat value is an arbitrary value to store in the link data structure for whatever purpose the programmer wishes; it is of no significance to any MathLink library function. The userfn value (if it is not NULL) specifies a function to be invoked when the link is closed. AppleTalk Data Stream Protocol MathLink now supports the AppleTalk Data Stream Protocol. This protocol is specified as "ADSP". When opening a link in Mathematica, choose this protocol by setting the LinkOpen option LinkProtocol->"ADSP"; when opening a link in an external program, use the sequence "-linkprotocol" "ADSP" in the MLOpen argument list. This protocol is useful for communicating with Macintosh computers running System 6. ADSP is available for System 6, and it is also supported by AppleTalk Remote Access. Note that PPC, a System 7 protocol, is also supported by AppleTalk Remote Access. New Packet Types The following packet types are defined in addition to those listed in the MathLink Reference Guide. - -------------------------------------------------------------------------------- | Packet Packet type code Contents | |------------------------------------------------------------------------------| | | | ILLEGALPKT (== 0) code returned by | | MLNextPacket for unrecognized | | packet head | | EvaluatePacket[expr] EVALUATEPKT an expression to be evaluated | | (by Mathematica), with no | | line number increment | | EnterTextPacket[string] ENTERTEXTPKT a string to be processed as an| | input string by Mathematica, | | including line number | | incrementing and emission of | | output and input prompts | | InputStringPacket[string] INPUTSTRPKT packet sent by Mathematica it | | evaluates InputString[string] | | SuspendPacket[args] SUSPENDPKT packet sent by Mathematica to | | suspend communication (when | | switching control to another | | front end) | | ResumePacket[args] RESUMEPKT packet sent by Mathematica to | | resume communication (when | | switching control from | | another front end) | | BeginDialogPacket[args] BEGINDLGPKT packet sent by Mathematica | | when it begins a dialog | | (using Dialog[ ]) | | EndDialogPacket[args] ENDDLGPKT packet sent by Mathematica | | when it ends a dialog | | (e.g., with Return[ ]) | | | - -------------------------------------------------------------------------------- Additional packet names, type codes returned by MLNextPacket, and descriptions of enclosed expression(s). Experimental Features ===================== The following features are implemented in Version 2.2 on an experimental basis. The interface to these functions may change, or the functions may be removed from future versions. Returning to a Marked Position in Incoming Data Marks have been added. A mark (C type MLINKMark) stands for a place in the stream of incoming data to a link. The MathLink library functions related to marks are MLCreateMark, MLSeekToMark, and MLDestroyMark, as illustrated in the following sequence. - -------------------------------------------------------------------------------- | | MLINKMark mark = MLCreateMark(mlp); MLGetInteger(mlp, &i); MLSeekToMark(mlp, mark, 0); MLGetInteger(mlp, &j); assert(i == j); MLDestroyMark(mlp, mark); | | - -------------------------------------------------------------------------------- Experimental functions for marking and returning to a location in incoming data. This provides a mechanism to return to previously marked positions in the stream. Forking a Link Forked links have been implemented with the MathLink library function MLDuplicateLink(MLINK mlp, char *name). By forking a link, a programmer can have two different code sequences independently access the same incoming data. - -------------------------------------------------------------------------------- | | MLINK childlink = MLDuplicateLink(parentlink, "child"); MLGetInteger(parentlink, &i); MLGetInteger(childlink, &j); assert(i == j); MLClose(childlink); | | - -------------------------------------------------------------------------------- Using the experimental link-forking feature. The fork feature has uses similar to those of the mark feature. It also allows passing link objects by value rather than by reference. Putting and Getting Arrays of Numbers The MathLink library has a number of functions for transmitting multidimensional arrays of numbers. For example, for arrays of integers there are MLPutIntegerArray(MLINK, int *, long *, char **, long), MLGetIntegerArray(MLINK, int **, long **, char ***, long *), and MLDisownIntegerArray(MLINK, int *, long *, char **, long). There are similar functions for short integers, long integers, floats, doubles, and long doubles. MLPutIntegerArray puts an array of integers onto a link. Its arguments are: a link pointer; a pointer to an array of integers; a pointer to a vector of long integers that specify the dimensions of the array; a pointer to a vector of strings giving the head to use in each dimension ( i.e., at each succeeding level in the expression); and a long integer giving the number of dimensions. For example, the following sequence in a C program puts a three-by-three matrix of integers onto a link. - -------------------------------------------------------------------------------- | | int iarray[3,3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} long ndims = 2; long dims[2] = {3, 3}; char *heads[2] = {"List", "List"}; MLPutIntegerArray(mlp, iarray, dims, heads, ndims); | | - -------------------------------------------------------------------------------- Putting an array of integers onto a link. A typical program sequence using MLGetIntegerArray to receive an array of integers might look like the following. - -------------------------------------------------------------------------------- | | int * iarray; long * dims; char ** heads; long ndims; MLGetIntegerArray(mlp, &iarray, &dims, &heads, &ndims) use_array(iarray, dims, heads, ndims); MLDisownIntegerArray(mlp, iarray, dims, heads, ndims) | | - -------------------------------------------------------------------------------- Getting an array from a link. After accessing the received data, a program should make the memory used by MathLink for the array available again by calling MLDisownIntegerArray. Other MathLink Developments =========================== The following MathLink features have been present since Version 2.1, but have not been covered in the MathLink Reference Guide. Accessing a Link's Name The C function MLName(MLINK) defined in the MathLink returns a pointer to the name of the specified link. The memory referenced by this pointer should be considered read-only memory: a program may look at this string, but should not change it or deallocate it. Generally, the link name is set when the link is created. User-Defined Error Conditions The MathLink library function MLSetError(MLINK, int) can be used to set the MathLink error condition for a link. The second argument should be an integer identifying the type of error; this integer will be returned by a subsequent call of MLError. MLSetError has no effect if the error condition is already set to something other than MLEOK. Once the error condition has been set, subsequent MathLink function calls will fail until the error condition is cleared with MLClearError. The programmer can expand on the set of predefined error codes in mathlink.h to include one or more additional values. Message Data It is often desirable for one program communicating with another to have a way to send urgent data---bypassing other data that have been sent, but have not yet been read by the other program. MathLink provides a message data channel for this purpose. The MathLink Reference Guide includes a limited description of message data features, in the context of interrupting Mathematica an external program or interrupting an installed external program from Mathematica. That discussion mentions the MathLink library function MLPutMessage(MLINK, unsigned long), which may be used to put messages onto a link. A message is a one of a set of predefined unsigned long constants defined in mathlink.h. The MathLink library includes several other functions related to message data. A message-handling function may be specified with the C function MLSetMessageHandler(MLINK, MLMessageHandlerType), and a pointer to the message handler can be retrieved with MLMessageHandler(MLINK). The message handler is invoked asynchronously whenever a message arrives on a link. To check for arriving messages and process them synchronously, the functions MLMessageReady(MLINK) and MLGetMessage(MLINK, unsigned long *, unsigned long *) are also provided. Pass NULL as the third argument to MLGetMessage. Establishing a Connection before Transmitting Expression Data When a link is opened with MLOpen or LinkOpen, a link data structure is created, but a working connection is not established until both partners in the communication have taken some further action. That further action can be simply to call a MathLink function for putting data to, or getting data from, the link. If necessary, the put or get function will block and wait for the other side of the connection to come up. Another option is to explicitly establish the connection by calling the MathLink library function MLConnect(MLINK). MLConnect attempts to establish a connection on an opened link, and will block until the connection is made. MLConnect allows the programmer to control where in the program blocking will occur while the connection is established. The programmer may want to set the yield function (see the following section) before calling MLConnect. Yield Functions Often, MathLink function calls must block and wait for something to be written at the other end of the connection. For many applications, it is desirable to have a program do something else while the MathLink function waits. To do this, a programmer may specify a yield function that should be invoked by MathLink while a link operation is blocked. The C functions MLSetYieldFunction(MLINK, MLYieldFunctionType) and MLYieldFunction(MLINK) in the MathLink library allow the programmer to specify or retrieve the yield function. Every time a MathLink function blocks, the yield function will be invoked. The link pointer for the link involved will be passed as the first argument to the yield function. A yield function must return 0 to tell MathLink to continue with the function call (if the function is still blocked, the yield function will be invoked again). The yield function may return 1 to tell MathLink to abort the blocked function call. The programmer should be aware that aborting the function call might cause the link to die. Non-ASCII String Manipulation Mathematica strings and symbols may contain characters outside of the ASCII standard character set, and strings containing such characters can be received and sent via MathLink. Mathematica uses its own encoding to represent these characters as a sequence of bytes. Therefore, if your program is going to handle Mathematica strings that may include non-ASCII characters, you may need to use special string functions defined in mathlink.h and the MathLink library. An important virtue of these functions is that they recognize characters that are encoded in multiple bytes and treat them as single characters for character-by-character operations. To iterate over the characters in a Mathematica string, use the macro MLforString, in a construction like the following. - -------------------------------------------------------------------------------- | | MLStringPosition pos; char *s; MLforString(s, pos){ /* Do something with string s and character position pos. */ } | | - -------------------------------------------------------------------------------- Iterating over the characters in a Mathematica string. In this loop construct, s is a Mathematica string and pos is a data structure that will be used as the loop index, representing a certain character position within the string. The functions for manipulating the string position and the character at a given position are MLStringChar(MLStringPosition pos) and MLPutCharToString(int, char **). MLStringChar should be used within an MLForString construct to access the characters in a string. Given an MLStringPosition argument representing a certain position within a string, MLStringChar returns an integer character code for the character at that position. MLPutCharToString takes an integer character code and a pointer to a pointer to char as arguments; it writes the character's Mathematica encoding to the given location, increments the pointer to point to the next character location, and returns an integer indicating how many bytes were needed for that character. If MLPutCharToString is called with NULL as the second argument, it returns the number of bytes needed for that character, but does not write the character anywhere. For examples of how these functions are used, refer to the reverse.tm program, which is among the MathLink examples included in your Mathematica distribution, or see the comments under ``MathLink non-ASCII string interface'' in mathlink.h. - ----------------------------------------- Copyright (c) 1993 Wolfram Research, Inc. Mathematica and MathLink are registered trademarks, and MathSource and Mathbook are trademarks of Wolfram Research, Inc. All other product names mentioned are trademarks of their producers.