IMSL C/Math Library User Guide
IMSL C/Math Library User Guide
IMSL
C functions
for
mathematical
applications
C/Math/Library 4.0
User's Guide
Quick Tips on How to Use this Online Manual
Click to display only the page. Click to go back to the previous page
from which you jumped.
Click and drag to page to magnify Click to fit the entire page within the
the view. window.
Click and drag to page to reduce the view. Click to fit the page width inside the
window.
Click and drag to the page to select text. Click to find part of a word, a complete
word, or multiple words in a active
document.
Click to go to the first page.
Printing an online file: Select Print from the File menu to print an online file. The dialog box that opens allows you
to print full text, range of pages, or selection.
Important Note: The last blank page of each chapter (appearing in the hard copy documentation) has been deleted
from the on-line documentation causing a skip in page numbering before the first page of the next chapter, for
instance, Chapter 4 in the on-line documentation ends on page 279 and Chapter 5 begins on page 281.
Numbering Pages. When you refer to a page number in the PDF online documentation, be aware that the page
number in the PDF online documentation will not match the page number in the original document. A PDF
publication always starts on page 1, and supports only one page-numbering sequence per file.
Copying text. Click the button and drag to select and copy text.
Viewing Multiple Online Manuals: Select Open from the File menu, and open the .PDF file you need.
Select Cascade from the Window menu to view multiple files.
Resizing the Bookmark Area in Windows: Drag the double-headed arrow that appears on the area’s border as you
pass over it.
Resizing the Bookmark Area in UNIX: Click and drag the button that appears on the area’s border at the
bottom of the vertical bar.
Jumping to Topics: Throughout the text of this manual, links to chapters and other sections appear in green color
text to indicate that you can jump to them. To return to the page from which you jumped, click the return
back icon on the toolbar. Note: If you zoomed in or out after jumping to a topic, you will return to the
previous zoom view(s) before returning to the page from which you jumped.
Let’s try it, click on the following green color text: Chapter 1: Linear Systems
If you clicked on the green color in the example above, Chapter 1: Linear Systems opened.
To return to this page, click the on the toolbar.
Visual Numerics, Inc. Visual Numerics Visual Numerics SARL
Corporate Headquarters International Ltd. Tour Europe
1300 W Sam Houston Pkwy., Ste 150 Centennial Court 33 Place des Corolles Cedex
Houston, Texas 77042-4548 Suite 1, North Wing F-92049 Paris La Defense
USA Easthampstead Road France
BRACKNELL BERSHIRE
PHONE: 713-784-3131 RG12 1YQ PHONE: +33-1-46-93-94-20
FAX: 713-781-9260 United Kingdom FAX: +33-1-46-93-94-39
e-mail: info@[Link] e-mail: info@[Link]
PHONE: +44-1-344-45-8700
FAX: +44-1-344-45-8748
e-mail: info@[Link]
Visual Numerics S. A. de C.V. Visual Numerics International GmbH Visual Numerics Japan, Inc
th
Florencia 57 Piso 10-01 Zettachring 10 GOBANCHO HIKARI Building 4 Floor
Col. Juarez D-70567 Stuttgart 14 Goban-cho ChIiyoda-KU
Mexico D. F. C. P. 06000 Germany Tokyo, 113
Mexico JAPAN
PHONE: +52-5514-9730 or 9628 PHONE: +49-711-13287-0
FAX: +52-5514-5880 FAX: +49-711-13287-99 PHONE: +81-3-5211-7760
e-mail: vni@[Link] FAX: +81-3-5211-7769
e-mail: vnijapan@[Link]
COPYRIGHT NOTICE: Copyright 1990-2000, an unpublished work by Visual Numerics, Inc. All rights reserved.
VISUAL NUMERICS, INC., MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THIS MATERIAL, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. Visual Numerics, Inc., shall not be liable for errors contained herein or for incidental, consequential, or other indirect
damages in connection with the furnishing, performance, or use of this material.
TRADEMARK NOTICE: IMSL, Visual Numerics, IMSL FORTRAN Numerical Libraries, IMSL Productivity Toolkit, IMSL
Libraries Environment and Installation Assurance Test, C Productivity Tools, FORTRAN Productivity Tools, IMSL C/Math/Library,
IMSL C/Stat/Library, IMSL Fortran 90 MP Library, and IMSL Exponent Graphics are registered trademarks or trademarks of Visual
Numerics, Inc., in the U.S. and other countries. Sun, SunOS, and Solaris are registered trademarks or trademarks of Sun Microsystems,
Inc. SPARC and SPARCompiler are registered trademarks or trademarks of SPARC International, Inc. Silicon Graphics is aregisterd
trademark of Silicon Graphics, Inc. IBM, AIX, and RS/6000 are registered trademarks or trademarks of International Business
Machines Corporation. HP is a trademark of Hewlett-Packard. Silicon Graphics and IRIX are registered trademarks or trademarks of
Silicon Graphics, Inc. DEC and AXP are registered trademarks or trademarks of Digital Equipment Corporation. All other trademarks
are the property of their respective owners.
Use of this document is governed by a Visual Numerics Software License Agreement. This document contains confidential and
proprietary information constituting valuable trade secrets. No part of this document may be reproduced or transmitted in any form
without the prior written consent of Visual Numerics.
RESTRICTED RIGHTS LEGEND: This documentation is provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by
the U.S. Government is subject to the restrictions set forth in subparagraph (c)(1)(ll) of the Rights in Technical Data and Computer
Software clause at DFAR 252.227-7013, and in subparagraphs (a) through (d) of the Commercial Computer Software - Restricted
Rights clause at FAR 52.227-19, and in similar clauses in the NASA FAR Supplement, when applicable. Contractor/Manufacturer is
Visual Numerics, Inc., 1300 W Sam Houston Pkwy., Ste 150, Houston, Texas 77042.
Fortran and C
IMSL Application Development Tools
Click here to go to C/Stat/Library
Contents
Introduction vii
Index i
Product Support v
IMSL C/Math/Library
The IMSL C/Math/Library is a library of C functions useful in scientific programming.
Each function is designed and documented to be used in research activities as well as
by technical specialists. A number of the example programs also show graphs of
resulting output.
Getting Started
To use any of the IMSL C/Math/Library functions, you first must write a program in C
to call the function. Each function conforms to established conventions in programming
and documentation. We give first priority in development to efficient algorithms, clear
documentation, and accurate results. The uniform design of the functions makes it easy
to use more than one function in a given application. Also, you will find that the design
consistency enables you to apply your experience with one IMSL C/Math/Library
function to all other IMSL functions that you use.
1 #include <math.h>
z bg
1
0
ln x x −1/ 2 dx = −4
2 #include <imsl.h>
3
4 float fcn(float x);
5
6 main()
7 {
8 float q, exact;
9 /* evaluate the integral */
Signal Handling
When calling C/Math/Library from a multithreaded application it is necessary to turn
C/Math/Library 's signal-handling capability off. This is accomplished by making a
single call to imsl_error_options before any calls are made to C/Math/Library.
For an example of turning off C/Math/Library's internal signal handling , see Example 3
of imsl_error_options.
C/Math/Library 's error handling in a multithreaded application behaves similarly to
how it behaves in a single-threaded application. The major difference is that an error
stack exists for each thread calling C/Math/Library functions. The result of separate
error stacks for each thread is greater control of the error handler options for each
thread. Each thread can set its own options for the C/Math/Library error handler using
imsl_error_options. For an example of setting error handler options for separate
threads, see Example 3 of imsl_error_options.
Input Arguments
In a multithreaded application attention must be given to the data sent to
C/Math/Library. Some arguments that may appear to be input-only are temporarily
modified during the call and restored before returning to the caller. Care must be used
to avoid usage of the same data space in separate threads calling functions in
C/Math/Library.
Note: If you are using non-ANSI C and the variables are of type auto, then the above
declarations would need to be declared as type static float.
General Mode
A general matrix is a square n × n matrix. The data type of a general array can be float,
double, f_complex, or d_complex.
Rectangular Mode
A rectangular matrix is an m × n matrix. The data type of a rectangular array can be
float, double, f_complex, or d_complex.
Symmetric Mode
A symmetric matrix is a square n × n matrix A, such that AT = A. (The matrix AT is the
transpose of A.) The data type of a symmetric array can be float or double.
Hermitian Mode
A Hermitian matrix is a square n × n matrix A, such that
AH = A T = A
The matrix A is the complex conjugate of A, and
AH ≡ AT
b[0].row = b[0].col = 0;
b[0].val = imsl_cf_convert (4.0, 0.0);
b[1].row = 1; b[1].col = 0;
b[1].val = imsl_cf_convert (1.0, 1.0);
b[2].row = b[2].col = 1;
b[2].val = imsl_cf_convert (4.0, 0.0);
b[3].row = 2; b[3].col = 1;
b[3].val = imsl_cf_convert (1.0, 1.0);
b[4].row = b[4].col = 2;
b[4].val = imsl_cf_convert (4.0, 0.0);
b[5].row = 3; b[5].col = 2;
b[5].val = imsl_cf_convert (1.0, 1.0);
b[6].row = b[6].col = 3;
b[6].val = imsl_cf_convert (4.0, 0.0);
}
The IMSL C/Math/Library cannot take advantage of the symmetry in matrices that are
not positive definite. The implication here is that a symmetric matrix that happens to be
indefinite cannot be stored in this compact symmetric form. Rather, both upper and
lower triangles must be specified and the sparse general solver called.
1,0
A1,1
A2 ,1
A2 ,2
A3,2
A3,3
A4 ,3
A4 ,4
0
PPQ
This data would then be stored contiguously, row-major order, in an array of length 20.
The following declaration will store this matrix in band storage format:
float a[] = {
0.0, 1.0, 2.0, 3.0, 4.0,
10.0, 20.0, 30.0, 40.0, 50.0,
5.0, 6.0, 7.0, 8.0, 0.0};
As in the sparse coordinate representation, there is a space saving symmetric version of
band storage. As an example, look at the following 5 × 5 symmetric problem:
LM A 0 ,0 A0 ,1 A0 ,2 0 0 OP
MM A 0 ,1 A1,1 A1,2 A1,3 0 PP
A= A A1,2 A2 ,2 A2 ,3 A2 ,4
MM 0 0 ,2
A1,3 A2 ,3 A3,3 A3,4
PP
MN 0 0 A2 ,4 A3,4 A4 ,4 PQ
In band symmetric storage format, the data would be arranged as
LM 0 0 A0 ,2 A1,3 A2 ,4 OP
MM 0 A0 ,1 A1,2 A2 ,3 A3,4 PP
NA
0 ,0 A1,1 A2 ,2 A3,3 A4 ,4 Q
The following Hermitian example illustrates the procedure:
LM b8,0g b11, g b11, g 0 OP 0
MMb1,−1g b8,0g b11, g b g
11
, P 0
H = b1,−1g
MM 0 b1,−1g b8,0g b g b g PP
11
, 11
,
b1,−1g b1,−1g b g b gP
8,0 11
,
MN 0 0 b1,−1g b g b gPQ
1,−1 8,0
The following program fragments would store H in h, using band symmetric storage
format.
f_complex h[] = {
{0.0, 0.0}, {0.0, 0.0}, {1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0},
{0.0, 0.0}, {1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0},
{8.0, 0.0}, {8.0, 0.0}, {8.0, 0.0}, {8.0, 0.0}, {8.0, 0.0}};
or equivalently
f_complex h[15];
h[0] = h[1] = h[5] = imsl_cf_convert (0.0, 0.0);
Subscripts 0 1 2 3 4 5 6 7 8 9 10
colptr 0 3 5 7 9 11
rowind 0 4 2 3 0 1 4 0 3 4 1
values 1 5 2 4 −3 −2 −5 −1 −4 6 3
The following program fragment shows the relation between CSC storage format and
coordinate representation:
k = 0;
for (i=0; i<n; i++) {
start = colptr[i];
stop = colptr[i+1];
for (j=start; j<stop; j++) {
a[k].row = rowind[j];
a[k].col = i;
a[k++].val = values[j];
}
}
nz =k;
Naming Conventions
Most functions are available in both a type float and a type double version, with names
of the two versions sharing a common root. Some functions also are available in type
int, or the IMSL-defined types f_complex or d_complex versions. A list of each type
and the corresponding prefix of the function name in which multiple type versions exist
follows:
Type Prefix
float imsl_f_
double imsl_d_
int imsl_i_
f_complex imsl_c_
d_complex imsl_z_
The section names for the functions only contain the common root to make finding the
functions easier. For example, the functions imsl_f_lin_sol_gen and
imsl_d_lin_sol_gen can be found in section lin_sol_gen in Chapter 1.
Where appropriate, the same variable name is used consistently throughout a chapter in
the IMSL C/Math/Library. For example, in the functions for eigensystem analysis,
eval denotes the vector of eigenvalues and n_eval denotes the number of eigenvalues
computed or to be computed.
When writing programs accessing the IMSL C/Math/Library, the user should choose C
names that do not conflict with IMSL external names. The careful user can avoid any
conflicts with IMSL names if, in choosing names, the following rule is observed:
Printing Results
Most functions in the IMSL C/Math/Library do not print any of the results; the output is
returned in C variables. You can print the results yourself.
The IMSL C/Math/Library contains some special functions just for printing arrays. For
example, imsl_f_write_matrix is a convenient function for printing matrices of
type float. See Chapter 11, “Printing Functions,” for detailed descriptions of these
functions.
Complex Arithmetic
Users can perform computations with complex arithmetic by using IMSL predefined
data types. These types are available in two floating-point precisions:
• f_complex for single-precision complex values
xviii • Error Handling, Underflow, Overflow, and Document Examples IMSL C/Math/Library
• d_complex for double-precision complex values
A description of complex data types and functions is given in the Reference Material.
Missing Values
Some of the functions in the IMSL C/Math/Library allow the data to contain missing
values. These functions recognize as a missing value the special value referred to as “not
a number,” or NaN. The actual value is different on different computers, but it can be
obtained by reference to the IMSL function imsl_f_machine, described in Chapter 12,
“Utilities.”
The way that missing values are treated depends on the individual function and is
described in the documentation for the function.
Routines
1.1 Linear Equations with Full Matrices
Factor, Solve, and Inverse for General Matrices
Real matrices......................................................................... lin_sol_gen 4
Complex matrices ..................................................lin_sol_gen (complex) 11
Factor, Solve, and Inverse for Positive Definite Matrices
Real matrices.....................................................................lin_sol_posdef 17
Complex matrices .............................................lin_sol_posdef (complex) 22
Usage Notes
Solving Systems of Linear Equations
A square system of linear equations has the form Ax = b, where A is a user-specified
n × n matrix, b is a given right-hand side n vector, and x is the solution n vector. Each
entry of A and b must be specified by the user. The entire vector x is returned as output.
When A is invertible, a unique solution to Ax = b exists. The most commonly used
direct method for solving Ax = b factors the matrix A into a product of triangular
matrices and solves the resulting triangular systems of linear equations. Functions that
use direct methods for solving systems of linear equations all compute the solution to
Ax = b. Thus, if a function with the prefix “imsl_f_lin_sol” is called with the
required arguments, a pointer to x is returned by default. Additional tasks, such as only
factoring the matrix A into a product of triangular matrices, can be done using
keywords.
Matrix Factorizations
In some applications, it is desirable to just factor the n × n matrix A into a product of
two triangular matrices. This can be done by calling the appropriate function for
solving the system of linear equations Ax = b. Suppose that in addition to the solution
x of a linear system of equations Ax = b, the LU factorization of A is desired. Use the
keyword IMSL_FACTOR in the function imsl_f_lin_sol_gen to obtain access to the
factorization. If only the factorization is desired, use the keywords
IMSL_FACTOR_ONLY and IMSL_FACTOR.
Besides the basic matrix factorizations, such as LU and LLT, additional matrix
factorizations also are provided. For a real matrix A, its QR factorization can be
computed by the function imsl_f_lin_least_squares_gen. Functions for
computing the singular value decomposition (SVD) of a matrix are discussed in a later
section.
Matrix Inversions
The inverse of an n × n nonsingular matrix can be obtained by using the keyword
IMSL_INVERSE in functions for solving systems of linear equations. The inverse of a
A= å q T
i =1 si ,i ui vi
xk = å k
i =1t i ,i eb u jv
T
i i
ti ,i =
R|S s
−1
i ,i if si ,i ≥ tol > 0
|T0 otherwise
The user specifies the value of tol. This value determines how “close” the given matrix
is to a singular matrix. Further restrictions may apply to the number of terms in the sum,
k ≤ q. For example, there may be a value of k ≤ q such that the scalars |(bTui)|, i > k are
smaller than the average uncertainty in the right-hand side b. This means that these
scalars can be replaced by zero; and hence, b is replaced by a vector that is within the
stated uncertainty of the problem.
lin_sol_gen
Solves a real general system of linear equations Ax = b. Using optional arguments, any
of several related computations can be performed. These extra tasks include computing
the LU factorization of A using partial pivoting, computing the inverse matrix A-1,
solving ATx = b, or computing the solution of Ax = b given the LU factorization of A.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_gen (int n, float a[], float b[], …, 0)
The type double procedure is imsl_d_lin_sol_gen.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float a[] (Input)
Array of size n × n containing the matrix.
float b[] (Input)
Array of size n containing the right-hand side.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_TRANSPOSE
Solve ATx = b.
Default: Solve Ax = b
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, int **p_pvt, float **p_factor (Output)
p_pvt: The address of a pointer to an array of length n containing the pivot
sequence for the factorization. On return, the necessary space is allocated by
imsl_f_lin_sol_gen. Typically, int *p_pvt is declared, and &p_pvt is
used as an argument.
p_factor: The address of a pointer to an array of size n × n containing the
LU factorization of A with column pivoting. On return, the necessary space is
allocated by imsl_f_lin_sol_gen. The lower-triangular part of this array
contains information necessary to construct L, and the upper-triangular part
contains U. Typically, float *p_factor is declared, and &p_factor is used
as an argument.
IMSL_FACTOR_USER, int pvt[], float factor[] (Input/Output)
Examples
Example 1
This example solves a system of three linear equations. This is the simplest use of the
function. The equations follow below:
x1 + 3x2 + 3x3 = 1
x1 + 3x2 + 4x3 = 4
x1 + 4x2 + 3x3 = −1
#include <imsl.h>
main()
{
int n = 3;
float *x;
float a[] = {1.0,
3.0, 3.0,
1.0,
3.0, 4.0,
1.0,
4.0, 3.0};
float b[] = {1.0,
4.0, -1.0};
/* Solve Ax = b for x */
x = imsl_f_lin_sol_gen (n, a, b, 0);
/* Print x */
Output
Solution, x, of Ax = b
1 2 3
-2 -2 3
Example 2
This example solves the transpose problem ATx = b and returns the LU factorization of
A with partial pivoting. The same data as the initial example is used, except the solution
x = A-Tb is returned in an array allocated in the main program. The L matrix is returned
in implicit form.
#include <imsl.h>
main()
{
int n = 3, pvt[3];
float factor[9];
float x[3];
float a[] = {1.0, 3.0, 3.0,
1.0, 3.0, 4.0,
1.0, 4.0, 3.0};
float b[] =
{1.0, 4.0, -1.0};
/* Solve trans(A)*x = b for x */
imsl_f_lin_sol_gen (n, a, b,
IMSL_TRANSPOSE,
IMSL_RETURN_USER, x,
IMSL_FACTOR_USER, pvt, factor,
0);
/* Print x */
imsl_f_write_matrix ("Solution, x, of trans(A)x = b", 1, n, x, 0);
Output
Solution, x, of trans(A)x = b
1 2 3
4 -4 1
LU factors of A
1 2 3
1 1 3 3
2 -1 1 0
3 -1 0 1
Pivot sequence
Example 3
This example computes the inverse of the 3 × 3 matrix A of the initial example and
solves the same linear system. The matrix product C = A-1A is computed and printed.
The function imsl_f_mat_mul_rect is used to compute C. The approximate result
C = I is obtained.
#include <imsl.h>
main()
{
int n = 3;
float *x;
float *p_inva;
float *C;
/* Solve Ax = b */
x = imsl_f_lin_sol_gen (n, a, b,
IMSL_INVERSE, &p_inva,
0);
/* Print solution */
Output
Solution, x, of Ax = b
1 2 3
-2 -2 3
Input A
1 2 3
1 1 3 3
2 1 3 4
3 1 4 3
Example 4
This example computes the solution of two systems. Only the right-hand sides differ.
The matrix and first right-hand side are given in the initial example. The second right-
hand side is the vector c = [0.5, 0.3, 0.4] T. The factorization information is computed
with the first solution and is used to compute the second solution. The factorization
work done in the first step is avoided in computing the second solution.
#include <imsl.h>
main()
{
int n = 3, pvt[3];
float factor[9];
float *x,*y;
/* Print x */
imsl_f_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
Output
Solution, x, of Ax = b
1 2 3
-2 -2 3
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is
“rcond” = #. The solution might not be accurate.
Fatal Errors
IMSL_SINGULAR_MATRIX The input matrix is singular.
lin_sol_gen (complex)
Solves a complex general system of linear equations Ax = b. Using optional arguments,
any of several related computations can be performed. These extra tasks include
computing the LU factorization of A using partial pivoting, computing the inverse
matrix A-1, solving AHx = b, or computing the solution of Ax = b given the LU
factorization of A.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_gen (int n, f_complex a[], f_complex b[], …,
0)
The type d_complex procedure is imsl_z_lin_sol_gen.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
f_complex a[] (Input)
Array of size n × n containing the matrix.
f_complex b[] (Input)
Array of length n containing the right-hand side.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space, use free.
If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_TRANSPOSE
Solve AHx = b
Default: Solve Ax = b
IMSL_RETURN_USER, f_complex x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, int **p_pvt, f_complex **p_factor (Output)
p_pvt: The address of a pointer to an array of length n containing the pivot
sequence for the factorization. On return, the necessary space is allocated by
imsl_c_lin_sol_gen. Typically, int *p_pvt is declared, and &p_pvt is
used as an argument.
p_factor: The address of a pointer to an array of size n × n containing the
LU factorization of A with column pivoting. On return, the necessary space is
allocated by imsl_c_lin_sol_gen. The lower-triangular part of this array
contains information necessary to construct L, and the upper-triangular part
contains U. Typically, f_complex *p_factor is declared, and &p_factor
is used as an argument.
IMSL_FACTOR_USER, int pvt[], f_complex factor[] (Input/Output)
pvt[]: A user-allocated array of size n containing the pivot sequence for the
factorization.
factor[]: A user-allocated array of size n × n containing the LU
factorization of A. The lower-triangular part of this array contains information
necessary to construct L, and the upper-triangular part contains U.
These parameters are input if IMSL_SOLVE is specified. They are output
otherwise. If A is not needed, factor and a can share the same storage.
Description
The function imsl_c_lin_sol_gen solves a system of linear algebraic equations with
a complex coefficient matrix A. It first computes the LU factorization of A with partial
pivoting such that L-1A = U. The matrix U is upper-triangular, while
L-1A ≡ PnLn-1Pn-1…L1P1A ≡ U. The factors Pi and Li are defined by the partial
pivoting. Each Pi is an interchange of row i with row j ≥ i. Thus, Pi is defined by that
value of j. Every
Li = I + mi eiT
Examples
Example 1
This example solves a system of three linear equations. The equations are:
(1 + i) x1 + (2 + 3i) x2 + (3 − 3i) x3 = 3 + 5i
main()
{
int n = 3;
f_complex *x;
/* Solve Ax = b for x */
x = imsl_c_lin_sol_gen (n, a, b, 0);
/* Print x */
imsl_c_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
}
Output
Solution, x, of Ax = b
1 2 3
( 1, -1) ( 2, 4) ( 3, -0)
main()
{
int n = 3, pvt[3];
f_complex factor[9];
f_complex x[3];
/* Solve ctrans(A)*x = b for x */
imsl_c_lin_sol_gen (n, a, b,
IMSL_TRANSPOSE,
IMSL_RETURN_USER, x,
IMSL_FACTOR_USER, pvt, factor,
0);
/* Print x */
imsl_c_write_matrix ("Solution, x, of ctrans(A)x = b", 1, n, x, 0);
Output
Solution, x, of ctrans(A)x = b
1 2 3
( -9.79, 11.23) ( 2.96, -3.13) ( 1.85, 2.47)
LU factors of A
1 2 3
1 ( -2.000, 1.000) ( -4.000, 4.000) ( 5.000, 3.000)
2 ( 0.600, 0.800) ( -1.200, 1.400) ( 2.200, 0.600)
3 ( 0.200, 0.600) ( -1.118, 0.529) ( 4.824, 1.294)
Pivot sequence
1 2 3
3 3 3
Example 3
This example computes the inverse of the 3 × 3 matrix A in the first example and also
solves the linear system. The product matrix C = A-1A is computed as a check. The
approximate result is C = I.
#include <imsl.h>
main()
{
int n = 3;
f_complex *x;
f_complex *p_inva;
f_complex *C;
/* Solve Ax = b for x */
x = imsl_c_lin_sol_gen (n, a, b,
IMSL_INVERSE, &p_inva,
0);
/* Print solution */
imsl_c_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
Output
Solution, x, of Ax = b
1 2 3
( 1, -1) ( 2, 4) ( 3, -0)
Input A
1 2 3
1 ( 1, 1) ( 2, 3) ( 3, -3)
2 ( 2, 1) ( 5, 3) ( 7, -5)
3 ( -2, 1) ( -4, 4) ( 5, 3)
Inverse of A
1 2 3
1 ( 1.330, 0.594) ( -0.151, 0.028) ( -0.604, 0.613)
2 ( -0.632, -0.538) ( 0.160, 0.189) ( 0.142, -0.245)
3 ( -0.189, 0.160) ( 0.193, -0.052) ( 0.024, 0.042)
Product, inv(A)*A
1 2 3
1 ( 1, -0) ( -0, -0) ( -0, 0)
2 ( 0, 0) ( 1, 0) ( 0, -0)
3 ( -0, -0) ( -0, 0) ( 1, 0)
Fatal Errors
IMSL_SINGULAR_MATRIX The input matrix is singular.
lin_sol_posdef
Solves a real symmetric positive definite system of linear equations Ax = b. Using
optional arguments, any of several related computations can be performed. These extra
tasks include computing the Cholesky factor, L, of A such that A = LLT, computing the
inverse matrix A-1, or computing the solution of Ax = b given the Cholesky factor, L.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_posdef (int n, float a[], float b[], …, 0)
The type double procedure is imsl_d_lin_sol_posdef.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float a[] (Input)
Array of size n × n containing the matrix.
float b[] (Input)
Array of size n containing the right-hand side.
Return Value
A pointer to the solution x of the symmetric positive definite linear system Ax = b.
To release this space, use free. If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, float **p_factor (Output)
The address of a pointer to an array of size n × n containing the
LLT factorization of A. On return, the necessary space is allocated by
imsl_f_lin_sol_posdef. The lower-triangular part of this array contains
L and the upper-triangular part contains LT. Typically, float *p_factor is
declared, and &p_factor is used as an argument.
IMSL_FACTOR_USER, float factor[] (Input/Output)
A user-allocated array of size n × n containing the LLT factorization of A.
The lower-triangular part of this array contains L, and the upper-triangular part
contains LT. If A is not needed, a and factor can share the same storage.
If IMSL_SOLVE is specified, it is input; otherwise, it is output.
IMSL_FAC_COL_DIM, int fac_col_dim (Input)
The column dimension of the array containing the LLT factorization of A.
Default: fac_col_dim = n
IMSL_INVERSE, float **p_inva (Output)
The address of a pointer to an array of size n × n containing the inverse of the
matrix A. On return, the necessary space is allocated by
imsl_f_lin_sol_posdef. Typically, float *p_inva is declared, and
&p_inva is used as an argument.
IMSL_INVERSE_USER, float inva[] (Output)
A user-allocated array of size n × n containing the inverse of A.
IMSL_INV_COL_DIM, int inva_col_dim (Input)
The column dimension of the array containing the inverse of A.
Default: inva_col_dim = n
IMSL_CONDITION, float *cond (Output)
A pointer to a scalar containing an estimate of the L1 norm condition number
of the matrix A. Do not use this option with IMSL_SOLVE_ONLY.
Description
The function imsl_f_lin_sol_posdef solves a system of linear algebraic equations
having a symmetric positive definite coefficient matrix A. The function first computes
the Cholesky factorization LLT of A. The solution of the linear system is then found by
solving the two simpler systems, y = L-1b and x = L-Ty. When the solution to the linear
system or the inverse of the matrix is sought, an estimate of the L1 condition number of
A is computed using the same algorithm as in Dongarra et al. (1979). If the estimated
condition number is greater than 1/ε (where ε is the machine precision), a warning
message is issued. This indicates that very small changes in A may produce large
changes in the solution x.
The function imsl_f_lin_sol_posdef fails if L, the lower-triangular matrix in the
factorization, has a zero diagonal element.
Examples
Example 1
A system of three linear equations with a symmetric positive definite coefficient matrix
is solved in this example. The equations are listed below:
x1 − 3x2 + 2x3 = 27
main()
{
/* Solve Ax = b for x */
x = imsl_f_lin_sol_posdef (n, a, b, 0);
/* Print x */
imsl_f_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
}
Output
Solution, x, of Ax = b
1 2 3
1 -4 7
Example 2
This example solves the same system of three linear equations as in the initial example,
but this time returns the LLT factorization of A. The solution x is returned in an array
allocated in the main program.
#include <imsl.h>
main()
{
int n = 3;
float x[3], *p_factor;
float a[] = {1.0, -3.0, 2.0,
-3.0, 10.0, -5.0,
2.0, -5.0, 6.0};
float b[] = {27.0, -78.0, 64.0};
/* Solve Ax = b for x */
imsl_f_lin_sol_posdef (n, a, b,
IMSL_RETURN_USER, x,
IMSL_FACTOR, &p_factor,
0);
/* Print x */
imsl_f_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
Output
Solution, x, of Ax = b
1 2 3
1 -4 7
Example 3
This example solves the same system as in the initial example, but given the Cholesky
factors of A.
#include <imsl.h>
main()
{
int n = 3;
float *x, *a;
float factor[ ] = {1.0, -3.0, 2.0,
-3.0, 1.0, 1.0,
2.0, 1.0, 1.0};
float b[ ] = {27.0, -78.0, 64.0};
/* Solve Ax = b for x */
x = imsl_f_lin_sol_posdef (n, a, b,
IMSL_FACTOR_USER, factor,
IMSL_SOLVE_ONLY,
0);
/* Print x */
imsl_f_write_matrix ("Solution, x, of Ax = b", 1, n, x, 0);
}
Output
Solution, x, of Ax = b
1 2 3
1 -4 7
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is
“rcond” = #. The solution might not be accurate.
Fatal Errors
IMSL_NONPOSITIVE_MATRIX The leading # by # submatrix of the input matrix is
not positive definite.
IMSL_SINGULAR_MATRIX The input matrix is singular.
IMSL_SINGULAR_TRI_MATRIX The input triangular matrix is singular. The index of
the first zero diagonal element is #.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_posdef (int n, f_complex a[], f_complex b[],
…, 0)
The type d_complex procedure is imsl_z_lin_sol_posdef.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
f_complex a[] (Input)
Array of size n × n containing the matrix.
f_complex b[] (Input)
Array of size n containing the right-hand side.
Return Value
A pointer to the solution x of the Hermitian positive definite linear system Ax = b. To
release this space, use free. If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
Description
The function imsl_c_lin_sol_posdef solves a system of linear algebraic equations
having a Hermitian positive definite coefficient matrix A. The function first computes
the LLH factorization of A. The solution of the linear system is then found by solving
the two simpler systems, y = L-1b and x = L-Hy. When the solution to the linear system
is required, an estimate of the L1 condition number of A is computed using the
algorithm in Dongarra et al. (1979). If the estimated condition number is greater than
1/ε (where ε is the machine precision), a warning message is issued. This indicates that
very small changes in A may produce large changes in the solution x. The function
imsl_c_lin_sol_posdef fails if L, the lower-triangular matrix in the factorization,
has a zero diagonal element.
Example 1
A system of five linear equations with a Hermitian positive definite coefficient matrix is
solved in this example. The equations are as follows:
2x1 +(−1 + i)x2 = 1 +5i
(−1 − i)x1 +4x2 + (1 + 2i)x3 = 12 − 6i
(1 − 2i)x2 +10x3 + 4ix4 = 1 − 16i
−4ix3 + 6x4 + (1 + i)x5 = −3 − 3i
(1 − i)x4 + 9x5 = 25 + 16i
#include <imsl.h>
main()
{
int n = 5;
f_complex *x;
f_complex a[] = {
{2.0,0.0}, {-1.0,1.0},{0.0,0.0}, {0.0,0.0}, {0.0,0.0},
{-1.0,-1.0},{4.0,0.0}, {1.0,2.0}, {0.0,0.0}, {0.0,0.0},
{0.0,0.0}, {1.0,-2.0},{10.0,0.0},{0.0,4.0}, {0.0,0.0},
{0.0,0.0}, {0.0,0.0}, {0.0,-4.0},{6.0,0.0}, {1.0,1.0},
{0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,-1.0},{9.0,0.0}
};
f_complex b[] = {
{1.0,5.0}, {12.0,-6.0}, {1.0,-16.0}, {-3.0,-3.0}, {25.0,16.0}
};
/* Solve Ax = b for x */
x = imsl_c_lin_sol_posdef(n, a, b, 0);
/* Print x */
imsl_c_write_matrix("Solution, x, of Ax = b", 1, n, x, 0);
}
Output
Solution, x, of Ax = b
1 2 3
( 2, 1) ( 3, -0) ( -1, -1)
4 5
( 0, -2) ( 3, 2)
Example 2
This example solves the same system of five linear equations as in the first example.
This time, the LLH factorization of A and the solution x is returned in an array allocated
in the main program.
#include <imsl.h>
main()
/* Print x */
imsl_c_write_matrix("Solution, x, of Ax = b", 1, n, x, 0);
Output
Solution, x, of Ax = b
1 2 3
( 2, 1) ( 3, -0) ( -1, -1)
4 5
( 0, -2) ( 3, 2)
4 5
1 ( 0.000, -0.000) ( 0.000, -0.000)
2 ( 0.000, -0.000) ( 0.000, -0.000)
3 ( 0.000, 1.386) ( 0.000, -0.000)
4 ( 2.020, 0.000) ( 0.495, 0.495)
5 ( 0.495, -0.495) ( 2.917, 0.000)
Fatal Errors
IMSL_NONPOSITIVE_MATRIX The leading # by # minor matrix of the input
matrix is not positive definite.
IMSL_HERMITIAN_DIAG_REAL During the factorization the matrix has a large
imaginary component on the diagonal. Thus, it
cannot be positive definite.
IMSL_SINGULAR_TRI_MATRIX The triangular matrix is singular. The index of
the first zero diagonal term is #.
lin_sol_gen_band
Solves a real general band system of linear equations, Ax = b. Using optional arguments, any
of several related computations can be performed. These extra tasks include computing the
LU factorization of A using partial pivoting, solving ATx = b, or computing the solution of
Ax = b given the LU factorization of A.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_gen_band (int n, float a[], int nlca, int nuca, float
b[], …, 0)
The type double procedure is imsl_d_lin_sol_gen_band.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float a[] (Input)
Array of size (nlca + nuca + 1) containing the n × n banded coefficient matrix
in band storage mode.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space use free.
If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_TRANSPOSE
Solve ATx = b.
Default: Solve Ax = b.
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, int **p_pvt, float **p_factor (Output)
p_pvt: The address of a pointer to an array of length n containing the pivot
sequence for the factorization. On return, the necessary space is allocated by
imsl_f_lin_sol_gen_band. Typically, int *p_pvt is declared and
&p_pvt is used as an argument.
p_factor: The address of a pointer to an array of size
(2nlca + nuca + 1) × n containing the LU factorization of A with column
pivoting. On return, the necessary space is allocated by
imsl_f_lin_sol_gen_band. Typically, float *p_factor is declared and
&p_factor is used as an argument.
IMSL_FACTOR_USER, int pvt[], float factor[] (Input/Output)
Description
The function imsl_f_lin_sol_gen_band solves a system of linear algebraic
equations with a real band matrix A. It first computes the LU factorization of A based
on the blocked LU factorization algorithm given in Du Croz et al. (1990). Level-3
BLAS invocations are replaced with inline loops. The blocking factor block_factor
has the default value of 1, but can be reset to any positive value not exceeding 32.
The solution of the linear system is then found by solving two simpler systems,
y = L-1b and x = U-1y. When the solution to the linear system or the inverse of the
matrix is sought, an estimate of the L1 condition number of A is computed using
Higham’s modifications to Hager’s method, as given in Higham (1988). If the
estimated condition number is greater than 1/ε (where ε is the machine precision), a
warning message is issued. This indicates that very small changes in A may produce
large changes in the solution x. The function imsl_f_lin_sol_gen_band fails if
U, the upper triangular part of the factorization, has a zero diagonal element.
Example 1
This example demonstrates the simplest use of this function by solving a system of four
linear equations. This is the simplest usage of the function. The equations are as
follows:
2x1 − x2 = 3
−3x1 + x2 − 2x3 = 1
−x3 + 2x4 = 11
2x3 + x4 = −2
#include <imsl.h>
void main ()
{
int n = 4;
int nuca = 1;
int nlca = 1;
float *x;
Output
Solution x, of Ax = b
1 2 3 4
2 1 -3 4
Example 2
In this example, the problem Ax = b is solved using the data from the first example.
This time, the factorizations are returned and the problem ATx = b is solved without
recomputing LU.
#include <imsl.h>
void main ()
{
Output
Solution of Ax = b
1 2 3 4
2 1 -3 4
Solution of trans(A)x = b
1 2 3 4
-6 -5 -1 -0
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is
"rcond" = #. The solution might not be accurate.
Fatal Errors
IMSL_SINGULAR_MATRIX The input matrix is singular.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_gen_band (int n, f_complex a[], int nlca,
int nuca, f_complex b[], …, 0)
The type double procedure is imsl_z_lin_sol_gen_band.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
f_complex a[] (Input)
Array of size (nlca + nuca + 1) × n containing the n × n banded coefficient
matrix in band storage mode.
int nlca (Input)
Number of lower codiagonals in a.
int nuca (Input)
Number of upper codiagonals in a.
f_complex b[] (Input)
Array of size n containing the right-hand side.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space use free.
If no solution was computed, NULL is returned.
Description
The function imsl_c_lin_sol_gen_band solves a system of linear algebraic
equations with a complex band matrix A. It first computes the LU factorization of A
Examples
Example 1
The following linear system is solved:
LM−2 − 3i 4 0 0 OP LM x OP LM −10 − 5i OP
0
#include <imsl.h>
void main()
{
int n = 4;
int nlca = 1;
int nuca = 1;
f_complex *x;
f_complex a[] =
{{0.0, 0.0}, {4.0, 0.0}, {-2.0, 2.0}, {-4.0, -1.0},
{-2.0, -3.0}, {-0.5, 3.0}, {3.0, -3.0}, {1.0, -1.0},
{6.0, 1.0}, {1.0, 1.0}, {0.0, 2.0}, {0.0, 0.0}};
f_complex b[] =
{{-10.0, -5.0}, {9.5, 5.5}, {12.0, -12.0}, {0.0, 8.0}};
Example 2
This example solves the problem Ax = b using the data from the first example. This
time, the factorizations are returned and then the problem AHx = b is solved without
recomputing LU.
#include <imsl.h>
#include <stdlib.h>
void main()
{
int n = 4;
int nlca = 1;
int nuca = 1;
int *pivot;
f_complex *x;
f_complex *factor;
f_complex a[] =
{{0.0, 0.0}, {4.0, 0.0}, {-2.0, 2.0}, {-4.0, -1.0},
{-2.0, -3.0}, {-0.5, 3.0}, {3.0, -3.0}, {1.0, -1.0},
{6.0, 1.0}, {1.0, 1.0}, {0.0, 2.0}, {0.0, 0.0}};
f_complex b[] =
{{-10.0, -5.0}, {9.5, 5.5}, {12.0, -12.0}, {0.0, 8.0}};
Output
solution of Ax = b
1 ( 3, -0)
solution of ctrans(A)x = b
1 ( 5.58, -2.91)
2 ( -0.48, -4.67)
3 ( -6.19, 7.15)
4 ( 12.60, 30.20)
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is
“rcond” = #. The solution might not be accurate.
Fatal Errors
IMSL_SINGULAR_MATRIX The input matrix is singular.
lin_sol_posdef_band
Solves a real symmetric positive definite system of linear equations Ax = b in band
symmetric storage mode. Using optional arguments, any of several related computations
can be performed. These extra tasks include computing the RTR Cholesky factorization
of A, computing the solution of Ax = b given the Cholesky factorization of A, or
estimating the L1 condition number of A.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_posdef_band (int n, float a[], int ncoda, float b[],
…, 0)
The type double procedure is imsl_d_lin_sol_posdef_band.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float a[] (Input)
Array of size (ncoda + 1) × n containing the n × n positive definite band
coefficient matrix in band symmetric storage mode.
int ncoda (Input)
Number of upper codiagonals of the matrix.
float b[] (Input)
Array of size n containing the right-hand side.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, float **p_factor (Output)
The address of a pointer to an array of size (ncoda + 1) × n containing the
LLT factorization of A. On return, the necessary space is allocated by
imsl_f_lin_sol_posdef_band. Typically, float *p_factor is declared
and &p_factor is used as an argument.
IMSL_FACTOR_USER, float factor[] (Input/Output)
A user-allocated array of size (ncoda + 1) × n containing the LLT factorization
of A in band symmetric form. If A is not needed, factor and a can share the
same storage.
These parameters are “Input” if IMSL_SOLVE is specified. They are “Output”
otherwise.
IMSL_CONDITION, float *cond (Output)
A pointer to a scalar containing an estimate of the L1 norm condition number
of the matrix A. This option cannot be used with the option
IMSL_SOLVE_ONLY.
IMSL_FACTOR_ONLY
Compute the LLT factorization of A. If IMSL_FACTOR_ONLY is used, either
IMSL_FACTOR or IMSL_FACTOR_USER is required. The argument b is then
ignored, and the returned value of imsl_f_lin_sol_posdef_band is NULL.
IMSL_SOLVE_ONLY
Solve Ax = b given the LLT factorization previously computed by
imsl_f_lin_sol_posdef_band. By default, the solution to Ax = b is
pointed to by imsl_f_lin_sol_posdef_band. If IMSL_SOLVE_ONLY is
Description
The function imsl_f_lin_sol_posdef_band solves a system of linear algebraic
equations with a real symmetric positive definite band coefficient matrix A. It computes
the RTR Cholesky factorization of A. R is an upper triangular band matrix.
When the solution to the linear system or the inverse of the matrix is sought, an
estimate of the L1 condition number of A is computed using Higham’s modifications to
Hager’s method, as given in Higham (1988). If the estimated condition number is
greater than 1/ε (where ε is the machine precision), a warning message is issued. This
indicates that very small changes in A may produce large changes in the solution x.
The function imsl_f_lin_sol_posdef_band fails if any submatrix of R is not
positive definite or if R has a zero diagonal element. These errors occur only if A is
very close to a singular matrix or to a matrix which is not positive definite.
The function imsl_f_lin_sol_posdef_band is partially based on the LINPACK
subroutines CPBFA and SPBSL; see Dongarra et al. (1979).
Example 1
Solves a system of linear equations Ax = b, where
LM 2 0 −1 0 OP
6 LM OP
A=M PP MM PP
0 4 2 1 −11
MM−1 2 7 −1
b=
−11
PQ MN PQ
N0 1 −1 3 19
#include <imsl.h>
void main()
{
int n = 4;
int ncoda = 2;
float *x;
Example 2
This example solves the same problem Ax = b given in the first example. The solution
is returned in user-allocated space and an estimate of κ1(A) is computed. Additionally,
the RTR factorization is returned. Then, knowing that κ1(A) = ||A|| ||A-1||, the condition
number is computed directly and compared to the estimate from Higham’s method.
#include <imsl.h>
void main()
{
int n = 4;
int ncoda = 2;
float a[] = {0.0, 0.0, -1.0, 1.0,
0.0, 0.0, 2.0, -1.0,
2.0, 4.0, 7.0, 3.0};
float b[] = {6.0, -11.0, -11.0, 19.0};
float x[4];
float e_i[4];
float *factor;
float condition;
float column_norm;
float inverse_norm;
int i;
int j;
inverse_norm = 0.0;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) e_i[j] = 0.0;
e_i[i] = 1.0;
Output
Solution, x, of Ax = b
1 2 3 4
4 -6 2 9
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is
"rcond" = #. The solution might not be accurate.
Fatal Errors
IMSL_NONPOSITIVE_MATRIX The leading # by # submatrix of the input matrix is
not positive definite.
IMSL_SINGULAR_MATRIX The input matrix is singular.
lin_sol_posdef_band (complex)
Solves a complex Hermitian positive definite system of linear equations
Ax = b in band symmetric storage mode. Using optional arguments, any of several
related computations can be performed. These extra tasks include computing the
RHR Cholesky factorization of A, computing the solution of Ax = b given the
Cholesky factorization of A, or estimating the L1 condition number of A.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_posdef_band (int n, f_complex a[], int ncoda,
f_complex b[], …, 0)
The type double procedure is imsl_z_lin_sol_posdef_band.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space use free.
If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, f_complex x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_FACTOR, f_complex **p_factor (Output)
The address of a pointer to an array of size (ncoda + 1) × n containing the
RHR factorization of A. On return, the necessary space is allocated by
imsl_c_lin_sol_posdef_band. Typically, f_complex *p_factor is
declared and &p_factor is used as an argument.
IMSL_FACTOR_USER, f_complex factor[] (Input/Output)
A user-allocated array of size (ncoda + 1) × n containing the RHR
factorization of A in band symmetric form. If A is not needed, factor and a
can share the same storage.
These parameters are “Input” if IMSL_SOLVE is specified. They are “Output”
otherwise.
Description
The function imsl_c_lin_sol_posdef_band solves a system of linear algebraic
equations with a real symmetric positive definite band coefficient matrix A. It computes
the RHR Cholesky factorization of A. Argument R is an upper triangular band matrix.
When the solution to the linear system or the inverse of the matrix is sought, an
estimate of the L1 condition number of A is computed using Higham’s modifications to
Hager’s method, as given in Higham (1988). If the estimated condition number is
greater than 1/ε (where ε is the machine precision), a warning message is issued. This
indicates that very small changes in A may produce large changes in the solution x.
The function imsl_c_lin_sol_posdef_band fails if any submatrix of R is not positive
definite or if R has a zero diagonal element. These errors occur only if A is very close to a
singular matrix or to a matrix which is not positive definite.
The function imsl_c_lin_sol_posdef_band is based partially on the LINPACK
subroutines SPBFA and CPBSL; see Dongarra et al. (1979).
Examples
Example 1
Solve a linear system Ax = b where
LM 2 −1 + i 0 0 0 OP
MM−1 − i 4 1 + 2i 0 0 PP
A= 1 − 2i
MM 00 0
10
−4i
4i 0
6 1+ i
PP
MN 0 0 0 1− i 9 PQ
#include <imsl.h>
int n = 5;
int ncoda = 1;
f_complex *x;
f_complex a[] =
{1.0, 1.0},
{9.0, 0.0}};
f_complex b[] =
{25.0, 16.0}};
Output
Solution, x, of Ax = b
1 ( 2, 1)
2 ( 3, -0)
3 ( -1, -1)
4 ( 0, -2)
5 ( 3, 2)
Example 2
This example solves the same problem Ax = b given in the first example. The solution
is returned in user-allocated space and an estimate of κ1(A) is computed. Additionally,
void main()
{
int n = 5;
int ncoda = 1;
f_complex a[] =
{{0.0, 0.0}, {-1.0, 1.0}, {1.0, 2.0}, {0.0, 4.0},
{1.0, 1.0},
{2.0, 0.0}, {4.0, 0.0}, {10.0, 0.0}, {6.0, 0.0},
{9.0, 0.0}};
f_complex b[] =
{{1.0, 5.0}, {12.0, -6.0}, {1.0, -16.0},{-3.0, -3.0},
{25.0, 16.0}};
f_complex x[5];
f_complex e_i[5];
f_complex *factor;
float condition;
float column_norm;
float inverse_norm;
int i;
int j;
inverse_norm = 0.0;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) e_i[j] = imsl_cf_convert (0.0, 0.0);
e_i[i] = imsl_cf_convert (1.0, 0.0);
Output
Solution, x, of Ax = b
1 2 3
( 2, 1) ( 3, -0) ( -1, -1)
4 5
( 0, -2) ( 3, 2)
Warning Errors
IMSL_ILL_CONDITIONED The input matrix is too ill-conditioned. An estimate of
the reciprocal of its L1 condition number is "rcond" = #.
The solution might not be accurate.
Fatal Errors
IMSL_NONPOSITIVE_MATRIX The leading # by # submatrix of the input matrix is
not positive definite.
IMSL_SINGULAR_MATRIX The input matrix is singular.
lin_sol_gen_coordinate
Solves a sparse system of linear equations Ax = b. Using optional arguments, any of
several related computations can be performed. These extra tasks include returning the
LU factorization of A computing the solution of Ax = b given an LU factorization
setting drop tolerances, and controlling iterative refinement.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_gen_coordinate (int n, int nz, Imsl_f_sparse_elem
*a, float *b, ..., 0)
The type double function is imsl_d_lin_sol_gen_coordinate.
Return Value
A pointer to the solution x of the sparse linear system Ax = b. To release this space, use
free. If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_SPARSE_LU_FACTOR, Imsl_f_sparse_lu_factor *lu_factor
(Output)
The address of a structure of type Imsl_f_sparse_lu_factor. The pointers
within the structure are initialized to point to the LU factorization by
imsl_f_lin_sol_gen_coordinate.
IMSL_SUPPLY_SPARSE_LU_FACTOR, Imsl_f_sparse_lu_factor *lu_factor (Input)
The address of a structure of type Imsl_f_sparse_lu_factor. This structure
contains the LU factorization of the input matrix computed by
imsl_f_lin_sol_gen_coordinate with the
IMSL_RETURN_SPARSE_LU_FACTOR option.
IMSL_FREE_SPARSE_LU_FACTOR,
Before returning, free the linked list data structure containing the
LU factorization of A. Use this option only if the factors are no longer required.
IMSL_RETURN_SPARSE_LU_IN_COORD,
Imsl_f_sparse_elem **lu_coordinate, int **row_pivots,
int **col_pivots (Output)
The LU factorization is returned in coordinate form. This is more compact
than the internal representation encapsulated in Imsl_f_sparse_lu. The
disadvantage is that during a SOLVE_ONLY call, the internal representation of
the factor must be reconstructed. If however, the factor is to be stored after the
program exits, and loaded again at some subsequent run, the combination of
IMSL_RETURN_LU_IN_COORD and IMSL_SUPPLY_LU_IN_COORD is probably
the best choice, since the factors are in a format that is simple to store and
read.
IMSL_SUPPLY_SPARSE_LU_IN_COORD,
Imsl_f_sparse_elem *lu_coordinate, int *row_pivots,
int *col_pivots (Output)
Supply the LU factorization in coordinate form. See
IMSL_RETURN_SPARSE_LU_IN_COORD for a description.
IMSL_FACTOR_ONLY,
Compute the LU factorization of the input matrix and return. The argument b
is ignored.
IMSL_SOLVE_ONLY,
Solve Ax = b given the LU factorization of A. This option requires the use of
Description
The function imsl_f_lin_sol_gen_coordinate solves a system of linear equations
Ax = b, where A is sparse. In its default use, it solves the so-called one off problem, by
first performing an LU factorization of A using the improved generalized symmetric
Markowitz pivoting scheme. The factor L is not stored explicitly because the saxpy
operations performed during the elimination are extended to the right-hand side, along
with any row interchanges. Thus, the system Ly = b is solved implicitly. The factor U is
then passed to a triangular solver which computes the solution x from Ux = y.
If a sequence of systems Ax = b are to be solved where A is unchanged, it is usually
more efficient to compute the factorization once, and perform multiple forward and
back solves with the various right-hand sides. In this case, the factor L is explicitly
stored and a record of all row as well as column interchanges is made. The solve step
then solves the two triangular systems
Ly = b and Ux = y. The user specifies either the IMSL_RETURN_SPARSE_LU_FACTOR
or the IMSL_RETURN_LU_IN_COORD option to retrieve the factorization, then calls the
function subsequently with different right-hand sides, passing the factorization back in
using either IMSL_SUPPLY_SPARSE_LU_FACTOR or
IMSL_SUPPLY_SPARSE_LU_IN_COORD in conjunction with IMSL_SOLVE_ONLY. If
IMSL_RETURN_SPARSE_LU_FACTOR is used, the final call to
imsl_lin_sol_gen_coordinate should include IMSL_FREE_SPARSE_LU_FACTOR
to release the heap used to store L and U.
If the solution to ATx = b is required, specify the option IMSL_TRANSPOSE. This
keyword only alters the forward elimination and back substitution so that the operations
UTy = b and LTx = y are performed to obtain the solution. So, with one call to produce
the factorization, solutions to both Ax = b and ATx = b can be obtained.
The option IMSL_CONDITION is used to calculate and return an estimation of the
L1 condition number of A. The algorithm used is due to Higham. Specification of
IMSL_CONDITION causes a complete L to be computed and stored, even if a one off
problem is being solved. This is due to the fact that Higham’s method requires solution
to problems of the form Az = r and ATz = r.
Example 1
As an example, consider the following matrix:
LM10 0 0 0 0 0 OP
MM 0 10 −3 −1 0 0 PP
0 0 15 0 0 0
A=M PP
MM−2 0 0 10 −1 0
PP
MM −−11 0 0 −5 1 −3
PQ
N −2 0 0 0 6
Let xT = (1, 2, 3, 4, 5, 6) so that Ax = (10, 7, 45, 33, −34, 31)T. The number of
nonzeros in A is nz = 15.
#include <imsl.h>
#include <stdlib.h>
main()
{
Imsl_f_sparse_elem a[] = {0, 0, 10.0,
1, 1, 10.0,
1, 2, -3.0,
1, 3, -1.0,
2, 2, 15.0,
3, 0, -2.0,
free (x);
}
Output
solution
1 2 3 4 5 6
1 2 3 4 5 6
Example 2
This examples sets A = E(1000, 10). A linear system is solved and the LU factorization
returned. Then a second linear system is solved, using the same coefficient matrix A
just factored. Maximum absolute errors and execution time ratios are printed, showing
that forward and back solves take approximately 10 percent of the computation time of
a factor and solve. This ratio can vary greatly, depending on the order of the coefficient
matrix, the initial number of nonzeros, and especially on the amount of fill-in produced
during the elimination. Be aware that timing results are highly machine dependent.
#include <imsl.h>
#include <stdlib.h>
main()
{
Imsl_f_sparse_elem *a;
Imsl_f_sparse_lu_factor lu_factor;
float *b;
float *x;
float *mod_five;
float *mod_ten;
float error_factor_solve;
float error_solve;
double time_factor_solve;
double time_solve;
int n = 1000;
int c = 10;
int i;
int nz;
b = imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, mod_five,
0);
time_factor_solve = imsl_ctime();
x = imsl_f_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_RETURN_SPARSE_LU_FACTOR, &lu_factor,
0);
time_factor_solve = imsl_ctime() - time_factor_solve;
b = imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, mod_ten,
0);
time_solve = imsl_ctime();
x = imsl_f_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_SUPPLY_SPARSE_LU_FACTOR, &lu_factor,
IMSL_SOLVE_ONLY,
0);
time_solve = imsl_ctime() - time_solve;
error_solve = imsl_f_vector_norm (n, x,
IMSL_SECOND_VECTOR, mod_ten,
IMSL_INF_NORM, &index,
Output
absolute error (factor/solve) = 9.179115e-05
absolute error (solve) = 2.160072e-04
time_solve/time_factor_solve = 0.093750
Example 3
This example solves a system Ax = b, where A = E (500, 50). Then, the same system is
solved using a large drop tolerance. Finally, using the factorization just computed, the
same linear system is solved with iterative refinement. Be aware that timing results are
highly machine dependent.
#include <imsl.h>
#include <stdlib.h>
main()
{
Imsl_f_sparse_elem *a;
Imsl_f_sparse_lu_factor lu_factor;
float *b;
float *x;
float *mod_five;
float error_zero_drop_tol;
float error_nonzero_drop_tol;
float error_nonzero_drop_tol_IR;
double time_zero_drop_tol;
double time_nonzero_drop_tol;
double time_nonzero_drop_tol_IR;
int nz_nonzero_drop_tol;
int nz_zero_drop_tol;
int n = 500;
int c = 50;
int i;
int nz;
int index;
b = imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, mod_five,
0);
time_zero_drop_tol = imsl_ctime();
x = imsl_f_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_NUM_NONZEROS_IN_FACTOR, &nz_zero_drop_tol,
0);
time_zero_drop_tol = imsl_ctime() - time_zero_drop_tol;
time_nonzero_drop_tol = imsl_ctime();
x = imsl_f_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_RETURN_SPARSE_LU_FACTOR, &lu_factor,
IMSL_DROP_TOLERANCE, 0.005,
IMSL_NUM_NONZEROS_IN_FACTOR, &nz_nonzero_drop_tol,
0);
time_nonzero_drop_tol = imsl_ctime() - time_nonzero_drop_tol;
time_nonzero_drop_tol_IR = imsl_ctime();
x = imsl_f_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_SUPPLY_SPARSE_LU_FACTOR, &lu_factor,
IMSL_SOLVE_ONLY,
IMSL_ITERATIVE_REFINEMENT,
0);
time_nonzero_drop_tol_IR = imsl_ctime() - time_nonzero_drop_tol_IR;
Output
drop tolerance = 0.0
absolute error = 3.814697e-06
fillin = 9530
time_nonzero_drop_tol/time_zero_drop_tol = 1.086957
time_nonzero_drop_tol_IR/time_zero_drop_tol = 0.840580
Notice the absolute error when iterative refinement is not used. Also note that iterative
refinement itself can be quite expensive. In this case, for example, the IR solve took
approximately as much time as the factorization. For this problem the use of a drop
high drop tolerance and iterative refinement was able to reduce fill-in by 10 percent at a
time cost double that of the default usage. In tight memory situations, such a trade-off
may be acceptable. Users should be aware that a drop tolerance can be chosen large
enough, introducing large errors into LU, to prevent convergence of iterative
refinement.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_gen_coordinate (int n, int nz,
Imsl_c_sparse_elem *a, f_complex *b, ..., 0)
The type double function is imsl_z_lin_sol_gen_coordinate.
Required Arguments
int n (Input)
Number of rows in the matrix.
int nz (Input)
Number of nonzeros in the matrix.
Imsl_c_sparse_elem *a (Input)
Vector of length nz containing the location and value of each nonzero entry in
the matrix.
f_complex *b (Input)
Vector of length n containing the right-hand side.
Return Value
A pointer to the solution x of the sparse linear system Ax = b. To release this space, use
free. If no solution was computed, then NULL is returned.
Synopsis with Optional Arguments
#include <imsl.h>
f_complex *imsl_c_lin_sol_gen_coordinate (int n, int nz,
Imsl_c_sparse_elem *a, f_complex *b,
IMSL_RETURN_SPARSE_LU_FACTOR,
Imsl_c_sparse_lu_factor *lu_factor,
IMSL_SUPPLY_SPARSE_LU_FACTOR,
Imsl_c_sparse_lu_factor *lu_factor,
IMSL_FREE_SPARSE_LU_FACTOR,
IMSL_RETURN_SPARSE_LU_IN_COORD,
Imsl_c_sparse_elem **lu_coordinate,
int **row_pivots, int **col_pivots,
IMSL_SUPPLY_SPARSE_LU_IN_COORD,
Imsl_c_sparse_elem *lu_coordinate, int *row_pivots,
Optional Arguments
IMSL_RETURN_SPARSE_LU_FACTOR, Imsl_c_sparse_lu_factor *lu_factor
(Output)
The address of a structure of type Imsl_c_sparse_lu_factor. The pointers
within the structure are initialized to point to the LU factorization by
imsl_c_lin_sol_gen_coordinate.
IMSL_SUPPLY_SPARSE_LU_FACTOR, Imsl_c_sparse_lu_factor *lu_factor
(Input)
The address of a structure of type Imsl_c_sparse_lu_factor. This structure
contains the LU factorization of the input matrix computed by
imsl_c_lin_sol_gen_coordinate with the
IMSL_RETURN_SPARSE_LU_FACTOR option.
IMSL_FREE_SPARSE_LU_FACTOR,
Before returning, free the linked list data structure containing the LU
factorization of A. Use this option only if the factors are no longer required.
IMSL_RETURN_SPARSE_LU_IN_COORD,
Imsl_c_sparse_elem **lu_coordinate, int **row_pivots,
int **col_pivots (Output)
The LU factorization is returned in coordinate form. This is more compact
than the internal representation encapsulated in Imsl_c_sparse_lu. The
disadvantage is that during a SOLVE_ONLY call, the internal representation of
the factor must be reconstructed. If however, the factor is to be stored after the
program exits, and loaded again at some subsequent run, the combination of
IMSL_RETURN_LU_IN_COORD and IMSL_SUPPLY_LU_IN_COORD is probably
Description
The function imsl_c_lin_sol_gen_coordinate solves a system of linear equations
Ax = b, where A is sparse. In its default use, it solves the so-called one off problem, by
first performing an LU factorization of A using the improved generalized symmetric
Markowitz pivoting scheme. The factor L is not stored explicitly because the saxpy
operations performed during the elimination are extended to the right-hand side, along
with any row interchanges. Thus, the system Ly = b is solved implicitly. The factor U is
then passed to a triangular solver which computes the solution x from Ux = y.
If a sequence of systems Ax = b are to be solved where A is unchanged, it is usually
more efficient to compute the factorization once, and perform multiple forward and
back solves with the various right-hand sides. In this case the factor L is explicitly
stored and a record of all row as well as column interchanges is made. The solve step
then solves the two triangular systems
Ly = b and Ux = y. The user specifies either the IMSL_RETURN_SPARSE_LU_FACTOR
or the IMSL_RETURN_LU_IN_COORD option to retrieve the factorization, then calls the
function subsequently with different right-hand sides, passing the factorization back in
using either IMSL_SUPPLY_SPARSE_LU_FACTOR or
IMSL_SUPPLY_SPARSE_LU_IN_COORD in conjunction with IMSL_SOLVE_ONLY. If
IMSL_RETURN_SPARSE_LU_FACTOR is used, the final call to
imsl_lin_sol_gen_coordinate should include IMSL_FREE_SPARSE_LU_FACTOR
to release the heap used to store L and U.
If the solution to ATx = b is required, specify the option IMSL_TRANSPOSE. This
keyword only alters the forward elimination and back substitution so that the operations
UTy = b and LTx = y are performed to obtain the solution. So, with one call to produce
the factorization, solutions to both Ax = b and ATx = b can be obtained.
Examples
Example 1
As an example, consider the following matrix:
LM 10 + 7i 0 0 0 0 0 OP
MM 0 3 + 2i −3 −1 + 2i 0 0 PP
0 0 4 + 2i 0 0 0
A=M PP
MM −2 − 4i 0 0 1 + 6i −1 + 3i 0
PP
MM−−15++124ii 0 0 −5 12 + 2i −7 + 7i
PQ
N −2 + 8i 0 0 0 3 + 7i
Let
main()
{
static Imsl_c_sparse_elem a[] = {0, 0, {10.0, 7.0},
1, 1, {3.0, 2.0},
1, 2, {-3.0, 0.0},
1, 3, {-1.0, 2.0},
2, 2, {4.0, 2.0},
3, 0, {-2.0, -4.0},
3, 3, {1.0, 6.0},
3, 4, {-1.0, 3.0},
4, 0, {-5.0, 4.0},
4, 3, {-5.0, 0.0},
4, 4, {12.0, 2.0},
4, 5, {-7.0, 7.0},
5, 0, {-1.0, 12.0},
5, 1, {-2.0, 8.0},
5, 5, {3.0, 7.0}};
free (x);
}
Output
solution
1 ( 1, 1)
2 ( 2, 2)
3 ( 3, 3)
4 ( 4, 4)
5 ( 5, 5)
6 ( 6, 6)
Example 2
This examples sets A = E (1000, 10). A linear system is solved and the LU factorization
returned. Then a second linear system is solved using the same coefficient matrix A just
factored. Maximum absolute errors and execution time ratios are printed showing that
forward and back solves take a small percentage of the computation time of a factor and
solve. This ratio can vary greatly, depending on the order of the coefficient matrix, the
b = imsl_c_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, mod_five,
0);
time_factor_solve = imsl_ctime();
x = imsl_c_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_RETURN_SPARSE_LU_FACTOR, &lu_factor,
0);
time_factor_solve = imsl_ctime() - time_factor_solve;
b = imsl_c_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, mod_ten,
0);
time_solve = imsl_ctime();
x = imsl_c_lin_sol_gen_coordinate (n, nz, a, b,
IMSL_SUPPLY_SPARSE_LU_FACTOR, &lu_factor,
IMSL_SOLVE_ONLY,
0);
time_solve = imsl_ctime() - time_solve;
error_solve = imsl_c_vector_norm (n, x,
IMSL_SECOND_VECTOR, mod_ten,
IMSL_INF_NORM, &index,
0);
free (b);
free (x);
Output
absolute error (factor/solve) = 2.389053e-06
absolute error (solve) = 7.656095e-06
time_solve/time_factor_solve = 0.070313
lin_sol_posdef_coordinate
Solves a sparse real symmetric positive definite system of linear equations
Ax = b. Using optional arguments, any of several related computations can be
performed. These extra tasks include returning the symbolic factorization of A,
returning the numeric factorization of A, and computing the solution of Ax = b given
either the symbolic or numeric factorizations.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_posdef_coordinate (int n, int nz,
Imsl_f_sparse_elem *a, float *b, ..., 0)
Required Arguments
int n (Input)
Number of rows in the matrix.
int nz (Input)
Number of nonzeros in lower triangle of the matrix.
Imsl_f_sparse_elem *a (Input)
Vector of length nz containing the location and value of each nonzero entry in
the lower triangle of the matrix.
float *b (Input)
Vector of length n containing the right-hand side.
Return Value
A pointer to the solution x of the sparse symmetric positive definite linear system Ax = b.
To release this space, use free. If no solution was computed, then NULL is returned.
IMSL_SUPPLY_NUMERIC_FACTOR,
Imsl_f_numeric_factor *num_factor,
IMSL_NUMERIC_FACTOR_ONLY,
IMSL_SOLVE_ONLY,
IMSL_MULTIFRONTAL_FACTORIZATION,
IMSL_RETURN_USER, float x[],
IMSL_SMALLEST_DIAGONAL_ELEMENT, float *small_element,
IMSL_LARGEST_DIAGONAL_ELEMENT, float *largest_element,
IMSL_NUM_NONZEROS_IN_FACTOR, int *num_nonzeros,
IMSL_CSC_FORMAT, int *col_ptr, int *row_ind,
float *values,
0)
Description
The function imsl_f_lin_sol_posdef_coordinate solves a system of linear
algebraic equations having a sparse symmetric positive definite coefficient matrix A. In
this function’s default usage, a symbolic factorization of a permutation of the
coefficient matrix is computed first. Then a numerical factorization is performed. The
solution of the linear system is then found using the numeric factor.
The symbolic factorization step of the computation consists of determining a minimum
degree ordering and then setting up a sparse data structure for the Cholesky factor, L. This
step only requires the “pattern” of the sparse coefficient matrix, i.e., the locations of the
nonzeros elements but not any of the elements themselves. Thus, the val field in the
Imsl_f_sparse_elem structure is ignored. If an application generates different sparse
symmetric positive definite coefficient matrices that all have the same sparsity pattern, then
by using IMSL_RETURN_SYMBOLIC_FACTOR and IMSL_SUPPLY_SYMBOLIC_FACTOR,
the symbolic factorization need only be computed once.
Given the sparse data structure for the Cholesky factor L, as supplied by the symbolic
factor, the numeric factorization produces the entries in L so that
PAPT = LLT
LTy2 = y1
x = PTy2
Examples
Example 1
As an example consider the 5 × 5 coefficient matrix:
LM10 0 1 0 2 OP
MM 0 20 0 0 3 PP
a= 1 0 30 4 0
MM 0 0 4 40 5
PP
MN 2 3 0 5 50 PQ
Let xT = (5, 4, 3, 2, 1) so that Ax = (55, 83, 103, 97, 82) T. The number of nonzeros in
the lower triangle of A is nz = 10. The sparse coordinate form for the lower triangle is
given by the following:
row 0 1 2 2 3 3 4 4 4 4
col 0 1 0 2 2 3 0 1 3 4
val 10 20 1 30 4 40 2 3 5 50
Since this representation is not unique, an equivalent form would be as follows:
row 3 4 4 4 0 1 2 2 3 4
col 3 0 1 3 0 1 0 2 2 4
val 40 2 3 5 10 20 1 30 4 50
#include <imsl.h>
#include <stdlib.h>
main()
{
Imsl_f_sparse_elem a[] = {0, 0, 10.0,
1, 1, 20.0,
2, 0, 1.0,
2, 2, 30.0,
3, 2, 4.0,
3, 3, 40.0,
4, 0, 2.0,
4, 1, 3.0,
free (x);
}
Output
solution
1 2 3 4 5
5 4 3 2 1
Example 2
In this example, set A = E(2500, 50). Then solve the system Ax = b1 and return the
numeric factorization resulting from that call. Then solve the system Ax = b2 using the
numeric factorization just computed. The ratio of execution time is printed. Be aware
that timing results are highly machine dependent.
#include <imsl.h>
main()
{
Imsl_f_sparse_elem *a;
Imsl_f_numeric_factor numeric_factor;
float *b_1;
float *b_2;
float *x_1;
float *x_2;
int n;
int ic;
int nz;
double time_1;
double time_2;
ic = 50;
n = ic*ic;
Output
time_2/time_1 = 0.037037
lin_sol_posdef_coordinate (complex)
Solves a sparse Hermitian positive definite system of linear equations Ax = b. Using
optional arguments, any of several related computations can be performed. These extra
tasks include returning the symbolic factorization of A, returning the numeric
factorization of A, and computing the solution of Ax = b given either the symbolic or
numeric factorizations.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_sol_posdef_coordinate (int n, int nz,
Imsl_c_sparse_elem *a, f_complex *b, ..., 0)
The type d_complex function is imsl_z_lin_sol_posdef_coordinate.
Required Arguments
int n (Input)
Number of rows in the matrix.
int nz (Input)
Number of nonzeros in the lower triangle of the matrix.
Imsl_c_sparse_elem *a (Input)
Vector of length nz containing the location and value of each nonzero entry in
lower triangle of the matrix.
Return Value
A pointer to the solution x of the sparse Hermitian positive definite linear system Ax = b.
To release this space, use free. If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_SYMBOLIC_FACTOR, Imsl_symbolic_factor *sym_factor (Output)
A pointer to a structure of type Imsl_symbolic_factor containing, on return, the
symbolic factorization of the input matrix.
IMSL_SUPPLY_SYMBOLIC_FACTOR, Imsl_symbolic_factor *sym_factor (Input)
A pointer to a structure of type Imsl_symbolic_factor. This structure contains
the symbolic factorization of the input matrix computed by
imsl_c_lin_sol_posdef_coordinate with the
IMSL_RETURN_SYMBOLIC_FACTOR option.
IMSL_SYMBOLIC_FACTOR_ONLY,
Compute the symbolic factorization of the input matrix and return. The
argument b is ignored.
Description
The function imsl_c_lin_sol_posdef_coordinate solves a system of linear
algebraic equations having a sparse Hermitian positive definite coefficient matrix A. In
this function’s default use, a symbolic factorization of a permutation of the coefficient
PAPT = LLT
Ly1 = Pb
LTy2 = y1
x = PTy2
Example 1
As a simple example of default use, consider the following Hermitian positive definite
matrix
LM 2 −1 + i 0 OP
A = M−1 − i 4 1 + 2i P
MN 0 1 − 2i 10 PQ
Let xT = (1 + i, 2 + 2i, 3 + 3i) so that Ax = (−2 + 2i, 5 +15i, 36 + 28i)T. The number of
nonzeros in the lower triangle is nz = 5.
#include <imsl.h>
main()
{
Imsl_c_sparse_elem a[] = {0, 0, {2.0, 0.0},
1, 1, {4.0, 0.0},
2, 2, {10.0, 0.0},
1, 0, {-1.0, -1.0},
2, 1, {1.0, -2.0}};
free (x);
}
Output
Solution, x, of Ax = b
1 ( 1, 1)
2 ( 2, 2)
3 ( 3, 3)
Example 2
Set A = E(2500, 50). Then solve the system Ax = b1 and return the numeric
factorization resulting from that call. Then solve the system Ax = b2 using the numeric
factorization just computed. Absolute errors and execution time are printed.
#include <imsl.h>
main()
{
Imsl_c_sparse_elem *a;
Imsl_c_numeric_factor numeric_factor;
f_complex b_1[2500];
ic = 50;
n = ic*ic;
index = 0;
Output
time_2/time_1 = 0.096386
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_gen_min_residual (int n, void amultp (float *p,
float *z), float *b, ..., 0)
The type double function is imsl_d_lin_sol_gen_min_residual.
Required Arguments
int n (Input)
Number of rows in the matrix.
void amultp (float *p, float *z)
User-supplied function which computes z = Ap.
float *b (Input)
Vector of length n containing the right-hand side.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space, use free.
If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_MAX_ITER, int *maxit (Input/Output)
A pointer to an integer, initially set to the maximum number of GMRES
Description
The function imsl_f_lin_sol_gen_min_residual, based on the FORTRAN
subroutine GMRES by H.F. Walker, solves the linear system
Ax = b using the GMRES method. This method is described in detail by Saad and
Schultz (1986) and Walker (1988).
The GMRES method begins with an approximate solution x0 and an initial residual
r0 = b − Ax0. At iteration m, a correction zm is determined in the Krylov subspace
Examples
Example 1
As an example, consider the following matrix:
Let xT = (1, 2, 3, 4, 5, 6) so that Ax = (10, 7, 45, 33, −34, 31)T. The function
imsl_f_mat_mul_rect_coordinate is used to form the product Ax.
#include <imsl.h>
main()
{
float b[] = {10.0, 7.0, 45.0, 33.0, -34.0, 31.0};
int n = 6;
float *x;
imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, p,
IMSL_RETURN_USER_VECTOR, z,
0);
}
Example 2
In this example, the same system given in the first example is solved. This time a
preconditioner is provided. The preconditioned matrix is chosen as the diagonal of A.
#include <imsl.h>
main()
{
float b[] = {10.0, 7.0, 45.0, 33.0, -34.0, 31.0};
int n = 6;
float *x;
int maxit = 1000;
/* Set z = Ap */
imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, p,
IMSL_RETURN_USER_VECTOR, z,
0);
Output
Solution, x, to Ax = b
1 2 3 4 5 6
1 2 3 4 5 6
lin_sol_def_cg
Solves a real symmetric definite linear system using a conjugate gradient method.
Using optional arguments, a preconditioner can be supplied.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_def_cg (int n, void amultp ( ), float *b, ..., 0)
The type double function is imsl_d_lin_sol_def_cg.
Required Arguments
int n (Input)
Number of rows in the matrix.
void amultp (float *p, float *z)
User-supplied function which computes z = Ap.
float *b (Input)
Vector of length n containing the right-hand side.
Return Value
A pointer to the solution x of the linear system Ax = b. To release this space, use free.
If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x.
IMSL_MAX_ITER, int *maxit (Input/Output)
A pointer to an integer, initially set to the maximum number of iterations
allowed. On exit, the number of iterations used is returned.
IMSL_REL_ERR, float relative_error (Input)
The relative error desired.
Default: relative_error = sqrt(imsl_f_machine(4))
IMSL_PRECOND, void precond (float *r, float *z) (Input)
User supplied function which sets z = M-1r, where M is the preconditioning
matrix.
IMSL_JACOBI, float diagonal[] (Input)
Use the Jacobi preconditioner, i.e. M = diag(A). The user-supplied vector
diagonal should be set so that diagonal[i] = Ai,i.
Description
The function imsl_f_lin_sol_def_cg solves the symmetric definite linear system
Ax = b using the conjugate gradient method with optional preconditioning. This method
is described in detail by Golub and Van Loan (1983, Chapter 10), and in Hageman and
Young (1981, Chapter 7).
The preconditioning matrix M is a matrix that approximates A, and for which the linear
system Mz = r is easy to solve. These two properties are in conflict; balancing them is a
topic of much current research. In the default use of imsl_f_lin_sol_def_cg, M = I.
If the option IMSL_JACOBI is selected, M is set to the diagonal of A.
The number of iterations needed depends on the matrix and the error tolerance. As a
rough guide,
itmax = n for n >> 1
e je
β k = z kT rk / z kT−1rk −1 j
pk = z k + β k pk
endif
z k = Ap
e je
α k = z kT−1 z k −1 / z kT pk j
x k = x k + α k pk
rk = rk − α k z k
c b g h
if || z k ||2 ≤ τ 1 − λ || x k ||2 then
recompute λ
c b g h
if || z k ||2 ≤ τ 1 − λ || x k ||2 exit
endif
endfor
xk − x F 1 IF z I
x M
M
≤ GH 1 − λ bGg JK GH x JK
max
k M
k M
where
2
x M
= x T Mx
Usually the eigenvalue computation is needed for only a few of the iterations.
Example 1
In this example, the solution to a linear system is found. The coefficient matrix is stored
as a full matrix.
#include <imsl.h>
void main()
{
int n = 3;
float b[] = {27.0, -78.0, 64.0};
float *x;
imsl_f_mat_mul_rect ("A*x",
IMSL_A_MATRIX, n, n, a,
IMSL_X_VECTOR, n, p,
IMSL_RETURN_USER, z,
0);
}
Output
x
1 2 3
1 -4 7
void main()
{
int maxit = 1000;
int i;
int index;
float *b;
float *x;
float *mod_five;
float *diagonal;
float norm;
n = c*c;
mod_five = (float*) malloc (n*sizeof(*mod_five));
diagonal = (float*) malloc (n*sizeof(*diagonal));
b = (float*) malloc (n*sizeof(*b));
/* Set z = Ap */
/* Solve Mz = r */
if (first) {
imsl_f_lin_sol_posdef_band (n, m, 1, r,
IMSL_FACTOR_USER, factor,
IMSL_SOLVE_ONLY,
IMSL_RETURN_USER, z,
0);
}
Output
iterations = 115, norm = 1.382828e-05
iterations = 75, norm = 7.319450e-05
lin_least_squares_gen
Solves a linear least-squares problem Ax = b. Using optional arguments, the QR
factorization of A, AP = QR, and the solve step based on this factorization can be
computed.
Synopsis
#include <imsl.h>
float *imsl_f_lin_least_squares_gen (int m, int n, float a[], float b[],
…, 0)
The type double procedure is imsl_d_lin_least_squares_gen.
Required Arguments
int m (Input)
Number of rows in the matrix.
int n (Input)
Number of columns in the matrix.
float a[] (Input)
Array of size m × n containing the matrix.
float b[] (Input)
Array of size m containing the right-hand side.
Return Value
If no optional arguments are used, function imsl_f_lin_least_squares_gen
returns a pointer to the solution x of the linear least-squares problem Ax = b. To release
this space, use free. If no value can be computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of size n containing the least-squares solution x. If
IMSL_RETURN_USER is used, the return value of the function is a pointer to
the array x.
IMSL_BASIS, float tol, int *kbasis (Input, Input/Output)
tol: Nonnegative tolerance used to determine the subset of columns of A to
be included in the solution.
Default: tol = sqrt (imsl_amach(4))
kbasis: Integer containing the number of columns used in the solution.
kbasis = k if |rk+1,k+1| < |tol|*|r1,1| and |ri,i|≥ tol*|r1,1| for i = 1, 2, …, k. For
more information on the use of this option, see “Description” on page 87.
Default: kbasis = min (m, n)
IMSL_RESIDUAL, float **p_res (Output)
The address of a pointer to an array of size m containing the residual vector
b − Ax. On return, the necessary space is allocated by the function. Typically,
float *p_res is declared, and &p_res is used as an argument.
IMSL_RESIDUAL_USER, float res[] (Output)
A user-allocated array of size m containing the residual vector b − Ax.
IMSL_FACTOR, float **p_qraux, float **p_qr (Output)
**p_qraux: The address of a pointer qraux to an array of size n containing
the scalars τk of the Householder transformations in the first min (m, n)
Description
The function imsl_f_lin_least_squares_gen solves a system of linear least-
squares problems Ax = b with column pivoting. It computes a QR factorization of the
matrix AP, where P is the permutation matrix defined by the pivoting, and computes the
smallest integer k satisfying |rk+1, k+1| < |tol|*|r1,1| to the output variable kbasis.
Householder transformations
Qk = l − τ k uk ukT Q
Example 1
This example illustrates the least-squares solution of four linear equations in three
unknowns using column pivoting. The problem is equivalent to least-squares quadratic
polynomial fitting to four data values. Write the polynomial as p(t) = x1 + tx2 + t2x3 and
the data pairs (ti, bi), ti = 2i, i = 1, 2, 3, 4. A pointer to the solution to Ax = b is returned
by the function imsl_f_lin_least_squares_gen.
#include <imsl.h>
main()
{
int m = 4, n = 3;
float *x;
/* Solve Ax = b for x */
/* Print x */
imsl_f_write_matrix ("Solution vector", 1, n, x, 0);
}
Output
Solution vector
1 2 3
0.999 2.000 0.000
Example 2
This example uses the same coefficient matrix A as in the initial example. It computes
the QR factorization of A with column pivoting. The final and free columns are
specified by pvt and the column pivoting is done only among the free columns.
#include <imsl.h>
main()
{
int m = 4, n = 3;
float *x, *b;
float *p_qraux, *p_qr;
/* Print Q */
imsl_f_write_matrix ("The matrix Q", m, m, p_q, 0);
/* Print R */
imsl_f_write_matrix ("The matrix R", m, n, p_qr,
IMSL_PRINT_UPPER,
0);
/* Print pivots */
imsl_i_write_matrix ("The Pivot Sequence", 1, n, pvt, 0);
Output
The matrix Q
1 2 3 4
1 -0.1826 -0.8165 0.5000 -0.2236
2 -0.3651 -0.4082 -0.5000 0.6708
3 -0.5477 0.0000 -0.5000 -0.6708
4 -0.7303 0.4082 0.5000 0.2236
The matrix R
1 2 3
1 -10.95 -1.83 -73.03
2 -0.82 16.33
3 8.00
Example 3
This example computes the QR factorization with column pivoting for the matrix A of
the initial example. It computes the least-squares solutions to Ax = bi for i = 1, 2, 3.
#include <imsl.h>
main()
{
int m = 4, n = 3;
int i, k = 3;
float *p_qraux, *p_qr;
float tol = 1.e-4;
int *kbasis;
float *x, *p_res;
/* Factor A with the given pvt */
/* setting all variables to */
/* be free */
imsl_f_lin_least_squares_gen (m, n, a, b,
IMSL_BASIS, tol, &kbasis,
IMSL_PIVOT, pvt,
IMSL_FACTOR, &p_qraux, &p_qr,
IMSL_FACTOR_ONLY,
0);
/* Print some factorization */
/* information*/
Output
Number of Columns in the base
3
Upper triangular R Matrix
1 2 3
1 -75.26 -10.63 -1.59
2 -2.65 -1.15
3 0.36
Right-hand side, b
1 2 3 4
5 9 13 17
Solution, x
1 2 3
0.999 2.000 0.000
Residual, b - Ax
1 2 3 4
-0.0004 0.0012 -0.0012 0.0004
Right-hand side, b
1 2 3 4
2.000 3.142 5.110 0.000
Solution, x
1 2 3
-4.244 3.706 -0.391
Residual, b - Ax
1 2 3 4
0.395 -1.186 1.186 -0.395
Right-hand side, b
1 2 3 4
1.34 8.11 3.76 10.99
Solution, x
1 2 3
0.4735 0.9437 0.0286
Residual, b - Ax
1 2 3 4
-1.135 3.406 -3.406 1.135
Fatal Errors
IMSL_SINGULAR_TRI_MATRIX The input triangular matrix is singular. The index of
the first zero diagonal term is #.
lin_lsq_lin_constraints
Solves a linear least-squares problem with linear constraints.
Synopsis
#include <imsl.h>
Required Arguments
int nra (Input)
Number of least-squares equations.
int nca (Input)
Number of variables.
int ncon (Input)
Number of constraints.
float a[] (Input)
Array of size nra × nca containing the coefficients of the nra least-squares
equations.
float b[] (Input)
Array of length nra containing the right-hand sides of the least-squares
equations.
float c[] (Input)
Array of size ncon × nca containing the coefficients of the ncon constraints.
float bl[] (Input)
Array of length ncon containing the lower limit of the general constraints. If
there is no lower limit on the i-th constraint, then bl[i] will not be referenced.
float bu[] (Input)
Array of length ncon containing the upper limit of the general constraints. If
there is no upper limit on the i-th constraint, then bu[i] will not be referenced.
If there is no range constraint, bl and bu can share the same storage.
int con_type[] (Input)
Array of length ncon indicating the type of constraints exclusive of simple
bounds, where con_type[i] = 0, 1, 2, 3 indicates =, <=, >= and range
constraints, respectively.
float xlb[] (Input)
Array of length nca containing the lower bound on the variables. If there is no
lower bound on the i-th variable, then xlb[i] should be set to 1.0e30.
float xub[] (Input)
Array of length nca containing the upper bound on the variables. If there is no
lower bound on the i-th variable, then xub[i] should be set to −1.0e30.
Return Value
A pointer to the to a vector of length nca containing the approximate solution. To
release this space, use free. If no solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
Store the solution in the user supplied vector x of length nca.
IMSL_RESIDUAL, float **residual (Output)
The address of a pointer to an array containing the residuals b − Ax of the
least-squares equations at the approximate solution.
IMSL_RESIDUAL_USER, float residual_user[] (Output)
Store the residuals in the user-supplied vector of length nra.
IMSL_PRINT,
Debug output flag. Choose this option if more detailed output is desired.
IMSL_MAX_ITER, int max_iter (Input)
Set the maximum number of add/drop iterations.
Default: max_iter = 5*max(nra, nca)
IMSL_REL_FCN_TOL, float rel_tol (Input)
Relative rank determination tolerance to be used.
Default: rel_tol = sqrt(imsl_f_machine(4))
IMSL_ABS_FCN_TOL, float abs_tol (Input)
Absolute rank determination tolerance to be used.
Default: abs_tol = sqrt(imsl_f_machine(4))
Description
The function imsl_f_lin_lsq_lin_constraints solves linear least-squares
problems with linear constraints. These are systems of least-squares equations of the
form
Ax ≅ b
l
b ≤ Cx ≤ bu
xl ≤ x ≤ xu
Here A is the coefficient matrix of the least-squares equations, b is the right-hand side,
and C is the coefficient matrix of the constraints. The vectors bl, bu, xl and xu are the
lower and upper bounds on the constraints and the variables, respectively. The system
is solved by defining dependent variables y ≡ Cx and then solving the least-squares
system with the lower and upper bounds on x and y. The equation Cx − y = 0 is a set of
equality constraints. These constraints are realized by heavy weighting, i.e., a penalty
method, Hanson (1986, pp. 826-834).
Examples
Example 1
In this example, the following problem is solved in the least-squares sense:
x1 + x2 + x3 = 1.0
Subject to
x1 = x2 + x3 ≤ 1
0 ≤ x1 ≤ 0.5
0 ≤ x2 ≤ 0.5
0 ≤ x3 ≤ 0.5
#include <imsl.h>
main()
{
int nra = 4;
int nca = 3;
Output
Solution
1 2 3
0.5 0.3 0.2
Example 2
The same problem solved in the first example is solved again. This time residuals of the
least-squares equations at the approximate solution are returned, and the norm of the
residual vector is printed. Both the solution and residuals are returned in user-supplied
space.
#include <imsl.h>
main()
{
int nra = 4;
int nca = 3;
int ncon = 1;
float x[3];
float residual[4];
float a[] = {3.0, 2.0, 1.0,
4.0, 2.0, 1.0,
2.0, 2.0, 1.0,
1.0, 1.0, 1.0};
float b[] = {3.3, 2.3, 1.3, 1.0};
float c[] = {1.0, 1.0, 1.0};
float xlb[] = {0.0, 0.0, 0.0};
float xub[] = {0.5, 0.5, 0.5};
int con_type[] = {1};
float bc[] = {1.0};
Output
Solution
1 2 3
0.5 0.3 0.2
Residual
1 2 3 4
-1.0 0.5 0.5 -0.0
lin_svd_gen
Computes the SVD, A = USVT, of a real rectangular matrix A. An approximate
generalized inverse and rank of A also can be computed.
Synopsis
#include <imsl.h>
float *imsl_f_lin_svd_gen (int m, int n, float a[], …, 0)
The type double procedure is imsl_d_lin_svd_gen.
Required Arguments
int m (Input)
Number of rows in the matrix.
int n (Input)
Number of columns in the matrix.
float a[] (Input)
Array of size m × n containing the matrix.
Return Value
If no optional arguments are used, imsl_f_lin_svd_gen returns a pointer to an array
of size min (m, n) containing the ordered singular values of the matrix. To release this
space, use free. If no value can be computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_RETURN_USER, float s[] (Output)
A user-allocated array of size min (m, n) containing the singular values of A in
its first min (m, n) positions in nonincreasing order. If IMSL_RETURN_USER is
used, the return value of imsl_f_lin_svd_gen is s.
IMSL_RANK, float tol, int *rank (Input/Output)
tol: Scalar containing the tolerance used to determine when a singular value
is negligible and replaced by the value zero. If tol > 0, then a singular value
si,i is considered negligible if si,i ≤ tol. If tol < 0, then a singular value
si,i is considered negligible if si,i ≤ |tol|*||A||¥. In this case, |tol| should be
an estimate of relative error or uncertainty in the data.
*rank: Integer containing an estimate of the rank of A.
IMSL_U, float **p_u (Output)
**p_u: The address of a pointer to an array of size m × min (m, n) containing
the left- singular vectors of A. On return, the necessary space is allocated by
imsl_f_lin_svd_gen. Typically, float *p_u is declared, and &p_u is used
as an argument.
IMSL_U_USER, float u[] (Output)
u[]: A user-allocated array of size m × min (m, n)containing the left-singular
vectors of A. If m ≥ n, the left-singular vectors can be returned using the
storage locations of the array a.
Description
The function imsl_f_lin_svd_gen computes the singular value decomposition of a
real matrix A. It first reduces the matrix A to a bidiagonal matrix B by pre- and post-
multiplying Householder transformations. Then, the singular value decomposition of
B is computed using the implicit-shifted QR algorithm. An estimate of the rank of the
matrix A is obtained by finding the smallest integer k such that sk,k ≤ tol or
sk,k ≤ |tol|*||A||¥. Since si+1, i+1 ≤ si,i, it follows that all the si, i satisfy the same
inequality for i = k, …, min (m, n) − 1. The rank is set to the value k − 1. If A = USVT,
its generalized inverse is A+ = VS+ UT. Here,
e j
S + = diag s1−,11 ,K , si−,i1 ,0,K ,0
Only singular values that are not negligible are reciprocated. If IMSL_INVERSE or
IMSL_INVERSE_USER is specified, the function first computes the singular value
Examples
Example 1
This example computes the singular values of a real 6 × 4 matrix.
#include <imsl.h>
main()
{
int m = 6, n = 4;
float *s;
/* Compute singular values */
s = imsl_f_lin_svd_gen (m, n, a, 0);
/* Print singular values */
imsl_f_write_matrix ("Singular values", 1, n, s, 0);
}
Output
Singular values
1 2 3 4
11.49 3.27 2.65 2.09
Example 2
This example computes the singular value decomposition of the 6 × 4 real matrix A.
The singular values are returned in the user-provided array. The matrices U and V are
returned in the space provided by the function imsl_f_lin_svd_gen.
#include <imsl.h>
main()
{
int m = 6, n = 4;
float s[4], *p_u, *p_v;
/* Compute SVD */
imsl_f_lin_svd_gen (m, n, a,
IMSL_RETURN_USER, s,
Output
Singular values, S
1 2 3 4
11.49 3.27 2.65 2.09
Example 3
This example computes the rank and generalized inverse of a 3 × 2 matrix A. The rank
and the 2 × 3 generalized inverse matrix A+ are printed.
#include <imsl.h>
main()
{
int m = 3, n = 2;
float tol;
float gen_inva[6];
float *s;
int *rank;
/* Compute generalized inverse */
tol = 1.e-4;
s = imsl_f_lin_svd_gen (m, n, a,
IMSL_RANK, tol, &rank,
IMSL_INVERSE_USER, gen_inva,
IMSL_INV_COL_DIM, m,
0);
/* Print rank, singular values and */
/* generalized inverse. */
Output
Rank of matrix = 2
Singular values
1 2
111.8 1.4
Generalized inverse
1 2 3
1 0.100 0.300 0.006
2 0.200 0.600 -0.008
Warning Errors
IMSL_SLOWCONVERGENT_MATRIX Convergence cannot be reached after 30
iterations.
lin_svd_gen (complex)
Computes the SVD, A = USVH, of a complex rectangular matrix A. An approximate
generalized inverse and rank of A also can be computed.
Synopsis
#include <imsl.h>
f_complex *imsl_c_lin_svd_gen (int m, int n, f_complex a[], …, 0)
The type d_complex function is imsl_z_lin_svd_gen.
Required Arguments
int m (Input)
Number of rows in the matrix.
int n (Input)
Number of columns in the matrix.
f_complex a[] (Input)
Array of size m × n containing the matrix.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_RETURN_USER, f_complex s[] (Output)
A user-allocated array of length min (m, n) containing the singular values of A
in its first min (m, n) positions in nonincreasing order. The complex entries are
all real. If IMSL_RETURN_USER is used, the return value of
imsl_c_lin_svd_gen is s.
IMSL_RANK, float tol, int *rank (Input/Output)
tol: Scalar containing the tolerance used to determine when a singular value
is negligible and replaced by the value zero. If tol > 0, then a singular value
si,i is considered negligible if si,i ≤ tol. If tol < 0, then a singular value si,i is
considered negligible if si,i ≤ |tol|*||A||¥. In this case, should be an estimate of
relative error or uncertainty in the data.
*rank: Integer containing an estimate of the rank of A.
IMSL_U, f_complex **p_u (Output)
The address of a pointer to an array of size m × min (m, n) containing the left-
singular vectors of A. On return, the necessary space is allocated by
imsl_c_lin_svd_gen. Typically, f_complex *p_u is declared, and &p_u is
used as an argument.
Description
The function imsl_c_lin_svd_gen computes the singular value decomposition of a
complex matrix A. It first reduces the matrix A to a bidiagonal matrix B by pre- and
post-multiplying Householder transformations. Then, the singular value decomposition
of B is computed using the implicit-shifted QR algorithm. An estimate of the rank of the
matrix A is obtained by finding the smallest integer k such that sk,k ≤ tol or
sk,k ≤ |tol|*||A||¥. Since si+1,i+1 ≤ si,i, it follows that all the si,i satisfy the same inequality
for i = k, …, min (m, n) − 1. The rank is set to the value k − 1. If A = USVH, its
generalized inverse is A+ = VS+ UH.
e j
S + = diag s1−,11 ,K , si−,i1 ,0,K ,0
Only singular values that are not negligible are reciprocated. If IMSL_INVERSE or
IMSL_INVERSE_USER is specified, the function first computes the singular value
decomposition of the matrix A. The generalized inverse is then computed. The function
imsl_c_lin_svd_gen fails if the QR algorithm does not converge after 30 iterations
isolating an individual singular value.
Examples
Example 1
This example computes the singular values of a 6 × 3 complex matrix.
#include <imsl.h>
main()
{
int m = 6, n = 3;
f_complex *s;
f_complex a[] = {{1.0, 2.0}, {3.0, 2.0}, {1.0,-4.0},
{3.0,-2.0}, {2.0,-4.0}, {1.0, 3.0},
{4.0, 3.0}, {-2.0,1.0}, {1.0, 4.0},
{2.0,-1.0}, {3.0, 0.0}, {3.0,-1.0},
{1.0,-5.0}, {2.0,-5.0}, {2.0, 2.0},
{1.0, 2.0}, {4.0,-2.0}, {2.0,-3.0}};
/* Compute singular values */
s = imsl_c_lin_svd_gen (m, n, a, 0);
/* Print singular values */
imsl_c_write_matrix ("Singular values", 1, n, s, 0);
}
Output
Singular values
1 2 3
( 11.77, 0.00) ( 9.30, 0.00) ( 4.99, 0.00)
Example 2
This example computes the singular value decomposition of the 6 × 3 complex matrix
A. The singular values are returned in the user-provided array. The matrices U and V
are returned in the space provided by the function imsl_c_lin_svd_gen.
#include <imsl.h>
main()
{
int m = 6, n = 3;
f_complex s[3], *p_u, *p_v;
f_complex a[] = {{1.0, 2.0}, {3.0, 2.0}, {1.0,-4.0},
{3.0,-2.0}, {2.0,-4.0}, {1.0, 3.0},
Output
Singular values, S
1 2 3
( 11.77, 0.00) ( 9.30, 0.00) ( 4.99, 0.00)
Example 3
This example computes the rank and generalized inverse of a 6 × 4 matrix A. The rank
and the 4 × 6 generalized inverse matrix A+ are printed.
#include <imsl.h>
main()
{
int m = 6, n = 4;
int *rank;
float tol;
f_complex gen_inv[24], *s;
f_complex a[] = {{1.0, 2.0}, {3.0, 2.0}, {1.0,-4.0}, {1.0,0.0},
{3.0,-2.0}, {2.0,-4.0}, {1.0, 3.0}, {0.0,1.0},
{4.0, 3.0}, {-2.0,1.0}, {1.0, 4.0}, {0.0,0.0},
{2.0,-1.0}, {3.0, 0.0}, {3.0,-1.0}, {2.0,1.0},
{1.0,-5.0}, {2.0,-5.0}, {2.0, 2.0}, {1.0,3.1},
{1.0, 2.0}, {4.0,-2.0}, {2.0,-3.0}, {1.4,1.9}};
/* Factor a */
tol = 1.e-4;
s = imsl_c_lin_svd_gen (m, n, a,
IMSL_RANK, tol, &rank,
Output
Rank = 4
Singular values
1 2 3
( 12.13, 0.00) ( 9.53, 0.00) ( 5.67, 0.00)
4
( 1.74, 0.00)
Generalized inverse
1 2 3
1 ( 0.0266, 0.0164) ( -0.0185, 0.0453) ( 0.0720, 0.0700)
2 ( 0.0061, 0.0280) ( 0.0820, -0.1156) ( -0.0410, -0.0242)
3 ( -0.0019, -0.0572) ( 0.1174, 0.0812) ( 0.0499, 0.0463)
4 ( 0.0380, 0.0298) ( -0.0758, -0.2158) ( 0.0356, -0.0557)
4 5 6
1 ( -0.0220, -0.0428) ( -0.0003, -0.0709) ( 0.0254, 0.1050)
2 ( 0.0959, 0.0885) ( -0.0187, 0.0287) ( -0.0218, -0.1109)
3 ( -0.0234, 0.1033) ( -0.0769, 0.0103) ( 0.0810, -0.1074)
4 ( 0.2918, -0.0763) ( 0.0881, 0.2070) ( -0.1531, 0.0814)
Warning Errors
IMSL_SLOWCONVERGENT_MATRIX Convergence cannot be reached after 30
iterations.
lin_sol_nonnegdef
Solves a real symmetric nonnegative definite system of linear equations Ax = b. Using
options, computes a Cholesky factorization of the matrix A, such that A = RTR = LLT.
Computes the solution to Ax = b given the Cholesky factor.
Synopsis
#include <imsl.h>
float *imsl_f_lin_sol_nonnegdef (int n, float a[], float b[], …, 0)
The type double function is imsl_d_lin_sol_nonnegdef.
Return Value
Using required arguments, imsl_f_lin_sol_nonnegdef returns a pointer to a
solution x of the linear system. To release this space, use free. If no value can be
computed, NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the solution x. When this option
is specified, no storage is allocated for the solution, and
imsl_f_lin_sol_nonnegdef returns a pointer to the array x.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of the array a.
Default: a_col_dim = n
IMSL_FACTOR, float **p_factor (Output)
The address of a pointer to an array of size n × n containing the LLT
factorization of A. When this option is specified, the space for the factor
matrix is allocated by imsl_f_lin_sol_nonnegdef. The lower-triangular
part of the factor array contains L, and the upper-triangular part contains LTR.
Description
The function imsl_f_lin_sol_nonnegdef solves a system of linear algebraic
equations having a symmetric nonnegative definite (positive semidefinite) coefficient
where ε (specified in tol) may be set by the user. When a linear dependence is
declared, all elements in the i-th row of R (column of L) are set to zero.
Modifications due to Farebrother and Berry (1974) and Barrett and Healy (1978) for
checking for matrices that are not nonnegative definite also are incorporated. The
function imsl_f_lin_sol_nonnegdef declares A to not be nonnegative definite and
issues an error message if either of the following conditions are satisfied:
i −1
1. aii − å r2
j =1 ji
< − ε aii
i −1
2. rii = 0 and aik − år r ji jk > ε aii a kk ,k > i
j =1
Examples
Example 1
A solution to a system of four linear equations is obtained. Maindonald (1984, pp. 83−86
and 104−105) discusses the computations for the factorization and solution to this problem.
#include <imsl.h>
main()
{
int n = 4;
float *x;
float a[] = {36.0, 12.0, 30.0, 6.0,
12.0, 20.0, 2.0, 10.0,
30.0, 2.0, 29.0, 1.0,
6.0, 10.0, 1.0, 14.0};
float b[] = {18.0, 22.0, 7.0, 20.0};
/* Solve Ax = b for x */
x = imsl_f_lin_sol_nonnegdef(n, a, b, 0);
/* Print solution, x, of Ax = b */
imsl_f_write_matrix("Solution, x", 1, n, x, 0);
}
Output
Solution, x
1 2 3 4
0.167 0.500 0.000 1.000
Example 2
The symmetric nonnegative definite matrix in the initial example is used to compute the
factorization only in the first call to lin_sol_nonnegdef. The space needed for the
factor is provided by the user. On the second call, both the LLT factorization and the
right-hand side vector in the first example are used as the input to compute a solution x.
It also illustrates another way to obtain the solution array x.
#include <imsl.h>
main()
{
int n = 4, a_col_dim = 6;
float factor[36], x[5];
float a[] = {36.0, 12.0, 30.0, 6.0,
12.0, 20.0, 2.0, 10.0,
30.0, 2.0, 29.0, 1.0,
6.0, 10.0, 1.0, 14.0};
float b[] = {18.0, 22.0, 7.0, 20.0};
/* Factor A */
imsl_f_lin_sol_nonnegdef(n, a, b,
IMSL_FACTOR_USER, factor,
IMSL_FAC_COL_DIM, a_col_dim,
Output
factor
1 2 3 4
1 6 2 5 1
2 2 4 -2 2
3 5 -2 0 0
4 1 2 0 3
Solution, x, of Ax = b
1 2 3 4
0.167 0.500 0.000 1.000
Example 3
This example uses the IMSL_INVERSE option to compute the symmetric g inverse of
the symmetric nonnegative matrix in the first example. Maindonald (1984, p. 106)
discusses the computations for this problem.
#include <stdio.h>
#include <imsl.h>
void main()
{
int n = 4;
float *p_a_inva, *p_a_inva_a, *p_inva;
float a[] = {36.0, 12.0, 30.0, 6.0,
12.0, 20.0, 2.0, 10.0,
30.0, 2.0, 29.0, 1.0,
6.0, 10.0, 1.0, 14.0};
/* Get g2_inverse(a) */
imsl_f_lin_sol_nonnegdef(n, a, NULL,
IMSL_INVERSE, &p_inva,
IMSL_INVERSE_ONLY,
0);
/* Form a*g2_inverse(a) */
Output
The g2 inverse of a
1 2 3 4
1 0.0347 -0.0208 0.0000 0.0000
2 -0.0208 0.0903 0.0000 -0.0556
3 0.0000 0.0000 0.0000 0.0000
4 0.0000 -0.0556 0.0000 0.1111
a*g2_inverse(a)
violates condition 3 of the M-P inverse
1 2 3 4
1 1.0 -0.0 0.0 0.0
2 0.0 1.0 0.0 0.0
3 1.0 -0.5 0.0 0.0
4 0.0 -0.0 0.0 1.0
a = a*g2_inverse(a)*a
condition 1 of the M-P inverse
1 2 3 4
1 36 12 30 6
2 12 20 2 10
3 30 2 29 1
4 6 10 1 14
Warning Errors
IMSL_INCONSISTENT_EQUATIONS_2 The linear system of equations is
inconsistent.
IMSL_NOT_NONNEG_DEFINITE The matrix A is not nonnegative definite.
Routines
2.1 Linear Eigensystem Problems
General Matrices
Eigenvalues and eigenvectors .....................................................eig_gen 118
Eigenvalues and eigenvectors .................................... eig_gen (complex) 120
Real Symmetric Matrices
Eigenvalues and eigenvectors .................................................... eig_sym 123
Complex Hermitian Matrices
Eigenvalues and eigenvectors ..................................eig_herm (complex) 126
Usage Notes
An ordinary linear eigensystem problem is represented by the equation Ax = λx where
A denotes an n × n matrix. The value λ is an eigenvalue and x ≠ 0 is the corresponding
eigenvector. The eigenvector is determined up to a scalar factor. In all functions, we
have chosen this factor so that x has Euclidean length one, and the component of x of
largest magnitude is positive. If x is a complex vector, this component of largest
magnitude is scaled to be real and positive. The entry where this component occurs can
be arbitrary for eigenvectors having nonunique maximum magnitude values.
A generalized linear eigensystem problem is represented by Ax = λBx where
A and B are n × n matrices. The value λ is a generalized eigenvalue, and x is the
corresponding generalized eigenvector. The generalized eigenvectors are normalized in
the same manner as the ordinary eigensystem problem.
κ j = e Tj X −1
the Euclidean length of the j-th row of X-1. Users can choose to compute this matrix
using function imsl_c_lin_sol_gen in Chapter 1, “Linear Systems.” An
approximate bound for the accuracy of a computed eigenvalue is then given by κj ε||A||.
To compute an approximate bound for the relative accuracy of an eigenvalue, divide
this bound by |λj|.
Synopsis
#include <imsl.h>
f_complex *imsl_f_eig_gen (int n, float *a, …, 0)
The type d_complex function is imsl_d_eig_gen.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float *a (Input)
An array of size n × n containing the matrix.
Return Value
A pointer to the n complex eigenvalues of the matrix. To release this space, use free.
If no value can be computed, then NULL is returned.
Optional Arguments
IMSL_VECTORS, f_complex **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
matrix. On return, the necessary space is allocated by the function. Typically,
f_complex *evec is declared, and &evec is used as an argument.
IMSL_VECTORS_USER, f_complex evecu[] (Output)
Compute eigenvectors of the matrix. An array of size n × n containing the matrix
of eigenvectors is returned in the space evecu.
IMSL_RETURN_USER, f_complex evalu[] (Output)
Store the n eigenvalues in the space evalu.
Description
Function imsl_f_eig_gen computes the eigenvalues of a real matrix by a two-phase
process. The matrix is reduced to upper Hessenberg form by elementary orthogonal or
Gauss similarity transformations. Then, eigenvalues are computed using a QR or
combined LR-QR algorithm (Golub and Van Loan 1989, pp. 373−382, and Watkins
and Elsner 1990). The combined LR-QR algorithm is based on an implementation by
Jeff Haag and David Watkins. Eigenvectors are then calculated as required. When
eigenvectors are computed, the QR algorithm is used to compute the eigenexpansion.
When only eigenvalues are required, the combined LR-QR algorithm is used.
Examples
Example 1
#include <imsl.h>
main()
{
int n = 3;
float a[] = {8.0, -1.0, -5.0,
-4.0, 4.0, -2.0,
18.0, -5.0, -7.0};
f_complex *eval;
/* Compute eigenvalues of A */
eval = imsl_f_eig_gen (n, a, 0);
/* Print eigenvalues */
imsl_c_write_matrix ("Eigenvalues", 1, n, eval, 0);
}
Output
Eigenvalues
1 2 3
( 2, 4) ( 2, -4) ( 1, 0)
Example 2
This example is a variation of the first example. Here, the eigenvectors are computed as
well as the eigenvalues.
#include <imsl.h>
main()
{
int n = 3;
Output
Eigenvalues
1 2 3
( 2, 4) ( 2, -4) ( 1, 0)
Eigenvectors
1 2 3
1 ( 0.3162, 0.3162) ( 0.3162, -0.3162) ( 0.4082, 0.0000)
2 ( 0.0000, 0.6325) ( 0.0000, -0.6325) ( 0.8165, 0.0000)
3 ( 0.6325, 0.0000) ( 0.6325, 0.0000) ( 0.4082, 0.0000)
Warning Errors
IMSL_SLOW_CONVERGENCE_GEN The iteration for an eigenvalue did not converge
after # iterations.
eig_gen (complex)
Computes the eigenexpansion of a complex matrix A.
Synopsis
#include <imsl.h>
f_complex *imsl_c_eig_gen (int n, f_complex *a, …, 0)
The type d_complex procedure is imsl_z_eig_gen.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
f_complex *a (Input)
Array of size n × n containing the matrix.
Return Value
A pointer to the n complex eigenvalues of the matrix. To release this space, use free.
If no value can be computed, then NULL is returned.
Optional Arguments
IMSL_VECTORS, f_complex **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
matrix. On return, the necessary space is allocated by the function. Typically,
f_complex *evecu is declared, and &evecu is used as an argument.
IMSL_VECTORS_USER, f_complex evecu[] (Output)
Compute eigenvectors of the matrix. An array of size n × n containing the matrix
of eigenvectors is returned in the space evecu.
IMSL_RETURN_USER, f_complex evalu[] (Output)
Store the n eigenvalues in the space evalu.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of A.
Default: a_col_dim = n
IMSL_EVECU_COL_DIM, int evecu_col_dim (Input)
The column dimension of evecu.
Default: evecu_col_dim = n
Description
The function imsl_c_eig_gen computes the eigenvalues of a complex matrix by a
two-phase process. The matrix is reduced to upper Hessenberg form by elementary
Gauss transformations. Then, the eigenvalues are computed using an explicitly shifted
LR algorithm. Eigenvectors are calculated during the iterations for the eigenvalues
(Martin and Wilkinson 1971).
Examples
Example 1
#include <imsl.h>
main()
{
int n = 4;
f_complex a[] = { {5,9}, {5,5}, {-6,-6}, {-7,-7},
{3,3}, {6,10}, {-5,-5}, {-6,-6},
Output
Eigenvalues
1 2 3
( 4, 8) ( 3, 7) ( 2, 6)
4
( 1, 5)
Example 2
This example is a variation of the first example. Here, the eigenvectors are computed as
well as the eigenvalues.
#include <imsl.h>
main()
{
int n = 4;
f_complex a[] = { {5,9}, {5,5}, {-6,-6}, {-7,-7},
{3,3}, {6,10}, {-5,-5}, {-6,-6},
{2,2}, {3,3}, {-1, 3}, {-5,-5},
{1,1}, {2,2}, {-3,-3}, { 0, 4} };
f_complex *eval;
f_complex *evec;
/* Compute eigenvalues and eigenvectors */
eval = imsl_c_eig_gen (n, a,
IMSL_VECTORS, &evec,
0);
/* Print eigenvalues and eigenvectors */
imsl_c_write_matrix ("Eigenvalues", 1, n, eval, 0);
imsl_c_write_matrix ("Eigenvectors", n, n, evec, 0);
}
Output
Eigenvalues
1 2 3
( 4, 8) ( 3, 7) ( 2, 6)
4
( 1, 5)
Eigenvectors
1 2 3
1 ( 0.5773, -0.0000) ( 0.5774 0.0000) ( 0.3780, -0.0000)
2 ( 0.5773, -0.0000) ( 0.5773, -0.0000) ( 0.7559, 0.0000)
3 ( 0.5774, 0.0000) ( -0.0000, -0.0000) ( 0.3780, 0.0000)
4 ( -0.0000, -0.0000) ( 0.5774, 0.0000) ( 0.3780, -0.0000)
Fatal Errors
IMSL_SLOW_CONVERGENCE_GEN The iteration for an eigenvalue did not converge
after # iterations.
eig_sym
Computes the eigenexpansion of a real symmetric matrix A.
Synopsis
#include <imsl.h>
float *imsl_f_eig_sym (int n, float *a, …, 0)
The type double procedure is imsl_d_eig_sym.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
float *a (Input)
Array of size n × n containing the symmetric matrix.
Return Value
A pointer to the n eigenvalues of the symmetric matrix. To release this space, use free.
If no value can be computed, then NULL is returned.
Description
The function imsl_f_eig_sym computes the eigenvalues of a symmetric real matrix
by a two-phase process. The matrix is reduced to tridiagonal form by elementary
orthogonal similarity transformations. Then, the eigenvalues are computed using a
rational QR or bisection algorithm. Eigenvectors are calculated as required
(Parlett 1980, pp. 169 −173).
Examples
Example 1
#include <imsl.h>
main()
{
int n = 3;
float a[] = {7.0, -8.0, -8.0,
-8.0, -16.0, -18.0,
-8.0, -18.0, 13.0};
float *eval;
/* Compute eigenvalues */
eval = imsl_f_eig_sym(n, a, 0);
/* Print eigenvalues */
Output
Eigenvalues
1 2 3
-27.90 22.68 9.22
Example 2
This example is a variation of the first example. Here, the eigenvectors are computed as
well as the eigenvalues.
#include <imsl.h>
main()
{
int n = 3;
float a[] = {7.0, -8.0, -8.0,
-8.0, -16.0, -18.0,
-8.0, -18.0, 13.0};
float *eval;
float *evec;
/* Compute eigenvalues and eigenvectors */
eval = imsl_f_eig_sym(n, a,
IMSL_VECTORS, &evec,
0);
/* Print eigenvalues and eigenvectors */
imsl_f_write_matrix ("Eigenvalues", 1, n, eval, 0);
imsl_f_write_matrix ("Eigenvectors", n, n, evec, 0);
}
Output
Eigenvalues
1 2 3
-27.90 22.68 9.22
Eigenvectors
1 2 3
1 0.2945 -0.2722 0.9161
2 0.8521 -0.3591 -0.3806
3 0.4326 0.8927 0.1262
Warning Errors
IMSL_SLOW_CONVERGENCE_SYM The iteration for the eigenvalue failed to
converge in 100 iterations before deflating.
IMSL_SLOW_CONVERGENCE_2 Inverse iteration did not converge.
Eigenvector is not correct for the specified
eigenvalue.
IMSL_LOST_ORTHOGONALITY_2 The eigenvectors have lost orthogonality.
eig_herm (complex)
Computes the eigenexpansion of a complex Hermitian matrix A.
Synopsis
#include <imsl.h>
float *imsl_c_eig_herm (int n, f_complex *a, …, 0)
The type double procedure is imsl_d_eig_herm.
Required Arguments
int n (Input)
Number of rows and columns in the matrix.
f_complex *a (Input)
Array of size n × n containing the matrix.
Return Value
A pointer to the n eigenvalues of the matrix. To release this space, use free. If no
value can be computed, then NULL is returned.
Optional Arguments
IMSL_VECTORS, f_complex **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
matrix. On return, the necessary space is allocated by the function. Typically,
f_complex *evec is declared, and &evec is used as an argument.
Description
The function imsl_c_eig_herm computes the eigenvalues of a complex Hermitian
matrix by a two-phase process. The matrix is reduced to tridiagonal form by elementary
orthogonal similarity transformations. Then, the eigenvalues are computed using a
rational QR or bisection algorithm. Eigenvectors are calculated as required.
Examples
Example 1
#include <imsl.h>
main()
{
int n = 3;
f_complex a[] = { {1,0}, {1,-7}, {0,-1},
{1,7}, {5,0}, {10,-3},
{0,1}, {10,3}, {-2,0} };
float *eval;
/* Compute eigenvalues */
eval = imsl_c_eig_herm(n, a, 0);
/* Print eigenvalues */
imsl_f_write_matrix ("Eigenvalues", 1, n, eval, 0);
}
Output
Eigenvalues
1 2 3
15.38 -10.63 -0.75
main()
{
int n = 3;
f_complex a[] = { {1,0}, {1,-7}, {0,-1},
{1,7}, {5,0}, {10,-3},
{0,1}, {10,3}, {-2,0} };
float *eval;
f_complex *evec;
/* Compute eigenvalues and eigenvectors */
eval = imsl_c_eig_herm(n, a,
IMSL_VECTORS, &evec,
0);
/* Print eigenvalues and eigenvectors */
imsl_f_write_matrix ("Eigenvalues", 1, n, eval, 0);
imsl_c_write_matrix ("Eigenvectors", n, n, evec, 0);
}
Output
Eigenvalues
1 2 3
15.38 -10.63 -0.75
Eigenvectors
1 2 3
1 ( 0.0631, -0.4075) ( -0.0598, -0.3117) ( 0.8539, 0.0000)
2 ( 0.7703, 0.0000) ( -0.5939, 0.1841) ( -0.0313, -0.1380)
3 ( 0.4668, 0.1366) ( 0.7160, 0.0000) ( 0.0808, -0.4942)
Warning Errors
IMSL_LOST_ORTHOGONALITY The iteration for at least one eigenvector failed to
converge. Some of the eigenvectors may be
inaccurate.
IMSL_NEVAL_MXEVAL_MISMATCH The determined number of eigenvalues in the
interval (#, #) is #. However, the input value for
the maximum number of eigenvalues in this
interval is #.
Fatal Errors
IMSL_SLOW_CONVERGENCE_GEN The iteration for the eigenvalues did not
converge.
IMSL_HERMITIAN_DIAG_REAL The matrix element A (#, #) = #. The diagonal of
a Hermitian matrix must be real.
Synopsis
#include <imsl.h>
float *imsl_f_eig_symgen (int n, float *a, float *b, …, 0)
The type double procedure is imsl_d_eig_symgen.
Required Arguments
int n (Input)
Number of rows and columns in the matrices.
float *a (Input)
Array of size n × n containing the symmetric coefficient matrix A.
float *b (Input)
Array of size n × n containing the positive definite symmetric coefficient matrix
B.
Return Value
A pointer to the n eigenvalues of the symmetric matrix. To release this space, use free.
If no value can be computed, then NULL is returned.
Optional Arguments
IMSL_VECTORS, float **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
problem. On return, the necessary space is allocated by the function. Typically,
float *evec is declared, and &evec is used as an argument.
Description
The function imsl_f_eig_symgen computes the eigenvalues of a symmetric, positive
definite eigenvalue problem by a three-phase process (Martin and Wilkinson 1971).
The matrix B is reduced to factored form using the Cholesky decomposition. These
factors are used to form a congruence transformation that yields a symmetric real
matrix whose eigenexpansion is obtained. The problem is then transformed back to the
original coordinates. Eigenvectors are calculated and transformed as required.
Examples
Example 1
#include <imsl.h>
main()
{
int n = 3;
float a[] = {1.1, 1.2, 1.4,
1.2, 1.3, 1.5,
1.4, 1.5, 1.6};
float b[] = {2.0, 1.0, 0.0,
1.0, 2.0, 1.0,
0.0, 1.0, 2.0};
float *eval;
/* Solve for eigenvalues */
eval = imsl_f_eig_symgen (n, a, b, 0);
/* Print eigenvalues */
imsl_f_write_matrix ("Eigenvalues", 1, n, eval, 0);
}
Output
Eigenvalues
1 2 3
1.386 -0.058 -0.003
main()
{
int n = 3;
float a[] = {1.1, 1.2, 1.4,
1.2, 1.3, 1.5,
1.4, 1.5, 1.6};
float b[] = {2.0, 1.0, 0.0,
1.0, 2.0, 1.0,
0.0, 1.0, 2.0};
float *eval;
float *evec;
/* Solve for eigenvalues and eigenvectors */
eval = imsl_f_eig_symgen (n, a, b,
IMSL_VECTORS, &evec,
0);
/* Print eigenvalues and eigenvectors */
imsl_f_write_matrix ("Eigenvalues", 1, n, eval, 0);
imsl_f_write_matrix ("Eigenvectors", n, n, evec, 0);
}
Output
Eigenvalues
1 2 3
1.386 -0.058 -0.003
Eigenvectors
1 2 3
1 0.6431 -0.1147 -0.6817
2 -0.0224 -0.6872 0.7266
3 0.7655 0.7174 -0.0858
Warning Errors
IMSL_SLOW_CONVERGENCE_SYM The iteration for an eigenvalue failed to
converge in 100 iterations before deflating.
Fatal Errors
IMSL_SUBMATRIX_NOT_POS_DEFINITE The leading # by # submatrix of the input
matrix is not positive definite.
IMSL_MATRIX_B_NOT_POS_DEFINITE Matrix B is not positive definite.
Synopsis
#include <imsl.h>
void imsl_f_geneig (int n, float *a, float *b, f_complex *alpha, float
*beta, ..., 0)
The double analogue is imsl_d_geneig.
Required Arguments
int n (Input)
Number of rows and columns in A and B.
float *a (Input)
Array of size n × n containing the coefficient matrix A.
float *b (Input)
Array of size n × n containing the coefficient matrix B.
f_complex *alpha (Output)
Vector of size n containing scalars αi. If βi ≠ 0, λi = αi/βi for
i = 0, …, n − 1 are the eigenvalues of the system.
float *beta (Output)
Vector of size n.
Optional Arguments
IMSL_VECTORS, f_complex **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
problem. Each vector is normalized to have Euclidean length equal to the value
one. On return, the necessary space is allocated by the function. Typically,
f_complex *evec is declared, and &evec is used as an argument.
IMSL_VECTORS_USER, f_complex evecu[] (Output)
Compute eigenvectors of the matrix. An array of size n × n containing the matrix
Description
The function imsl_f_geneig uses the QZ algorithm to compute the eigenvalues and
eigenvectors of the generalized eigensystem Ax = λBx, where A and B are real matrices
of order n. The eigenvalues for this problem can be infinite, so α and β are returned
instead of λ. If β is nonzero, λ = α/β.
The first step of the QZ algorithm is to simultaneously reduce A to upper-Hessenberg
form and B to upper-triangular form. Then, orthogonal transformations are used to
reduce A to quasi-upper-triangular form while keeping B upper triangular. The
generalized eigenvalues and eigenvectors for the reduced problem are then computed.
The function imsl_f_geneig is based on the QZ algorithm due to Moler and Stewart
(1973), as implemented by the EISPACK routines QZHES, QZIT and QZVAL; see
Garbow et al. (1977).
Examples
Example 1
In this example, the eigenvalue, λ, of system Ax = λBx is computed, where
LM 10. OP
0.5 0.0 LM
0.5 0.0 0.0 OP
A = M−10.0 PP MM
2.0 0.0 and B = 3.0 3.0 0.0 PP
MN 5.0 10
. 0.5 Q N
4.0 0.5 10
. Q
#include <imsl.h>
main()
{
int n = 3;
f_complex alpha[3];
float beta[3];
int i;
f_complex eval[3];
float a[] = {1.0, 0.5, 0.0,
-10.0, 2.0, 0.0,
5.0, 1.0, 0.5};
/* Compute eigenvalues */
/* Print eigenvalues */
Output
Eigenvalues
1 2 3
( 0.833, 1.993) ( 0.833, -1.993) ( 0.500, 0.000)
Example 2
This example finds the eigenvalues and eigenvectors of the same eigensystem given in
the last example.
#include <imsl.h>
main()
{
int n = 3;
f_complex alpha[3];
float beta[3];
int i;
f_complex eval[3];
f_complex *evec;
float a[] = {1.0, 0.5, 0.0,
-10.0, 2.0, 0.0,
5.0, 1.0, 0.5};
float b[] = {0.5, 0.0, 0.0,
3.0, 3.0, 0.0,
4.0, 0.5, 1.0};
/* Print eigenvectors */
Output
Eigenvalues
1 2 3
( 0.833, 1.993) ( 0.833, -1.993) ( 0.500, -0.000)
Eigenvectors
1 2 3
1 ( -0.197, 0.150) ( -0.197, -0.150) ( -0.000, 0.000)
2 ( -0.069, -0.568) ( -0.069, 0.568) ( -0.000, 0.000)
3 ( 0.782, 0.000) ( 0.782, 0.000) ( 1.000, 0.000)
geneig (complex)
Computes the generalized eigenexpansion of a system Ax = λBx, with A and B complex.
Synopsis
#include <imsl.h>
void imsl_c_geneig (int n, f_complex *a, f_complex *b, f_complex *alpha,
float *beta, ..., 0)
The double analogue is imsl_z_geneig.
Required Arguments
int n (Input)
Number of rows and columns in A and B.
f_complex *a (Input)
Array of size n × n containing the coefficient matrix A.
f_complex *b (Input)
Array of size n × n containing the coefficient matrix B
f_complex *alpha (Output)
Vector of size n containing scalars αi. If βi ≠ 0, λi = αi/βi for
i = 0, …, n − 1 are the eigenvalues of the system.
f_complex *beta (Output)
Vector of size n.
Optional Arguments
IMSL_VECTORS, f_complex **evec (Output)
The address of a pointer to an array of size n × n containing eigenvectors of the
problem. Each vector is normalized to have Euclidean length equal to the value
one. On return, the necessary space is allocated by the function. Typically,
f_complex *evec is declared, and &evec is used as an argument.
IMSL_VECTORS_USER, f_complex evecu[] (Output)
Compute eigenvectors of the matrix. An array of size n × n containing the matrix
of generalized eigenvectors is returned in the space evecu. Each vector is
normalized to have Euclidean length equal to the value one.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of A.
Default: a_col_dim =
IMSL_B_COL_DIM, int b_col_dim (Input)
The column dimension of B.
Default: b_col_dim = n.
IMSL_EVECU_COL_DIM, int evecu_col_dim (Input)
The column dimension of evecu.
Default: evecu_col_dim = n.
Description
The function imsl_c_geneig uses the QZ algorithm to compute the eigenvalues and
eigenvectors of the generalized eigensystem Ax = λBx, where A and B are complex
matrices of order n. The eigenvalues for this problem can be infinite, so α and β are
returned instead of λ. If β is nonzero, λ = α/β.
The first step of the QZ algorithm is to simultaneously reduce A to upper-Hessenberg
form and B to upper-triangular form. Then, orthogonal transformations are used to
reduce A to quasi-upper-triangular form while keeping B upper triangular. The
generalized eigenvalues and eigenvectors for the reduced problem are then computed.
The function imsl_c_geneig is based on the QZ algorithm due to Moler and Stewart
(1973).
Example 1
In this example, the eigenvalue, λ, of system Ax = λBx is solved, where
LM 1 0.5 + i 5i OP 0.5 LM 0 0 OP
A = M -10 2+i 0 PP MM
and B = 3 + 3i 3 + 3i i PP
MN5 + i 1 0.5 + 3i Q N
4 + 2i 0.5 + i 1 + i Q
#include <imsl.h>
main()
{
int n = 3;
f_complex alpha[3];
f_complex beta[3];
int i;
f_complex eval[3];
f_complex zero = {0.0, 0.0};
f_complex a[] = {{1.0, 0.0}, {0.5, 1.0}, {0.0, 5.0},
{-10.0, 0.0}, {2.0, 1.0}, {0.0, 0.0},
{5.0, 1.0}, {1.0, 0.0}, {0.5, 3.0}};
f_complex b[] = {{0.5, 0.0}, {0.0, 0.0}, {0.0, 0.0},
{3.0, 3.0}, {3.0, 3.0}, {0.0, 1.0},
{4.0, 2.0}, {0.5, 1.0}, {1.0, 1.0}};
/* Compute eigenvalues */
/* Print eigenvalues */
Output
Eigenvalues
1 2 3
( -8.18, -25.38) ( 2.18, 0.61) ( 0.12, -0.39)
Example 2
This example finds the eigenvalues and eigenvectors of the same eigensystem given in
the last example.
#include <imsl.h>
main()
/* Print eigenvalues */
/*Print eigenvectors */
Output
Eigenvalues
1 2 3
( -8.18, -25.38) ( 2.18, 0.61) ( 0.12, -0.39)
Eigenvectors
1 2 3
1 ( -0.3267, -0.1245) ( -0.3007, -0.2444) ( 0.0371, 0.1518)
2 ( 0.1767, 0.0054) ( 0.8959, 0.0000) ( 0.9577, 0.0000)
3 ( 0.9201, 0.0000) ( -0.2019, 0.0801) ( -0.2215, 0.0968)
Routines
3.1 Cubic Spline Interpolation
Derivative end conditions..................................cub_spline_interp_e_cnd 145
Shape preserving..............................................cub_spline_interp_shape 152
Piecewise Polynomials
A univariate piecewise polynomial (function) p is specified by giving its breakpoint
sequence ξ ∈ Rn, the order k (degree k − 1) of its polynomial pieces, and the k × (n − 1)
matrix c of its local polynomial coefficients. In terms of this information, the piecewise
polynomial (ppoly) function is given by
b g å c b xb−j −ξ 1gg !
k j −1
i
p x = ji for ξ i ≤ x ≤ ξ i +1
j =1
The breakpoint sequence ξ is assumed to be strictly increasing, and we extend the ppoly
function to the entire real axis by extrapolation from the first and last intervals. This
representation is redundant when the ppoly function is known to be smooth. For
example, if p is known to be continuous, then we can compute c1,i+1 from the cji as
follows:
b g åc
c1,i +1 = p ξ i +1 =
k
bξ i +1 − ξi g j −1
j =1
ji
b j − 1g !
For smooth ppoly, we prefer to use the nonredundant representation in terms of the
“basis” or B-splines, at least when such a function is first to be determined.
Cubic Splines
Cubic splines are smooth (i.e., C1 or C2), fourth-order ppoly functions. For historical
and other reasons, cubic splines are the most heavily used ppoly functions. Therefore,
we provide special functions for their construction and evaluation. These routines use
the ppoly representation as described above for general ppoly functions (with k = 4).
We provide two cubic spline interpolation functions:
imsl_f_cub_spline_interp_e_cnd and imsl_f_cub_spline_interp_shape.
The function imsl_f_cub_spline_interp_e_cnd allows the user to specify various
endpoint conditions (such as the value of the first or second derivative at the right and
left points). This means that the natural cubic spline can be obtained using this function
by setting the second derivative to zero at both endpoints. The function
imsl_f_cub_spline_interp_shape is designed so that the shape of the curve
matches the shape of the data. In particular, one option of this function preserves the
convexity of the data while the default attempts to minimize oscillations.
It is possible that the cubic spline interpolation functions will produce unsatisfactory
results. For example, the interpolant may not have the shape required by the user, or the
data may be noisy and require a least-squares fit. The interpolation function
imsl_f_spline_interp is more flexible, as it allows you to choose the knots and
order of the spline interpolant. We encourage the user to use this routine and exploit the
flexibility provided.
å åc nm Bn ,k x ,t x b xgB m ,k y ,t y b yg
m= 0 n = 0
lx q Nx
i i =1
and
ly q Ny
i i =1
for which the corresponding univariate interpolation problem can be solved, the tensor-
product interpolation problem finds the coefficients cnm so that
N y −1 N x −1
å åc nm Bn ,k x ,t x b x gB
i m ,k y ,t y dy i = f
j ij
m= 0 n = 0
Least Squares
The IMSL C/Math/Library includes functions for smoothing noisy data. The function
imsl_f_user_fcn_least_squares computes regressions with user-supplied
functions. The function imsl_f_spline_least_squares computes a least-squares
fit using splines with fixed knots or variable knots. These functions produce cubic
spline, least-squares fit by default. Optional arguments allow the user to choose the
order and the knot sequence. IMSL C/Math/Library also includes a tensor-product
spline regression function (imsl_f_spline_2d_least_squares) mentioned above.
The function imsl_f_radial_scattered_fit computes an approximation to
scattered data in RN using radial-basis functions.
In addition to the functions listed above, several functions in Chapter 10, “Statistics and
Random Number Generation”, provide for polynomial regression and general linear
regression.
s : Rd → Rr
This implies that such a spline s must have d knot sequences and orders (one for each
domain dimension). Thus, associated with s, we have knots and orders
t0, …, td-1
k0, …, kd-1
The precise form of the spline follows:
s(x) = (s0(x), …, sr-1(x)) x = (x1, …, xd) ∈ Rd
where the following equation is true.
nd −1 −1 n0 −1
b g å Låc
si x : = i
j0 , K, jd −1 B j0 ,k 0 ,t 0K B jd −1 ,k d −1 ,t d −1
jd −1 = 0 j0 = 0
sp-> domain_dim = d
sp-> target_dim = r
sp-> order [i] = ki i = 0, …, d − 1
sp-> num_coef [i] = mi i = 0, … , d − 1
sp-> num_knots [i] = n i + ki i = 0, …, d − 1
sp-> knots [i] [j] = t ij
i = 0, …, d − 1 j = 0, …, ni + ki − 1
sp-> coef [i] [j] = cij
i = 0, …, r − 1 j = j0 + j1 n0 + … + jd-1 n0…nd-2
For ppoly functions, we view a ppoly as a mapping with domain Rd and target
Rr where d and r are positive integers. Thus, if p is a ppoly, then for some d and r the
following is true.
p : Rd → Rr
For this version of the C/Math/Library, only r = 1 is supported. This implies that such a
ppoly p must have d breakpoint sequences and orders (one for each domain
dimension). Thus, associated with p, we have breakpoints and orders
ξ1, …, ξd
k1, …, kd
The precise form of the ppoly follows:
b g åKå
pi x : =
k d −1 k1 −1
c iL1 ,K, Ld , l ,K, l
ex − ξ j K ex
1
1
L1 d − ξ dLd j ld
ld = 0 l1 = 0
1 d l1 ! ld !
with
ppoly-> domain_dim =d
ppoly-> target_dim =r
ppoly-> order [i] = ki i = 0, …, d − 1
ppoly-> num_coef [i] = ki (ni − 1) i = 0, …, d − 1
ppoly-> num_breakpoints [i] = ni i = 0, …, d − 1
ppoly-> breakpoints [i] [j] = ξ ij
i = 0, …, d − 1 j = 0, …, ni − 1
ppoly->coef [i[ [j] = cij
i = 0, …, r − 1
j = 0, …, k0(n0 − 1)…kd-1(nd-1 − 1)
cub_spline_interp_e_cnd
Computes a cubic spline interpolant, specifying various endpoint conditions. The
default interpolant satisfies the “not-a-knot” condition.
Synopsis
#include <imsl.h>
Imsl_f_ppoly *imsl_f_cub_spline_interp_e_cnd (int ndata,
float xdata[], float fdata[], …, 0)
The type Imsl_d_ppoly function is imsl_d_cub_spline_interp_e_cnd.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the interpolation
problem.
float fdata[] (Input)
Array with ndata components containing the ordinates for the interpolation
problem.
Optional Arguments
IMSL_LEFT, int ileft, float left (Input)
Set the value for the first or second derivative of the interpolant at the left
endpoint. If ileft = i, then the interpolant s satisfies
s(i)(xL) = left
where xL is the leftmost abscissa. The only valid values for ileft are 1 or 2.
IMSL_RIGHT, int iright, float right (Input)
Set the value for the first or second derivative of the interpolant at the right
endpoint. If iright = i, then the interpolant s satisfies
s(i)(xR) = right
where xR is the rightmost abscissa. The only valid values for iright are 1 or 2.
IMSL_PERIODIC
Compute the C2 periodic interpolant to the data. That is, we require
s(i)(xL) = s(i)(xR) i = 0, 1, 2
Description
The function imsl_f_cub_spline_interp_e_cnd computes a C2 cubic spline
interpolant to a set of data points (xi, fi) for i = 0, …, ndata − 1 = n. The breakpoints of
the spline are the abscissas. We emphasize here that for all the univariate interpolation
functions, the abscissas need not be sorted. Endpoint conditions are to be selected by
the user. The user may specify “not-a-knot” or first derivative or second derivative at
each endpoint, or C2 periodicity may be requested (see de Boor 1978, Chapter 4). If no
defaults are selected, then the “not-a-knot” spline interpolant is computed. If the
IMSL_PERIODIC keyword is selected, then all other keywords are ignored; and a
C2 periodic interpolant is computed. In this case, if the fdata values at the left and
≤C fb g
4 4
f −s ξ 0 ,ξ n
ξ
ξ 0 ,ξ n
where
ξ := max ξ i +1 − ξ i
i = 0 ,K, n −1
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_ppoly *ppoly;
/* Compute xdata and fdata */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
ppoly = imsl_f_cub_spline_interp_e_cnd (NDATA, xdata, fdata, 0);
/* Print results */
printf(" x F(x) Interpolant Error\n");
for (i = 0; i < 2*NDATA-1; i++){
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_cub_spline_value(x,ppoly,0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.809 0.1270
0.100 0.997 0.997 0.0000
0.150 0.778 0.723 0.0552
0.200 0.141 0.141 0.0000
0.250 -0.572 -0.549 0.0228
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.843 0.0162
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.441 0.0093
0.500 0.938 0.938 0.0000
0.550 0.923 0.903 0.0199
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.315 0.0049
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.938 0.0295
0.800 -0.537 -0.537 0.0000
Example 2
In this example, a cubic spline interpolant to a function f is computed. The value of the
derivative at the left endpoint and the value of the second derivative at the right
endpoint are specified. The values of this spline are then compared with the exact
function values.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i, ileft, iright;
float left, right, x, y, fdata[NDATA], xdata[NDATA];
Imsl_f_ppoly *pp;
/* Compute xdata and fdata */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)(i)/(NDATA-1);
fdata[i] = F(xdata[i]);
}
/* Specify end conditions */
ileft = 1;
left = 0.0;
iright = 2;
right =-225.0*sin(15.0);
/* Compute cubic spline interpolant */
pp = imsl_f_cub_spline_interp_e_cnd(NDATA, xdata, fdata,
IMSL_LEFT, ileft, left,
IMSL_RIGHT, iright, right,
0);
/* Print results for first half */
/* of interval */
printf(" x F(x) Interpolant Error\n\n");
for (i=0; i<NDATA; i++){
x = (float)(i)/(float)(2*NDATA-2);
y = imsl_f_cub_spline_value(x,pp,0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.438 0.2441
0.100 0.997 0.997 0.0000
0.150 0.778 0.822 0.0442
0.200 0.141 0.141 0.0000
Example 3
This example computes the natural cubic spline interpolant to a function f by forcing
the second derivative of the interpolant to be zero at both endpoints. As in the previous
example, the exact function values are computed with the values of the spline.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i, ileft, iright;
float left, right, x, y, fdata[NDATA],
xdata[NDATA];
Imsl_f_ppoly *pp;
/* Compute xdata and fdata */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)(i)/(NDATA-1);
fdata[i] = F(xdata[i]);
}
/* Specify end conditions */
ileft = 2;
left = 0.0;
iright = 2;
right = 0.0;
/* Compute cubic spline interpolant */
pp = imsl_f_cub_spline_interp_e_cnd(NDATA, xdata, fdata,
IMSL_LEFT, ileft, left,
IMSL_RIGHT, iright, right,
0);
/* Print results for first half */
/* of interval */
printf(" x F(x) Interpolant Error\n\n");
for (i = 0; i < NDATA; i++){
x = (float)(i)/(float)(2*NDATA-2);
y = imsl_f_cub_spline_value(x,pp,0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.667 0.0150
0.100 0.997 0.997 0.0000
0.150 0.778 0.761 0.0172
Example 4
This example computes the cubic spline interpolant to a functions, and imposes the
periodic end conditions s(a) = s(b), s'(a) = s'(b), and s"(a) = s"(b), where a is the
leftmost abscissa and b is the rightmost abscissa.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function*/
#define F(x) (float)(sin(x))
main()
{
int i;
float x, y, twopi, fdata[NDATA], xdata[NDATA];
Imsl_f_ppoly *pp;
/* Compute xdata and fdata */
twopi = 2.0*imsl_f_constant("pi", 0);
for (i = 0; i < NDATA; i++) {
xdata[i] = twopi*(float)(i)/(NDATA-1);
fdata[i] = F(xdata[i]);
}
fdata[NDATA-1] = fdata[0];
/* Compute periodic cubic spline */
/* interpolant */
pp = imsl_f_cub_spline_interp_e_cnd(NDATA, xdata, fdata,
IMSL_PERIODIC,
0);
/* Print results for first half */
/* of interval */
printf(" x F(x) Interpolant Error\n\n");
for (i = 0; i < NDATA; i++){
x = (twopi/20.)*i;
y = imsl_f_cub_spline_value(x, pp, 0);
printf(" %6.3f %10.3f %10.3f %10.4f\n",x,F(x), y,
fabs(F(x)-y));
}
}
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.314 0.309 0.309 0.0001
0.628 0.588 0.588 0.0000
0.942 0.809 0.809 0.0004
1.257 0.951 0.951 0.0000
1.571 1.000 1.000 0.0004
1.885 0.951 0.951 0.0000
Warning Errors
IMSL_NOT_PERIODIC The data is not periodic. The rightmost fdata
value is set to the leftmost fdata value.
Fatal Errors
IMSL_DUPLICATE_XDATA_VALUES The xdata values must be distinct.
cub_spline_interp_shape
Computes a shape-preserving cubic spline.
Synopsis
#include <imsl.h>
Imsl_f_ppoly *imsl_f_cub_spline_interp_shape (int ndata, float xdata[],
float fdata[], …, 0)
The type Imsl_d_ppoly function is imsl_d_cub_spline_interp_shape.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the interpolation
problem.
float fdata[] (Input)
Array with ndata components containing the ordinates for the interpolation
problem.
Return Value
A pointer to the structure that represents the cubic spline interpolant. If an interpolant
cannot be computed, then NULL is returned. To release this space, use free.
z xn
x1
b g ′′g
2
over all convex C1 functions that interpolate the data. In the general case, when the data
have both convex and concave regions, the convexity of the spline is consistent with the
data, and the above integral is minimized under the appropriate constraints. For more
information on this interpolation scheme, refer to Michelli et al. (1985) and Irvine et al.
(1986).
One important feature of the splines produced by this function is that it is not possible,
a priori, to predict the number of breakpoints of the resulting interpolant. In most cases,
there will be breakpoints at places other than data locations. This function should be
used when it is important to preserve the convex and concave regions implied by the
data.
Both methods are nonlinear, and although the interpolant is a piecewise cubic, cubic
polynomials are not reproduced. (However, linear polynomials are reproduced.) This
explains the theoretical error estimate below.
If the data points arise from the values of a smooth (say C4) function f, i.e. fi = f(xi),
then the error will behave in a predictable fashion. Let ξ be the breakpoint vector for
either of the above spline interpolants. Then, the maximum absolute error satisfies
≤C fb g
2 2
f −s ξ 0 ,ξ m
ξ
ξ 0 ,ξ m
where
ξ := max ξ i +1 − ξ i
i = 0 ,K, m −1
Examples
Example 1
In this example, a cubic spline interpolant to a function f is computed. The values of
this spline are then compared with the exact function values.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.818 0.1360
0.100 0.997 0.997 0.0000
0.150 0.778 0.615 0.1635
0.200 0.141 0.141 0.0000
0.250 -0.572 -0.478 0.0934
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.812 0.0464
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.386 0.0645
0.500 0.938 0.938 0.0000
0.550 0.923 0.854 0.0683
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.276 0.0433
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.889 0.0789
0.800 -0.537 -0.537 0.0000
0.850 0.183 0.149 0.0338
0.900 0.804 0.804 0.0000
0.950 0.994 0.932 0.0613
1.000 0.650 0.650 0.0000
Example 2
In this example, a cubic spline interpolant to a function f is computed. The values of
this spline are then compared with the exact function values.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.667 0.0150
0.100 0.997 0.997 0.0000
0.150 0.778 0.761 0.0172
0.200 0.141 0.141 0.0000
0.250 -0.572 -0.559 0.0126
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.840 0.0189
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.440 0.0098
0.500 0.938 0.938 0.0000
0.550 0.923 0.902 0.0208
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.311 0.0086
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.952 0.0156
0.800 -0.537 -0.537 0.0000
0.850 0.183 0.200 0.0174
0.900 0.804 0.804 0.0000
0.950 0.994 0.892 0.1020
1.000 0.650 0.650 0.0000
Warning Errors
IMSL_MAX_ITERATIONS_REACHED The maximum number of iterations has been
reached. The best approximation is returned.
Fatal Errors
IMSL_DUPLICATE_XDATA_VALUES The xdata values must be distinct.
Synopsis
#include <imsl.h>
float imsl_f_cub_spline_value (float x, Imsl_f_ppoly *ppoly, …, 0)
The type double function is imsl_d_cub_spline_value.
Required Arguments
float x (Input)
Evaluation point for the cubic spline.
Imsl_f_ppoly *ppoly (Input)
Pointer to the piecewise polynomial structure that represents the cubic spline.
Return Value
The value of a cubic spline or one of its derivatives at the point x. If no value can be
computed, then NaN is returned.
Optional Arguments
IMSL_DERIV, int deriv (Input)
Let d = deriv and let s be the cubic spline that is represented by the structure
*ppoly, then this option produces the d-th derivative of s at x, s(d) (x).
IMSL_GRID, int n, float *xvec, float **value (Input/Output)
The array xvec of length n contains the points at which the cubic spline is to
be evaluated. The d-th derivative of the spline at the points in xvec is returned
in value.
IMSL_GRID_USER, int n, float *xvec, float value_user[] (Input/Output)
The array xvec of length n contains the points at which the cubic spline is to
be evaluated. The d-th derivative of the spline at the points in xvec is returned
in the user-supplied space value_user.
Examples
Example 1
In this example, a cubic spline interpolant to a function f is computed. The values of
this spline are then compared with the exact function values. Since the default settings
are used, the interpolant is determined by the “not-a-knot” condition (see de Boor
1978).
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_ppoly *pp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
pp = imsl_f_cub_spline_interp_e_cnd (NDATA, xdata, fdata, 0);
/* Print results */
printf(" x F(x) Interpolant Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++) {
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_cub_spline_value(x, pp, 0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
Output
x F(x) Interpolant Error
0.250 -0.572 -0.549 0.0228
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.843 0.0162
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.441 0.0093
0.500 0.938 0.938 0.0000
0.550 0.923 0.903 0.0199
Example 2
Recall that in the first example, a cubic spline interpolant to a function f is computed.
The values of this spline are then compared with the exact function values. This
example compares the values of the first derivatives.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define functions */
#define F(x) (float)(sin(15.0*x))
#define FP(x) (float)(15.*cos(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_ppoly *pp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
pp = imsl_f_cub_spline_interp_e_cnd (NDATA, xdata,fdata, 0);
/* Print results */
printf(" x FP(x) Interpolant Deriv Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++){
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_cub_spline_value(x, pp,
IMSL_DERIV, 1,
0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, FP(x), y,
fabs(FP(x)-y));
}
}
Output
x FP(x) Interpolant Deriv Error
0.250 -12.308 -12.559 0.2510
0.300 -3.162 -3.218 0.0560
0.350 7.681 7.796 0.1151
0.400 14.403 13.919 0.4833
0.450 13.395 13.530 0.1346
0.500 5.200 5.007 0.1926
0.550 -5.786 -5.840 0.0535
0.600 -13.667 -13.201 0.4660
0.650 -14.214 -14.393 0.1798
0.700 -7.133 -6.734 0.3990
0.750 3.775 3.911 0.1359
Synopsis
#include <imsl.h>
float imsl_f_cub_spline_integral (float a, float b, Imsl_f_ppoly *ppoly)
The type double function is imsl_d_cub_spline_integral.
Required Arguments
float a (Input)
float b (Input)
Endpoints for integration.
Imsl_f_ppoly *ppoly (Input)
Pointer to the piecewise polynomial structure that represents the cubic spline.
Return Value
The integral from a to b of the cubic spline. If no value can be computed, then NaN is
returned.
Description
The function imsl_f_cub_spline_integral computes the integral of a cubic spline
from a to b.
z bg
b
a
s x dx
Example
In this example, a cubic spline interpolant to a function f is computed. The values of the
integral of this spline are then compared with the exact integral values. Since the
default settings are used, the interpolant is determined by the “not-a-knot” condition
(see de Boor 1978).
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 21
/* Define function */
#define F(x) (float)(sin(15.0*x))
/* Integral from 0 to x */
#define FI(x) (float)((1.-cos(15.0*x))/15.)
main()
{
int i;
Output
x FI(x) Interpolant Integral Error
0.250 0.121 0.121 0.0001
0.275 0.104 0.104 0.0001
0.300 0.081 0.081 0.0001
0.325 0.056 0.056 0.0001
0.350 0.033 0.033 0.0001
0.375 0.014 0.014 0.0002
0.400 0.003 0.003 0.0002
0.425 0.000 0.000 0.0002
0.450 0.007 0.007 0.0002
0.475 0.022 0.022 0.0001
0.500 0.044 0.044 0.0001
0.525 0.068 0.068 0.0001
0.550 0.092 0.092 0.0001
0.575 0.113 0.113 0.0001
0.600 0.127 0.128 0.0001
0.625 0.133 0.133 0.0001
0.650 0.130 0.130 0.0001
0.675 0.118 0.118 0.0001
0.700 0.098 0.098 0.0001
0.725 0.075 0.075 0.0001
0.750 0.050 0.050 0.0001
spline_interp
Compute a spline interpolant.
Synopsis
#include <imsl.h>
Imsl_f_spline *imsl_f_spline_interp (int ndata, float xdata[],
float fdata[], …, 0)
The type Imsl_d_spline function is imsl_d_spline_interp.
Return Value
A pointer to the structure that represents the spline interpolant. If an interpolant cannot
be computed, then NULL is returned. To release this space, use free.
Optional Arguments
IMSL_ORDER, int order (Input)
The order of the spline subspace for which the knots are desired. This option
is used to communicate the order of the spline subspace.
Default: order = 4, i.e., cubic splines
IMSL_KNOTS, float knots[] (Input)
This option requires the user to provide the knots.
Default: knots are selected by the function imsl_f_spline_knots using its
defaults.
Description
Given the data points x = xdata, f = fdata, and the number n = ndata of elements in
xdata and fdata, the default action of imsl_f_spline_interp computes a cubic
(k = 4) spline interpolant s to the data using the default knot sequence generated by
imsl_f_spline_knots.
The optional argument IMSL_ORDER allows the user to choose the order of the spline
interpolant. The optional argument IMSL_KNOTS allows user specification of knots.
The function imsl_f_spline_interp is based on the routine SPLINT by de Boor
(1978, p. 204).
f −s ≤C f bk g t
k
t k −1 ,t n t k −1 ,t n
where
t := max t i +1 − t i
i = k −1, K, n −1
For more information on this problem, see de Boor (1978, Chapter 13) and his
reference. This function can be used in place of the IMSL function
imsl_f_cub_spline_interp.
The return value for this function is a pointer of type Imsl_f_spline. The calling
program must receive this in a pointer Imsl_f_spline *sp. This structure contains all the
information to determine the spline (stored as a linear combination of B-splines) that is
computed by this function. For example, the following code sequence evaluates this
spline at x and returns the value in y.
y = imsl_f_spline_value (x, sp, 0)
Three spline interpolants of order 2, 3, and 5 are plotted. These splines use the default
knots.
Examples
Example 1
In this example, a cubic spline interpolant to a function f is computed. The values of
this spline are then compared with the exact function values. Since the default settings
are used, the interpolant is determined by the “not-a-knot” condition (see de Boor
1978).
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
float xdata[NDATA], fdata[NDATA], x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
sp = imsl_f_spline_interp (NDATA, xdata, fdata, 0);
/* Print results */
printf(" x F(x) Interpolant Error\n");
for (i = 0; i < 2*NDATA-1; i++){
Output
x F(x) Interpolant Error
0.000 0.000 0.000 0.0000
0.050 0.682 0.809 0.1270
0.100 0.997 0.997 0.0000
0.150 0.778 0.723 0.0552
0.200 0.141 0.141 0.0000
0.250 -0.572 -0.549 0.0228
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.843 0.0162
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.441 0.0093
0.500 0.938 0.938 0.0000
0.550 0.923 0.903 0.0199
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.315 0.0049
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.938 0.0295
0.800 -0.537 -0.537 0.0000
0.850 0.183 0.148 0.0347
0.900 0.804 0.804 0.0000
0.950 0.994 1.086 0.0926
1.000 0.650 0.650 0.0000
Example 2
Recall that in the first example, a cubic spline interpolant to a function f is computed.
The values of this spline are then compared with the exact function values. This
example chooses to use a quadratic (k = 3) and a quintic k = 6 spline interpolant to the
data instead of the default values.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i, order;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
for (order =3; order<7; order += 3) {
Output
The order of the spline is 3
x F(x) Interpolant Error
0.250 -0.572 -0.542 0.0299
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.819 0.0397
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.429 0.0210
0.500 0.938 0.938 0.0000
0.550 0.923 0.879 0.0433
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.305 0.0149
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.922 0.0459
Warning Errors
IMSL_ILL_COND_INTERP_PROB The interpolation matrix is ill-conditioned. The
solution might not be accurate.
Fatal Errors
IMSL_DUPLICATE_XDATA_VALUES The xdata values must be distinct.
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
spline_knots
Computes the knots for a spline interpolant
Synopsis
#include <imsl.h>
float *imsl_f_spline_knots (int ndata, float xdata[], …, 0)
The type double function is imsl_d_spline_knots.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the interpolation
problem.
Return Value
A pointer to the knots. If the knots cannot be computed, then NULL is returned. To
release this space, use free.
Description
Given the data points x = xdata, the order of the spline k = order, and the number
n = ndata of elements in xdata, the default action of imsl_f_spline_knots
returns a pointer to a knot sequence that is appropriate for interpolation of data on x by
splines of order k (the default order is k = 4). The knot sequence is contained in its first
n + k positions. If k is even, and we assume that the entries in the input vector x are
increasing, then the resulting knot sequence t is returned as
ti = x0 for i = 0, …, k − 1
ti = xi-k/2-1 for i = k, …, n − 1
ti = xn-1 for i = n, …, n + k − 1
There is some discussion concerning this selection of knots in de Boor (1978, p. 211).
If k is odd, then t is returned as
t i = x0 for i = 0, K , k − 1
ti = ( x k −1 +x k −2 )/ 2 for i = k , K , n − 1
i− −1 i −1−
2 2
t i = xn −1 for i = n , K , n = k − 1
It is not necessary to sort the values in xdata.
If the option IMSL_OPT is selected, then the knot sequence returned minimizes the
constant c in the error estimate
Examples
Example 1
In this example, knots for a cubic spline are generated and printed. Notice that the knots
are stacked at the endpoints and that the second and next to last data points are not
knots.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 6
main()
{
int i;
float *knots, xdata[NDATA];
Output
The knots for the cubic spline are:
0 1 2 3 4 5
0 0 0 0 2 3
6 7 8 9
5 5 5 5
Example 2
This is a continuation of the examples for imsl_f_spline_interp (page 161).
Recall that in these examples, a cubic spline interpolant to a function f is computed
first. The values of this spline are then compared with the exact function values. The
second example uses a quadratic (k = 3) and a quintic (k = 6) spline interpolant to the
data. Now, instead of using the default knots, select the “optimal” knots as described
above. Notice that the error is actually worse in this case.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
main()
{
int i, order;
float fdata[NDATA], xdata[NDATA], *knots, x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
for(order = 3; order < 7; order += 3) {
knots = imsl_f_spline_knots(NDATA, xdata, IMSL_ORDER, order,
IMSL_OPT,
0);
/* Compute spline interpolant */
sp = imsl_f_spline_interp (NDATA, xdata,fdata,
IMSL_ORDER, order,
IMSL_KNOTS, knots,
0);
/* Print results */
printf("\nThe order of the spline is %d\n", order);
printf(" x F(x) Interpolant Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++) {
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_spline_value(x, sp, 0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
}
Output
The order of the spline is 3
x F(x) Interpolant Error
0.250 -0.572 -0.543 0.0290
0.300 -0.978 -0.978 0.0000
0.350 -0.859 -0.819 0.0401
0.400 -0.279 -0.279 0.0000
0.450 0.450 0.429 0.0210
0.500 0.938 0.938 0.0000
0.550 0.923 0.879 0.0433
0.600 0.412 0.412 0.0000
0.650 -0.320 -0.305 0.0150
0.700 -0.880 -0.880 0.0000
0.750 -0.968 -0.920 0.0478
Warning Errors
IMSL_NO_CONV_NEWTON Newton’s method iteration did not converge.
Fatal Errors
IMSL_DUPLICATE_XDATA_VALUES The xdata values must be distinct.
IMSL_ILL_COND_LIN_SYS Interpolation matrix is singular. The xdata
values may be too close together.
spline_2d_interp
Computes a two-dimensional, tensor-product spline interpolant from two-dimensional,
tensor-product data.
Synopsis
#include <imsl.h>
Imsl_f_spline *imsl_f_spline_2d_interp (int num_xdata, float xdata[], int
num_ydata, float ydata[], float fdata[], …, 0)
The type Imsl_d_spline function is imsl_d_spline_2d_interp.
Required Arguments
int num_xdata (Input)
Number of data points in the X direction.
float xdata[] (Input)
Array with num_xdata components containing the data points in the X
direction.
int num_ydata (Input)
Number of data points in the Y direction.
float ydata[] (Input)
Array with num_ydata components containing the data points in the Y
direction.
float fdata[] (Input)
Array of size num_data × num_data containing the values to be interpolated.
fdata[i][j] is the value at (xdata[i], ydata[j]).
Optional Arguments
IMSL_ORDER, int xorder, int yorder (Input)
This option is used to communicate the order of the spline subspace.
Default: xorder, yorder = 4, (i.e., tensor-product cubic splines)
IMSL_KNOTS, float xknots[], float yknots[] (Input)
This option requires the user to provide the knots. The default knots are
selected by the function imsl_f_spline_knots using its defaults.
IMSL_FDATA_COL_DIM, int fdata_col_dim (Input)
The column dimension of the matrix fdata.
Default: fdata_col_dim = num_xdata
Description
The function imsl_f_spline_2d_interp computes a tensor-product spline
interpolant. The tensor-product spline interpolant to data {(xi, yj, fij)}, where
0 ≤ i ≤ nx − 1 and 0 ≤ j ≤ ny − 1 has the form
n y −1n x −1
å åc nm Bn ,k x ,t x b xgB
m ,k y ,t y b yg
m= 0 n = 0
where kx and ky are the orders of the splines. These numbers are defaulted to be 4, but
can be set to any positive integer using the keyword, IMSL_ORDER. Likewise, tx and ty
are the corresponding knot sequences (xknots and yknots). These values are
defaulted to the knots returned by imsl_f_spline_knots. The algorithm requires
that
tx(kx − 1) ≤ xi ≤ tx(nx) 0 ≤ i ≤ nx − 1
ty(ky − 1) ≤ yj ≤ ty(ny − 1) 0 ≤ j ≤ ny − 1
Tensor-product spline interpolants in two dimensions can be computed quite efficiently
by solving (repeatedly) two univariate interpolation problems.
å åc nm Bn ,k x ,t x b x gB
i m ,k y ,t y dy i = f
j ij
m= 0 n = 0
Setting
hmi = å
n x −1
n=0
cnm Bn ,k x ,t x xi b g
note that for each fixed i from 0 to nx − 1, we have ny linear equations in the same
number of unknowns as can be seen below:
n y −1
åh mi Bm ,k y ,t y by g = f
i ij
m= 0
n y −1n x −1
å åc nm Bn ,k x ,t x b x gB
i m ,k y ,t y dy i = f
j ij
m= 0 n = 0
Setting
hmi = å
n x −1
n=0
cnm Bn ,k x ,t x xi b g
note that for each fixed i from 1 to nx − 1, we have ny − 1 linear equations in the same
number of unknowns as can be seen below:
n y −1
åh mi Bm ,k y ,t y by g = f
i ij
m= 0
d i
Bm ,k y ,t y y j 1 ≤ m, j ≤ n y − 1
Thus, only factor this matrix once and then apply this factorization to the nx right-hand
sides. Once this is done and hmi is computed, then solve for the coefficients cnm using
the relation
n x −1
åc nm Bn ,k x ,t x bx g = h
i mi
n=0
for m from 0 to ny − 1, which again involves one factorization and ny solutions to the
different right-hand sides. The function imsl_f_spline_2d_interp is based on the
routine SPLI2D by de Boor (1978, p. 347).
The return value for this function is a pointer to the structure Imsl_f_spline. The
calling program must receive this in a pointer Imsl_f_spline *sp. This structure
contains all the information to determine the spline (stored in B-spline format) that is
Examples
Example 1
In this example, a tensor-product spline interpolant to a function f is computed.
The values of the interpolant and the error on a 4 × 4 grid are displayed.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
#define OUTDATA 2
/* Define function */
#define F(x, y) (float)(x*x*x+y*y)
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NDATA][NDATA], xdata[NDATA], ydata[NDATA];
float x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = ydata[i] = (float)i / ((float)(NDATA-1));
}
for (i = 0; i < NDATA; i++) {
for (j = 0; j < NDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = num_ydata = NDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_interp(num_xdata, xdata, num_ydata,
ydata, fdata, 0);
/* Print results */
printf(" x y F(x, y) Interpolant Error \n");
for (i = 0; i < OUTDATA; i++) {
x = (float) i / (float) (OUTDATA);
for (j = 0; j < OUTDATA; j++) {
y = (float) j / (float) (OUTDATA);
z = imsl_f_spline_2d_value(x, y, sp, 0);
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, F(x,y), z, fabs(F(x,y)-z));
}
}
}
Output
x y F(x, y) Interpolant Error
0.000 0.000 0.000 0.000 0.0000
0.000 0.500 0.250 0.250 0.0000
0.500 0.000 0.125 0.125 0.0000
0.500 0.500 0.375 0.375 0.0000
#define NDATA 7
#define OUTDATA 4
/* Define function */
#define F(x,y) (float)(x*x*x+y*y)
main()
{
int i, j, num_xdata, num_ydata, order;
float fdata[NDATA][NDATA], xdata[NDATA], ydata[NDATA];
float x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = ydata[i] = (float) i / ((float) (NDATA - 1));
}
for (i = 0; i < NDATA; i++) {
for (j = 0; j < NDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = num_ydata = NDATA;
Warning Errors
IMSL_ILL_COND_INTERP_PROB The interpolation matrix is ill-conditioned. The
solution might not be accurate.
Fatal Errors
IMSL_XDATA_NOT_INCREASING The xdata values must be strictly increasing.
IMSL_YDATA_NOT_INCREASING The ydata values must be strictly increasing.
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
IMSL_KNOT_NOT_INCREASING The knots must be nondecreasing.
spline_value
Computes the value of a spline or the value of one of its derivatives.
Synopsis
#include <imsl.h>
float imsl_f_spline_value (float x, Imsl_f_spline *sp, …, 0)
The type double function is imsl_d_spline_value.
Required Arguments
float x (Input)
Evaluation point for the spline.
Imsl_f_spline *sp (Input)
Pointer to the structure that represents the spline.
Return Value
The value of a spline or one of its derivatives at the point x. If no value can be
computed, NaN is returned.
Optional Arguments
IMSL_DERIV, int deriv (Input)
Let d = deriv and let s be the spline that is represented by the structure *sp.
Then, this option produces the d-th derivative of s at x, s(d) (x).
Default: deriv = 0
Description
The function imsl_f_spline_value computes the value of a spline or one of its
derivatives. This function is based on the routine BVALUE by de Boor (1978, p. 144).
Examples
Example 1
In this example, a cubic spline interpolant to a function f is computed. The values of
this spline are then compared with the exact function values. Since the default settings
are used, the interpolant is determined by the “not-a-knot” condition (see de Boor
1978).
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
sp = imsl_f_spline_interp (NDATA, xdata,fdata, 0);
/* Print results */
printf(" x F(x) Interpolant Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++){
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_spline_value(x, sp, 0);
printf(" %6.3f %10.3f %10.3f %10.4f\n", x, F(x), y,
fabs(F(x)-y));
}
}
Example 2
Recall that in the first example, a cubic spline interpolant to a function f is computed.
The values of this spline are then compared with the exact function values. This
example compares the values of the first derivatives.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
/* Define function */
#define F(x) (float)(sin(15.0*x))
#define FP(x) (float)(15.*cos(15.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
sp = imsl_f_spline_interp (NDATA, xdata, fdata, 0);
/* Print results */
printf(" x FP(x) Interpolant Deriv Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++) {
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_spline_value(x, sp, IMSL_DERIV, 1, 0);
printf(" %6.3f %10.3f %10.3f %10.4f \n", x, FP(x), y,
fabs(FP(x)-y));
}
}
Output
x FP(x) Interpolant Deriv Error
0.250 -12.308 -12.559 0.2510
0.300 -3.162 -3.218 0.0560
0.350 7.681 7.796 0.1151
0.400 14.403 13.919 0.4833
Fatal Errors
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
IMSL_KNOT_NOT_INCREASING The knots must be nondecreasing.
spline_integral
Computes the integral of a spline.
Synopsis
#include <imsl.h>
float imsl_f_spline_integral (float a, float b, Imsl_f_spline *sp)
The type double function is imsl_d_spline_integral.
Required Arguments
float a (Input)
float b (Input)
Endpoints for integration.
Imsl_f_spline *sp (Input)
Pointer to the structure that represents the spline.
Return Value
The integral of a spline. If no value can be computed, then NaN is returned.
Description
The function imsl_f_spline_integral computes the integral of a spline from a to
b
z bg
b
a
s x dx
This routine uses the identity (22) on page 151 of de Boor (1978).
#define NDATA 21
/* Define function */
#define F(x) (float)(sin(15.0*x))
/* Integral from 0 to x */
#define FI(x) (float)((1.-cos(15.0*x))/15.)
main()
{
int i;
float fdata[NDATA], xdata[NDATA], x, y;
Imsl_f_spline *sp;
/* Set up a grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = (float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]);
}
/* Compute cubic spline interpolant */
sp = imsl_f_spline_interp (NDATA, xdata, fdata, 0);
/* Print results */
printf(" x FI(x) Interpolant Integral Error\n");
for (i = NDATA/2; i < 3*NDATA/2; i++) {
x = (float) i /(float)(2*NDATA-2);
y = imsl_f_spline_integral(0.0, x, sp);
printf(" %6.3f %10.3f %10.3f %10.4f \n", x, FI(x), y,
fabs(FI(x)-y));
}
}
Output
x FI(x) Interpolant Integral Error
0.250 0.121 0.121 0.0001
0.275 0.104 0.104 0.0001
0.300 0.081 0.081 0.0001
0.325 0.056 0.056 0.0001
0.350 0.033 0.033 0.0001
0.375 0.014 0.014 0.0002
0.400 0.003 0.003 0.0002
0.425 0.000 0.000 0.0002
0.450 0.007 0.007 0.0002
0.475 0.022 0.022 0.0001
0.500 0.044 0.044 0.0001
0.525 0.068 0.068 0.0001
0.550 0.092 0.092 0.0001
0.575 0.113 0.113 0.0001
0.600 0.127 0.128 0.0001
0.625 0.133 0.133 0.0001
Warning Errors
IMSL_SPLINE_SMLST_ELEMNT The data arrays xdata and ydata must satisfy
datai ≤ torder-1, for i = 1, …, num_data.
IMSL_SPLINE_EQUAL_LIMITS The upper and lower endpoints of integration
are equal. The indefinite integral is zero.
IMSL_LIMITS_LOWER_TOO_SMALL The left endpoint is less than torder-1.
Integration occurs only from torder-1 to b.
IMSL_LIMITS_UPPER_TOO_SMALL The right endpoint is less than torder-1.
Integration occurs only from torder-1 to a.
IMSL_LIMITS_UPPER_TOO_BIG The right endpoint is greater than
tspline_space_dim-1. Integration occurs only from
a to tspline_space_dim-1.
IMSL_LIMITS_LOWER_TOO_BIG The left endpoint is greater than
tspline_space_dim-1. Integration occurs only from
b to tspline_space_dim-1.
Fatal Errors
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
IMSL_KNOT_NOT_INCREASING The knots must be nondecreasing.
spline_2d_value
Computes the value of a tensor-product spline or the value of one of its partial
derivatives.
Synopsis
#include <imsl.h>
float imsl_f_spline_2d_value (float x, float y, Imsl_f_spline *sp, …, 0)
The type double function is imsl_d_spline_2d_value.
Required Arguments
float x (Input)
Return Value
The value of a tensor-product spline or one of its derivatives at the point (x, y).
Optional Arguments
IMSL_DERIV, int x_partial, int y_partial (Input)
Let p = x_partial and q = y_partial, and let s be the spline that is
represented by the structure *sp, then this option produces the (p, q)-th
derivative of s at (x, y), s(p,q) (x, y).
Default: x_partial = y_partial = 0
IMSL_GRID, int nx, float *xvec, int ny, float *yvec, float **value
(Input/Output)
The argument xvec is the array of length nx containing the X coordinates at
which the spline is to be evaluated. The argument yvec is the array of length
ny containing the Y coordinates at which the spline is to be evaluated. The
value of the spline on the nx by ny grid is returned in value.
IMSL_GRID_USER, int nx, float *xvec, int ny, float *yvec,
float value_user[] (Input/Output)
The argument xvec is the array of length nx containing the X coordinates at
which the spline is to be evaluated. The argument yvec is the array of length
ny containing the Y coordinates at which the spline is to be evaluated. The
value of the spline on the nx by ny grid is returned in the user-supplied space
value_user.
Description
The function imsl_f_spline_2d_value computes the value of a tensor-product
spline or one of its derivatives. This function is based on the discussion in de Boor
(1978, pp. 351 −353).
Example 1
In this example, a spline interpolant s to a function f is constructed. Using the procedure
imsl_f_spline_2d_interp to compute the interpolant,
imsl_f_spline_2d_value is employed to compute s(x, y). The values of this partial
derivative and the error are computed on a 4 × 4 grid and then displayed.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
#define OUTDATA 2
/* Define function */
#define F(x,y) (float)(x*x*x+y*y)
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NDATA][NDATA], xdata[NDATA], ydata[NDATA];
float x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = ydata[i] = (float) i / ((float) (NDATA - 1));
}
for (i = 0; i < NDATA; i++) {
for (j = 0; j < NDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = num_ydata = NDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_interp(num_xdata, xdata, num_ydata,
ydata, fdata, 0);
/* Print results */
printf(" x y F(x, y) Value Error\n");
for (i = 0; i < OUTDATA; i++) {
x = (float) (1+i) / (float) (OUTDATA+1);
for (j = 0; j < OUTDATA; j++) {
y = (float) (1+j) / (float) (OUTDATA+1);
z = imsl_f_spline_2d_value(x, y, sp, 0);
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, F(x,y), z, fabs(F(x,y)-z));
}
}
}
Output
x y F(x, y) Value Error
0.333 0.333 0.148 0.148 0.0000
0.333 0.667 0.481 0.481 0.0000
0.667 0.333 0.407 0.407 0.0000
0.667 0.667 0.741 0.741 0.0000
#define NDATA 11
#define OUTDATA 2
/* Define function */
#define F(x, y) (float)(x*x*x*y*y)
#define F21(x,y) (float)(6.*x*2.*y)
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NDATA][NDATA], xdata[NDATA], ydata[NDATA];
float x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = ydata[i] = (float)i / ((float)(NDATA-1));
}
for (i = 0; i < NDATA; i++) {
for (j = 0; j < NDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = num_ydata = NDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_interp(num_xdata, xdata, num_ydata,
ydata, fdata, 0);
/* Print results */
printf(" x y F21(x, y) 21InterpDeriv Error\n");
for (i = 0; i < OUTDATA; i++) {
x = (float) (1+i) / (float) (OUTDATA+1);
for (j = 0; j < OUTDATA; j++) {
y = (float) (1+j) / (float) (OUTDATA+1);
z = imsl_f_spline_2d_value(x, y, sp,
IMSL_DERIV, 2, 1,
0);
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, F21(x, y), z, fabs(F21(x,y)-z));
}
}
}
Output
x y F21(x, y) 21InterpDeriv Error
0.333 0.333 1.333 1.333 0.0000
0.333 0.667 2.667 2.667 0.0000
0.667 0.333 2.667 2.667 0.0000
0.667 0.667 5.333 5.333 0.0001
spline_2d_integral
Evaluates the integral of a tensor-product spline on a rectangular domain.
Synopsis
#include <imsl.h>
float imsl_f_spline_2d_integral (float a, float b, float c, float d,
Imsl_f_spline *sp)
The type double function is imsl_d_spline_2d_integral.
Required Arguments
float a (Input)
float b (Input)
The integration limits for the first variable of the tensor-product spline.
float c (Input)
float d (Input)
The integration limits for the second variable of the tensor-product spline.
Imsl_f_spline *sp (Input)
Pointer to the structure that represents the spline.
Return Value
The value of the integral of the tensor-product spline over the rectangle
[a, b] × [c, d]. If no value can be computed, NaN is returned.
Description
The function imsl_f_spline_2d_integral computes the integral of a tensor-
product spline. If s is the spline, then this function returns
zz b
b d
a c
g
s x , y dydx
LMå a OPB b xg
zt0
x n -1
i =0
bg
r -1
å a i Bi ,k t dt = å
i =0 N
i
j =0
j
t j+k - t j
k Qi , k +1
where t0 ≤ x ≤ tr.
It assumes (for all knot sequences) that the first and last k knots are stacked, that is,
t0 = … = tk-1 and tn = … = tn+k-1 , where k is the order of the spline in the x or y
direction.
Example
This example integrates a two-dimensional, tensor-product spline over the rectangle [0,
x] × [0, y].
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 11
#define OUTDATA 2
/* Define function */
#define F(x,y) (float)(x*x*x+y*y)
/* The integral of F from 0 to x */
/* and 0 to y */
#define FI(x,y) (float)(y*x*x*x*x/4. + x*y*y*y/3.)
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NDATA][NDATA], xdata[NDATA], ydata[NDATA];
float x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NDATA; i++) {
xdata[i] = ydata[i] = (float) i / ((float)(NDATA-1));
}
for (i = 0; i < NDATA; i++) {
for (j = 0; j < NDATA; j++) {
fdata[i][j] = F(xdata[i],ydata[j]);
}
}
num_xdata = num_ydata = NDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_interp(num_xdata, xdata, num_ydata,
ydata, fdata, 0);
/* Print results */
printf(" x y FI(x, y) Integral Error\n");
for (i = 0; i < OUTDATA; i++) {
x = (float) (1+i) / (float) (OUTDATA+1);
for (j = 0; j < OUTDATA; j++) {
y = (float) (1+j) / (float) (OUTDATA+1);
z = imsl_f_spline_2d_integral(0.0, x, 0.0, y, sp);
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, FI(x, y), z, fabs(FI(x,y)-z));
}
Output
x y FI(x, y) Integral Error
0.333 0.333 0.005 0.005 0.0000
0.333 0.667 0.035 0.035 0.0000
0.667 0.333 0.025 0.025 0.0000
0.667 0.667 0.099 0.099 0.0000
Warning Errors
IMSL_SPLINE_LEFT_ENDPT The left endpoint of X integration is not within
the knot sequence. Integration occurs only
from torder-1 to b.
IMSL_SPLINE_RIGHT_ENDPT The right endpoint of X integration is not
within the knot sequence. Integration occurs
only from torder-1 to a.
IMSL_SPLINE_LEFT_ENDPT_1 The left endpoint of X integration is not within
the knot sequence. Integration occurs only
from b to
tspline_space_dim-1.
IMSL_SPLINE_RIGHT_ENDPT_1 The right endpoint of X integration is not
within the knot sequence. Integration occurs
only from a to
tspline_space_dim-1.
IMSL_SPLINE_LEFT_ENDPT_2 The left endpoint of Y integration is not within
the knot sequence. Integration occurs only
from torder-1 to d.
IMSL_SPLINE_RIGHT_ENDPT_2 The right endpoint of Y integration is not
within the knot sequence. Integration occurs
only from torder-1 to c.
IMSL_SPLINE_LEFT_ENDPT_3 The left endpoint of Y integration is not within
the knot sequence. Integration occurs only
from d to
tspline_space_dim-1.
IMSL_SPLINE_RIGHT_ENDPT_3 The right endpoint of Y integration is not
within the knot sequence. Integration occurs
only from c to
tspline_space_dim-1.
Fatal Errors
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
user_fcn_least_squares
Computes a least-squares fit using user-supplied functions.
Synopsis
#include <imsl.h>
float *imsl_f_user_fcn_least_squares (float fcn (int k, float x), int
nbasis, int ndata, float xdata[], float ydata[], …, 0)
The type double function is imsl_d_user_fcn_least_squares.
Required Arguments
float fcn (int k, float x) (Input)
User-supplied function that defines the subspace from which the least-squares
fit is to be performed. The k-th basis function evaluated at x is f(k, x) where
k = 1, 2, …, nbasis.
int nbasis (Input)
Number of basis functions.
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the least-squares
problem.
float ydata[] (Input)
Array with ndata components containing the ordinates of the least-squares
problem.
Return Value
A pointer to the vector containing the coefficients of the basis functions. If a fit cannot
be computed, then NULL is returned. To release this space, use free.
Description
The function imsl_f_user_fcn_least_squares computes a best least-squares
approximation to given univariate data of the form
mb x , f gr
i i
n −1
i =0
by M basis functions
nF s j
M
j =1
(where M = nbasis). In particular, the default for this function returns the coefficients
a which minimize
LM
n −1 M O 2
å M f − åa
w F b x gP
i =0N
i i
j =1
j −1 j
PQi
n −1 L M O 2
å w MM f − intercept − å a
i i j −1 F b x gP
j
PQ i
i =0 N j =1
Examples
Example 1
This example fits the following two functions (indexed by δ):
1 + sinx + 7 sin3x + δε
#define NDATA 90
/* Define function */
#define F(x) (float)(1.+ sin(x)+7.*sin(3.0*x))
main()
{
int nbasis = 4, i, delta;
float ydata[NDATA], xdata[NDATA], *random, *coef;
/* Generate random numbers */
imsl_random_seed_set(1234567);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for(delta = 0; delta < 2; delta++) {
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
ydata[i] = F(xdata[i]) + (delta)*2.*(random[i]-.5);
}
coef = imsl_f_user_fcn_least_squares(fcn, nbasis, NDATA, xdata,
ydata, 0);
printf("\nFor delta = %1d", delta);
imsl_f_write_matrix("the computed coefficients are\n",
1, nbasis, coef, 0);
}
}
1 2 3 4
1 1 -0 7
For delta = 1
the computed coefficients are
1 2 3 4
0.979 0.998 0.096 6.839
Example 2
Recall that the first example fitted the following two functions (indexed by δ):
1 + sinx + 7 sin3x + δε
#define NDATA 90
/* Define function */
#define F(x) (float)(1.+ sin(x)+7.*sin(3.0*x))
main()
{
int nbasis = 4, i, delta;
float ydata[NDATA], xdata[NDATA], *random, *coef, intercept;
/* Generate random numbers */
imsl_random_seed_set(1234567);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for(delta = 0; delta < 2; delta++){
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
ydata[i] = F(xdata[i]) + (delta)*2.*(random[i]-.5);
}
coef = imsl_f_user_fcn_least_squares(fcn, nbasis, NDATA, xdata,
ydata,
IMSL_INTERCEPT, &intercept,
0);
printf("\nFor delta = %1d\n", delta);
printf("The predicted intercept value is %10.3f\n" ,
intercept);
imsl_f_write_matrix("the computed coefficients are\n",
1, nbasis, coef, 0);
}
}
Output
For delta = 0
The predicted intercept value is 1.000
1 2 3 4
1 0 7 -0
For delta = 1
1 2 3 4
0.998 0.097 6.841 0.075
Warning Errors
IMSL_LINEAR_DEPENDENCE Linear dependence of the basis functions
exists. One or more components of coef are
set to zero.
IMSL_LINEAR_DEPENDENCE_CONST Linear dependence of the constant function
and basis functions exists. One or more
components of coef are set to zero.
Fatal Errors
IMSL_NEGATIVE_WEIGHTS_2 All weights must be greater than or equal to
zero.
spline_least_squares
Computes a least-squares spline approximation.
Synopsis
#include <imsl.h>
Imsl_f_spline *imsl_f_spline_least_squares (int ndata, float xdata[],
float fdata[], int spline_space_dim, …, 0)
The type Imsl_d_spline function is imsl_d_spline_least_squares.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the least-squares
problem.
float fdata[] (Input)
Array with ndata components containing the ordinates of the least-squares
problem.
int spline_space_dim (Input)
The linear dimension of the spline subspace. It should be smaller than ndata
and greater than or equal to order (whose default value is 4).
LM
n −1 OP m
2
å M å
w f −ia B bix g PQ j j i
i =0N j =1
where the Bj, j = 1, …, m are a (B-spline) basis for the spline subspace.
The optional argument IMSL_ORDER allows the user to choose the order of the spline
fit. The optional argument IMSL_KNOTS allows user specification of knots. The
function imsl_f_spline_least_squares is based on the routine L2APPR by de
Boor (1978, p. 255).
If the option IMSL_OPTIMIZE is chosen, then the procedure attempts to find the best
placement of knots that will minimize the least-squares error to the given data by a
spline of order k with m coefficients. For this problem to make sense, it is necessary
that m > k. We then attempt to find the minimum of the functional
L n −1 O m −1
b g å w MM f − å a B b x gPP
F a,t = i i j j ,k ,t i
N i =0 Q j =0
The technique employed here uses the fact that for a fixed knot sequence t the
minimization in a is a linear least-squares problem that can be easily solved. Thus, we
can think of our objective function F as a function of just t by setting
bg
G t = min F a , t
a
b g
A Gauss-Seidel (cyclic coordinate) method is then used to reduce the value of the new
objective function G. In addition to this local method, there is a global heuristic built
into the algorithm that will be useful if the data arise from a smooth function. This
heuristic is based on the routine NEWNOT of de Boor (1978, pp. 184 and 258−261).
The initial guess, tg, for the knot sequence is either provided by the user or is the
default. This guess must be a valid knot sequence for splines of order k with
t 0g ≤ K ≤ t kg -1 ≤ xi ≤ t mg ≤ K ≤ t mg + k −1 i = 1, K , M
with tg nondecreasing, and
t ig < t ig+ k for i = 0, K , m − 1
Both splines are cubics with the same spline_space_dim = 8. The first spline is
computed with the default settings, while the second spline is computed by optimizing
the knot locations using the keyword IMSL_OPTIMIZE.
Examples
Example 1
This example fits data generated from a trigonometric polynomial
1 + sinx + 7 sin3x + ε
where ε is a random uniform deviate over the range [−1, 1]. The data are obtained by
evaluating this function at 90 equally spaced points on the interval [0, 6]. This data is
fitted with a cubic spline with 12 degrees of freedom (eight equally spaced interior
knots). The error at 10 equally spaced points is printed out.
#define NDATA 90
/* Define function */
#define F(x) (float)(1.+ sin(x)+7.*sin(3.0*x))
main()
{
int i, spline_space_dim = 12;
float fdata[NDATA], xdata[NDATA], *random;
Imsl_f_spline *sp;
/* Generate random numbers */
imsl_random_seed_set(123457);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]) + 2.*(random[i]-.5);
}
sp = imsl_f_spline_least_squares(NDATA, xdata, fdata,
spline_space_dim, 0);
printf(" x error \n");
for(i = 0; i < 10; i++) {
float x, error;
x = 6.*i/9.;
error = F(x) - imsl_f_spline_value(x, sp, 0);
printf("%10.3f %10.3f\n", x, error);
}
}
Output
x Error
0.000 -0.356
0.667 -0.004
1.333 0.434
2.000 -0.069
2.667 -0.494
3.333 0.362
4.000 -0.273
4.667 -0.247
5.333 0.303
6.000 0.578
Example 2
This example continues with the first example in which we fit data generated from the
trigonometric polynomial
1 + sinx + 7 sin3x + ε
where ε is random uniform deviate over the range [−1, 1]. The data is obtained by
evaluating this function at 90 equally spaced points on the interval [0, 6]. This data was
fitted with a cubic spline with 12 degrees of freedom (in this case, the default gives us
eight equally spaced interior knots) and the error sum of squares was printed. In this
#define NDATA 90
/* Define function */
#define F(x) (float)(1.+ sin(x)+7.*sin(3.0*x))
main()
{
int i, spline_space_dim = 12;
float fdata[NDATA], xdata[NDATA], *random, sse1, sse2;
Imsl_f_spline *sp;
/* Generate random numbers */
imsl_random_seed_set(123457);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]) + 2.*(random[i]-.5);
}
sp = imsl_f_spline_least_squares(NDATA, xdata, fdata,
spline_space_dim,
IMSL_SSE, &sse1,
0);
sp = imsl_f_spline_least_squares(NDATA, xdata, fdata,
spline_space_dim,
IMSL_OPTIMIZE,
IMSL_SSE, &sse2,
0);
printf("The error sum of squares before optimizing is %10.1f\n",
sse1);
printf("The error sum of squares after optimizing is %10.1f\n\n",
sse2);
printf(" x error\n");
for(i = 0; i < 10; i++){
float x, error;
x = 6.*i/9.;
error = F(x) - imsl_f_spline_value(x, sp, 0);
printf("%10.3f %10.3f\n", x, error);
}
}
Output
The error sum of squares before optimizing is 32.6
The error sum of squares after optimizing is 27.0
x Error
0.000 -0.656
0.667 0.107
1.333 0.055
2.000 -0.243
2.667 -0.063
3.333 -0.015
4.000 -0.424
Warning Errors
IMSL_OPT_KNOTS_STACKED_1 The knots found to be optimal are stacked
more than order. This indicates fewer knots
will produce the same error sum of squares.
The knots have been separated slightly.
Fatal Errors
IMSL_XDATA_TOO_LARGE The array xdata must satisfy xdatai ≤ tndata,
for i = 1, …, ndata.
IMSL_XDATA_TOO_SMALL The array xdata must satisfy
xdatai ≥ torder-1, for i = 1, …, ndata.
IMSL_NEGATIVE_WEIGHTS All weights must be greater than or equal to
zero.
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
IMSL_KNOT_NOT_INCREASING The knots must be nondecreasing.
IMSL_OPT_KNOTS_STACKED_2 The knots found to be optimal are stacked
more than order. This indicates fewer knots
will produce the same error sum of squares.
spline_2d_least_squares
Computes a two-dimensional, tensor-product spline approximant using least squares.
Synopsis
#include <imsl.h>
Imsl_f_spline *imsl_f_spline_2d_least_squares (int num_xdata, float
xdata[], int num_ydata, float ydata[], float fdata[], int
x_spline_space_dim, int y_spline_space_dim, …, 0)
The type Imsl_d_spline function is imsl_d_spline_2d_least_squares.
Required Arguments
int num_xdata (Input)
Number of data points in the X direction.
float xdata[] (Input)
Array with num_xdata components containing the data points in the X
direction.
Return Value
A pointer to the structure that represents the tensor-product spline interpolant. If an
interpolant cannot be computed, then NULL is returned. To release this space, use free.
Optional Arguments
IMSL_SSE, float *sse (Output)
This option places the weighted error sum of squares in the place pointed to by
sse.
IMSL_ORDER, int xorder, int yorder (Input)
This option is used to communicate the order of the spline subspace.
Default: xorder, yorder = 4 (i.e., tensor-product cubic splines)
Description
The imsl_f_spline_2d_least_squares procedure computes a tensor-product
spline least-squares approximation to weighted tensor-product data. The input for this
function consists of data vectors to specify the tensor-product grid for the data, two
vectors with the weights (optional, the default is 1), the values of the surface on the
grid, and the specification for the tensor-product spline (optional, a default is chosen).
The grid is specified by the two vectors x = xdata and y = ydata of length
n = num_xdata and m = num_ydata, respectively. A two-dimensional array f = fdata
contains the data values which are to be fit. The two vectors wx = xweights and
wy = yweights contain the weights for the weighted least-squares problem. The
information for the approximating tensor-product spline can be provided using the
keywords IMSL_ORDER and IMSL_KNOTS. This information is contained in
kx = xorder, tx = xknots, and N = xspline_space_dim for the spline in the first
variable, and in ky = yorder, ty = yknots and M = y_spline_space_dim for the
spline in the second variable.
This function computes coefficients for the tensor-product spline by solving the normal
equations in tensor-product form as discussed in de Boor (1978, Chapter 17). The
interested reader might also want to study the paper by Grosse (1980).
As the computation proceeds, we obtain coefficients c minimizing
n − 1 m −1 L N − 1 M −1 OP 2
å å w bi gw b j gMMå å c B b x , y g − f PQ
i =0 j =0
x
N y
k =0 l =0
kl kl i i ij
where the function Bkl is the tensor-product of two B-splines of order kx and ky.
Specifically, we have
b g bg
Bkl x , y = Bk ,k x ,t x x Bl ,k y ,t y y bg
The spline
N −1 M −1
å åc kl Bkl
k =0 l = 0
Examples
Example 1
The data for this example comes from the function ex sin (x + y) on the rectangle [0, 3]
× [0, 5]. This function is sampled on a 50 × 25 grid. Next try to recover it by using
tensor-product cubic splines. The values of the function ex sin (x + y) are printed on a
2 × 2 grid and compared with the values of the tensor-product spline least-squares fit.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NXDATA 50
#define NYDATA 25
#define OUTDATA 2
/* Define function */
#define F(x,y) (float)(exp(x)*sin(x+y))
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NXDATA][NYDATA];
float xdata[NXDATA], ydata[NYDATA], x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NXDATA; i++) {
xdata[i] = 3.*(float) i / ((float)(NXDATA-1));
}
for (i = 0; i < NYDATA; i++) {
ydata[i] = 5.*(float) i / ((float)(NYDATA-1));
}
/* Compute function values on grid */
for (i = 0; i < NXDATA; i++) {
for (j = 0; j < NYDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = NXDATA;
num_ydata = NYDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_least_squares(num_xdata, xdata, num_ydata,
ydata, fdata, 5, 7, 0);
/* Print results */
printf(" x y F(x, y) Fitted Values Error\n");
for (i = 0; i < OUTDATA; i++) {
x = (float)i / (float)(OUTDATA);
for (j = 0; j < OUTDATA; j++) {
y = (float)j / (float)(OUTDATA);
}
}
Output
x y F(x, y) Fitted Values Error
0.000 0.000 0.000 -0.020 0.0204
0.000 0.500 0.479 0.500 0.0208
0.500 0.000 0.790 0.816 0.0253
0.500 0.500 1.387 1.384 0.0031
Example 2
The same data is used as in the previous example. Optional argument IMSL_SSE is
used to return the error sum of squares.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NXDATA 50
#define NYDATA 25
#define OUTDATA 2
/* Define function */
#define F(x,y) (float)(exp(x)*sin(x+y))
main()
{
int i, j, num_xdata, num_ydata;
float fdata[NXDATA][NYDATA];
float xdata[NXDATA], ydata[NYDATA], x, y, z;
Imsl_f_spline *sp;
/* Set up grid */
for (i = 0; i < NXDATA; i++) {
xdata[i] = 3.*(float) i / ((float) (NXDATA - 1));
}
for (i = 0; i < NYDATA; i++) {
ydata[i] = 5.*(float) i / ((float) (NYDATA - 1));
}
/* Compute function values on grid */
for (i = 0; i < NXDATA; i++) {
for (j = 0; j < NYDATA; j++) {
fdata[i][j] = F(xdata[i], ydata[j]);
}
}
num_xdata = NXDATA;
num_ydata = NYDATA;
/* Compute tensor-product interpolant */
sp = imsl_f_spline_2d_least_squares(num_xdata, xdata, num_ydata,
ydata, fdata, 5, 7,
IMSL_SSE, &x,
0);
/* Print results */
printf("The error sum of squares is %10.3f\n\n", x);
Output
The error sum of squares is 3.753
Warning Errors
IMSL_ILL_COND_LSQ_PROB The least-squares matrix is ill-conditioned. The
solution might not be accurate.
IMSL_SPLINE_LOW_ACCURACY There may be less than one digit of accuracy in
the least-squares fit. Try using a higher
precision if possible.
Fatal Errors
IMSL_KNOT_MULTIPLICITY Multiplicity of the knots cannot exceed the
order of the spline.
IMSL_KNOT_NOT_INCREASING The knots must be nondecreasing.
IMSL_SPLINE_LRGST_ELEMNT The data arrays xdata and ydata must satisfy
datai ≤ tspline_space_dim, for i = 1,
…, num_data.
IMSL_SPLINE_SMLST_ELEMNT The data arrays xdata and ydata must satisfy
datai ≥ torder-1, for i = 1, …, num_data.
IMSL_NEGATIVE_WEIGHTS All weights must be greater than or equal to
zero.
IMSL_DATA_DECREASING The xdata values must be nondecreasing.
Synopsis
#include <imsl.h>
Imsl_f_ppoly *imsl_f_cub_spline_smooth (int ndata, float xdata[], float
fdata[], …, 0)
The type Imsl_d_ppoly function is imsl_d_cub_spline_smooth.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the problem.
float fdata[] (Input)
Array with ndata components containing the ordinates of the problem.
Return Value
A pointer to the structure that represents the cubic spline. If a smoothed cubic spline
cannot be computed, then NULL is returned. To release this space, use free.
Optional Arguments
IMSL_WEIGHTS, float weights[] (Input)
This option requires the user to provide the weights.
Default: all weights are equal to 1.
IMSL_SMOOTHING_PAR, float sigma (Input)
This option sets the smoothing parameter σ = sigma explicitly.
z
b
bg
s ′′ x dx
2
å csb x g − f hw
i =0
i i i ≤σ
Examples
Example 1
In this example, function values are contaminated by adding a small “random” amount
to the correct values. The function imsl_f_cub_spline_smooth is used to
approximate the original, uncontaminated data.
#define NDATA 90
/* Define function */
#define F(x) (float)(1.+ sin(x)+7.*sin(3.0*x))
main()
{
int i;
float fdata[NDATA], xdata[NDATA], *random;
Imsl_f_ppoly *pp;
/* Generate random numbers */
imsl_random_seed_set(123457);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]) + .5*(random[i]-.5);
}
pp = imsl_f_cub_spline_smooth(NDATA, xdata, fdata, 0);
printf(" x error \n");
for(i = 0; i < 10; i++){
float x, error;
x = 6.*i/9.;
error = F(x) - imsl_f_cub_spline_value(x, pp, 0);
printf("%10.3f %10.3f\n", x, error);
}
}
Output
x Error
0.000 -0.201
0.667 0.070
1.333 -0.008
2.000 -0.058
2.667 -0.025
3.333 0.076
4.000 -0.002
4.667 -0.008
5.333 0.045
6.000 0.276
Example 2
Recall that in the first example, function values are contaminated by adding a small
“random” amount to the correct values. Then, imsl_f_cub_spline_smooth is used
to approximate the original, uncontaminated data. This example explicitly inputs the
value of the smoothing parameter to be 5.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 90
/* Define function */
main()
{
int i;
float fdata[NDATA], xdata[NDATA], *random;
Imsl_f_ppoly *pp;
/* Generate random numbers */
imsl_random_seed_set(123457);
random = imsl_f_random_uniform(NDATA, 0);
/* Set up data */
for (i = 0; i < NDATA; i++) {
xdata[i] = 6.*(float)i /((float)(NDATA-1));
fdata[i] = F(xdata[i]) + .5*(random[i]-.5);
}
pp = imsl_f_cub_spline_smooth(NDATA, xdata, fdata,
IMSL_SMOOTHING_PAR, 5.0,
0);
printf(" x error \n");
for(i = 0; i < 10; i++){
float x, error;
x = 6.*i/9.;
error = F(x) - imsl_f_cub_spline_value(x, pp, 0);
printf("%10.3f %10.3f\n", x, error);
}
}
Output
x Error
0.000 -0.593
0.667 0.230
1.333 -0.116
2.000 -0.106
2.667 0.176
3.333 -0.071
4.000 -0.171
4.667 0.196
5.333 -0.036
6.000 0.971
Warning Errors
IMSL_MAX_ITERATIONS_REACHED The maximum number of iterations has been
reached. The best approximation is returned.
Fatal Errors
IMSL_DUPLICATE_XDATA_VALUES The xdata values must be distinct.
IMSL_NEGATIVE_WEIGHTS All weights must be greater than or equal to
zero.
Synopsis
#include <imsl.h>
Imsl_f_spline *imsl_f_spline_lsq_constrained (int ndata, float xdata[],
float fdata[], int spline_space_dim, int num_con_pts,
f_constraint_struct constraints[], …, 0)
The type Imsl_d_spline function is imsl_d_spline_lsq_constrained.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the least-squares
problem.
float fdata[] (Input)
Array with ndata components containing the ordinates of the least-squares
problem.
int spline_space_dim (Input)
The linear dimension of the spline subspace. It should be smaller than ndata
and greater than or equal to order (whose default value is 4).
int num_con_pts (Input)
The number of points in the vector constraints.
f_constraint_struct constraints[] (Input)
A structure containing the abscissas at which the fit is to be constrained, the
derivative of the spline that is to be constrained, the type of constraints, and
any lower or upper limits. A description of the structure fields follows:
Field Description
xval point at which fit is constrained
der derivative value of the spline to be constrained
type types of the general constraints
bl lower limit of the general constraints
bu upper limit of the general constraints
Notes: If you want to constrain the integral of the spline over the closed
interval (c, d), then set constraints[i].der = constraints
[i+1].der = −1 and constraints[i].xval = c and
constraints[i+1].xval = d. For consistency, insist that
f b g b xi g ≥ bli
d
3 i
bl ≤ f b g b x g ≤ bu
d
z
4 i
i
i i
bli = bg
zz bb gg
5 f t dt
c
6 f t dt ≤ bui
c
f t dt ≥ bli
z bg
7
c
8 bli ≤ f t dt ≤ bui
c
20 periodic end conditions
99 disregard this constraint
11 f b d gi
b xi g − f bd g b xi +1 g ≥ bli
i +1
bl ≤ f b g b x g − f b g b x g ≤ bu
d d
12 i
i
i
i +1
i +1 i
Return Value
A pointer to the structure that represents the spline fit. If a fit cannot be computed, then
NULL is returned. To release this space, use free.
Description
The function imsl_f_spline_lsq_constrained produces a constrained, weighted
least-squares fit to data from a spline subspace. Constraints involving one point, two
points, or integrals over an interval are allowed. The types of constraints supported by
the functions are of four types:
Ep[f] = f
d j idy i
p
p
=
d j idy i − f d j idy
p+1
i
z
p
or f p p +1
or =
yp
bg
f t dt
or = periodic end conditions
å f − å a B bx g
i =1
i
j =1
j j i wi
subject to
LM
m OP
Ep
MNå PQ ∈ I
a
j =1
B j j p p = 1, K , n f
Examples
Example 1
This is a simple application of imsl_f_lsq_constrained. Data is generated from
the function
x x
+ sin( )
2 2
and contaminated with random noise and fit with cubic splines. The function is
increasing, so least-squares fit should also be increasing. This is not the case for the
unconstrained least-squares fit generated by imsl_f_spline_least_squares. Then,
the derivative is forced to be greater than 0 at num_con_pts = 15 equally spaced
points and imsl_f_lsq_constrained is called. The resulting curve is monotone.
The error is printed for the two fits averaged over 100 equally spaced points.
#include <imsl.h>
#include <math.h>
#define MXKORD 4
#define MXNCOF 20
#define MXNDAT 51
#define MXNXVL 15
main()
{
f_constraint_struct constraint[MXNXVL];
int i, korder, ncoef, ndata, nxval;
float *noise, errlsq, errnft, grdsiz, x;
float fdata[MXNDAT], xdata[MXNDAT];
Imsl_f_spline *sp, *spls;
korder = 4;
ndata = 15;
nxval = 15;
ncoef = 8;
/*
* Compute original xdata and fdata with random noise.
*/
imsl_random_seed_set (234579);
noise = imsl_f_random_uniform (ndata, 0);
grdsiz = 10.0;
for (i = 0; i < ndata; i++) {
xdata[i] = grdsiz * ((float) (i) / (float) (ndata - 1));
fdata[i] = F1 (xdata[i]) + (noise[i] - .5);
}
Output
Average error with spline_least_squares fit: 0.20250
Average error with spline_lsq_constrained fit: 0.14334
z−7
7
bg
s x dx ≤ 2.3
s(−7) = s(7)
Notice that the last constraint was generated using the periodic option (requiring only
the zero-th derivative to be periodic). The error is printed for the two fits averaged over
100 equally spaced points.
#include <imsl.h>
#include <math.h>
#define KORDER 4
#define NDATA 51
#define NXVAL 12
#define NCOEF 13
main()
{
f_constraint_struct constraint[NXVAL];
int i;
float *noise, errlsq, errnft, grdsiz, x;
float fdata[NDATA], xdata[NDATA], xknot[NDATA+KORDER];
Imsl_f_spline *sp, *spls;
imsl_random_seed_set (234579);
noise = imsl_f_random_uniform (NDATA, 0);
grdsiz = 14.0;
for (i = 0; i < NDATA; i++) {
xdata[i] = grdsiz * ((float)(i)/(float)(NDATA - 1))
- grdsiz/2.0;
fdata[i] = F1 (xdata[i]) + 0.125*(noise[i] - .5);
}
constraint[9].xval = -7.0;
constraint[9].itype = 6;
constraint[9].bu = 2.3;
constraint[10].xval = 7.0;
constraint[10].itype = 6;
constraint[10].bu = 2.3;
constraint[11].xval = -7.0;
constraint[11].itype = 20;
constraint[11].ider = 0;
errlsq = 0.0;
errnft = 0.0;
for (i = 0; i < 100; i++) {
x = grdsiz * (float) (i) / 99.0 - grdsiz/2.0;
errnft += fabs (F1 (x) - imsl_f_spline_value(x,sp,0));
errlsq += fabs (F1 (x) - imsl_f_spline_value(x,spls,0));
}
/* Print results */
printf (" Average error with BSLSQ fit: %8.5f\n",
Output
Average error with BSLSQ fit: 0.01783
Average error with CONFT fit: 0.01339
smooth_1d_data
Smooth one-dimensional data by error detection.
Synopsis
#include <imsl.h>
float *imsl_f_smooth_1d_data (int ndata,
float xdata[], float fdata[], …, 0)
The type double function is imsl_d_smooth_1d_data.
Required Arguments
int ndata (Input)
Number of data points.
float xdata[] (Input)
Array with ndata components containing the abscissas of the data points.
float ydata[] (Input)
Array with ndata components containing the ordinates of the data points.
Return Value
A pointer to the vector of length ndata containing the smoothed data.
Algorithm
The function imsl_f_smooth_1d_data is designed to smooth a data set that is
mildly contaminated with isolated errors. In general, the routine will not work well if
more than 25% of the data points are in error. The routine imsl_f_smooth_1d_data
is based on an algorithm of Guerra and Tapia (1974).
Setting ndata = n, ydata = f, sdata = s and xdata = x, the algorithm proceeds as
follows. Although the user need not input an ordered xdata sequence, we will assume
that x is increasing for simplicity. The algorithm first sorts the xdata values into an
increasing sequence and then continues. A cubic spline interpolant is computed for each
of the 6-point data sets (initially setting s = f)
(xj, sj) j = i − 3, …, i + 3 j ≠ i,
where i = 4, …, n − 3. For each i the interpolant, which we will call Si, is compared
with the current value of si, and a ‘point energy’ is computed as
pei = Si(xi) − si
Setting sc = sc, the algorithm terminates either if itmax iterations have taken place or
if
e j
pei ≤ sc xi +3 − xi − 3 / 6 i = 4,K , n − 3
If the above inequality is violated for any i, then we update the i-th element of s by
setting si = si + d(pei), where d = dis. Note that neither the first three nor the last three
data points are changed. Thus, if these points are inaccurate, care must be taken to
interpret the results.
The choice of the parameters d, sc and itmax are crucial to the successful usage of this
subroutine. If the user has specific information about the extent of the contamination,
then he should choose the parameters as follows: d = 1, sc = 0 and itmax to be the
number of data points in error. On the other hand, if no such specific information is
available, then choose d = .5, itmax ≤ 2n, and
Example
We take 91 uniform samples from the function 5 + (5 + t2 sin t)/t on the interval [1, 10].
Then, we contaminate 10 of the samples and try to recover the original function values.
#include "imsl.h"
#include "stdlib.h"
#include "math.h"
#define NDATA 91
#define F(X) (X*X*sin((double)(X))+5.0)/X + 5.0
main()
{
int i, maxit;
int isub[10] = {5, 16, 25, 33, 41, 48, 55, 61, 74, 82};
float dis, fdata[NDATA], sc, *sdata=NULL;
float xdata[NDATA], s_user[NDATA];
float rnoise[10] = {2.5, -3., -2., 2.5, 3.,
-2., -2.5, 2., -2., 3.};
/*
* A warning message is produced because the maximum
* number of iterations is reached.
*/
scattered_2d_interp
Computes a smooth bivariate interpolant to scattered data that is locally a quintic
polynomial in two variables.
Synopsis
#include <imsl.h>
float *imsl_f_scattered_2d_interp (int ndata, float xydata[], float
fdata[], int nx_out, int ny_out, float x_out[], float y_out[], …,
0)
Required Arguments
int ndata (Input)
Number of data points.
float xydata[] (Input)
Array with ndata*2 components containing the data points for the
interpolation problem. The i-th data point (xi, yi) is stored consecutively in the
2i and 2i + 1 positions of xydata.
float fdata[] (Input)
Array of size ndata containing the values to be interpolated.
int nx_out (Input)
Number of data points in the x direction for the output grid.
int ny_out (Input)
Number of data points in the y direction for the output grid.
float x_out[] (Input)
Array of length nx_out specifying the x values for the output grid. It must be
strictly increasing.
float y_out[] (Input)
Array of length ny_out specifying the y values for the output grid. It must be
strictly increasing.
Return Value
A pointer to the nx_out × ny_out grid of values of the interpolant. If no answer can
be computed, then NULL is returned. To release this space, use free.
Optional Arguments
IMSL_RETURN_USER, float surface[] (Output)
This option allows the user to provide his own space for the result. In this
case, the answer will be returned in surface.
IMSL_SUR_COL_DIM, int surface_col_dim (Input)
This option requires the user to provide the column dimension of the two-
Description
The function imsl_f_scattered_2d_interp computes a C1 interpolant to scattered
data in the plane. Given the data points
mb x , y , f gr
i i i
n −1
i =0
mb x , y gr
i i
n −1
i =0
b g åc
s x, y = T m n
mn x y ∀x , y ∈ T
m + n ≤5
Examples
Example 1
In this example, the interpolant to the linear function (3 + 7x + 2y) is computed from 20
data points equally spaced on the circle of radius 3. Then the values are printed on a
3 × 3 grid.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define NDATA 20
#define OUTDATA 3
/* Define function */
#define F(x,y) (float)(3.+7.*x+2.*y)
pi = imsl_f_constant("pi", 0);
/* Set up output grid */
for (i = 0; i < OUTDATA; i++) {
x_out[i] = y_out[i] = (float) i / ((float) (OUTDATA - 1));
}
for (i = 0; i < 2*NDATA; i += 2) {
xydata[i] = 3.*cos(pi*i/NDATA);
xydata[i+1] = 3.*sin(pi*i/NDATA);
fdata[i/2] = F(xydata[i], xydata[i+1]);
}
/* Compute scattered data interpolant */
surf = imsl_f_scattered_2d_interp (NDATA, xydata, fdata, OUTDATA,
OUTDATA, x_out, y_out, 0);
/* Print results */
printf(" x y F(x, y) Interpolant Error\n");
for (i = 0; i < OUTDATA; i++) {
for (j = 0; j < OUTDATA; j++) {
x = x_out[i];
y = y_out[j];
z = SURF(i,j);
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, F(x,y), z, fabs(F(x,y)-z));
}
}
}
Output
x y F(x, y) Interpolant Error
0.000 0.000 3.000 3.000 0.0000
0.000 0.500 4.000 4.000 0.0000
0.000 1.000 5.000 5.000 0.0000
0.500 0.000 6.500 6.500 0.0000
0.500 0.500 7.500 7.500 0.0000
0.500 1.000 8.500 8.500 0.0000
1.000 0.000 10.000 10.000 0.0000
1.000 0.500 11.000 11.000 0.0000
1.000 1.000 12.000 12.000 0.0000
Example 2
Recall that in the first example, the interpolant to the linear function 3 + 7x + 2y is
computed from 20 data points equally spaced on the circle of radius 3. We then print
the values on a 3 × 3 grid. This example used the optional arguments to indicate that the
answer is stored noncontiguously in a two-dimensional arraysurf with column
dimension equal to 11.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
main()
{
int i, j;
float fdata[NDATA], xydata[2*NDATA];
float surf[OUTDATA][COLDIM];
float x, y, z, x_out[OUTDATA], y_out[OUTDATA], pi;
pi = imsl_f_constant("pi", 0);
/* Set up output grid */
for (i = 0; i < OUTDATA; i++) {
x_out[i] = y_out[i] = (float) i / ((float) (OUTDATA - 1));
}
for (i = 0; i < 2*NDATA; i += 2) {
xydata[i] = 3.*cos(pi*i/NDATA);
xydata[i+1] = 3.*sin(pi*i/NDATA);
fdata[i/2] = F(xydata[i], xydata[i+1]);
}
/* Compute scattered data interpolant */
imsl_f_scattered_2d_interp (NDATA, xydata, fdata, OUTDATA,
OUTDATA, x_out, y_out,
IMSL_RETURN_USER, surf,
IMSL_SUR_COL_DIM, COLDIM,
0);
/* Print results */
printf(" x y F(x, y) Interpolant Error\n");
for (i = 0; i < OUTDATA; i++) {
for (j = 0; j < OUTDATA; j++) {
x = x_out[i];
y = y_out[j];
z = surf[i][j];
printf(" %6.3f %6.3f %10.3f %10.3f %10.4f\n",
x, y, F(x,y), z, fabs(F(x,y)-z));
}
}
}
Output
x y F(x, y) Interpolant Error
0.000 0.000 3.000 3.000 0.0000
0.000 0.500 4.000 4.000 0.0000
0.000 1.000 5.000 5.000 0.0000
0.500 0.000 6.500 6.500 0.0000
0.500 0.500 7.500 7.500 0.0000
0.500 1.000 8.500 8.500 0.0000
1.000 0.000 10.000 10.000 0.0000
1.000 0.500 11.000 11.000 0.0000
1.000 1.000 12.000 12.000 0.0000
radial_scattered_fit
Computes an approximation to scattered data in Rn for n ≥ 1 using radial-basis
functions.
Synopsis
#include <imsl.h>
Imsl_f_radial_basis_fit *imsl_f_radial_scattered_fit (int dimension,
int num_points, float abscissae[], float fdata[],
int num_centers, …, 0)
The type Imsl_d_radial_basis_fit function is imsl_d_radial_scattered_fit.
Required Arguments
int dimension (Input)
Number of dimensions.
int num_points (Input)
The number of data points.
float abscissae[] (Input)
Array of size dimension × num_points containing the abscissae of the data
points. The argument abscissae[i][j] is the abscissa value of the (i+1)-th
data point in the (j+1)-th dimension.
float fdata[] (Input)
Array with num_points components containing the ordinates for the
problem.
int num_centers (Input)
The number of centers to be used when computing the radial-basis fit. The
argument num_centers should be less than or equal to num_points.
Return Value
A pointer to the structure that represents the radial-basis fit. If a fit cannot be computed,
then NULL is returned. To release this space, use free.
Optional Arguments
IMSL_CENTERS (Input)
User-supplied centers. See the “Description” section of this function for
details.
IMSL_CENTERS_RATIO, float ratio (Input)
The desired ratio of centers placed on an evenly spaced grid to the total
number of centers. The condition that the same number of centers placed on a
grid for each dimension must be equal. Thus, the actual number of centers
placed on a grid is usually less than ratio*num_centers, but will never be
more than ratio*num_centers. The remaining centers are randomly chosen
from the set of abscissae given in abscissae.
Default: ratio = 0.5
IMSL_RANDOM_SEED, int seed
The value of the random seed used when determining the random subset of
abscissae to use as centers. By changing the value of seed on different calls to
imsl_f_radial_scattered_fit, with the same data set, a different set of
random centers will be chosen. Setting seed to zero forces the random
number seed to be based on the system clock, so a possibly different set of
centers will be chosen each time the program is executed.
Default: seed = 234579
IMSL_SUPPLY_BASIS, float radial_function (float distance) (Input)
User-supplied function to compute the values of the radial functions.
Default: Hardy multiquadric
IMSL_SUPPLY_DELTA, float delta (Input)
The delta used in the default basis function
bg
φ r = r2 + δ2
Default: delta = 1
Description
The function imsl_f_radial_scattered_fit computed a least-squares fit to
scattered data in Rd where d = dimension. More precisely, let n = ndata,
x = abscissae, f = fdata, and d = dimension. Then we have
x 0 ,K , x n −1 ⊂ R d f 0 ,K , f n −1 ⊂ R 1
This function computes a function F which approximates the above data in the sense
that it minimizes the sum-of-squares error
n −1 2
å w eFex j − f j
i
i
i
i =0
where w = weights. Of course, we must restrict the functional form of F. This is done
as follows:
b g å α φFGH IJ
k −1
2
F x := x − cj + δ2
j =0
j
K
The function φ is called the radial function. It maps R1 into R1, only defined for the
nonnegative reals. For the purpose of this routine, the user-supplied function
b g er
φr = 2
+ δ2 j
Note that the value of delta is defaulted to 1. It can be set by the user by using the
keyword IMSL_DELTA. The parameter δ is used to scale the problem. Generally choose
δ to be near the minimum spacing of the centers.
The default basis function is called the Hardy multiquadric, and it is defined as
b g er
φr = 2
+ δ2 j
A key feature of this routine is the user’s control over the selection of the basis
function.
To obtain the default selection of centers, we first compute the number of centers that
will be on a grid and how many are on a random subset of the abscissae. Next, we
compute those centers on a grid. Finally, a random subset of abscissa are obtained
determining where the centers are placed. Let us examine the selection of centers in
more detail.
α = (centers_ratio) (num_centers)
β = ëα1/dimensionû
num_gridded = βdimension
Note that there are β grid values in each of the dimension directions. Then we have
num_random = (num_centers) − (num_gridded)
Now we know how many centers will be placed on a grid and how many will be placed
on a random subset of the abscissae. The gridded centers are computed such that they
are equally spaced in each of the dimension directions. The last problem is to
compute a random subset, without replacement, of the abscissa. The selection is based
on a random seed. The default seed is 234579. The user can change this using the
optional argument IMSL_RANDOM_SEED. Once the subset is computed, we use the
abscissae as centers.
Since the selection of good centers for a specific problem is an unsolved problem at this
time, we have given the ultimate flexibility to the user. That is, you can select your own
centers using the keyword IMSL_CENTERS. As a rule of thumb, the centers should be
interspersed with the abscissae.
The return value for this function is a pointer to the structure, which contains all the
information necessary to evaluate the fit. This pointer is then passed to the function
imsl_f_radial_evaluate to produce values of the fitted function.
Examples
Example 1
This example, generates data from a function and contaminates it with noise on a grid
of 10 equally spaced [Link] fit is evaluated on a finer grid and compared with the
actual function values.
#include <imsl.h>
#include <math.h>
#define NDATA 10
#define NUM_CENTERS 5
#define NOISE_SIZE 0.25
#define F(x) ((float)(sin(2*pi*x)))
main ()
{
int i;
int dim = 1;
float fdata[NDATA];
float *fdata2;
float xdata[NDATA];
float xdata2[2*NDATA];
float pi;
imsl_random_seed_set (234579);
noise = imsl_f_random_uniform(NDATA, 0);
Output
I TRUE APPROX ERROR
1 0.00000 -0.08980 0.08980
2 0.34202 0.38795 -0.04593
3 0.64279 0.75470 -0.11191
4 0.86603 0.99915 -0.13312
5 0.98481 1.11597 -0.13116
6 0.98481 1.10692 -0.12211
7 0.86603 0.98183 -0.11580
8 0.64279 0.75826 -0.11547
9 0.34202 0.46078 -0.11876
10 -0.00000 0.11996 -0.11996
11 -0.34202 -0.23007 -0.11195
12 -0.64279 -0.55348 -0.08931
13 -0.86603 -0.81624 -0.04979
14 -0.98481 -0.98752 0.00271
15 -0.98481 -1.04276 0.05795
16 -0.86603 -0.96471 0.09868
17 -0.64279 -0.74472 0.10193
18 -0.34202 -0.38203 0.04001
19 0.00000 0.11600 -0.11600
20 0.34202 0.73553 -0.39351
main()
{
int i;
int ndata;
double *fit;
double ratio;
double fdata[NDATA+1];
double xydata[2 * NDATA+1];
double pi;
double *noise;
int num_centers;
Imsl_d_radial_basis_fit *radial_struct;
imsl_random_seed_set (234579);
noise = imsl_d_random_uniform (NRANDOM+1, 0);
for (i = 0; i < NRANDOM; ++i) noise[i] = 1.0 - 2.0 * noise[i];
printf(" NDATA || Error ||_2 \n");
radial_evaluate
Evaluates a radial-basis fit.
Synopsis
#include <imsl.h>
float *imsl_f_radial_evaluate (int n, float x[],
Imsl_d_radial_basis_fit *radial_fit, …, 0)
The type double function is imsl_d_evaluate.
Required Arguments
int n (Input)
The number of points at which the fit will be evaluated.
float x[] (Input)
Array of size (radial_fit − > dimension) × n containing the abscissae of
the data points at which the fit will be evaluated. The argument x[i][j] is the
abscissa value of the (i+1)-th data point in the (j+1)-th dimension.
Imsl_f_radial_basis_fit *radial_fit (Input)
A pointer to radial-basis structure to be used for the evaluation. (Input).
Optional Arguments
IMSL_RETURN_USER, value[] (Input)
A user-allocated array of length n containing the returned values.
Description
The function imsl_f_radial_evaluate evaluates a radial-basis fit from data
generated by imsl_f_radial_scattered_fit.
Example
#include <imsl.h>
#include <math.h>
#define NDATA 10
#define NUM_CENTERS 5
#define NOISE_SIZE 0.25
#define F(x) ((float)(sin(2*pi*x)))
main ()
{
int i;
int dim = 1;
float fdata[NDATA];
float *fdata2;
float xdata[NDATA];
float xdata2[2*NDATA];
float pi;
float *noise;
Imsl_f_radial_basis_fit *radial_fit;
imsl_random_seed_set (234579);
noise = imsl_f_random_uniform(NDATA, 0);
Output
I TRUE APPROX ERROR
1 0.00000 -0.08980 0.08980
2 0.34202 0.38795 -0.04593
3 0.64279 0.75470 -0.11191
4 0.86603 0.99915 -0.13312
5 0.98481 1.11597 -0.13116
6 0.98481 1.10692 -0.12211
7 0.86603 0.98183 -0.11580
8 0.64279 0.75826 -0.11547
9 0.34202 0.46078 -0.11876
10 -0.00000 0.11996 -0.11996
11 -0.34202 -0.23007 -0.11195
12 -0.64279 -0.55348 -0.08931
13 -0.86603 -0.81624 -0.04979
14 -0.98481 -0.98752 0.00271
15 -0.98481 -1.04276 0.05795
16 -0.86603 -0.96471 0.09868
17 -0.64279 -0.74472 0.10193
18 -0.34202 -0.38203 0.04001
19 0.00000 0.11600 -0.11600
20 0.34202 0.73553 -0.39351
Routines
4.1 Univariate Quadrature
Adaptive general-purpose endpoint singularity..................... int_fcn_sing 237
Adaptive general purpose.............................................................. int_fcn 241
Adaptive general-purpose points of singularity...............int_fcn_sing_pts 245
Adaptive weighted algebraic singularities........................ int_fcn_alg_log 249
Adaptive infinite interval........................................................... int_fcn_inf 252
Adaptive weighted oscillatory (trigonometric) ......................... int_fcn_trig 256
Adaptive weighted Fourier (trigonometric).........................int_fcn_fourier 260
Cauchy principal value......................................................int_fcn_cauchy 264
Nonadaptive general purpose.......................................... int_fcn_smooth 267
4.2 Multivariate Quadrature
Two-dimensional iterated integral............................................ int_fcn_2d 270
Iterated integral on a hyper-rectangle......................... int_fcn_hyper_rect 274
4.3 Gauss Quadrature
Gauss quadrature formulas .......................................... gauss_quad_rule 277
4.4 Differentiation
First, second, or third derivative of a function .................... fcn_derivative 281
Usage Notes
Univariate Quadrature
The first nine functions in this chapter are designed to compute approximations to
integrals of the form
z bgbg
c
b
f x w x dx
z z bgbg
b b
bgbg
f x w x dx − R ≤ E ≤ max{ ε ,ρ f x w x dx }
a a
Multivariate Quadrature
Two functions have been included in this chapter that are of use in approximating
certain multivariate integrals. In particular, the function imsl_f_int_fcn_2d returns
an approximation to an iterated two-dimensional integral of the form
zz
b h x
a
bg
gb x g
f b x , y gdydx
z z
b1
a1
K
bn
an
b g
f x1 , K , xn dxn K dx1
When working with two-dimensional tensor-product tabular data, use the IMSL
spline interpolation function imsl_f_spline_2d_interp, followed by the IMSL
spline integration function imsl_f_spline_2d_integral described in
Chapter 3, “Interpolation and Approximation”.
Gauss Quadrature
Before computing Gauss quadratures, you must compute so-called Gauss quadrature
rules that integrate polynomials of as high degree as possible. These quadrature rules
can be easily computed using the function imsl_f_gauss_quad_rule, which
produces the points {wi} for i = 1, …, N that satisfy
za
b
bgbg
f x w x dx =
N
å f b x gw
i =1
i i
for all functions f that are polynomials of degree less than 2N. The weight functions w
may be selected from the following table.
e− x
2
(−∞, ∞) Hermite
int_fcn_sing
Integrates a function, which may have endpoint singularities, using a globally adaptive
scheme based on Gauss-Kronrod rules.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_sing (float fcn(), float a, float b, …, 0)
Required Arguments
float fcn (float x) (input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
Return Value
An estimate of
za
b
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
Description
This function is designed to handle functions with endpoint singularities. However, the
performance on functions that are well-behaved at the endpoints is also quite good.
The function imsl_f_int_fcn_sing is a general-purpose integrator that uses a
globally adaptive scheme in order to reduce the absolute error. It subdivides the interval
[a, b] and uses a 21-point Gauss-Kronrod rule to estimate the integral over each
subinterval. The error for each subinterval is estimated by comparison with the 10-point
Gauss quadrature rule. The subinterval with the largest estimated error is then bisected,
and the same procedure is applied to both halves. The bisection process is continued
until either the error criterion is satisfied, roundoff error is detected, the subintervals
become too small, or the maximum number of subintervals allowed is reached. This
function uses an extrapolation procedure known as the ε-algorithm.
The function imsl_f_int_fcn_sing is based on the subroutine QAGS by
Piessens et al. (1983).
Examples
Example 1
The value of
z bg
0
1
ln x x −1/ 2 dx = −4
is estimated.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact;
/* Evaluate the integral */
q = imsl_f_int_fcn_sing (fcn, 0.0, 1.0, 0);
/* Print the result and */
/*the exact answer */
exact = -4.0;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
return log(x)/sqrt(x);
}
Example 2
The value of
z bg
1
ln x x −1/ 2 dx = −4
0
is again estimated. The values of the actual and estimated errors are printed as well.
Note that these numbers are machine dependent. Furthermore, usually the error
estimate is pessimistic. That is, the actual error is usually smaller than the error estimate
as is in this example.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact, err_est, exact_err;
/* Evaluate the integral */
q = imsl_f_int_fcn_sing (fcn, 0.0, 1.0,
IMSL_ERR_EST, &err_est,
0);
/* Print the result and */
/* the exact answer */
exact = -4.0;
exact_err = fabs(exact - q);
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
printf("error estimate = %e\nexact error = %e\n", err_est,
exact_err);
}
float fcn(float x)
{
return log(x)/sqrt(x);
}
Output
integral = -4.000
exact = -4.000
error estimate = 3.175735e-04
exact error = 6.556511e-05
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
Fatal Errors
IMSL_DIVERGENT Integral is probably divergent or slowly
convergent.
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn
Integrates a function using a globally adaptive scheme based on Gauss-Kronrod rules.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn (float fcn(), float a, float b, …, 0)
The type double function is imsl_d_int_fcn.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
Return Value
The value of
za
b
bg
fcn x dx
Optional Arguments
IMSL_RULE, int rule (Input)
Choice of quadrature rule.
rule Gauss-Kronrod Rule
1 7-15 points
2 10-21 points
3 15-31 points
4 20-41 points
5 25-51 points
6 30-61 points
Default: rule = 1
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
IMSL_N_SUBINTER, int *n_subinter (Output)
Address to store the number of subintervals generated.
IMSL_N_EVALS, int *n_evals (Output)
Address to store the number of evaluations of fcn.
Description
The function imsl_f_int_fcn is a general-purpose integrator that uses a globally
adaptive scheme to reduce the absolute error. It subdivides the interval [a, b] and uses a
(2k + 1)-point Gauss-Kronrod rule to estimate the integral over each subinterval. The
error for each subinterval is estimated by comparison with the k-point Gauss quadrature
rule. The subinterval with the largest estimated error is then bisected, and the same
Examples
Example 1
The value of
z0
2
xe x dx = e 2 + 1
is computed. Since the integrand is not oscillatory, all of the default values are used.
The values of the actual and estimated error are machine dependent.
#include <math.h>
#include <imsl.h>
main()
{
/* evaluate the integral */
q = imsl_f_int_fcn (fcn, 0.0, 2.0, 0);
/* print the result and the exact answer */
exact = exp(2.0) + 1.0;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
float y;
y = x * (exp(x));
return y;
}
Output
integral = 8.389
exact = 8.389
Example 2
The value of
z 0
1
b g
sin 1 / x dx
main()
{
float q, err_est, err_abs= 0.0001, exact = 0.50406706, error;
float fcn(float x)
{
/* compute sin(1/x), avoiding division by zero */
return ((x)>1.0e-5) ? sin(1.0/(x)) : 0.0;
}
Output
integral = 0.504
exact = 0.504
error = 0.000
err_est = 0.000170593
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
Fatal Errors
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_sing_pts (float fcn(), float a, float b, int npoints,
float points[], …, 0)
The type double function is imsl_d_int_fcn_sing_pts.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
int npoints (Input)
The number of singularities of the integrand.
float points[] (Input)
The abscissas of the singularities. These values should be interior to the
interval [a, b].
Return Value
The value of
za
b
bg
fcn x dx
Description
The function imsl_f_int_fcn_sing_pts is a special-purpose integrator that uses a
globally adaptive scheme in order to reduce the absolute error. It subdivides the interval
[a, b] into npoints + 1 user-supplied subintervals and uses a 21-point Gauss-Kronrod
rule to estimate the integral over each subinterval. The error for each subinterval is
estimated by comparison with the 10-point Gauss quadrature rule. The subinterval with
the largest estimated error is then bisected, and the same procedure is applied to both
halves. The bisection process is continued until either the error criterion is satisfied,
roundoff error is detected, the subintervals become too small, or the maximum number
of subintervals allowed is reached. This function uses an extrapolation procedure
known as the ε-algorithm.
The function imsl_f_int_fcn_sing_pts is based on the subroutine QAGP by
Piessens et al. (1983).
Examples
Example 1
The value of
z0
3
e je j
x 3 ln x 2 − 1 x 2 − 2 dx = 61 ln 2 +
77
4
ln 7 − 27
main()
{
int npoints = 2;
float q, exact, points[2];
/* Set singular points */
points[0] = 1.0;
points[1] = sqrt(2.);
/* Evaluate the integral */
q = imsl_f_int_fcn_sing_pts (fcn, 0.0, 3.0, npoints, points, 0);
/* print the result and */
/* the exact answer */
exact = 61.*log(2.) + (77./4)*log(7.) - 27.;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
return x*x*x*(log(fabs((x*x-1.)*(x*x-2.))));
}
Output
integral = 52.741
exact = 52.741
Example 2
The value of
z0
3
e je j
x 3 ln x 2 − 1 x 2 − 2 dx = 61 ln 2 +
77
4
ln 7 − 27
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as in this example. The number of function evaluations also are printed.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals, npoints = 2;
float q, exact, err_est, exact_err, points[2];
/* Set singular points */
points[0] = 1.0;
float fcn(float x)
{
return x*x*x*(log(fabs((x*x-1.)*(x*x-2.))));
}
Output
integral = 52.741
exact = 52.741
error estimate = 1.258850e-04
exact error = 3.051758e-05
The number of function evaluations = 819
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
IMSL_EXTRAPOLATION_ROUNDOFF Roundoff error in the extrapolation table,
preventing the requested tolerance from
being achieved, has been detected.
Fatal Errors
IMSL_DIVERGENT Integral is probably divergent or slowly
convergent.
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_alg_log (float fcn(), float a, float b, Imsl_quad
weight, float alpha, float beta, …, 0)
The type double function is imsl_d_int_fcn_alg_log.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
Imsl_quad weight, float alpha, float beta (Input)
These three parameters are used to describe the weight function that may have
algebraic or logarithmic singularities at the endpoints. The parameter weight
can take on four values as described below. The parameters alpha = α and
beta = β specify the strength of the singularities at a or b and hence, must be
greater than −1.
weight Integration Weight
IMSL_ALG ( x − a ) a ( b − x) b
IMSL_ALG_LEFT_LOG (x − a)a (b − x)blog (x − a)
IMSL_ALG_RIGHT_LOG (x − a)a (b − x)blog (b − x)
IMSL_ALG_LOG (x − a)a (b − x)blog (x − a) log (b − x)
Return Value
The value of
z
a
b
bgbg
fcn x w x dx
is returned where w(x) is one of the four weights above. If no value can be computed,
then NaN is returned.
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
IMSL_N_SUBINTER, int *n_subinter (Output)
Address to store the number of subintervals generated.
IMSL_N_EVALS, int *n_evals (Output)
Address to store the number of evaluations of fcn.
Description
The function imsl_f_int_fcn_alg_log is a special-purpose integrator that uses a
globally adaptive scheme to reduce the absolute error. It computes integrals whose
integrands have the special form w(x)f(x) where w(x) is a weight function described
above. A combination of modified Clenshaw-Curtis and Gauss-Kronrod formulas is
employed. This function is based on the subroutine QAWS, which is fully documented by
Piessens et al. (1983).
Examples
Example 1
The value of
main()
{
float q, exact;
/* Evaluate the integral */
q = imsl_f_int_fcn_alg_log (fcn, 0.0, 1.0,
IMSL_ALG_LEFT_LOG, 1.0, 0.5,
0);
/* Print the result and the */
/* exact answer */
exact = (3.*log(2.)-4.)/9.;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
return sqrt(1+x);
}
Output
integral = -0.213
exact = -0.213
Example 2
The value of
z0
1
b1 + xgb1 − xg
1/ 2
bg
x ln x dx =
bg
3 ln 2 − 4
9
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as in this example. The number of function evaluations also are printed.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals;
float q, exact, err_est, exact_err;
/* Evaluate the integral */
q = imsl_f_int_fcn_alg_log (fcn, 0.0, 1.0,
IMSL_ALG_LEFT_LOG, 1.0, 0.5,
float fcn(float x)
{
return sqrt(1+x);
}
Output
integral = -0.213
exact = -0.213
error estimate = 3.725290e-09
exact error = 1.490116e-08
The number of function evaluations = 50
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
Fatal Errors
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn_inf
Integrates a function over an infinite or semi-infinite interval.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_inf (float fcn(), float bound, Imsl_quad interval,
…, 0)
The type double procedure is imsl_d_int_fcn_inf.
Return Value
The value of
za
b
bg
fcn x dx
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
Description
The function imsl_f_int_fcn_inf is a special-purpose integrator that uses a
globally adaptive scheme to reduce the absolute error. It initially transforms an infinite
or semi-infinite interval into the finite interval [0, 1]. It then uses the same strategy as
the function imsl_f_int_fcn_sing.
The function imsl_f_int_fcn_inf is based on the subroutine QAGI by Piessens et
al. (1983).
Examples
Example 1
The value of
z0
∞ bg
ln x
b g
1 + 10 x
2
dx =
20
b g
− π ln 10
is computed.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact, pi;
pi = imsl_f_constant("pi", 0);
/* Evaluate the integral */
q = imsl_f_int_fcn_inf (fcn, 0.0,
IMSL_BOUND_INF,
0);
/* Print the result and the */
/* exact answer */
exact = -pi*log(10.)/20.;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
Output
integral = -0.362
exact = -0.362
Example 2
The value of
z0
∞ ln x
b g
1 + 10 x
2
dx =
20
b g
− π ln 10
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as in this example. The number of function evaluations also are printed.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals;
float q, exact, err_est, exact_err, pi;
pi = imsl_f_constant("pi", 0);
/* Evaluate the integral */
q = imsl_f_int_fcn_inf (fcn, 0.0,
IMSL_BOUND_INF,
IMSL_ERR_EST, &err_est,
IMSL_N_EVALS, &n_evals,
0);
/* Print the result and the */
/* exact answer */
exact = -pi*log(10.)/20.;
exact_err = fabs(exact - q);
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
printf("error estimate = %e\nexact error = %e\n", err_est,
exact_err);
printf("The number of function evaluations = %d\n", n_evals);
}
float fcn(float x)
{
float z;
z = 10.*x;
return log(x)/(1+ z*z);
}
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
IMSL_EXTRAPOLATION_ROUNDOFF Roundoff error in the extrapolation table,
preventing the requested tolerance from
being achieved, has been detected.
Fatal Errors
IMSL_DIVERGENT Integral is probably divergent or slowly
convergent.
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn_trig
Integrates a function containing a sine or a cosine factor.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_trig (float fcn(), float a, float b, Imsl_quad weight,
float omega, …, 0)
The type double function is imsl_d_int_fcn_trig.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
Return Value
The value of
za
b
bg b g
fcn x cos ωx dx
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
Description
The function imsl_f_int_fcn_trig is a special-purpose integrator that uses a
globally adaptive scheme to reduce the absolute error. It computes integrals whose
integrands have the special form w(x)f(x) where w(x) is either cos(ωx) or sin(ωx).
Depending on the length of the subinterval in relation to the size of ω, either a modified
Clenshaw-Curtis procedure or a Gauss-Kronrod 7/15 rule is employed to approximate
the integral on a subinterval. This function uses the general strategy of the function
imsl_f_int_fcn_sing. The function imsl_f_int_fcn_trig is based on the
subroutine QAWO by Piessens et al. (1983).
Examples
Example 1
The value of
z0
1
bg b g
ln x sin 10πx dx
is computed. Notice that we have coded around the singularity at zero. This is
necessary since this procedure evaluates the integrand at the two endpoints.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact, omega;
float fcn(float x)
{
return (x==0.0) ? 0.0 : log(x);
}
Output
integral = -0.128
exact = -0.128
Example 2
The value of
z0
1
bg b g
ln x sin 10πx dx
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, it is usually the case that
the error estimate is pessimistic. That is, the actual error is usually smaller than the
error estimate as is the case in this example. The number of function evaluations are
also printed.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals;
float q, exact, omega, err_est, exact_err;
float fcn(float x)
{
Output
integral = -0.128
exact = -0.128
error estimate = 7.504603e-05
exact error = 5.245209e-06
The number of function evaluations = 215
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
IMSL_EXTRAPOLATION_ROUNDOFF Roundoff error in the extrapolation table,
preventing the requested tolerance from
being achieved, has been detected.
Fatal Errors
IMSL_DIVERGENT Integral is probably divergent or slowly
convergent.
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn_fourier
Computes a Fourier sine or cosine transform.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_fourier (float fcn(), float a, Imsl_quad weight,
float omega, …, 0)
The type double function is imsl_d_int_fcn_fourier.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration. The upper limit of integration is ∞.
Return Value
The return value is
za
∞
bg b g
fcn x cos ωx dx
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
IMSL_MAX_CYCLES, int max_cycles (Input)
Number of cycles allowed.
Default: max_subinter = 50
Description
The function imsl_f_int_fcn_fourier is a special-purpose integrator that uses a
globally adaptive scheme to reduce the absolute error. It computes integrals whose
integrands have the special form w(x)f(x) where w(x) is either cosωx or sinωx. The
integration interval is always semi-infinite of the form
[a, ∞]. These Fourier integrals are approximated by repeated calls to the function
imsl_f_int_fcn_trig followed by extrapolation.
The function imsl_f_int_fcn_fourier is based on the subroutine QAWF by
Piessens et al. (1983).
Examples
Example 1
The value of
z0
∞
b g
x −1/ 2 cos πx / 2 dx = 1
is computed. Notice that the integrand is coded to protect for the singularity at zero.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact, omega;
float fcn(float x)
{
return (x==0.) ? 0. : 1./sqrt(x);
}
Example 2
The value of
z0
∞
b g
x −1/ 2 cos πx / 2 dx = 1
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as is the case in this [Link] number of function evaluations also are printed.
Notice that the integrand is coded to protect for the singularity at zero.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals;
float q, exact, omega, err_est, exact_err;
float fcn(float x)
{
return (x==0.) ? 0. : 1./sqrt(x);
}
Output
integral = 1.000
exact = 1.000
error estimate = 1.803637e-04
exact error = 1.013279e-06
The number of function evaluations = 405
Fatal Errors
IMSL_MAX_CYCLES Maximum number of cycles allowed has
been reached.
int_fcn_cauchy
Computes integrals of the form
z b
a
b g dx
f x
x−c
in the Cauchy principal value sense.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_cauchy (float fcn(), float a, float b, float c, …, 0)
The type double function is imsl_d_int_fcn_cauchy.
Required Arguments
float fcn (float x) (Input)
User-supplied function to be integrated.
float a (Input)
Lower limit of integration.
float b (Input)
Upper limit of integration.
float c (Input)
Singular point, c must not equal a or b.
Return Value
The value of
z
a
b fcn
x−c
b xg dx
is returned. If no value can be computed, NaN is returned.
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
IMSL_N_SUBINTER, int *n_subinter (Output)
Address to store the number of subintervals generated.
IMSL_N_EVALS, int *n_evals (Output)
Address to store the number of evaluations of fcn.
Description
The function imsl_f_int_fcn_cauchy uses a globally adaptive scheme in an
attempt to reduce the absolute error. It computes integrals whose integrands have the
special form w(x)f(x) where w(x) = 1/(x − c). If c lies in the interval of integration, then
the integral is interpreted as a Cauchy principal value. A combination of modified
Clenshaw-Curtis and Gauss-Kronrod formulas are employed.
The function imsl_f_int_fcn_cauchy is an implementation of the subroutine
QAWC by Piessens et al. (1983).
Example 1
The Cauchy principal value of
z−1
5
e
1
3
x 5x + 6 j
dx =
b
18
g
ln 125 / 631
is computed.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact;
/* Evaluate the integral */
q = imsl_f_int_fcn_cauchy (fcn, -1.0, 5.0, 0.0, 0);
/* Print the result and the */
/* exact answer */
exact = log(125./631.)/18.;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
return 1.0/(5.0*x*x*x+6.0);
}
Output
integral = -0.090
exact = -0.090
Example 2
The Cauchy principal value of
z−1
5
e
1
3
x 5x + 6 j
dx =
b
18
g
ln 125 / 631
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as is the case in this example. The number of function evaluations also are printed.
#include <math.h>
#include <imsl.h>
main()
float fcn(float x)
{
return 1.0/(5.0*x*x*x+6.0);
}
Output
integral = -0.090
exact = -0.090
error estimate = 2.160174e-06
exact error = 0.000000e+00
The number of function evaluations = 215
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
Fatal Errors
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn_smooth
Integrates a smooth function using a nonadaptive rule.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_smooth (float fcn(), float a, float b, …, 0)
The type double function is imsl_d_int_fcn_smooth.
Return Value
The value of
za
b
bg
fcn x dx
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
Description
The function imsl_f_int_fcn_smooth is designed to integrate smooth functions. It
implements a nonadaptive quadrature procedure based on nested Paterson rules of
order 10, 21, 43, and 87. These rules are positive quadrature rules with degree of
accuracy 19, 31, 64, and 130, respectively. The function imsl_f_int_fcn_smooth
applies these rules successively, estimating the error, until either the error estimate
satisfies the user-supplied constraints or the last rule is applied.
Examples
Example 1
The value of
z0
2
xe x dx = e 2 + 1
is computed.
#include <math.h>
#include <imsl.h>
main()
{
float q, exact;
/* Evaluate the integral */
q = imsl_f_int_fcn_smooth (fcn, 0., 2., 0);
/* Print the result and the */
/* exact answer */
exact = exp(2.0) + 1.0;
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float fcn(float x)
{
return x * exp(x);
}
Output
integral = 8.389
exact = 8.389
Example 2
The value of
z0
2
xe x dx = e 2 + 1
is again computed. The values of the actual and estimated error are printed as well.
Note that these numbers are machine dependent. Furthermore, the error estimate is
usually pessimistic. That is, the actual error is usually smaller than the error estimate,
as is the case in this example.
main()
{
float q, exact, err_est, exact_err;
/* Evaluate the integral */
q = imsl_f_int_fcn_smooth (fcn, 0.0, 2.0,
IMSL_ERR_EST, &err_est,
0);
/* Print the result and the */
/* exact answer */
exact = exp(2.0) + 1.0;
exact_err = fabs(exact - q);
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
printf("error estimate = %e\nexact error = %e\n", err_est,
exact_err);
}
float fcn(float x)
{
return x * exp(x);
}
Output
integral = 8.389
exact = 8.389
error estimate = 5.000267e-05
exact error = 9.536743e-07
Fatal Errors
IMSL_MAX_STEPS The maximum number of steps allowed have been
taken. The integrand is too difficult for this routine.
int_fcn_2d
Computes a two-dimensional iterated integral.
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_2d (float fcn(), float a, float b, float gcn (float x),
float hcn (float x), …, 0)
The type double function is imsl_d_int_fcn_2d.
Required Arguments
float fcn (float x, float y) (Input)
User-supplied function to be integrated.
Return Value
The value of
zz
b hcn x
a
bg
gcn b x g
fcnb x , y g dydx
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_SUBINTER, int max_subinter (Input)
Number of subintervals allowed.
Default: max_subinter = 500
Description
The function imsl_f_int_fcn_2d approximates the two-dimensional iterated integral
zz
b h x
a
bg
gb x g
f b x , y g dydx
An estimate of the error is returned in err_est. The lower-numbered rules are used for
less smooth integrands while the higher-order rules are more efficient for smooth
(oscillatory) integrands.
Examples
Example 1
In this example, compute the value of the integral
zz
1 3
0 1
e j
y cos x + y 2 dydx
#include <math.h>
#include <imsl.h>
main()
{
float q, exact;
/* Evaluate the integral */
q = imsl_f_int_fcn_2d (fcn, 0.0, 1.0, gcn, hcn, 0);
/* print the result and the exact answer */
exact = 0.5*(cos(9.0)+cos(2.0)-cos(10.0)-cos(1.0));
printf("integral = %10.3f\nexact = %10.3f\n", q, exact);
}
float gcn(float x)
{
return 1.0;
}
float hcn(float x)
{
return 3.0;
}
Example 2
In this example, compute the value of the integral
zz1 3
0 1
e j
y cos x + y 2 dydx
The values of the actual and estimated error are printed as well. Note that these
numbers are machine dependent. Furthermore, the error estimate is usually pessimistic.
That is, the actual error is usually smaller than the error estimate, as is the case in this
example. The number of function evaluations also are printed.
#include <math.h>
#include <imsl.h>
main()
{
int n_evals;
float q, exact, err_est, exact_err;
/* Evaluate the integral */
q = imsl_f_int_fcn_2d (fcn, 0., 1., gcn, hcn,
IMSL_ERR_EST, &err_est,
IMSL_N_EVALS, &n_evals,
0);
/* Print the result and the */
/* exact answer */
exact = 0.5*(cos(9.0)+cos(2.0)-cos(10.0)-cos(1.0));
exact_err = fabs(exact - q);
float gcn(float x)
{
return 1.0;
}
float hcn(float x)
{
return 3.0;
}
Warning Errors
IMSL_ROUNDOFF_CONTAMINATION Roundoff error, preventing the requested
tolerance from being achieved, has been
detected.
IMSL_PRECISION_DEGRADATION A degradation in precision has been
detected.
Fatal Errors
IMSL_MAX_SUBINTERVALS The maximum number of subintervals
allowed has been reached.
int_fcn_hyper_rect
Integrate a function on a hyper-rectangle,
z z
b0
a0
K
bn−1
an −1
b g
f x0 , K , xn −1 dxn −1K dx0
Synopsis
#include <imsl.h>
float imsl_f_int_fcn_hyper_rect (float fcn(), int ndim, float a[],
float b[], …, 0)
The type double function is imsl_d_int_fcn_hyper_rect.
Required Arguments
float fcn (int ndim, float x) (Input)
User-supplied function to be integrated.
int ndim (Input)
The dimension of the hyper-rectangle.
float a[] (Input)
Lower limits of integration.
float b[] (Input)
Upper limits of integration.
Return Value
The value of
a0
K
bn−1
an −1
b g
f x0 , K , xn −1 dxn −1K dx0
Optional Arguments
IMSL_ERR_ABS, float err_abs (Input)
Absolute accuracy desired.
Default: err_ abs = ε
where ε is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Relative accuracy desired.
Default: err_ rel = ε
where ε is the machine precision
IMSL_ERR_EST, float *err_est (Output)
Address to store an estimate of the absolute value of the error.
IMSL_MAX_EVALS, int max_evals (Input)
Number of evaluations allowed.
Default: max_evals = 32n.
Description
The function imsl_f_int_fcn_hyper_rect approximates the n-dimensional
iterated integral
z z
b
a0
K
bn−1
an −1
b g
f x0 , K , xn −1 dxn −1K dx0
Example
In this example, we compute the integral of
e
e
− x12 + x22 + x32 j
on an expanding cube. The values of the error estimates are machine dependent. The
exact integral over R3 is π3/2.
#include <math.h>
#include <imsl.h>
main()
{
int i, j, ndim = 3;
float q, limit, a[3], b[3];
Output
integral limit
0.785 5.568
3.332 5.568
5.021 5.568
5.491 5.568
5.561 5.568
5.568 5.568
Fatal Errors
IMSL_NOT_CONVERGENT The maximum number of function evaluations has
been reached, and convergence has not been
attained.
gauss_quad_rule
Computes a Gauss, Gauss-Radau, or Gauss-Lobatto quadrature rule with various
classical weight functions.
Synopsis
#include <imsl.h>
void imsl_f_gauss_quad_rule (int n, float weights[], float points[], …,
0)
The type double procedure is imsl_d_gauss_quad_rule.
Required Arguments
int n (Input)
Number of quadrature points.
float weights[] (Output)
Array of length n containing the quadrature weights.
float points[] (Output)
Array of length n containing quadrature points. The default action of this
routine is to produce the Gauss Legendre points and weights.
1 / 1− x2
on the interval (−1, 1).
IMSL_CHEBYSHEV_SECOND
Compute the Gauss points and weights using the weight function
1− x2
on the interval (−1, 1).
IMSL_HERMITE
Compute the Gauss points and weights using the weight function exp (−x2) on
the interval (−∞, ∞).
IMSL_COSH
Compute the Gauss points and weights using the weight function 1 / (cosh (x))
on the interval (−∞, ∞).
IMSL_JACOBI, float alpha, float beta (Input)
Compute the Gauss points and weights using the weight function
(1 − x)a (1 + x)b on the interval (−1, 1).
IMSL_GEN_LAGUERRE, float alpha (Input)
Compute the Gauss points and weights using the weight function exp (−x)xa
on the interval (0, ∞).
IMSL_FIXED_POINT, float a (Input)
Compute the Gauss-Radau points and weights using the specified weight
function and the fixed point a. This formula will integrate polynomials of
degree less than 2n − 1 exactly.
IMSL_TWO_FIXED_POINTS, float a, float b (Input)
Compute the Gauss-Lobatto points and weights using the specified weight
function and the fixed points a and b. This formula will integrate polynomials
of degree less than 2n − 2 exactly.
Description
The function imsl_f_gauss_quad_rule produces the points and weights for the
Gauss, Gauss-Radau, or Gauss-Lobatto quadrature formulas for some of the most
popular weights. The default weight is the weight function identically equal to 1 on the
interval (−1, 1). In fact, it is slightly more general than this suggests, because the extra
one or two points that may be specified do not have to lie at the endpoints of the
interval. This function is a modification of the subroutine GAUSSQUADRULE
(Golub and Welsch 1969).
In the default case, the function returns points in x = points and weights in
w = weights so that
å f b x gw
i =1
i i
for all functions f that are polynomials of degree less than 2n.
If the keyword IMSL_FIXED_POINT is specified, then one of the above xi is equal to a.
Similarly, if the keyword IMSL_TWO_FIXED_POINTS is specified, then two of the
components of x are equal to a and b. In general, the accuracy of the above quadrature
formula degrades when n increases. The quadrature rule will integrate all functions f
that are polynomials of degree less than 2n − F, where F is the number of fixed points.
Examples
Example 1
The three-point Gauss Legendre quadrature points and weights are computed and used
to approximate the integrals
z 1
−1
x i dx i = 0, K , 6
Notice that the integrals are exact for the first six monomials, but that the last
approximation is in error. In general, the Gauss rules with k points integrate
polynomials with degree less than 2k exactly.
#include <math.h>
#include <imsl.h>
#define QUADPTS 3
#define POWERS 7
main()
{
int i, j;
float weights[QUADPTS], points[QUADPTS], s[POWERS];
/* Produce the Gauss Legendre */
/* quadrature points */
imsl_f_gauss_quad_rule (QUADPTS, weights, points, 0);
/* integrate the functions */
/* 1, x, ..., pow(x,POWERS-1) */
for(i = 0; i < POWERS; i++) {
s[i] = 0.0;
for(j = 0; j < QUADPTS; j++) {
s[i] += weights[j]*imsl_fi_power(points[j], i);
}
}
printf("The integral from -1 to 1 of pow(x, i) is\n");
printf("Function Quadrature Exact\n\n");
for(i = 0; i < POWERS; i++){
float z;
z = (1-i%2)*2./(i+1.);
printf("pow(x, %d) %10.3f %10.3f\n", i, s[i], z);
}
}
Example 2
The three-point Gauss Laguerre quadrature points and weights are computed and used
to approximate the integrals
z0
∞
x i xe − x dx = i ! i = 0, K , 6
Notice that the integrals are exact for the first six monomials, but that the last
approximation is in error. In general, the Gauss rules with k points integrate
polynomials with degree less than 2k exactly.
#include <math.h>
#include <imsl.h>
#define QUADPTS 3
#define POWERS 7
main()
{
int i, j;
float weights[QUADPTS], points[QUADPTS], s[POWERS], z;
/* Produce the Gauss Legendre */
/* quadrature points */
imsl_f_gauss_quad_rule (QUADPTS, weights, points,
IMSL_GEN_LAGUERRE, 1.0,
0);
/* Integrate the functions */
/* 1, x, ..., pow(x,POWERS-1) */
for(i = 0; i < POWERS; i++) {
s[i] = 0.0;
for(j = 0; j < QUADPTS; j++){
s[i] += weights[j]*imsl_fi_power(points[j], i);
}
}
printf("The integral from 0 to infinity of pow(x, i)*x*exp(x) is\n");
printf("Function Quadrature Exact\n\n");
for(z = 1.0, i = 0; i < POWERS; i++){
z *= (i+1);
printf("pow(x, %d) %10.3f %10.3f \n", i, s[i], z);
}
}
fcn_derivative
Computes the first, second, or third derivative of a user-supplied function.
Synopsis
#include <imsl.h>
float imsl_f_fcn_derivative (float fcn(), float x, …, 0)
The type double procedure is imsl_d_fcn_derivative.
Required Arguments
float fcn(float x) (Input)
User-supplied function whose derivative at x will be computed.
float x (Input)
Point at which the derivative will be evaluated.
Return Value
An estimate of the first, second or third derivative of fcn at x. If no value can be
computed, NaN is returned.
Optional Arguments
IMSL_ORDER, int order (Input)
The order of the desired derivative (1, 2 or 3).
Default: order = 1.
IMSL_INITIAL_STEPSIZE, float stepsize (Input)
Beginning value used to compute the size of the interval for approximating the
Description
The function imsl_f_fcn_derivative produces an estimate to the first, second, or
third derivative of a function. The estimate originates from first computing a spline
interpolant to the input function using value within the interval
(x − 4.0*stepsize, x + 4.0*stepsize), then differentiating the spline at x.
Examples
Example 1
This example obtains the approximate first derivative of the function
f(x) = −2sin(3x/2) at the point x = 2.
#include <imsl.h>
#include <math.h>
void main()
{
float fcn(float);
float x;
float deriv;
x = 2.0;
float fcn(float x)
{
return -2.0*sin(1.5*x);
}
Output
f’(x) = 2.9701
Example 2
This example obtains the approximate first, second, and third derivative of the function
f(x) = −2sin(3x/2) at the point x = 2.
void main()
{
double fcn(double);
double x;
double tolerance;
double deriv;
x = 2.0;
deriv = imsl_d_fcn_derivative(fcn, x,
0);
printf ("f'(x) = %7.3f, error = %5.2e\n", deriv,
fabs(deriv+3.0*cos(1.5*x)));
deriv = imsl_d_fcn_derivative(fcn, x,
IMSL_ORDER, 2,
0);
printf ("f''(x) = %7.4f, error = %5.2e\n", deriv,
fabs(deriv-4.5*sin(1.5*x)));
deriv = imsl_d_fcn_derivative(fcn, x,
IMSL_ORDER, 3,
0);
printf ("f'''(x) = %7.4f, error = %5.2e\n", deriv,
fabs(deriv-6.75*cos(1.5*x)));
}
double fcn(double x)
{
return -2.0*sin(1.5*x);
}
Output
f’(x) = 2.970, error = 1.11e-07
f’’(x) = 0.6350, error = 8.52e-09
f’’’(x) = -6.6824, error = 1.12e-08
Routines
Runge-Kutta method......................................................ode_runge_kutta 287
Adam’s or Gear’s method .............................................ode_adams_gear 292
Method of lines ...................................................... pde_method_of_lines 299
Fast Poisson solver ....................................................... fast_poisson_2d 315
Usage Notes
Ordinary Differential Equations
An ordinary differential equation is an equation involving one or more dependent
variables called yi, one independent variable, t, and derivatives of the yi with respect to t.
In the initial-value problem (IVP), the initial or starting values of the dependent
variables yi at a known value t = t0 are given. Values of yi(t) for t > t0 or t < t0 are
required.
The functions imsl_f_ode_runge_kutta and imsl_f_ode_adams_gear solve the
IVP for ODEs of the form
dyi
dt
b
= yi′ = f i t , y1 , K , y N g i = 1, K , N
n∂y ′ / ∂y s
i j
b g ∂∂ux bag
α 1b g ui a + β1b g bg
i i i
= γ1 t
bg
α u bbg + β
i b g ∂u bbg
i i
= γ2 bt g
2 i 2
∂x
and subject to the initial conditions
over a rectangle, subject to boundary conditions on each of the four sides. The scalar
constant c and the function f are user specified.
Synopsis
#include <imsl.h>
float imsl_f_ode_runge_kutta_mgr (int task, void **state, …, 0)
void imsl_f_ode_runge_kutta (int neq, float *t, float tend, float y[],
void *state, void fcn())
The type double functions are imsl_d_ode_runge_kutta_mgr and
imsl_d_ode_runge_kutta.
yprime =
dy
dt
b g
= y′ = f t, y
Optional Arguments
IMSL_TOL, float tol (Input)
Tolerance for error control. An attempt is made to control the norm of the
local error such that the global error is proportional to tol.
Default: tol = 100.0*imsl_f_machine(4)
IMSL_HINIT, float hinit (Input)
Initial value for the step size h. Steps are applied in the direction of
integration.
Default: hinit = 0.001|tend − t|
IMSL_HMIN, float hmin (Input)
Minimum value for the step size h.
Default: hmin − 0.0
IMSL_HMAX, float hmax (Input)
Maximum value for the step size h.
Default: hmax = 2.0
IMSL_MAX_NUMBER_STEPS, int max_steps (Input)
Maximum number of steps allowed.
Default: max_steps = 500
IMSL_MAX_NUMBER_FCN_EVALS, int max_fcn_evals (Input)
Maximum number of function evaluations allowed.
Default: max_fcn_evals = No enforced limit
Description
The function imsl_f_ode_runge_kutta finds an approximation to the solution of a
system of first-order differential equations of the form
dy
dt
b g
= y′ = f t, y
with given initial conditions for y at the starting value for t. The function attempts to
keep the global error proportional to a user-specified tolerance. The proportionality
depends on the differential equation and the range of integration.
The function imsl_f_ode_runge_kutta is efficient for nonstiff systems where the
evaluations of f(t, y) are not expensive. The code is based on an algorithm designed by
Hull et al. (1976, 1978). It uses Runge-Kutta formulas of order five and six developed
by J.H. Verner.
main()
{
int neq = 1; /* Number of ode’s */
float t = 0.0; /* Initial time */
float tend = 1.0; /* Final time */
float y[1] = {1.0}; /* Initial condition */
void *state;
/* Initialize the ODE solver */
imsl_f_ode_runge_kutta_mgr(IMSL_ODE_INITIALIZE, &state, 0);
/* Integrate from t=0 to tend=1 */
imsl_f_ode_runge_kutta (neq, &t, tend, y, state, fcn);
/* Print the solution and error */
printf("y[%f] = %f\n", t, y[0]);
printf("Error is: %e\n", exp( (double)(-tend) )-y[0]);
}
Output
y[1.000000] = 0.367879
Error is: -9.149755e-09
Example 2
Consider a predator-prey problem with rabbits and foxes. Let r be the density of
rabbits, and let f be the density of foxes. In the absence of any predator-prey interaction,
the rabbits would increase at a rate proportional to their number, and the foxes would
die of starvation at a rate proportional to their number. Mathematically, the model
without species interaction is approximated by the equation
r′ = 2r
ƒ′= −ƒ
r′ = 2r − 2rƒ
ƒ′ = −ƒ + rƒ
For illustration, the initial conditions are taken to be r(0) = 1 and f(0) = 3. The interval
of integration is 0 ≤ t ≤ 10. In the program, y[0] = r and y[1] = f. The ODE solver is
initialized by a call to imsl_f_ode_runge_kutta_mgr. The error tolerance is set to
0.0005. Absolute error control is selected by setting IMSL_NORM to the value one. We
also request that nstep be set to the current number of steps in the integration. The
function imsl_f_ode_runge_kutta is then called in a loop to integrate from t = 0 to
t = 10 in steps of δt = 1. At each step, the solution is printed. Note that nstep is
updated even though it is not an argument to this function. Its address has been stored
within imsl_f_ode_runge_kutta_mgr into the area pointed to by state. The last
call to imsl_f_ode_runge_kutta_mgr with IMSL_ODE_RESET releases workspace.
#include <imsl.h>
main()
{
int neq = 2;
float t = 0.0; /* Initial time */
float tend; /* Final time */
float y[2] = {1.0, 3.0}; /* Initial conditions */
int k;
int nstep;
void *state;
/* Initialize the ODE solver */
imsl_f_ode_runge_kutta_mgr(IMSL_ODE_INITIALIZE, &state,
IMSL_TOL, 0.0005,
IMSL_NSTEP, &nstep,
IMSL_NORM, 1,
0);
Output
Start End Density of Density of Number of
Time Time Rabbits Foxes Steps
Fatal Errors
IMSL_ODE_TOO_MANY_EVALS Completion of the next step would make the
number of function evaluations #, but only #
evaluations are allowed.
IMSL_ODE_TOO_MANY_STEPS Maximum number of steps allowed, #, used. The
problem may be stiff.
IMSL_ODE_FAIL Unable to satisfy the error requirement.
“tol” = # may be too small.
ode_adams_gear
Solves a stiff initial-value problem for ordinary differential equations using the Adams-
Gear methods.
Synopsis
#include <imsl.h>
float imsl_f_ode_adams_gear_mgr (int task, void **state, …, 0)
void imsl_f_ode_adams_gear (int neq, float *t, float tend, float y[],
void *state, void fcn())
The type double functions are imsl_d_ode_adams_gear_mgr and
imsl_d_ode_adams_gear.
yprime =
dy
dt
b g
= y′ = f t, y
Optional Arguments
IMSL_JACOBIAN, void fcnj (int neq, float t, float *y, float yprime[],
float dypdy[])
User-supplied function to evaluate the Jacobian matrix where
float yprime[] (Input)
Array with neq components containing the vector y′ = f(t, y).
float dypdy[] (Output)
Array of size neq × neq containing the partial derivatives. Each
derivative ∂y¢i / ∂yi is evaluated at the provided (t, y) values and is
returned in array location dypdy[(i − 1)*n + j − 1].
and neq, t, and *y are described in the “Required Arguments” section.
with given initial conditions for y at the starting value for t. The function attempts to
keep the global error proportional to a user-specified tolerance. The proportionality
depends on the differential equation and the range of integration.
The code is based on using backward difference formulas not exceeding order five as
outlined in Gear (1971) and implemented by Hindmarsh (1974). There is an optional
use of the code that employs implicit Adams formulas. This use is intended for nonstiff
problems with expensive functions y′ = ƒ(t, y).
Examples
Example 1
This is a mildly stiff example problem (F2) from the test set of Enright and Pryce
(1987):
main()
{
int neq = 2; /* Number of ode’s */
float t = 0.0; /* Initial time */
float tend = 240.0; /* Final time */
Output
y[240.000000] = 0.392391, 0.001334
Example 2
This problem is a stiff example (F5) from the test set of Enright and Pryce (1987). An
initial step size of h = 10-7 is suggested by these authors. It is necessary to provide for
more evaluations of y′ and for more steps than the default value allows. Both have been
set to 4000.
main()
{
int neq = 4; /* Number of ode’s */
float t = 0.0; /* Initial time */
float tend = 100.0; /* Final time */
/* Initial condition */
float y[4] = {3.365e-7, 8.261e-3, 1.642e-3, 9.380e-6};
void *state;
int *nfcn;
/* Initialize the ODE solver */
imsl_f_ode_adams_gear_mgr(IMSL_ODE_INITIALIZE, &state,
IMSL_HINIT, 1.e-7,
IMSL_MAX_NUMBER_STEPS, 4000,
IMSL_MAX_NUMBER_FCN_EVALS, 4000,
IMSL_NFCN, &nfcn,
0);
/* Integrate from t=0 to tend=100 */
imsl_f_ode_adams_gear (neq, &t, tend, y, state, fcn);
/* Release workspace and reset */
imsl_f_ode_adams_gear_mgr(IMSL_ODE_RESET, &state, 0);
/* Print the solution */
printf("y[%f] = %f, %f, %f, %f\n", t, y[0], y[1], y[2], y[3]);
/* Print the number of evaluations
of yprime[] */
printf("Number of yprime[] evaluations: %d\n", nfcn);
}
Output
y[100.000000] = 0.000000, 0.003352, 0.005586, 0.000009
Number of yprime[] evaluations: 3630
Fatal Errors
IMSL_ODE_TOO_MANY_EVALS Completion of the next step would make the
number of function evaluations #, but only # are
allowed.
IMSL_ODE_TOO_MANY_STEPS Maximum number of steps allowed, # have been
used. Try increasing the maximum number of
steps allowed or increase the tolerance.
Synopsis
#include <imsl.h>
void imsl_f_pde_method_of_lines_mgr (int task, void **state, ..., 0)
void imsl_f_pde_method_of_lines (int npdes, float *t, float tend,
int nx, float xbreak[], float y[], void *state,
void fcn_ut(), void fcn_bc())
The type double functions are imsl_d_pde_method_of_lines_mgr and
imsl_d_pde_method_of_lines.
Optional Arguments
IMSL_TOL, float tol (Input)
Differential equation error tolerance. An attempt is made to control the local
error in such a way that the global relative error is proportional to tol.
Default: tol = 100.0*imsl_f_machine(4)
IMSL_HINIT, float hinit (Input)
Initial step size in the t integration. This value must be nonnegative. If hinit
is zero, an initial step size of 0.001|tend - t0| will be arbitrarily used. The step
will be applied in the direction of integration.
Default: hinit = 0.0
IMSL_INITIAL_VALUE_DERIVATIVE, float initial_deriv[] (Input/Output)
Supply the derivative values ux(x, t0). This derivative information is input as
Description
Let M = npdes, N = nx and xi = xbreaK(I). The routine
imsl_f_pde_method_of_lines uses the method of lines to solve the partial
differential equation system
uk = uk(x, t) at t = t0
a f b a f a f a f a fg
N
uk x , t = å ai , k t f i x + bi ,k t y i x
i =1
where φi(x) and ψi(x) are the standard basis functions for the cubic Hermite
polynomials with the knots x1 < x2 < … < xN. These are piecewise cubic polynomials
with continuous first derivatives. At the breakpoints, they satisfy
b g
φ i xl = δ il b g
ψ i xl = 0
dφ dψ i
dx
bx g = 0
i
l
dx
b g
xl = δ il
According to the collocation method, the coefficients of the approximation are obtained
so that the trial solution satisfies the differential equation at the two Gaussian points in
each subinterval,
3− 3
p2 j −1 = x j +
6
d
x j +1 − x j i
3− 3
p2 j = xj +
6
d
x j +1 + x j i
for j = 1, …, N. The collocation approximation to the differential equation is
dai , k dbi ,k
dt
d i
φi p j +
dt
d iψi p j =
fk e p , t , u$ d p i, K, u$ d p i, K, bu$ g d p i, K, bu$ g d p ij
j 1 j M j 1 xx j M xx j
MM φ bp g ψ5 bp g φ b p g ψ b p gP
φ b p g ψ b p gP
5 5 5 6 5 6 5
φ bp g bp g
MM 5 6 ψ5 6 6 6 6
PP 6
N α 4 β Q4
The vector c is
b g b g b g b g b g b g b g b g
F = γ ′ x1 , f p1 , f p2 , f p3 , f p4 , f p5 , f p6 , γ ′ x4
T
If M > 1, then each entry in the above matrix is replaced by an M × M diagonal matrix.
The element α1 is replaced by diag(α1,1, …, α1,M). The elements αN, β1 and βN are
handled in the same manner. The φi(pj) and ψi(pj) elements are replaced by φi(pj)IM and
ψi(pj)IM where IM is the identity matrix of order M. See Madsen and Sincovec (1979)
for further details about discretization errors and Jacobian matrix structure.
The input/output array Y contains the values of the ak,i. The initial values of the bk,i are
obtained by using the IMSL cubic spline routine imsl_f_cub_spline_interp_e_cnd
(Chapter 3, “Interpolation and Approximation”) to construct functions
b g
uk x , t 0
such that
b g
uk xi , t 0 = a ki
The IMSL routine imsl_f_cub_spline_value , Chapter 3, “Interpolation and
Approximation” is used to approximate the values
#include <imsl.h>
#include <math.h>
main()
{
void fcnut(int, float, float, float *, float *, float *,
float *);
void fcnbc(int, float, float, float *, float *,
float *);
int npdes = 1;
int nx = 8;
int i;
imsl_f_pde_method_of_lines_mgr(IMSL_PDE_INITIALIZE, &state,
0);
void fcnut(int npdes, float x, float t, float *u, float *ux, float *uxx,
float *ut)
{
/* Define the PDE */
*ut = *uxx;
}
if (x == 0.0) {
*alpha = 1.0;
*beta = 0.0;
*gamp = 0.0;
if (t <= delta)
*gamp = imsl_f_cub_spline_value(t, ppoly,
IMSL_DERIV, 1,
0);
} else {
/* These are for x = 1 */
*alpha = 0.0;
*beta = 1.0;
*gamp = 0.0;
}
}
Output
solution at t = 0.01
1 2 3 4 5 6
0.969 0.997 1.000 1.000 1.000 1.000
7 8
1.000 1.000
solution at t = 0.04
1 2 3 4 5 6
0.625 0.871 0.962 0.991 0.998 1.000
7 8
1.000 1.000
solution at t = 0.09
1 2 3 4 5 6
0.1000 0.4602 0.7169 0.8671 0.9436 0.9781
solution at t = 0.16
1 2 3 4 5 6
0.1000 0.3130 0.5071 0.6681 0.7893 0.8708
7 8
0.9168 0.9315
solution at t = 0.25
1 2 3 4 5 6
0.1000 0.2567 0.4045 0.5354 0.6428 0.7224
7 8
0.7710 0.7874
solution at t = 0.36
1 2 3 4 5 6
0.1000 0.2176 0.3292 0.4292 0.5125 0.5751
7 8
0.6139 0.6270
solution at t = 0.49
1 2 3 4 5 6
0.1000 0.1852 0.2661 0.3386 0.3992 0.4448
7 8
0.4731 0.4827
solution at t = 0.64
1 2 3 4 5 6
0.1000 0.1588 0.2147 0.2648 0.3066 0.3381
7 8
0.3577 0.3643
solution at t = 0.81
1 2 3 4 5 6
0.1000 0.1387 0.1754 0.2083 0.2358 0.2565
7 8
0.2694 0.2738
solution at t = 1.00
1 2 3 4 5 6
0.1000 0.1242 0.1472 0.1678 0.1850 0.1980
7 8
0.2060 0.2087
Example 2
Here, Problem C is solved from Sincovec and Madsen (1975). The equation is of
diffusion-convection type with discontinuous coefficients. This problem illustrates a
simple method for programming the evaluation routine for the derivative,ut. Note that
ub x , 0g = S
R1 if x = 0
T0 if x > 0
ub0, t g = 1, ub1, t g = 0
#include <imsl.h>
#include <math.h>
main()
{
void fcnut(int, float, float, float *, float *, float *,
float *);
void fcnbc(int, float, float, float *, float *,
float *);
int npdes = 1;
int nx = 100;
int i;
int j = 1;
int nstep = 10;
float t = 0.0;
float tend;
float xbreak[100];
float y[100];
float tol, hinit;
char title[50];
void *state;
tol = sqrt(imsl_f_machine(4));
hinit = 0.01*tol;
imsl_f_pde_method_of_lines_mgr(IMSL_PDE_INITIALIZE, &state,
IMSL_TOL, tol,
IMSL_HINIT, hinit,
0);
void fcnut(int npdes, float x, float t, float *u, float *ux, float *uxx,
float *ut)
{
/* Define the PDE */
float v;
float d;
if (x <= 0.5) {
d = 5.0;
v = 1000.0;
}
else
d = v = 1.0;
Output
solution at t = 1.00
1 2 3 4 5 6
1.000 1.000 1.000 1.000 1.000 1.000
7 8 9 10 11 12
1.000 1.000 1.000 1.000 1.000 1.000
13 14 15 16 17 18
1.000 1.000 1.000 1.000 1.000 1.000
19 20 21 22 23 24
1.000 1.000 1.000 1.000 1.000 1.000
25 26 27 28 29 30
1.000 1.000 1.000 1.000 1.000 1.000
37 38 39 40 41 42
1.000 1.000 1.000 1.000 1.000 1.000
43 44 45 46 47 48
1.000 1.000 1.000 1.000 1.000 1.000
49 50 51 52 53 54
1.000 0.997 0.984 0.969 0.953 0.937
55 56 57 58 59 60
0.921 0.905 0.888 0.872 0.855 0.838
61 62 63 64 65 66
0.821 0.804 0.786 0.769 0.751 0.733
67 68 69 70 71 72
0.715 0.696 0.678 0.659 0.640 0.621
73 74 75 76 77 78
0.602 0.582 0.563 0.543 0.523 0.502
79 80 81 82 83 84
0.482 0.461 0.440 0.419 0.398 0.376
85 86 87 88 89 90
0.354 0.332 0.310 0.288 0.265 0.242
91 92 93 94 95 96
0.219 0.196 0.172 0.148 0.124 0.100
97 98 99 100
0.075 0.050 0.025 0.000
Example 3
In this example, using imsl_f_pde_method_of_lines, the linear normalized
diffusion PDE ut = uxx is solved but with an optional use that provides values of the
derivatives, ux, of the initial data. Due to errors in the numerical derivatives computed
by spline interpolation, more precise derivative values are required when the initial data
is u(x, 0) = 1 + cos[(2n − 1)πx], n > 1. The boundary conditions are “zero flux”
conditions ux(0, t) = ux(1, t) = 0 for t > 0. Note that the initial data is compatible with
these end conditions since the derivative function
b g
ux x, 0 =
b g = −b2n − 1gπ sin b2n − 1gπx
du x , 0
dx
vanishes at x = 0 and x = 1.
This optional usage signals that the derivative of the initial data is passed by the user.
The values u(x, tend) and ux(x, tend) are output at the breakpoints with the optional
usage.
main()
{
void fcnut(int, float, float, float *, float *, float *,
float *);
void fcnbc(int, float, float, float *, float *, float *);
int npdes = 1;
int nx = 10;
int i;
int j = 1;
int nstep = 10;
float t = 0.0;
float tend = 0.0;
float xbreak[10];
float y[10], deriv[10];
float tol, hinit;
float pi, arg;
char title1[50];
char title2[50];
void *state;
pi = imsl_d_constant("pi", 0);
arg = 9.0 * pi;
tol = sqrt(imsl_f_machine(4));
imsl_f_pde_method_of_lines_mgr(IMSL_PDE_INITIALIZE, &state,
IMSL_TOL, tol,
IMSL_INITIAL_VALUE_DERIVATIVE,
deriv,
0);
if (j % 2) {
sprintf(title1, "\nsolution at t = %5.3f\0", t);
sprintf(title2, "\nderivative at t = %5.3f\0", t);
imsl_f_write_matrix(title1, npdes, nx, y, 0);
imsl_f_write_matrix(title2, npdes, nx, deriv, 0);
void fcnut(int npdes, float x, float t, float *u, float *ux, float *uxx,
float *ut)
{
/* Define the PDE */
ut[0] = uxx[0];
}
alpha[0] = 0.0;
beta[0] = 1.0;
gamp[0] = 0.0;
}
Output
solution at t = 0.002
1 2 3 4 5 6
1.233 0.767 1.233 0.767 1.233 0.767
7 8 9 10
1.233 0.767 1.233 0.767
derivative at t = 0.002
1 2 3 4 5 6
0.000e+00 -5.172e-07 1.911e-06 1.818e-06 -5.230e-07 2.408e-06
7 8 9 10
-2.517e-06 3.194e-06 -3.608e-06 2.023e-06
solution at t = 0.004
1 2 3 4 5 6
1.053 0.947 1.053 0.947 1.053 0.947
7 8 9 10
1.053 0.947 1.053 0.947
derivative at t = 0.004
1 2 3 4 5 6
0.000e+00 -1.332e-06 -9.059e-06 -4.401e-06 5.006e-06 -2.134e-06
7 8 9 10
-1.733e-06 4.625e-06 6.741e-07 2.023e-06
solution at t = 0.006
7 8 9 10
1.012 0.988 1.012 0.988
derivative at t = 0.006
1 2 3 4 5 6
0.000e+00 -1.408e-06 -1.018e-06 -6.572e-07 -8.213e-07 -1.151e-06
7 8 9 10
1.051e-06 1.257e-06 -2.920e-07 2.023e-06
solution at t = 0.008
1 2 3 4 5 6
1.003 0.997 1.003 0.997 1.003 0.997
7 8 9 10
1.003 0.997 1.003 0.997
derivative at t = 0.008
1 2 3 4 5 6
0.000e+00 -1.028e-06 4.270e-06 3.114e-06 -3.085e-06 -1.492e-06
7 8 9 10
2.126e-06 -1.280e-06 -1.541e-06 2.023e-06
solution at t = 0.010
1 2 3 4 5 6
1.001 0.999 1.001 0.999 1.001 0.999
7 8 9 10
1.001 0.999 1.001 0.999
derivative at t = 0.010
1 2 3 4 5 6
0.000e+00 -7.596e-07 2.819e-07 1.547e-07 -1.469e-06 -9.516e-07
7 8 9 10
2.889e-07 8.956e-08 5.992e-07 2.023e-06
Example 4
In this example, consider the linear normalized hyperbolic PDE, utt = uxx, the “vibrating
string” equation. This naturally leads to a system of first order PDEs. Define a new
dependent variable ut = v. Then, vt = uxx is the second equation in the system. Take as
initial data u(x, 0) = sin(πx) and ut(x, 0) = v(x, 0) = 0. The ends of the string are fixed so
u(0, t) = u(1, t) = v(0, t) = v(1, t) = 0. The exact solution to this problem is
u(x, t) = sin(πx) cos(πt). Residuals are computed at the output values of t for 0 < t ≤ 2.
Output is obtained at 200 steps in increments of 0.01.
main()
{
void fcnut(int, float, float, float *, float *, float *,
float *);
void fcnbc(int, float, float, float *, float *, float *);
int npdes = 2;
int nx = 10;
int i;
int j = 1;
int nstep = 200;
float t = 0.0;
float tend = 0.0;
float xbreak[20];
float y[20], deriv[20];
float tol, hinit;
float pi;
float error[10], erru;
void *state;
pi = imsl_d_constant("pi", 0);
tol = sqrt(imsl_f_machine(4));
imsl_f_pde_method_of_lines_mgr(IMSL_PDE_INITIALIZE, &state,
IMSL_TOL, tol,
IMSL_INITIAL_VALUE_DERIVATIVE,
deriv,
0);
void fcnut(int npdes, float x, float t, float *u, float *ux, float *uxx,
float *ut)
{
/* Define the PDE */
ut[0] = u[1];
ut[1] = uxx[0];
}
alpha[0] = 1.0;
beta[0] = 0.0;
gamp[0] = 0.0;
alpha[1] = 1.0;
beta[1] = 0.0;
gamp[1] = 0.0;
}
Output
Maximum error in u(x,t) = 6.228203e-04
fast_poisson_2d
Solves Poisson’s or Helmholtz’s equation on a two-dimensional rectangle using a fast
Poisson solver based on the HODIE finite-difference scheme on a uniform mesh.
Synopsis
#include <imsl.h>
float *imsl_f_fast_poisson_2d (float rhs_pde(), float rhs_bc(), float
coeff_u, int nx, int ny, float ax, float bx, float ay, float by,
Imsl_bc_type bc_type[], ..., 0)
The type double function is imsl_d_fast_poisson_2d.
Optional Arguments
IMSL_RETURN_USER, float u_user[] (Output)
User-supplied array of size nx by ny containing solution at the grid points.
IMSL_ORDER, int order (Input)
Order of accuracy of the finite-difference approximation. It can be either 2 or
4.
Default: order = 4
Description
Let c = coeff_u, ax = ax, bx = bx, ay = ay, by = by, nx = nx and ny = ny.
imsl_f_fast_poisson_2d is based on the code HFFT2D by Boisvert (1984). It
solves the equation
∂2u ∂2u
+ + cu = p
∂x 2 ∂y 2
on the rectangular domain (ax, bx) × (ay, by) with a user-specified combination of
Dirichlet (solution prescribed), Neumann (first-derivative prescribed), or periodic
boundary conditions. The sides are numbered clockwise, starting with the right side.
y
by Side 4
Side 3 Side 1
ay
x
ax Side 2 bx
Example
In this example, the equation
∂2u ∂2u
+
∂x2 ∂y 2
b g
+ 3u = −2 sin x + 2 y + 16e 2 x + 3 y
main()
{
float rhs_pde(float, float);
float rhs_bc(Imsl_pde_side, float, float);
int nx = 17;
int nxtabl = 5;
int ny = 33;
int nytabl = 5;
ax = 0.0;
bx = 0.25;
ay = 0.0;
by = 0.50;
bc_type[IMSL_RIGHT_SIDE] = IMSL_DIRICHLET_BC;
bc_type[IMSL_BOTTOM_SIDE] = IMSL_NEUMANN_BC;
bc_type[IMSL_LEFT_SIDE] = IMSL_DIRICHLET_BC;
bc_type[IMSL_TOP_SIDE] = IMSL_DIRICHLET_BC;
/* Coefficient of u */
coefu = 3.0;
/* Compute interpolant */
printf(" x y u error\n\n");
for (i = 0; i < nxtabl; i++)
for (j = 0; j < nytabl; j++) {
x = ax + (bx - ax) * (float) j / (float) (nxtabl -
1);
y = ay + (by - ay) * (float) i / (float) (nytabl -
1);
u_table = imsl_f_spline_2d_value(x, y, sp, 0);
abs_error = fabs(u_table - sin(x + 2.0 * y) -
exp(2.0 * x + 3.0 * y));
if (side == IMSL_BOTTOM_SIDE)
return (2.0 * cos(x + 2.0 * y) + 3.0 * exp(2.0 * x + 3.0 *
y));
else
return (sin(x + 2.0 * y) + exp(2.0 * x + 3.0 * y));
}
Output
x y u error
0.0000 0.0000 1.0000 0.00e+00
0.0625 0.0000 1.1956 5.12e-06
0.1250 0.0000 1.4087 7.19e-06
0.1875 0.0000 1.6414 5.10e-06
0.2500 0.0000 1.8961 8.67e-08
0.0000 0.1250 1.7024 1.73e-07
0.0625 0.1250 1.9562 6.39e-06
0.1250 0.1250 2.2345 9.50e-06
0.1875 0.1250 2.5407 6.36e-06
0.2500 0.1250 2.8783 1.66e-07
0.0000 0.2500 2.5964 2.60e-07
0.0625 0.2500 2.9322 9.25e-06
0.1250 0.2500 3.3034 1.34e-05
0.1875 0.2500 3.7148 9.27e-06
0.2500 0.2500 4.1720 9.40e-08
0.0000 0.3750 3.7619 4.84e-07
0.0625 0.3750 4.2163 9.16e-06
0.1250 0.3750 4.7226 1.36e-05
0.1875 0.3750 5.2878 9.44e-06
0.2500 0.3750 5.9199 5.72e-07
0.0000 0.5000 5.3232 5.93e-07
0.0625 0.5000 5.9520 9.84e-07
0.1250 0.5000 6.6569 1.34e-06
0.1875 0.5000 7.4483 4.55e-07
0.2500 0.5000 8.3380 2.27e-06
Routines
6.1 Real Trigonometric FFTs
Real FFT........................................................................................fft_real 323
Real FFT initialization ............................................................. fft_real_init 327
Usage Notes
Fast Fourier Transforms
A fast Fourier transform (FFT) is simply a discrete Fourier transform that is computed
efficiently. Basically, the straightforward method for computing the Fourier transform
takes approximately n2 operations where n is the number of points in the transform,
while the FFT (which computes the same values) takes approximately n log n
operations. The algorithms in this chapter are modeled on the Cooley-Tukey (1965)
b g b gb g
f ω = ℑf ω = z−∞
∞
bg
f t e −2 πiωt dt
bg
f$ ω ≈ z bg
T/2
−T / 2
f t e −2 πiωt dt
= zb T
f t −T / 2 e g b
−2 πiω t − T / 2 gdt
zb
0
= e πiωT
0
T
g
f t − T / 2 e −2 πiωt dt
If we approximate the last integral using the rectangle rule with spacing h = T / n, we
have
n −1
bg
f ω ≈ e πiωT h åe −2 πiωkh
b
f kh − T / 2 g
k =0
where the vector f h = (f(−T/2), …, f( (n − 1)h − T/2)). Thus, after scaling the
components by (−1)jh, the discrete Fourier transform, as computed in
imsl_c_fft_complex (with input f h) is related to an approximation of the
continuous Fourier transform by the above formula.
If the function f is expressed as a C function, then the continuous Fourier transform
fft_real
Computes the real discrete Fourier transform of a real sequence.
Synopsis
#include <imsl.h>
float *imsl_f_fft_real (int n, float p[], …, 0)
The type double function is imsl_d_fft_real.
Required Arguments
int n (Input)
Length of the sequence to be transformed.
float p[] (Input)
Array with n components containing the periodic sequence.
Return Value
A pointer to the transformed sequence. To release this space, use free. If no value can
be computed, then NULL is returned.
Optional Arguments
IMSL_BACKWARD
Compute the backward transform and return a pointer to the (backward)
transformed sequence.
IMSL_PARAMS, float params[] (Input)
Pointer returned by a previous call to imsl_f_fft_real_init. If
imsl_f_fft_real is used repeatedly with the same value of n, then it is
more efficient to compute these parameters only once.
Description
The function imsl_f_fft_real computes the discrete Fourier transform of a real
vector of size n. The method used is a variant of the Cooley-Tukey algorithm, which is
most efficient when n is a product of small prime factors. If n satisfies this condition,
then the computational effort is proportional to n log n.
By default, imsl_f_fft_real computes the forward transform. If n is even, then the
forward transform is
n −1
2 πkm
q2 m−1 = åp
k =0
k cos
n
m = 1, K , n / 2
n −1
2 πkm
q2 m− 2 =− åp
k =0
k sin
n
m = 1, K , n / 2 − 1
n −1
q0 = åp
k =0
k
We will assume that n is odd for the remainder of this discussion. The function
imsl_f_fft_real treats this sequence as if it were periodic of period n. In particular,
it assumes that f(t0) = f(t0 + n∆). Hence, the period of the function is assumed to be
T = n∆. We can invert the above transform for p as follows:
This formula is very revealing. It can be interpreted in the following manner. The
coefficients q produced by imsl_f_fft_real determine an interpolating
trigonometric polynomial to the data. That is, if we define
1L 2 πk bt − t g O
b gn−3 /2
b g − 2b g
n−3 /2
= Mq + 2 å q PP
2πk t − t 0
nM
0 2 k +1 cos å q2 k + 2 sin
0
N k =0
T k =0
T
Q
then we have
f(t0 + (i − 1) ∆) = g(t0 + (i − 1) ∆
Now suppose we want to discover the dominant frequencies, forming the vector P of
length (n + 1)/2 as follows:
P0 : = q0
Pk : = q22k − 2 + q22k −1 b g
k = 1, 2 , K , n − 1 / 2
These numbers correspond to the energy in the spectrum of the signal. In particular,
Pk corresponds to the energy level at frequency
k k n −1
= k = 0, 1, K ,
T n∆ 2
Furthermore, note that there are only (n + 1)/2 ≈ T/(2∆) resolvable frequencies when
n observations are taken. This is related to the Nyquist phenomenon, which is induced
by discrete sampling of a continuous signal. Similar relations hold for the case when
n is even.
If the optional argument IMSL_BACKWARD is specified, then the backward transform is
computed. If n is even, then the backward transform is
n / 2 −1 n / 2−2
2 πkm 2πkm
qm = p0 + −1 b g m
pn −1 + 2 å p2 k +1 cos
n
−2 åp 2 k +2 sin
n
k =0 k =0
If n is odd,
bn − 3g / 2 2πkm
bn − 3g / 2 2 πkm
qm = p0 + 2 å
k =0
p2 k +1 cos
n
−2 å
k =0
p2 k + 2 sin
n
The backward Fourier transform is the unnormalized inverse of the forward Fourier
transform.
The function imsl_f_fft_real is based on the real FFT in FFTPACK, which was
developed by Paul Swarztrauber at the National Center for Atmospheric Research.
Example 1
In this example, a pure cosine wave is used as a data vector, and its Fourier series is
recovered. The Fourier series is a vector with all components zero except at the
appropriate frequency where it has an n.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
main()
{
int k, n = 7;
float two_pi = 2*imsl_f_constant("pi", 0);
float p[8], *q;
/* Fill q with a pure exponential signal */
for (k = 0; k < n; k++)
p[k] = cos(k*two_pi/n);
Output
index p q
0 1.00 0.00
1 0.62 3.50
2 -0.22 0.00
3 -0.90 -0.00
4 -0.90 -0.00
5 -0.22 0.00
6 0.62 -0.00
Example 2
This example computes the Fourier transform of the vector x, where xj = (−1)j for j = 0 to n − 1.
The backward transform of this vector is now computed by using the optional argument
IMSL_BACKWARD. Note that s = nx, that is,
sj = (−1)jn, for j = 0 to n − 1.
#include <imsl.h>
#include <stdio.h>
main()
{
int k, n = 7;
float *q, *s, x[8];
/* Fill data vector */
x[0] = 1.0;
for (k = 1; k<n; k++)
x[k] = -x[k-1];
/* Compute the forward transform of x */
Output
index x q s
0 1.00 1.00 7.00
1 -1.00 1.00 -7.00
2 1.00 0.48 7.00
3 -1.00 1.00 -7.00
4 1.00 1.25 7.00
5 -1.00 1.00 -7.00
6 1.00 4.38 7.00
fft_real_init
Computes the parameters for imsl_f_fft_real.
Synopsis
#include <imsl.h>
float *imsl_f_fft_real_init (int n)
The type double function is imsl_d_fft_real_init.
Required Arguments
int n (Input)
Length of the sequence to be transformed.
Return Value
A pointer to the parameter vector of length 2n + 15 that can then be used by
imsl_f_fft_real when the optional argument IMSL_PARAMS is specified. To
release this space, use free. If no value can be computed, then NULL is returned.
Description
The function imsl_f_fft_real_init should be used when many calls are to be
made to imsl_f_fft_real without changing the sequence length n. This function
computes the parameters that are necessary for the real Fourier transform.
The function imsl_f_fft_real_init is based on the routine RFFTI in FFTPACK,
which was developed by Paul Swarztrauber at the National Center for Atmospheric
Research.
main()
{
int k, j, n = 7;
float two_pi = 2*imsl_f_constant("pi", 0);
float p[8], *q, *work;
work = imsl_f_fft_real_init (n);
for (j = 0; j < 3; j++){
/* Fill p with a pure sinusoidal signal */
for (k = 0; k < n; k++)
p[k] = cos(k*two_pi*j/n);
q = imsl_f_fft_real (n, p,
IMSL_PARAMS, work, 0);
Output
index p q
0 1.00 7.00
1 1.00 0.00
2 1.00 0.00
3 1.00 0.00
4 1.00 0.00
5 1.00 -0.00
6 1.00 0.00
index p q
0 1.00 0.00
1 0.62 3.50
2 -0.22 0.00
3 -0.90 -0.00
4 -0.90 -0.00
5 -0.22 0.00
6 0.62 -0.00
index p q
0 1.00 -0.00
1 -0.22 0.00
2 -0.90 -0.00
3 0.62 3.50
4 0.62 -0.00
5 -0.90 0.00
6 -0.22 0.00
Synopsis
#include <imsl.h>
f_complex *imsl_c_fft_complex (int n, f_complex p[], …, 0)
The type d_complex function is imsl_z_fft_complex.
Required Arguments
int n (Input)
Length of the sequence to be transformed.
f_complex p[] (Input)
Array with n components containing the periodic sequence.
Return Value
If no optional arguments are used, imsl_c_fft_complex returns a pointer to the
transformed sequence. To release this space, use free. If no value can be computed,
then NULL is returned.
Optional Arguments
IMSL_BACKWARD
Compute the backward transform.
IMSL_PARAMS, float params[] (Input)
Pointer returned by a previous call to imsl_c_fft_complex_init. If
imsl_c_fft_complex is used repeatedly with the same value of n, then it is
more efficient to compute these parameters only once.
IMSL_RETURN_USER, f_complex q[] (Output)
Store the result in the user-provided space pointed to by q. Therefore, no
storage is allocated for the solution, and imsl_c_fft_complex returns q.
The array q must be of length at least n.
This formula reveals the fact that, after properly normalizing the Fourier coefficients,
you have the coefficients for a trigonometric interpolating polynomial to the data. The
function imsl_c_fft_complex is based on the complex FFT in FFTPACK, which
was developed by Paul Swarztrauber at the National Center for Atmospheric Research.
If the option IMSL_BACKWARD is selected, then the following computation is
performed.
n −1
qj = åp me
2πimj / n
m= 0
Furthermore, the relation between the forward and backward transforms is that they are
unnormalized inverses of each other. That is, the following code fragment begins with a
vector p and concludes with a vector p2 = np.
q = imsl_c_fft_complex(n, p, 0);
p2 = imsl_c_fft_complex(n, q, IMSL_BACKWARD, 0);
Examples
Example 1
This example inputs a pure exponential data vector and recovers its Fourier series,
which is a vector with all components zero except at the appropriate frequency where it
has an n.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
main()
{
int k, n = 7;
float two_pi = 2*imsl_f_constant("pi", 0);
Output
index [Link] [Link] [Link] [Link]
0 1.00 0.00 0.00 -0.00
1 0.62 0.78 7.00 0.00
2 -0.22 0.97 -0.00 -0.00
3 -0.90 0.43 0.00 -0.00
4 -0.90 -0.43 0.00 0.00
5 -0.22 -0.97 -0.00 0.00
6 0.62 -0.78 0.00 -0.00
Example 2
The backward transform is used to recover the original sequence. Notice that the
forward transform followed by the backward transform multiplies the entries in the
original sequence by the length of the sequence.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
main()
{
int k, n = 7;
float two_pi = 2*imsl_f_constant("pi", 0);
f_complex p[7], *q, *pp;
/* Fill p with an increasing signal */
for (k = 0; k < n; k++) {
p[k].re = (float) k;
p[k].im = 0.;
}
q = imsl_c_fft_complex (n, p, 0);
pp = imsl_c_fft_complex (n, q,
IMSL_BACKWARD,
0);
printf(" index [Link] [Link] [Link] [Link] \n");
for (k = 0; k < n; k++)
printf("%11d%10.2f%10.2f%10.2f%10.2f\n", k, p[k].re, p[k].im,
pp[k].re , pp[k].im);
}
fft_complex_init
Computes the parameters for imsl_c_fft_complex.
Synopsis
#include <imsl.h>
float *imsl_c_fft_complex_init (int n)
The type double function is imsl_z_fft_complex_init.
Required Arguments
int n (Input)
Length of the sequence to be transformed.
Return Value
A pointer to the parameter vector of type float and length 2n + 15 which can then be
used by imsl_c_fft_complex when the optional argument IMSL_PARAMS is
specified. To release this space, use free. If no value can be computed, then NULL is
returned.
Description
The routine imsl_c_fft_complex_init should be used when many calls are to be
made to imsl_c_fft_complex without changing the sequence length n. This routine
computes constants which are necessary for the real Fourier transform.
The function imsl_c_fft_complex_init is based on the routine CFFTI in
FFTPACK, which was developed by Paul Swarztrauber at the National Center for
Atmospheric Research.
Example
This example computes three distinct complex FFTs by calling
imsl_c_fft_complex_init once, then calling imsl_c_fft_complex 3 times.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
Output
index [Link] [Link] [Link] [Link]
0 1.00 0.00 7.00 0.00
1 1.00 0.00 0.00 0.00
2 1.00 0.00 0.00 0.00
3 1.00 0.00 0.00 0.00
4 1.00 0.00 0.00 0.00
5 1.00 0.00 0.00 0.00
6 1.00 0.00 0.00 0.00
Synopsis
#include <imsl.h>
float *imsl_f_fft_cosine (int n, float p[], …, 0)
The type double procedure is imsl_d_fft_cosine.
Required Arguments
int n (Input)
Length of the sequence to be transformed. It must be greater than 1.
float p[] (Input)
Array of size n containing the sequence to be transformed.
Return Value
A pointer to the transformed sequence. To release this space, use free. If no solution
was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float q[] (Output)
Store the result in the user-provided space pointed to by q. Therefore, no
storage is allocated for the solution, and imsl_f_fft_cosine returns q. The
array must be of length n at least.
IMSL_PARAMS, float params[] (Input)
Pointer returned by a previous call to imsl_f_fft_cosine_init. If
imsl_f_fft_cosine is used repeatedly with the same value of n, then it is
more efficient to compute these parameters only once.
Default: Initializing parameters computed each time imsl_f_fft_cosine is
entered
Description
The function imsl_f_fft_cosine computes the discrete Fourier cosine transform of
a real vector of size N. The method used is a variant of the Cooley-Tukey algorithm,
which is most efficient when N − 1 is a product of small prime factors. If N satisfies this
n =1
Finally, note that the Fourier cosine transform is its own (unnormalized) inverse. The
imsl_f_fft_cosine function is based on the sine FFT in FFTPACK. The package
FFTPACK was developed by Paul Swarztrauber at the National Center for
Atmospheric Research.
Example
This example inputs a pure cosine wave as a data vector and recovers its Fourier cosine
series, which is a vector with all components zero, except n − 1 at the appropriate
frequency.
#include <imsl.h>
#include <math.h>
main()
{
int n = 7;
int i;
float p[7];
float *q;
float pi;
pi = imsl_f_constant("pi", 0);
Output
index p q
0 1.00 -0.00
1 0.87 6.00
2 0.50 0.00
3 -0.00 0.00
4 -0.50 -0.00
5 -0.87 -0.00
6 -1.00 -0.00
Synopsis
#include <imsl.h>
float *imsl_f_fft_cosine_init (int n)
The type double procedure is imsl_d_fft_cosine_init.
Required Arguments
int n (Input)
Length of the sequence to be transformed. It must be greater than 1.
Return Value
A pointer to parameter vector of length (3*n + 15) that can then be used by
imsl_f_fft_cosine when the optional argument IMSL_PARAMS is specified. To
release this space, use free. If no solution was computed, then NULL is returned.
Description
The function imsl_f_fft_cosine_init should be used when many calls must be
made to imsl_f_fft_cosine without changing the sequence length n. The function
imsl_f_fft_cosine_init is based on the routine COSTI in FFTPACK. The
package FFTPACK was developed by Paul Swarztrauber at the National Center for
Atmospheric Research.
Example
This example computes three distinct sine FFTs by calling
imsl_f_fft_cosine_init once, then calling imsl_f_fft_cosine three times.
The internal parameter initialization in imsl_f_fft_cosine is now skipped.
#include <imsl.h>
#include <math.h>
main()
{
int n = 7;
int i, k;
float p[7];
float q[7];
float pi;
float *params;
pi = imsl_f_constant("pi", 0);
imsl_f_fft_cosine (n, p,
IMSL_PARAMS, params,
IMSL_RETURN_USER, q,
0);
}
}
Output
index p q
0 1.00 -0.00
1 0.87 6.00
2 0.50 0.00
3 -0.00 0.00
4 -0.50 -0.00
5 -0.87 -0.00
6 -1.00 -0.00
index p q
0 1.00 0.00
1 0.50 -0.00
2 -0.50 6.00
3 -1.00 0.00
4 -0.50 0.00
5 0.50 0.00
6 1.00 -0.00
index p q
0 1.00 -0.00
1 -0.00 0.00
2 -1.00 -0.00
3 0.00 6.00
4 1.00 0.00
5 -0.00 -0.00
6 -1.00 0.00
Synopsis
#include <imsl.h>
float *imsl_f_fft_sine (int n, float p[], …, 0)
The type double procedure is imsl_d_fft_sine.
Required Arguments
int n (Input)
Length of the sequence to be transformed. It must be greater than 1.
float p[] (Input)
Array of size n containing the sequence to be transformed.
Return Value
A pointer to the transformed sequence. To release this space, use free. If no solution
was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float q[] (Output)
Store the result in the user-provided space pointed to by q. Therefore, no
storage is allocated for the solution, and imsl_f_fft_sine returns q. The
array must be of length at least n + 1.
IMSL_PARAMS, float params[] (Input)
Pointer returned by a previous call to imsl_f_fft_sine_init. If
imsl_f_fft_sine is used repeatedly with the same value of n, then it is
more efficient to compute these parameters only once.
Default: Initializing parameters computed each time imsl_f_fft_sine is
entered
Description
The function imsl_f_fft_sine computes the discrete Fourier sine transform of a real
vector of size N. The method used is a variant of the Cooley-Tukey algorithm, which is
most efficient when N + 1 is a product of small prime factors. If N satisfies this
Finally, note that the Fourier sine transform is its own (unnormalized) inverse. The
function imsl_f_fft_sine is based on the sine FFT in FFTPACK. The package
FFTPACK was developed by Paul Swarztrauber at the National Center for
Atmospheric Research.
Example
This example inputs a pure sine wave as a data vector and recovers its Fourier sine
series, which is a vector with all components zero, except n at the appropriate
frequency.
#include <imsl.h>
#include <math.h>
main()
{
int n = 7;
int i;
float p[7];
float *q;
float pi;
pi = imsl_f_constant("pi", 0);
Output
index p q
0 0.38 8.00
1 0.71 0.00
2 0.92 0.00
3 1.00 0.00
4 0.92 0.00
5 0.71 0.00
6 0.38 0.00
Synopsis
#include <imsl.h>
float *imsl_f_fft_sine_init (int n)
The type double procedure is imsl_d_fft_sine_init.
Required Arguments
int n (Input)
Length of the sequence to be transformed. It must be greater than 1.
Return Value
A pointer to parameter vector of length (int) (2.5*n + 15) that can then be used by
imsl_f_fft_sine when the optional argument IMSL_PARAMS is specified. To release
this space, use free. If no solution was computed, then NULL is returned.
Description
The function imsl_f_fft_sine_init should be used when many calls must be made
to imsl_f_fft_sine without changing the sequence length n. The function
imsl_f_fft_sine_init is based on the routine SINTI in FFTPACK. The package
FFTPACK was developed by Paul Swarztrauber at the National Center for
Atmospheric Research.
Example
This example computes three distinct sine FFTs by calling imsl_f_fft_sine_init
once, then calling imsl_f_fft_sine three times. The internal parameter initialization
in imsl_f_fft_sine is now skipped.
#include <imsl.h>
#include <math.h>
main()
{
int n = 7;
int i, k;
float p[7];
float q[8];
float pi;
float *params;
pi = imsl_f_constant("pi", 0);
imsl_f_fft_sine (n, p,
IMSL_PARAMS, params,
IMSL_RETURN_USER, q,
0);
}
}
Output
index p q
0 0.38 8.00
1 0.71 0.00
2 0.92 0.00
3 1.00 0.00
4 0.92 0.00
5 0.71 0.00
6 0.38 0.00
index p q
0 0.71 -0.00
1 1.00 8.00
2 0.71 0.00
3 -0.00 -0.00
4 -0.71 0.00
5 -1.00 -0.00
6 -0.71 0.00
index p q
0 0.92 0.00
1 0.71 -0.00
2 -0.38 8.00
3 -1.00 0.00
4 -0.38 0.00
5 0.71 0.00
6 0.92 0.00
Synopsis
#include <imsl.h>
f_complex *imsl_c_fft_2d_complex (int n, int m, f_complex p[], …, 0)
The type d_complex function is imsl_z_fft_2d_complex.
Required Arguments
int n (Input)
Number of rows in the two-dimensional transform.
int m (Input)
Number of columns in the two-dimensional transform.
f_complex p[] (Input)
Two-dimensional array of size n × m containing the sequence that is to be
transformed.
Return Value
A pointer to the transformed array. To release this space, use free. If no value can be
computed, then NULL is returned.
Optional Arguments
IMSL_P_COL_DIM, int p_col_dim (Input)
The column dimension of p.
Default: p_col_dim = m
IMSL_BACKWARD
Compute the backward transform.
Description
The function imsl_c_fft_2d_complex computes the discrete Fourier transform of
a two-dimensional complex array of size n × m. The method used is a variant of the
Cooley-Tukey algorithm, which is most efficient when bothn and m are a product of
small prime factors. If n and m satisfy this condition, then the computational effort is
proportional to nm log nm.
By default, imsl_c_fft_2d_complex computes the forward transform below.
n −1 m −1
q jk = ååp st e
−2 πijs / n −2 πikt / m
e
s= 0 t = 0
This formula reveals the fact that, after properly normalizing the Fourier coefficients,
you have the coefficients for a trigonometric interpolating polynomial to the data. The
function imsl_c_fft_2d_complex is based on the complex FFT in FFTPACK,
which was developed by Paul Swarztrauber at the National Center for Atmospheric
Research.
If the option IMSL_BACKWARD is selected, then the following computation is
performed.
n −1 m −1
p jk = å åq st e
2 πijs / n 2 πikt / m
e
s= 0 t =0
The relation between the forward and backward transforms is that they are
unnormalized inverses of each other. That is, the following code fragment begins with a
vector p and concludes with a vector p2 = nmp.
q = imsl_c_fft_2d_complex(n, m, p, 0);
p2 = imsl_c_fft_2d_complex(n, m, q, IMSL_BACKWARD, 0);
Example 1
This example computes the Fourier transform of the pure frequency input for a 5 × 4
array
for 0 ≤ n ≤ 4 and 0 ≤ m ≤ 3. The result, p = q , has all zeros except in the [2][3]
position.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
main()
{
int s, t, n = 5, m =4;
float two_pi = 2*imsl_f_constant("pi", 0);
f_complex p[5][4], *q, z, w;
/* Fill p with a pure exponential signal */
for (s = 0; s < n; s++) {
[Link] = 0.;
[Link] = s*two_pi*2./n;
for(t =0; t < m; t++){
[Link] = 0.;
[Link] = t*two_pi*3./m;
p[s][t] = imsl_c_mul(imsl_c_exp(z),imsl_c_exp(w));
}
}
q = imsl_c_fft_2d_complex (n, m, p, 0);
/* Write the input */
imsl_c_write_matrix ("The input matrix is ", 5, 4, p,
IMSL_ROW_NUMBER_ZERO,
IMSL_COL_NUMBER_ZERO, 0);
imsl_c_write_matrix ("The output matrix is ", 5, 4, q,
IMSL_ROW_NUMBER_ZERO,
IMSL_COL_NUMBER_ZERO, 0);
}
Output
The input matrix is
0 1 2
0 ( 1.000, 0.000) ( 0.000, -1.000) ( -1.000, -0.000)
1 ( -0.809, 0.588) ( 0.588, 0.809) ( 0.809, -0.588)
2 ( 0.309, -0.951) ( -0.951, -0.309) ( -0.309, 0.951)
3 ( 0.309, 0.951) ( 0.951, -0.309) ( -0.309, -0.951)
4 ( -0.809, -0.588) ( -0.588, 0.809) ( 0.809, 0.588)
3
0 ( -0.000, 1.000)
1 ( -0.588, -0.809)
2 ( 0.951, 0.309)
3 ( -0.951, 0.309)
4 ( 0.588, -0.809)
3
0 ( 0, -0)
1 ( 0, -0)
2 ( 20, 0)
3 ( -0, -0)
4 ( -0, -0)
Example 2
This example uses the backward transform to recover the original sequence. Notice that
the forward transform followed by the backward transform multiplies the entries in the
original sequence by the product of the lengths of the two dimensions.
#include <imsl.h>
#include <math.h>
#include <stdio.h>
main()
{
int s, t, n = 5, m =4;
f_complex p[5][4], *q, *p2;
/* Fill p with a pure exponential signal */
for (s = 0; s < n; s++) {
for(t =0; t < m; t++){
p[s][t].re = s + 5*t;
p[s][t].im = 0.;
}
} /* Forward transform */
q = imsl_c_fft_2d_complex (n, m, p, 0);
/* Backward transform */
p2 = imsl_c_fft_2d_complex (n, m, q,
IMSL_BACKWARD, 0);
/* Write the input */
imsl_c_write_matrix ("The input matrix is ", 5, 4, p,
IMSL_ROW_NUMBER_ZERO,
IMSL_COL_NUMBER_ZERO, 0);
imsl_c_write_matrix ("The output matrix is ", 5, 4, p2,
IMSL_ROW_NUMBER_ZERO,
IMSL_COL_NUMBER_ZERO, 0);
}
Output
The input matrix is
0 1 2
0 ( 0, 0) ( 5, 0) ( 10, 0)
1 ( 1, 0) ( 6, 0) ( 11, 0)
2 ( 2, 0) ( 7, 0) ( 12, 0)
3 ( 3, 0) ( 8, 0) ( 13, 0)
4 ( 4, 0) ( 9, 0) ( 14, 0)
3
0 ( 300, 0)
1 ( 320, 0)
2 ( 340, 0)
3 ( 360, 0)
4 ( 380, 0)
convolution
Computes the convolution, and optionally, the correlation of two real vectors.
Synopsis
#include <imsl.h>
float *imsl_f_convolution (int nx, float x[], int ny, float y[], int *nz, …
, 0)
The type double function is imsl_d_convolution.
Required Arguments
int nx (Input)
Length of the vector x.
float x[] (Input)
Real vector of length nx.
int ny (Input)
Length of the vector y.
float y[] (Input)
Real vector of length ny.
int *nz (Output)
Length of the output vector.
where the index on x is interpreted as a positive number between 1 and nz, modulo nz.
The technique used to compute the zi’s is based on the fact that the (complex discrete)
Fourier transform maps convolution into multiplication. Thus, the Fourier transform of
z is given by
bg bgbg
z n = x n y n
The technique used here to compute the convolution is to take the discrete Fourier
transform of x and y, multiply the results together component-wise, and then take the
inverse transform of this product. It is very important to make sure that nz is the product
of small primes if option IMSL_PERIODIC is selected. If nz is a product of small
primes, then the computational effort will be proportional to nzlog(nz). If option
IMSL_PERIODIC is not selected, then a good value is chosen for nz so that the Fourier
transforms are efficient and nz ≥ nx + ny − 1. This will mean that both vectors will be
padded with zeros.
We point out that no complex transforms of x or y are taken since both sequences are
real, and real transforms can simulate the complex transform above. Such a strategy is
six times faster and requires less space than when using the complex transform.
Optionally, the function imsl_f_convolution computes the discrete correlation of
two sequences x and y. More precisely, let n be the length of x and y. If a circular
correlation is desired, then option IMSL_PERIODIC must be selected. We set (on
output)
nz = n if IMSL_PERIODIC is chosen
where α, β, and γ are nonnegtive integers yielding the smallest number of the type
2a3b5g satisfying the inequality. Once nz is determined, we pad out the vectors with
zeros. Then, we compute
nz
zi = åx
j =1
i + j −1 y j
to be the largest component of z. The technique used to compute the zi’s is based on the
fact that the (complex discrete) Fourier transform maps correlation into multiplication.
Thus, the Fourier transform of z is given by
z j = x j y j
m =1
Thus, the technique used here to compute the correlation is to take the discrete Fourier
transform of x and the conjugate of the discrete Fourier transform of y, multiply the
results together component-wise, and then take the inverse transform of this product. It
is very important to make sure that nz is the product of small primes if
IMSL_PERIODIC is selected. If nz is the product of small primes, then the
computational effort will be proportional to nzlog (nz). If IMSL_PERIODIC is not
chosen, then a good value is chosen for nz so that the Fourier transforms are efficient
and nz ≥ 2n − 1. This will mean that both vectors will be padded with zeros.
We point out that no complex transforms of x or y are taken since both sequences are
real, and real transforms can simulate the complex transform above. Such a strategy is
six times faster and requires less space than when using the complex transform.
Examples
Example 1
This example computes a nonperiodic convolution. The idea here is that you can
compute a moving average of the type found in digital filtering using this function. The
averaging operator in this case is especially simple and is given by averaging five
consecutive points in the sequence. We try to recover the values of an exponential
function contaminated by noise. The large error for the last value has to do with the fact
that the convolution is averaging the zeros in the “pad” rather than the function values.
Notice that the signal size is 100, but only reports the errors at 10 points.
#include "imsl.h"
#include <math.h>
#define NFLTR 5
/* Define function */
/*
* Set up y-vector for the nonperiodic casE.
*/
total1 = 0.0;
total2 = 0.0;
for (i = 0; i < NY; i++) {
if (i >= NY-2)
k = i - NY + 2;
else
k = i + 2;
x = (float)(i) / (float) (NY - 1);
origer = fabs(y[i] - F1(x));
fltrer = fabs(z[i+2] - F1(x));
if ((i % 11) == 0) {
printf(" %10.4f%13.4f%18.4f%18.4f\n",
x, F1(x), origer, fltrer);
}
total1 += origer;
total2 += fltrer;
}
printf(" Average absolute error before filter:%10.5f\n",
total1 / (NY));
printf(" Average absolute error after filter:%11.5f\n",
total2 / (NY));
Output
Nonperiodic Case
x F1(x) Original Error Filtered Error
0.0000 1.0000 0.0811 0.3523
0.1111 1.1175 0.0226 0.0754
0.2222 1.2488 0.1526 0.0488
0.3333 1.3956 0.0959 0.0161
0.4444 1.5596 0.1747 0.0276
0.5556 1.7429 0.1035 0.0250
0.6667 1.9477 0.0402 0.0562
0.7778 2.1766 0.0673 0.0835
0.8889 2.4324 0.1044 0.0050
1.0000 2.7183 0.0154 1.1255
Average absolute error before filter: 0.12481
Average absolute error after filter: 0.06785
Example 2
This example computes both a periodic correlation between two distinct signals x and y.
There are 100 equally spaced points on the interval [0, 2π] and f1(x) = sin (x). Define x
and y as follows:
xi = f 1
FG 2πi IJ i = 0, K , n − 1
H n − 1K
= f G
F 2πi + π IJ i = 0, K , n − 1
yi 1
H n −1 2K
Note that the maximum value of z (the correlation of x with) occurs at i = 25, which
corresponds to the offset.
#include "imsl.h"
#include <math.h>
#define N 100
/* Define function */
main()
{
int i, k, nz;
float pi, max,
x[N], y[N], *z, xnorm, ynorm;
/*
* Set up y-vector for the nonperiodic case.
*/
z = imsl_f_convolution(N, x, N, y, &nz,
IMSL_CORRELATION, IMSL_PERIODIC,0);
max = z[0];
k = 0;
for (i = 1; i < N; i++) {
if (max < z[i]) {
max = z[i];
k = i;
}
}
Output
The element of Z with the largest normalized
value is Z(25).
The normalized value of Z(25) is 1.000
convolution (complex)
Computes the convolution, and optionally, the correlation of two complex vectors.
Synopsis
#include <imsl.h>
f_complex *imsl_c_convolution (int nx, f_complex x[], int ny, f_complex
y[], int *nz, …, 0)
The type double function is imsl_d_convolution.
Required Arguments
int nx (Input)
Length of the vector x.
Return Value
A pointer to an array of length nz containing the convolution of x and y. To release this
space, use free. If no zeros are computed, then NULL is returned.
Optional Arguments
IMSL_PERIODIC
The input is periodic.
IMSL_CORRELATION
Return the correlation of x and y.
IMSL_FIRST_CALL
If the function is called multiple times with the same nx and ny, select this
option on the first call.
IMSL_CONTINUE_CALL
If the function is called multiple times with the same nx and ny, select this
option on intermediate calls.
IMSL_LAST_CALL
If the function is called multiple times with the same nx and ny, select this
option on the final call.
Description
The function imsl_c_convolution, by default, computes the discrete convolution of
two sequences x and y. More precisely, let nx be the length of x, and ny denote the
length of y. If a circular convolution is desired, the optional argument IMSL_PERIODIC
must be selected. We set
nz = max {ny, nx}
and we pad out the shorter vector with zeros. Then, we compute
nz
zi = åx
j =1
i − j +1 y j
where the index on x is interpreted as a positive number between 1 and nz, modulo nz.
The technique used to compute the zi’s is based on the fact that the (complex discrete)
Fourier transform maps convolution into multiplication. Thus, the Fourier transform of
z is given by
bg bgbg
z n = x n y n
The technique used here to compute the convolution is to take the discrete Fourier
transform of x and y, multiply the results together component-wise, and then take the
inverse transform of this product. It is very important to make sure that nz is the product
of small primes if option IMSL_PERIODIC is selected. If nz is a product of small
primes, then the computational effort will be proportional to nzlog (nz). If option
IMSL_PERIODIC is not selected, then a good value is chosen for nz so that the Fourier
transforms are efficient and nz ≥ nx + ny − 1. This will mean that both vectors will be
padded with zeros.
Optionally, the function imsl_c_convolution computes the discrete correlation of
two sequences x and y. More precisely, let n be the length of x and y. If a circular
correlation is desired, then option IMSL_PERIODIC must be selected.
where α, β, and γ are nonnegative integers yielding the smallest number of the type
2a3b5g satisfying the inequality. Once nz is determined, we pad out the vectors with
zeros. Then, we compute
nz
zi = åx
j =1
i + j −1 y j
where the index on x is interpreted as a positive number between one and nz, modulo nz.
Note that this means that
z nz − k
to be the largest component of ℜz. The technique used to compute the zi’s is based on
the fact that the (complex discrete) Fourier transform maps correlation into
multiplication.
Thus, the Fourier transform of z is given by
z j = x j y j
m =1
Thus, the technique used here to compute the correlation is to take the discrete Fourier
transform of x and the conjugate of the discrete Fourier transform of y, multiply the
results together component-wise, and then take the inverse transform of this product. It
is very important to make sure that nz is the product of small primes if
IMSL_PERIODIC is selected. If nz is the product of small primes, then the
computational effort will be proportional to nzlog (nz). If IMSL_PERIODIC is not
chosen, then a good value is chosen for nz so that the Fourier transforms are efficient
and nz ≥ 2n − 1. This will mean that both vectors will be padded with zeros.
No complex transforms of x or y are taken since both sequences are real, and real
transforms can simulate the complex transform above. Such a strategy is six times faster
and requires less space than when using the complex transform.
Example 1
This example computes a nonperiodic convolution. The purpose is to compute a
moving average of the type found in digital filtering. The averaging operator in this
case is especially simple and is given by averaging five consecutive points in the
sequence. We try to recover the values of an exponential function contaminated by
noise. The large error for the last value has to do with the fact that the convolution is
averaging the zeros in the “pad” rather than the function values. Notice that the signal
size is 100, but only report the errors at ten points.
#include "imsl.h"
#include <math.h>
#define NFLTR 5
#define NY 100
main()
{
int i, nz;
f_complex fltr[NFLTR], temp,
y[NY], *z;
float x, twopi, total1, total2, *noise, origer, fltrer;
/* Print results */
printf(" Periodic Case\n");
printf(" x F1(x) Original Error");
printf(" Filtered Error\n");
total1 = 0.0;
total2 = 0.0;
for (i = 0; i < NY; i++) {
x = (float)(i) / (NY - 1);
origer = imsl_c_abs(imsl_c_sub(y[i],F1(x)));
fltrer = imsl_c_abs(imsl_c_sub(z[i+2],F1(x)));
total1 += origer;
total2 += fltrer;
}
printf(" Average absolute error before filter:%10.5f\n",
total1 / (NY));
printf(" Average absolute error after filter:%11.5f\n",
total2 / (NY));
}
Output
Periodic Case
x F1(x) Original Error Filtered Error
0.0000 (1.0000,0.0000) 0.1684 0.3524
0.1111 (1.1106,0.1239) 0.0582 0.0822
0.2222 (1.2181,0.2752) 0.1991 0.1054
0.3333 (1.3188,0.4566) 0.1487 0.1001
0.4444 (1.4081,0.6706) 0.2381 0.1004
0.5556 (1.4808,0.9192) 0.1037 0.0708
0.6667 (1.5307,1.2044) 0.1312 0.0904
0.7778 (1.5508,1.5273) 0.1695 0.0856
0.8889 (1.5331,1.8885) 0.1851 0.0698
1.0000 (1.4687,2.2874) 0.2130 1.0760
Average absolute error before filter: 0.19057
Average absolute error after filter: 0.10024
Example 2
This example computes both a periodic correlation between two distinct signals x and y.
There are 100 equally spaced points on the interval [0, 2π] and f1 (x) = cos (x) + i sin
(x). Define x and y as follows:
F 2πbi − 1g I
GH n − 1 JK
xi = f 1 i = 1, K , n
y = f G
F 2πbi − 1g + π I
i
H n − 1 2 JK
1 i = 1, K , n
Note that the maximum value of z (the correlation of x with) occurs at i = 25, which
corresponds to the offset.
#include "imsl.h"
#include <math.h>
#define N 100
/* Define function */
main()
{
z = imsl_c_convolution(N, x, N, y, &nz,
IMSL_CORRELATION, IMSL_PERIODIC,0);
max = zreal[0];
k = 0;
for (i = 1; i < N; i++) {
if (max < zreal[i]) {
max = zreal[i];
k = i;
}
}
Output
The element of Z with the largest normalized
value is Z(25).
The normalized value of Z(25) is 1.000
inverse_laplace
Computes the inverse Laplace transform of a complex function.
Required Arguments
f_complex fcn(f_complex z) (Input)
User-supplied function for which the inverse Laplace transform will be
computed.
float sigma0 (Input)
An estimate for the maximum of the real parts of the singularities of fcn. If
unknown, set sigma0 = 0.0.
int n (Input)
The number of points at which the inverse Laplace transform is desired.
float t[] (Input)
Array of size n containing the points at which the inverse Laplace transform is
desired.
Return Value
A pointer to the array of length n whose i-th component contains the approximate value
of the inverse Laplace transform at the point t[i]. To release this space, use free. If no
solution was computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, float x[] (Output)
A user-allocated array of length n containing the approximate value of the
inverse Laplace transform.
IMSL_PSEUDO_ACCURACY, float pseudo_accuracy (Input)
The required absolute uniform pseudo accuracy for the coefficients and
inverse Laplace transform values.
Default: pseudo_accuracy = ε , where ε is machine epsilon
IMSL_FIRST_LAGUERRE_PARAMETER, float sigma (Input)
The first parameter of the Laguerre expansion. If sigma is not greater than
sigma0, it is reset to sigma0 + 0.7.
Default: sigma = sigma0 + 0.7
IMSL_SECOND_LAGUERRE_PARAMETER, float bvalue (Input)
The second parameter of the Laguerre expansion. If bvalue is less than
2.0*(sigma − sigma0), it is reset to 2.5*(sigma − sigma0).
Default: bvalue = 2.5*(sigma − sigma0)
IMSL_MAXIMUM_COEFFICIENTS, int mtop (Input)
An upper limit on the number of coefficients to be computed in the Laguerre
expansion. Argument mtop must be a multiple of four.
Default: mtop = 1024
IMSL_ERR_EST, float *error_est (Output)
Overall estimate of the pseudo error, disc_error_est +
trunc_error_est + cond_error_est. See Discussion section for details.
IMSL_DISCRETIZATION_ERROR_EST, float *disc_error_est (Output)
Estimate of the pseudo discretization error.
IMSL_TRUNCATION_ERROR_EST, float *trunc_error_est (Output)
Estimate of the pseudo truncation error.
IMSL_CONDITION_ERROR_EST, float *cond_error_est (Output)
Estimate of the pseudo condition error on the basis of minimal noise levels in
the function values.
IMSL_DECAY_FUNCTION_COEFFICIENT, float *k (Output)
The coefficient of the decay function. See Discussion section for details.
IMSL_DECAY_FUNCTION_BASE, float *r (Output)
The base of the decay function. See Discussion section for details.
IMSL_LOG_LARGEST_COEFFICIENTS, float *log_largest_coefs (Output)
The logarithm of the largest coefficient in the decay function. See
Discussion section for details.
Description
The function imsl_f_inverse_laplace computes the inverse Laplace transform of
a complex-valued function. Recall that if f is a function that vanishes on the negative
real axis, then the Laplace transform of f is defined by
bg
L f s = z0
∞
bg
e − sx f x dx
where ε = pseudo_accuracy and σ = sigma > sigma0. The expression on the left is
called the pseudo error. An estimate of the pseudo error in available in error_est.
The first step in the method is to transform F to φ where
bg
φz =
b
F(
b b
− +σ)
1− z 1− z 2
Then, if f is smooth, it is known that φ is analytic in the unit disc of the complex plane
and hence has a Taylor series expansion
∞
b g åa z
φz = s
s
s=0
which converges for all z whose absolute value is less than the radius of convergence
Rc. This number is estimated in r, obtained through the optional argument
IMSL_DECAY_FUNCTION_BASE. Using optional argument
IMSL_DECAY_FUNCTION_COEFFICIENT, the smallest number K is estimated which
satisfies
K
| a s| <
Rs
Examples
Example 1
This example computes the inverse Laplace transform of the function (s − 1)-2, and
prints the computed approximation, true transform value, and difference at five points.
The correct inverse transform is xex. From Abramowitz and Stegun (1964).
#include <imsl.h>
#include <math.h>
main()
{
f_complex f(f_complex s)
{
/* Return 1/(s-1)**2 */
return (imsl_c_div(one,
imsl_c_mul(imsl_c_sub(s, one), imsl_c_sub(s, one))));
}
Output
t f_inv true diff
0.5 0.824 0.824 1.5e-05
1.5 6.722 6.723 1.0e-05
2.5 30.456 30.456 5.6e-07
3.5 115.906 115.904 1.8e-05
4.5 405.054 405.077 5.8e-05
Example 2
This example computes the inverse Laplace transform of the function e-1/s/s, and prints
the computed approximation, true transform value, and difference at five points.
Additionally, the inverse is returned in user-supplied space, and a required accuracy for
the inverse transform values is specified. The correct inverse transform is
e j
J0 2 x
main()
{
f_complex f(f_complex);
int n = 5;
int i;
float t[5];
float true_inverse[5];
float relative_diff[5];
float inverse[5];
Imsl_laplace_flow *indicators;
imsl_f_inverse_laplace(f, 0.0, n, t,
IMSL_PSEUDO_ACCURACY, 1.0e-6,
IMSL_UNDER_OVERFLOW_INDICATORS, &indicators,
IMSL_RETURN_USER, inverse,
0);
/* Compute true inverse, relative
difference */
f_complex f(f_complex s)
{
/* Return (1/s)(exp(-1/s) */
Routines
7.1 Zeros of a Polynomial
Real coefficients using Jenkins-Traub method....................... zeros_poly 368
Complex coefficients
using Jenkins-Traub method ................................. zeros_poly (complex) 370
Usage Notes
Zeros of a Polynomial
A polynomial function of degree n can be expressed as follows:
p(z) = anzn + an-1 zn-1 + … + a1z + a0
Zeros of a Function
The function imsl_f_zeros_fcn uses Müller’s method to find the real zeros of a
real-valued function.
zeros_poly
Finds the zeros of a polynomial with real coefficients using the Jenkins-Traub, three-
stage algorithm.
Synopsis
#include <imsl.h>
f_complex *imsl_f_zeros_poly (int ndeg, float coef[], …, 0)
The type d_complex function is imsl_d_zeros_poly.
Required Arguments
int ndeg (Input)
Degree of the polynomial.
float coef[] (Input)
Array with ndeg + 1 components containing the coefficients of the polynomial
in increasing order by degree. The polynomial is
coef[n] zn + coef [n − 1] zn-1 + … + coef [0], where n = ndeg.
Return Value
A pointer to the complex array of zeros of the polynomial. To release this space, use
free. If no zeros are computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, f_complex root[] (Output)
Array with ndeg components containing the zeros of the polynomial.
Description
The function imsl_f_zeros_poly computes the n zeros of the polynomial
bg
p z = an z n + an −1z n −1 + K + a1z + a 0
Examples
Example 1
This example finds the zeros of the third-degree polynomial
p(z) = z3 − 3z2 + 4z − 2
#define NDEG 3
main()
{
f_complex *zeros;
static float coeff[NDEG + 1] = {-2.0, 4.0, -3.0, 1.0};
Output
The complex zeros found are
1 2 3
( 1, 0) ( 1, 1) ( 1, -1)
Example 2
The same problem is solved with the return option.
#include <imsl.h>
#define NDEG 3
main()
{
f_complex zeros[3];
static float coeff[NDEG + 1] = {-2.0, 4.0, -3.0, 1.0};
imsl_f_zeros_poly(NDEG, coeff,
IMSL_RETURN_USER, zeros, 0);
Output
The complex zeros found are
1 2 3
( 1, 0) ( 1, 1) ( 1, -1)
Warning Errors
IMSL_ZERO_COEFF The first several coefficients of the polynomial are
equal to zero. Several of the last roots will be set to
machine infinity to compensate for this problem.
IMSL_FEWER_ZEROS_FOUND Fewer than ndeg zeros were found. The root vector
will contain the value for machine infinity in the
locations that do not contain zeros.
zeros_poly (complex)
Finds the zeros of a polynomial with complex coefficients using the Jenkins-Traub,
three-stage algorithm.
Synopsis
#include <imsl.h>
f_complex *imsl_c_zeros_poly (int ndeg, f_complex coef[], …, 0)
The type d_complex function is imsl_z_zeros_poly.
Required Arguments
int ndeg (Input)
Degree of the polynomial.
f_complex coef[] (Input)
Array with ndeg + 1 components containing the coefficients of the polynomial
in increasing order by degree. The degree of the polynomial is
coef [n] zn + coef [n − 1] zn-1 + … + coef [0]
where n = ndeg.
Return Value
A pointer to the complex array of zeros of the polynomial. To release this space, use
free. If no zeros are computed, then NULL is returned.
Optional Arguments
IMSL_RETURN_USER, f_complex root[] (Output)
Array with ndeg components containing the zeros of the polynomial.
Description
The function imsl_c_zeros_poly computes the n zeros of the polynomial
p(z) = anzn + an-1 zn-1 + … + a1z + a0
where the coefficients ai for i = 0, 1, …, n are complex and n is the degree of the
polynomial.
The function imsl_c_zeros_poly uses the Jenkins-Traub, three-stage complex
algorithm (Jenkins and Traub 1970, 1972). The zeros are computed one at a time in
roughly increasing order of modulus. As each zero is found, the polynomial is deflated
to one of lower degree.
Examples
Example 1
This example finds the zeros of the third-degree polynomial
p(z) = z3 − (3 + 6i) z2 − (8 − 12i) z + 10
#define NDEG 3
main()
{
f_complex *zeros;
f_complex coeff[NDEG + 1] = { {10.0, 0.0},
{-8.0, 12.0},
{-3.0, -6.0},
{ 1.0, 0.0} };
Example 2
The same problem is solved with the return option.
#include <imsl.h>
#define NDEG 3
main()
{
f_complex zeros[3];
f_complex coeff[NDEG + 1] = { {10.0, 0.0},
{-8.0, 12.0},
{-3.0, -6.0},
{ 1.0, 0.0} };
Output
Warning Errors
IMSL_ZERO_COEFF The first several coefficients of the polynomial are
equal to zero. Several of the last roots will be set to
machine infinity to compensate for this problem.
IMSL_FEWER_ZEROS_FOUND Fewer than ndeg zeros were found. The root vector
will contain the value for machine infinity in the
locations that do not contain zeros.
zeros_fcn
Finds the real zeros of a real function using Müller’s method.
Synopsis
#include <imsl.h>
float *imsl_f_zeros_fcn (float fcn(), …, 0)
The type double function is imsl_d_zeros_fcn.
Optional Arguments
IMSL_XGUESS, float xguess[] (Input)
Array with nroot components containing the initial guesses for the zeros.
Default: xguess = 0
IMSL_NUM_ROOTS, int nroot (Input)
The number of zeros to be found by imsl_f_zeros_fcn.
Default: nroot = 1
IMSL_ERR_ABS, float err_abs (Input)
First stopping criterion. A zero xi is accepted if |f(xi)| < err_abs.
Default:
err_ abs = ε
where e is the machine precision
IMSL_ERR_REL, float err_rel (Input)
Second stopping criterion. A zero xi is accepted if the relative change of two
successive approximations to xi is less than err_rel.
Default:
err_ rel = ε
where ε is the machine precision
Description
The function imsl_f_zeros_fcn computes n real zeros of a real function f. Given a
user-supplied function f(x) and an n-vector of initial guesses x1, x2, …, xn, the function
uses Müller’s method to locate n real zeros of f. The function has two convergence
criteria: the first requires that
e b gj
f xi
m
be less than err_abs; the second requires that the relative change of any two
successive approximations to an xi be less than err_rel. Here,
b mg
xi
Criterion 2:
xi
bm+1g − x bmg
i
< ε2
x
b mg
i
Examples
Example 1
This example finds a real zero of the third-degree polynomial
f(x) = x3 − 3x2 + 3x − 1
#include <imsl.h>
main()
{
float *x;
/* Solve fcn(x)=0 for x */
x = imsl_f_zeros_fcn (fcn, 0);
/* Print x */
imsl_f_write_matrix ("x", 1, 1, x, 0);
}
float fcn(float x)
{
return x * x * x - 3.0 * x * x + 3.0 * x - 1.0;
}
Output
x
1
Example 2
This example finds three real zeros of the third-degree polynomial
f(x) = x3 + 3x2 − 4x − 6
main()
float fcn(float x)
{
return x * x * x + 3.0 * x * x - 4.0 * x - 6.0;
}
Output
x
1 2 3
1.646 -1.000 -3.646
In the following plot, the initial guesses x = 0.0 and x = 4.6 are marked with hollow
circles, and the solutions are marked with filled circles. The other initial guess
x = −193.3 does not fit on this plot.
zeros_sys_eqn
Solves a system of n nonlinear equations f(x) = 0 using a modified Powell hybrid
algorithm.
Synopsis
#include <imsl.h>
float *imsl_f_zeros_sys_eqn (void fcn(), int n, …, 0)
The type double function is imsl_d_zeros_sys_eqn.
Required Arguments
void fcn (int n, float x[], float f[]) (Input/Output)
User-supplied function to evaluate the system of equations to be solved, where
n is the size of x and f, x is the point at which the functions are evaluated, and
f contains the computed function values at the point x.
int n (Input)
The number of equations to be solved and the number of unknowns.
Return Value
A pointer to the vector x that is a solution of the system of equations. To release this
space, use free. If no solution can be computed, then NULL is returned.
Optional Arguments
IMSL_XGUESS, float xguess[] (Input)
Array with n components containing the initial estimate of the root.
Default: xguess = 0
at the point x.
Description
The function imsl_f_zeros_sys_eqn is based on the MINPACK subroutine
HYBRDJ, which uses a modification of the hybrid algorithm due to M.J.D. Powell.
This algorithm is a variation of Newton’s method, which takes precautions to avoid
undesirable large steps or increasing residuals. For further description, see Moré et al.
(1980).
Examples
Example 1
The following 2 × 2 system of nonlinear equations
bg
f 1 x = x1 + x2 − 3
f b xg = x
2
2
1 + x22 − 9
is solved.
#define N 2
void main()
{
float *x;
x = imsl_f_zeros_sys_eqn(fcn, N, 0);
imsl_f_write_matrix("The solution to the system is", 1, N, x, 0);
}
Output
The solution to the system is
1 2
0 3
Example 2
The following 3 × 3 system of nonlinear equations
bg b
f 1 x = x1 + e x1 −1 + x2 + x3 g 2
− 27
f b xg = e
2
x2 − 2
/ x1 + x32 − 10
f b xg = x
3 3 b g
+ sin x2 − 2 + x22 − 7
#define N 3
void main()
{
int maxitn = 100;
float *x, err_rel = 0.0001, fnorm;
float xguess[N] = {4.0, 4.0, 4.0};
x = imsl_f_zeros_sys_eqn(fcn, N,
IMSL_ERR_REL, err_rel,
IMSL_MAX_ITN, maxitn,
IMSL_XGUESS, xguess,
IMSL_FNORM, &fnorm,
Output
The solution to the system is
1 2 3
1 2 3
Warning Errors
IMSL_TOO_MANY_FCN_EVALS The number of function evaluations has exceeded
max_itn. A new initial guess may be tried.
IMSL_NO_BETTER_POINT Argument err_rel is too small. No further
improvement in the approximate solution is
possible.
IMSL_NO_PROGRESS The iteration has not made good progress. A new
initial guess may be tried.
Routines
8.1 Unconstrained Minimization
Univariate Function
Using function values only ...................................................... min_uncon 383
Using function and first derivative values ..................... min_uncon_deriv 387
Multivariate Function
Using quasi-Newton method.................................... min_uncon_multivar 391
Nonlinear Least Squares
Using Levenberg-Marquardt algorithm ...................nonlin_least_squares 397
Usage Notes
Unconstrained Minimization
The unconstrained minimization problem can be stated as follows:
minn f x
x ∈R
bg
where f : Rn → R is continuous and has derivatives of all orders required by the
algorithms. The functions for unconstrained minimization are grouped into three
categories: univariate functions, multivariate functions, and nonlinear least-squares
functions.
min_uncon
Find the minimum point of a smooth function f(x) of a single variable using only
function evaluations.
Synopsis
#include <imsl.h>
float imsl_f_min_uncon (float fcn(), float a, float b, …, 0)
The type double function is imsl_d_min_uncon.
Required Arguments
float fcn(float x) (Input/Output)
User-supplied function to compute the value of the function to be minimized
where x is the point at which the function is evaluated, and fcn is the
computed function value at the point x.
float a (Input)
The lower endpoint of the interval in which the minimum point of fcn is to be
located.
float b (Input)
The upper endpoint of the interval in which the minimum point of fcn is to be
located.
Return Value
The point at which a minimum value of fcn is found. If no value can be computed,
NaN is returned.
Optional Arguments
IMSL_XGUESS, float xguess (Input)
An initial guess of the minimum point of fcn.
Default: xguess = (a + b)/2
IMSL_STEP, float step (Input)
An order of magnitude estimate of the required change in x.
Default: step = 1.0
IMSL_ERR_ABS, float err_abs (Input)
The required absolute accuracy in the final value of x. On a normal return,
there are points on either side of x within a distance err_abs at which fcn is
no less than fcn at x.
Default: err_abs = 0.0001
IMSL_MAX_FCN, int max_fcn (Input)
Maximum number of function evaluations allowed.
Default: max_fcn = 1000
Description
The function imsl_f_min_uncon uses a safeguarded quadratic interpolation method
to find a minimum point of a univariate function. Both the code and the underlying
algorithm are based on the subroutine ZXLSF written by M.J.D. Powell at the
University of Cambridge.
The function imsl_f_min_uncon finds the least value of a univariate function, f,
which is specified by the function fcn. Other required data are two points a and b that
define an interval for finding a minimum point from an initial estimate of the solution,
x0 where x0 = xguess. The algorithm begins the search by moving from
x0 to x = x0 + s where s = step is an estimate of the required change in x and may be
positive or negative. The first two function evaluations indicate the direction to the
minimum point and the search strides out along this direction until a bracket on a
minimum point is found or until x reaches one of the endpoints a or b. During this
stage, the step length increases by a factor of between two and nine per function
evaluation. The factor depends on the position of the minimum point that is predicted
by quadratic interpolation of the three most recent function values.
When an interval containing a solution has been found, we have three points,
x1, x2, x3, with x1 < x2 < x3, f(x1) ≥ f(x2), and f(x2) ≤ f(x3).
Examples
Example 1
A minimum point of f(x) = ex − 5x is found.
#include <imsl.h>
#include <math.h>
float fcn(float);
void main ()
{
float a = -100.0;
float b = 100.0;
float fx, x;
float fcn(float x)
{
Output
The solution is: 1.6094
The function evaluated at the solution is: -3.0472
Example 2
A minimum point of f(x) = x(x3 − 1) + 10 is found with an initial guess x0 = 3.
#include <imsl.h>
float fcn(float);
void main ()
{
int max_fcn = 50;
float a = -10.0;
float b = 10.0;
float xguess = 3.0;
float step = 0.1;
float err_abs = 0.001;
float fx, x;
x = imsl_f_min_uncon (fcn, a, b,
IMSL_XGUESS, xguess,
IMSL_STEP, step,
IMSL_ERR_ABS, err_abs,
IMSL_MAX_FCN, max_fcn,
0);
fx = fcn(x);
float fcn(float x)
{
return x*(x*x*x-1.0) + 10.0;
}
Output
The solution is: 0.6298
The function evaluated at the solution is: 9.5275
Warning Errors
IMSL_MIN_AT_BOUND The final value of x is at a bound.
IMSL_NO_MORE_PROGRESS Computer rounding errors prevent further
refinement of x.
IMSL_TOO_MANY_FCN_EVAL Maximum number of function evaluations
exceeded.
Synopsis
#include <imsl.h>
float imsl_f_min_uncon_deriv (float fcn(), float grad(), float a, float b,
…, 0)
The type double function is imsl_d_min_uncon_deriv.
Required Arguments
float fcn (float x) (Input/Output)
User-supplied function to compute the value of the function to be minimized
where x is the point at which the function is evaluated, and fcn is the
computed function value at the point x.
float grad (float x) (Input/Output)
User-supplied function to compute the first derivative of the function where
x is the point at which the derivative is evaluated, and grad is the computed
value of the derivative at the point x.
float a (Input)
The lower endpoint of the interval in which the minimum point of fcn is to be
located.
float b (Input)
The upper endpoint of the interval in which the minimum point of fcn is to be
located.
Return Value
The point at which a minimum value of fcn is found. If no value can be computed,
NaN is returned.
Description
The function f_min_uncon_deriv uses a descent method with either the secant
method or cubic interpolation to find a minimum point of a univariate function. It starts
with an initial guess and two endpoints. If any of the three points is a local minimum
point and has least function value, the function terminates with a solution. Otherwise,
the point with least function value will be used as the starting point.
From the starting point, say xc, the function value fc = f(xc), the derivative value
gc = g(xc), and a new point xn defined by xn = xc − gc are computed. The function
fn = f(xn), and the derivative gn = g(xn) are then evaluated. If either
x s = xc − gc
FG g n − gc IJ
Hx n − xc K
Let xn = xs, and repeat this process until an interval containing a minimum is found or
one of the convergence criteria is satisfied. The convergence criteria are as follows:
Criterion 1: |xc − xn| ≤ εc
Criterion 2: |gc| ≤ εg
where εc = max {1.0, |xc|} ε, ε is an error tolerance, and εg is a gradient tolerance.
When convergence is not achieved, a cubic interpolation is performed to obtain a new
point. Function and derivative are then evaluated at that point, and accordingly a
smaller interval that contains a minimum point is chosen. A safeguarded method is used
to ensure that the interval be reduced by at least a fraction of the previous interval.
Another cubic interpolation is then performed, and this function is repeated until one of
the stopping criteria is met.
Examples
Example 1
In this example, a minimum point of f(x) = ex − 5x is found.
#include <imsl.h>
#include <math.h>
float fcn(float);
float deriv(float);
void main ()
{
float a = -10.0;
float b = 10.0;
float fx, gx, x;
float fcn(float x)
{
return exp(x) - 5.0*(x);
Output
The solution is: 1.609
The function evaluated at the solution is: -3.047
The derivative evaluated at the solution is: -0.001
Example 2
A minimum point of f(x) = x(x3 − 1) + 10 is found with an initial guess x0 = 3.
#include <imsl.h>
#include <stdio.h>
float fcn(float);
float deriv(float);
void main ()
{
int max_fcn = 50;
float a = -10.0;
float b = 10.0;
float xguess = 3.0;
float fx, gx, x;
float fcn(float x)
{
return x*(x*x*x-1) + 10.0;
}
float deriv(float x)
{
return 4.0*(x*x*x) - 1.0;
}
Output
The solution is: 0.630
The function evaluated at the solution is: 9.528
The derivative evaluated at the solution is: 0.000
min_uncon_multivar
Minimizes a function f(x) of n variables using a quasi-Newton method.
Synopsis
#include <imsl.h>
float *imsl_f_min_uncon_multivar (float fcn(), int n, …, 0)
The type double function is imsl_d_min_uncon_multivar.
Required Arguments
float fcn (int n, float x[]) (Input/Output)
User-supplied function to evaluate the function to be minimized where n is the
size of x, x is the point at which the function is evaluated, and fcn is the
computed function value at the point x.
int n (Input)
Number of variables.
Return Value
A pointer to the minimum point x of the function. To release this space, use free. If no
solution can be computed, then NULL is returned.
Optional Arguments
IMSL_XGUESS, float xguess[] (Input)
Array with n components containing an initial guess of the computed solution.
Default: xguess = 0
IMSL_GRAD, void grad (int n, float x[], float g[]) (Input/Output)
User-supplied function to compute the gradient at the point x where n is the
size of x, x is the point at which the gradient is evaluated, and g is the
computed gradient at the point x.
IMSL_XSCALE, float xscale[] (Input)
Array with n components containing the scaling vector for the variables.
xscale is used mainly in scaling the gradient and the distance between two
points. See keywords IMSL_GRAD_TOL and IMSL_STEP_TOL for more detail.
Default: xscale[] = 1.0
IMSL_FSCALE, float fscale (Input)
Scalar containing the function scaling. fscale is used mainly in scaling the
gradient. See keyword IMSL_GRAD_TOL for more detail.
Default: fscale = 1.0
IMSL_GRAD_TOL, float grad_tol (Input)
Scaled gradient tolerance. The i-th component of the scaled gradient at x is
calculated as
c
gi ∗ max xi , 1 / sih
maxe f b x g , f j
s
å bs t g
n 2
ε1 = i i
i =1
e bg j
max f t , f s ∗ si2
Description
The function f_min_uncon_multivar uses a quasi-Newton method to find the
minimum of a function f(x) of n variables. The problem is stated as follows:
min f x
x ∈R n
bg
Given a starting point xc, the search direction is computed according to the formula
d = −B-1 gc
where B is a positive definite approximation of the Hessian, and gc is the gradient
evaluated at xc. A line search is then used to find a new point
Bss T B yy T
B ← B− +
s T Bs yT s
Examples
Example 1
The function
bg e
f x = 100 x2 − x12 j + b1 − x g
2
1
2
is minimized. In the following plot, the solid circle marks the minimum.
#include <stdio.h>
#include <imsl.h>
void main()
{
int i, n=2;
float *result, fx;
static float rosbrk(int, float[]);
/* Minimize Rosenbrock function */
/* Print results */
f1 = x[1] - x[0]*x[0];
f2 = 1.0 - x[0];
Output
The solution is 1.000 1.000
Example 2
The function
bg e
f x = 100 x2 − x12 j + b1 − x g
2
1
2
void main()
{
int i, n=2;
float *result, fx;
static float rosbrk(int, float[]);
static void rosgrd(int, float[], float[]);
static float xguess[2] = {-1.2e0, 1.0e0};
static float grad_tol = .0001;
/* Print results */
f1 = x[1] - x[0]*x[0];
f2 = 1.0e0 - x[0];
} /* End of function */
Output
The solution is 1.000 1.000
Informational Errors
IMSL_STEP_TOLERANCE Scaled step tolerance satisfied. The current point
may be an approximate local solution, but it is
Warning Errors
IMSL_REL_FCN_TOLERANCE Relative function convergence—Both the actual
and predicted relative reductions in the function
are less than or equal to the relative function
convergence tolerance rfcn_tol = #.
IMSL_TOO_MANY_ITN Maximum number of iterations exceeded.
IMSL_TOO_MANY_FCN_EVAL Maximum number of function evaluations
exceeded.
IMSL_TOO_MANY_GRAD_EVAL Maximum number of gradient evaluations
exceeded.
IMSL_UNBOUNDED Five consecutive steps have been taken with the
maximum step length.
IMSL_NO_FURTHER_PROGRESS The last global step failed to locate a lower point
than the current x value.
Fatal Errors
IMSL_FALSE_CONVERGENCE False convergence—The iterates appear to be
converging to a noncritical point. Possibly
incorrect gradient information is used, or the
function is discontinuous, or the other stopping
tolerances are too tight.
nonlin_least_squares
Solve a nonlinear least-squares problem using a modified Levenberg-Marquardt
algorithm.
Synopsis
#include <imsl.h>
float *imsl_f_nonlin_least_squares (void fcn(), int m, int n, …, 0)
The type double function is imsl_d_nonlin_least_squares.
Required Arguments
void fcn (int m, int n, float x[], float f[]) (Input/Output)
User-supplied function to evaluate the function that defines the least-squares
problem where x is a vector of length n at which point the function is
Return Value
A pointer to the solution x of the nonlinear least-squares problem. To release this space,
use free. If no solution can be computed, then NULL is returned.
c
gi ∗max xi , 1 / si h
F b xg
1 2
2 2
b g = å f b xg
F x
2
2
m
i =1 i
2
Default:
grad_ tol = ε
3
ε in double where ε is the machine precision
IMSL_STEP_TOL, float step_tol (Input)
Scaled step tolerance. The i-th component of the scaled step between two
points x and y is computed as
å bs t g
n 2
ε1 = i i , ε2 = s 2
i =1
i =1
where m ≥ n, F : Rn → Rm, and fi(x) is the i-th component function of F(x). From a
current point, the algorithm uses the trust region approach,
b g b gb
min F xc + J xc xn − xc
x ∈R n
g 2
subject to xn − xc 2
≤ δc
where µc = 0 if δc ≥ ||(J(xc)T J(xc))-1 J(xc)T F(xc)||2 and µc > 0, otherwise. The value
µc is defined by the function. The vector and matrix F(xc) and J(xc) are the function
values and the Jacobian evaluated at the current point xc, respectively. This function is
repeated until the stopping criteria are satisfied.
The first stopping criterion for imsl_f_nonlin_least_squares occurs when the
norm of the function is less than the absolute function tolerance fcn_tol. The second
stopping criterion occurs when the norm of the scaled gradient is less than the given
gradient tolerance grad_tol. The third stopping criterion for
imsl_f_nonlin_least_squares occurs when the scaled distance between the last
two steps is less than the step tolerance step_tol. For more details, see Levenberg
(1944), Marquardt (1963), or Dennis and Schnabel (1983, Chapter 10).
Examples
Example 1
In this example, the nonlinear data-fitting problem found in Dennis and Schnabel
(1983, p. 225),
3
å f b xg
1 2
min i
2 i=1
where
bg
f i x = e t i x − yi
void main()
{
int m=3, n=1;
float *result, fx[3];
/* Print results */
} /* End of function */
Output
The solution is
0.4401
Example 2
In this example, imsl_f_nonlin_least_squares is first invoked to fit the
following nonlinear regression model discussed by Neter et al. (1983, pp. 475−478):
yi = θ1e θ 2 xi + ε i i = 1, 2 , K , 15
where the εi’s are independently distributed each normal with mean zero and variance
σ2. The estimate of σ2 is then computed as
å
15
e2
2 i =1 i
s =
15 − rank J bg
where ei is the i-th residual and J is the Jacobian. The estimated asymptotic variance-
covariance matrix of θ 1 and θ 2 is computed as
ej e j
est. asy. var θ = s 2 J T J
−1
Finally, the diagonal elements of this matrix are used together with imsl_f_t_inverse_cdf
(Chapter 9) to compute 95% confidence intervals on θ1 and θ2.
#include <math.h>
#include <imsl.h>
void main()
{
int i, j, m=15, n=2, rank;
float a, *result, e[15], jtj_inv[4], s2, dfe;
char *fmt="%12.5e";
result = imsl_f_nonlin_least_squares(exampl, m, n,
IMSL_XGUESS, xguess,
IMSL_GRAD_TOL, grad_tol,
IMSL_FVEC_USER, e,
IMSL_RANK, &rank,
IMSL_JTJ_INVERSE_USER, jtj_inv,
0);
dfe = (float) (m - rank);
s2 = 0.0;
for (i=0; i<m; i++)
s2 += e[i] * e[i];
s2 = s2 / dfe;
j = n * n;
for (i=0; i<j; i++)
jtj_inv[i] = s2 * jtj_inv[i];
/* Print results */
imsl_f_write_matrix (
"Estimated Asymptotic Variance-Covariance Matrix",
2, 2, jtj_inv, IMSL_WRITE_FORMAT, fmt, 0);
printf(" \n 95%% Confidence Intervals \n ");
printf(" Estimate Lower Limit Upper Limit \n ");
for (i=0; i<n; i++) {
j = i * (n+1);
a = imsl_f_t_inverse_cdf (0.975, dfe) * sqrt(jtj_inv[j]);
printf(" %10.3f %12.3f %12.3f \n", result[i],
result[i] - a, result[i] + a);
}
} /* End of main */
} /* End of function */
Output
Estimated Asymptotic Variance-Covariance Matrix
1 2
1 2.17524e+00 -1.80141e-03
2 -1.80141e-03 2.97216e-06
lin_prog
Solves a linear programming problem using the revised simplex algorithm.
Synopsis
#include <imsl.h>
float *imsl_f_lin_prog (int m, int n, float a[], float b[],
float c[], …, 0)
The type double function is imsl_d_lin_prog.
Required Arguments
int m (Input)
Number of constraints.
int n (Input)
Number of variables.
float a[] (Input)
Array of size m × n containing a matrix with coefficients of the m constraints.
Return Value
A pointer to the solution x of the linear programming problem. To release this space,
use free. If no solution can be computed, then NULL is returned.
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of a.
Default: a_col_dim = n
IMSL_UPPER_LIMIT, float bu[] (Input)
Array with m components containing the upper limit of the constraints that
have both the lower and the upper bounds. If no such constraint exists, then
bu is not needed.
IMSL_CONSTR_TYPE, int irtype[] (Input)
Array with m components indicating the types of general constraints in the
matrix a. Let ri = ai1x1 + … + ainxn. Then, the value of irtype(i) signifies
the following:
irtype(i) Constraint
0 ri = bi
1 ri ≤ bui
2 ri ≥ bi
Default: irtype = 0
IMSL_LOWER_BOUND, float xlb[] (Input)
Array with n components containing the lower bound on the variables. If there
is no lower bound on a variable, then 1030 should be set as the lower bound.
Default: xlb = 0
IMSL_UPPER_BOUND, float xub[] (Input)
Array with n components containing the upper bound on the variables. If there
is no upper bound on a variable, then −1030 should be set as the upper bound.
Default: xub = ∞
IMSL_MAX_ITN, int max_itn (Input)
Maximum number of iterations.
Default: max_itn = 10000
IMSL_OBJ, float *obj (Output)
Optimal value of the objective function.
IMSL_RETURN_USER, float x[] (Output)
Array with n components containing the primal solution.
IMSL_DUAL, float **y (Output)
The address of a pointer y to an array with m components containing the dual
solution. On return, the necessary space is allocated by imsl_f_lin_prog.
Typically, float *y is declared, and &y is used as an argument.
IMSL_DUAL_USER, float y[] (Output)
A user-allocated array of size m. On return, y contains the dual solution.
Description
The function imsl_f_lin_prog uses a revised simplex method to solve linear
programming problems, i.e., problems of the form
min c T x subject to bl ≤ Ax ≤ bu
x ∈R n
xl ≤ x ≤ x u
where c is the objective coefficient vector, A is the coefficient matrix, and the vectors
bl, bu, xl, and xu are the lower and upper bounds on the constraints and the variables,
respectively.
For a complete description of the revised simplex method, see Murtagh (1981) or
Murty (1983).
Examples
Example 1
The linear programming problem in the standard form
main()
{
int m = 4;
int n = 6;
float a[ ] = {1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
1.0, 1.0, 0.0, -1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
float b[ ] = {1.5, 0.5, 1.0, 1.0};
float c[ ] = {-1.0, -3.0, 0.0, 0.0, 0.0, 0.0};
float *x;
/* Solve the LP problem */
Example 2
The linear programming problem in the previous example can be formulated as follows:
min f(x) = −x1 − 3x2
subject to 0.5 ≤ x1 + x2 ≤ 1.5
0 ≤ x1 ≤1.0
0 ≤ x2 ≤ 1.0
This problem can be solved more efficiently.
#include <imsl.h>
main()
{
int irtype[ ] = {3};
int m = 1;
int n = 2;
float xub[ ] = {1.0, 1.0};
float a[ ] = {1.0, 1.0};
float b[ ] = {0.5};
float bu[ ] = {1.5};
float c[ ] = {-1.0, -3.0};
float d[1];
x = imsl_f_lin_prog (m, n, a, b, c,
IMSL_UPPER_LIMIT, bu,
IMSL_CONSTR_TYPE, irtype,
IMSL_UPPER_BOUND, xub,
IMSL_DUAL_USER, d,
IMSL_OBJ, &obj,
0);
/* Print x */
imsl_f_write_matrix ("x", 1, 2, x, 0);
/* Print d */
imsl_f_write_matrix ("d", 1, 1, d, 0);
printf("\n obj = %g \n", obj);
}
Output
x
1 2
0.5 1.0
d
-1
obj = -3.5
Warning Errors
IMSL_PROB_UNBOUNDED The problem is unbounded.
IMSL_TOO_MANY_ITN Maximum number of iterations exceeded.
IMSL_PROB_INFEASIBLE The problem is infeasible.
Fatal Errors
IMSL_NUMERIC_DIFFICULTY Numerical difficulty occurred (moved to a vertex
that is poorly conditioned). If float is currently
being used, using double precision may help.
IMSL_BOUNDS_INCONSISTENT The bounds are inconsistent.
quadratic_prog
Solves a quadratic programming problem subject to linear equality or inequality
constraints.
Synopsis
#include <imsl.h>
float *imsl_f_quadratic_prog (int m, int n, int meq, float a[], float b[],
float g[], float h[], …, 0)
The type double function is imsl_d_quadratic_prog.
Return Value
A pointer to the solution x of the QP problem. To release this space, use free. If no
solution can be computed, then NULL is returned.
Synopsis with Optional Arguments
#include <imsl.h>
float *imsl_f_quadratic_prog (int m, int n, int meq, float a[], float b[],
float g[], float h[],
IMSL_A_COL_DIM, int a_col_dim,
IMSL_H_COL_DIM, int h_col_dim,
IMSL_RETURN_USER, float x[],
IMSL_DUAL, float **y,
IMSL_DUAL_USER, float y[],
IMSL_ADD_TO_DIAG_H, float *diag,
IMSL_OBJ, float *obj,
0)
Optional Arguments
IMSL_A_COL_DIM, int a_col_dim (Input)
Leading dimension of A exactly as specified in the dimension statement of the
calling program.
Default: a_col_dim = n
Description
The function imsl_f_quadratic_prog is based on M.J.D. Powell’s implementation
of the Goldfarb and Idnani dual quadratic programming (QP) algorithm for convex QP
problems subject to general linear equality/inequality constraints (Goldfarb and Idnani
1983); i.e., problems of the form
1 T
min g T x + x Hx
x ∈R n 2
subject to A1 x = b1
A2 x ≥ b2
given the vectors b1, b2, and g, and the matrices H, A1, and A2. H is required to be
positive definite. In this case, a unique x solves the problem or the constraints are
inconsistent. If H is not positive definite, a positive definite perturbation of H is used in
place of H. For more details, see Powell (1983, 1985).
If a perturbation of H, H + αI, is used in the QP problem, then H + αI also should be
used in the definition of the Lagrange multipliers.
Examples
Example 1
The quadratic programming problem
main()
{
int m = 2;
int n = 5;
int meq = 2;
float *x;
float h[ ] = {2.0, 0.0, 0.0, 0.0, 0.0,
0.0, 2.0,-2.0, 0.0, 0.0,
0.0,-2.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 2.0,-2.0,
0.0, 0.0, 0.0,-2.0, 2.0};
float a[ ] = {1.0, 1.0, 1.0, 1.0, 1.0,
0.0, 0.0, 1.0,-2.0,-2.0};
float b[ ] = {5.0, -3.0};
float g[ ] = {-2.0, 0.0, 0.0, 0.0, 0.0};
/* Solve the QP problem */
x = imsl_f_quadratic_prog (m, n, meq, a, b, g, h, 0);
/* Print x */
imsl_f_write_matrix ("x", 1, 5, x, 0);
}
Output
x
1 2 3 4 5
1 1 1 1 1
Example 2
Another quadratic programming problem
bg
min f x = x12 + x22 + x32 subject to x1 + 2 x2 − x3 = 4
x1 − x2 + x3 = −2
is solved.
#include <imsl.h>
Output
x
1 2 3
0.286 1.429 -0.857
d
1 2
1.143 -0.571
obj = 2.85714
Warning Errors
IMSL_NO_MORE_PROGRESS Due to the effect of computer rounding error, a
change in the variables fail to improve the
objective function value; usually the solution is
close to optimum.
Fatal Errors
IMSL_SYSTEM_INCONSISTENT The system of equations is inconsistent. There is
no solution.
min_con_gen_lin
Minimizes a general objective function subject to linear equality/inequality constraints.
Synopsis
#include <imsl.h>
float *imsl_f_min_con_gen_lin (void fcn(), int nvar, int ncon, int neq,
float a[], float b[], float xlb[], float xub[], ..., 0)
The type double function is imsl_d_min_con_gen_lin.
Return Value
A pointer to the solution x. To release this space, use free. If no solution can be
computed, then NULL is returned.
Optional Arguments
IMSL_XGUESS, float xguess[] (Input)
Array with n components containing an initial guess.
Default: xguess = 0
IMSL_GRADIENT, void gradient (int n, float x[], float g[]) (Input)
User-supplied function to compute the gradient at the point x, where x is a
vector of length n, and g is the vector of length n containing the values of the
gradient of the objective function.
IMSL_MAX_FCN, int max_fcn (Input)
Maximum number of function evaluations.
Default: max_fcn = 400
IMSL_NUMBER_ACTIVE_CONSTRAINTS, int *nact (Output)
Final number of active constraints.
IMSL_ACTIVE_CONSTRAINT, int **iact (Output)
The address of a pointer to an int, which on exit, points to an array containing
the nact indices of the final active constraints.
IMSL_ACTIVE_CONSTRAINT_USER, int *iact_user (Output)
A user-supplied array of length at least ncon + 2*nvar containing the indices
of the final active constraints in the first nact locations.
IMSL_LAGRANGE_MULTIPLIERS, float **lagrange (Output)
The address of a pointer, which on exit, points to an array containing the
Lagrange multiplier estimates of the final active constraints in the first nact
locations.
IMSL_LAGRANGE_MULTIPLIERS_USER, float *lagrange_user (Output)
A user-supplied array of length at least nvar containing the Lagrange
multiplier estimates of the final active constraints in the first nact locations.
IMSL_TOLERANCE, float tolerance (Input)
The nonnegative tolerance on the first order conditions at the calculated
solution.
Default: tolerance = ε , where ε is machine epsilon
IMSL_OBJ, float *obj (Output)
The value of the objective function.
Description
The function imsl_f_min_con_gen_lin is based on M.J.D. Powell’s TOLMIN,
which solves linearly constrained optimization problems, i.e., problems of the form
min f (x)
subject to
A1x = b1
A2x ≤ b2
xl ≤ x ≤ xu
given the vectors b1, b2, xl ,and xu and the matrices A1 and A2.
The algorithm starts by checking the equality constraints for inconsistency and
redundancy. If the equality constraints are consistent, the method will revise x0, the
initial guess, to satisfy
A1x = b1
Next, x0 is adjusted to satisfy the simple bounds and inequality constraints. This is done
by solving a sequence of quadratic programming subproblems to minimize the sum of
the constraint or bound violations.
Now, for each iteration with a feasible xk, let Jk be the set of indices of inequality
constraints that have small residuals. Here, the simple bounds are treated as inequality
constraints. Let Ik be the set of indices of active constraints. The following quadratic
programming problem
1
e j e j
min f x k + d T ∇ f x k + d T B k d
2
subject to
ajd = 0, j ∈ Ik
ajd ≤ 0, j ∈ Jk
is solved to get (dk, λk) where aj is a row vector representing either a constraint in
A1 or A2 or a bound constraint on x. In the latter case, the aj = ei for the bound
constraint xi ≤ (xu)i and aj = −ei for the constraint −xi ≤ (xl)i. Here, ei is a vector with 1
as the i-th component, and zeros elsewhere. Variables λk are the Lagrange multipliers,
and Bk is a positive definite approximation to the second derivative ∇2 f(xk).
After the search direction dk is obtained, a line search is performed to locate a better
point. The new point xk+1 = xk +αkdk has to satisfy the conditions
f(xk + αkdk) ≤ f(xk) + 0.1 αk (dk)T ∇ f(xk)
and
Example 1
In this example, the problem
bg
min f x = x12 + x22 + x32 + x42 + x52 − 2 x2 x3 − 2 x4 x5 − 2 x1
subject to x1 + x2 + x3 + x4 + x5 = 5
x3 − 2 x4 − 2 x5 = −3
0 ≤ x ≤ 10
is solved.
#include "imsl.h"
main()
{
void fcn(int, float *, float *);
int neq = 2;
int ncon = 2;
int nvar = 5;
main()
{
void fcn(int, float *, float *);
void grad(int, float *, float *);
int neq = 0;
int ncon = 2;
int nvar = 3;
int lda = 2;
float obj, x[3];
float a[] = {-1.0, -2.0, -2.0,
1.0, 2.0, 2.0};
float xlb[] = {0.0, 0.0, 0.0};
float xub[] = {20.0, 11.0, 42.0};
float xguess[] = {10.0, 10.0, 10.0};
float b[] = {0.0, 72.0};
bounded_least_squares
Solves a nonlinear least-squares problem subject to bounds on the variables using a
modified Levenberg-Marquardt algorithm.
Synopsis
#include <imsl.h>
float *imsl_f_bounded_least_squares (void fcn(), int m, int n,
int ibtype, float xlb[], float xub[], ..., 0)
The type double function is imsl_d_bounded_least_squares.
Required Arguments
void fcn (int m, int n, float x[], float f[]) (Input/Output)
User-supplied function to evaluate the function that defines the least-squares
problem where x is a vector of length n at which point the function is
evaluated, and f is a vector of length m containing the function values at point
x.
int m (Input)
Number of functions.
int n (Input)
Number of variables where n ≤ m.
int ibtype (Input)
Scalar indicating the types of bounds on the variables.
ibtype Action
0 User will supply all the bounds.
1 All variables are nonnegative
2 All variables are nonpositive.
3 User supplies only the bounds on 1st variable, all other
variables will have the same bounds
Return Value
A pointer to the solution x of the nonlinear least-squares problem. To release this space,
use free. If no solution can be computed, then NULL is returned.
b g = å f b xg
2 m 2
F x
2 i =1 i
å bs t g
n 2
ε1 = i i , ε 2 =|| s||2
i =1
Description
The function imsl_f_bounded_least_squares uses a modified Levenberg-
Marquardt method and an active set strategy to solve nonlinear least-squares problems
subject to simple bounds on the variables. The problem is stated as follows:
m
min
1
2
b g F b xg = 21 å f b xg
F x
T
i
2
i =1
subject to l ≤ x ≤ u
where m ≥ n, F : Rn → Rm, and fi(x) is the i-th component function of F(x). From a
given starting point, an active set IA, which contains the indices of the variables at their
bounds, is built. A variable is called a “free variable” if it is not in the active set. The
routine then computes the search direction for the free variables according to the
formula
g (xi) < 0, xi = ui
g (xi) >0, xi = li
where ε is a gradient tolerance. This process is repeated until the optimality criterion is
achieved.
The active set is changed only when a free variable hits its bounds during an iteration or
the optimality condition is met for the free variables but not for all variables in IA, the
active set. In the latter case, a variable that violates the optimality condition will be
dropped out of IA. For more detail on the Levenberg-Marquardt method, see
Examples
Example 1
In this example, the nonlinear least-squares problem
1
å f b xg
1 2
min i
2 i =0
−2 ≤ x0 ≤ 0.5
−1 ≤ x1 ≤ 2
where
f 0 ( x ) = 10( x1 − x02 ) and f 1 ( x ) = ( 1 − x0 )
is solved with an initial guess (−1.2, 1.0).
#include "imsl.h"
#include <math.h>
#define M 2
#define N 2
#define LDFJAC 2
main()
{
void rosbck(int, int, float *, float *);
int ibtype = 0;
float xlb[N] = {-2.0, -1.0};
float xub[N] = {0.5, 2.0};
float *x;
Example 2
This example solves the nonlinear least-squares problem
1
å f b xg
1 2
min i
2 i =0
−2 ≤ x0 ≤ 0.5
−1 ≤ x1 ≤ 2
where
f 0 ( x ) = 10( x1 − x02 ) and f 1 ( x ) = ( 1 − x0 )
This time, an initial guess (−1.2, 1.0) is supplied, as well as the analytic Jacobian. The
residual at the approximate solution is returned.
#include "imsl.h"
#include <math.h>
#define M 2
#define N 2
#define LDFJAC 2
main()
{
void rosbck(int, int, float *, float *);
void jacobian(int, int, float *, float *, int);
int ibtype = 0;
float xlb[N] = {-2.0, -1.0};
float xub[N] = {0.5, 2.0};
float xguess[N] = {-1.2, 1.0};
float *fvec;
float *x;
void jacobian (int m, int n, float *x, float *fjac, int fjac_col_dim)
Output
x[0] = 0.500000
x[1] = 0.250000
fvec[0] = 0.000000
fvec[1] = 0.500000
min_con_nonlin
Solves a general nonlinear programming problem using the successive quadratic
programming algorithm.
Synopsis
#include <imsl.h>
float *imsl_f_min_con_nonlin (void fcn(), int m, int meq, int n,
int ibtype, float xlb[], float xub[], …, 0)
The type double function is imsl_d_min_con_nonlin.
Required Arguments
void fcn (int m, int meq, int n, float x[], int active[], float *f, float g[])
User-supplied function to evaluate the functions at a given point where
int m (Input)
Total number of constraints.
int meq (Input)
Number of equality constraints.
int n (Input)
Number of variables.
float x[] (Input)
Array with n components at which point the function is evaluated.
int active[] (Input)
Array with mmax components indicating the active constraints, where
mmax is the maximum of (1, m).
float *f (Output)
The computed function value at the point x.
ibtype Action
0 User will supply all the bounds.
1 All variables are nonnegative.
2 All variables are nonpositive.
3 User supplies only the bounds on first
variable, all other variables will have the same
bounds.
Default: iprint = 0
IMSL_RETURN_USER, float x[] (Output)
Array with n components containing the computed solution.
Description
The function f_min_con_nonlin is based on subroutine NLPQL developed by
Schittkowski (1986). It uses a successive quadratic programming method to solve the
general nonlinear programming problem. The problem is stated as follows:
min f x
x ∈R n
bg
bg
subject to g j x = 0, for j = 1, K , me
bg
g j x ≥ 0, for j = me + 1, K , m
bx l ≤ x ≤ xu g
where all problem functions are assumed to be continuously differentiable. The method,
based on the iterative formulation and solution of quadratic programming (QP)
minn
x ∈R
1 T
2
d Bk d + ∇f x k b g T
d
b g d + g b x g = 0, for j = 1, K , m
subject to ∇g j x k
T
j k e
∇g b x g d + g b x g ≥ 0, for j = m + 1, K , m
T
j k j k e
xl − x k ≤ d ≤ xu − x k
Examples
Example 1
The problem
bg b
min F x = x1 − 2 g + b x − 1g
2
2
2
subject to g b xg = x − 2 x + 1 = 0
1 1 2
g b xg = − x / 4 − x + 1 ≥ 0
2
2
1
2
2
is solved.
#include <imsl.h>
#define M 2
#define ME 1
#define N 2
void main()
{
int ibtype = 0;
float *x;
void fcn(int, int, int, float[], int[], float*, float[]);
static float xlb[N] = {-1.0e6, -1.0e6};
static float xub[N] = {1.0e6, 1.0e6};
/* Himmelblau problem 1 */
void fcn(int m, int me, int n, float x[], int active[], float *f,
float g[])
{
float tmp1, tmp2;
if (active[0])
g[0] = x[0] - 2.0e0 * x[1] + 1.0e0;
if (active[1])
g[1] = -(x[0]*x[0]) / 4.0e0 - x[1]*x[1] + 1.0e0;
return;
}
Output
The solution is
1 2
0.8229 0.9115
Example 2
The previous example is solved with an initial guess (2.0, 2.0).
#include <imsl.h>
#define M 2
#define ME 1
#define N 2
void main()
{
int ibtype = 0;
float *x;
void fcn(int, int, int, float[], int[], float*,
float[]);
void grad(int, int, int, int, float[], int[], float,
float[], float[], float[]);
static float xguess[N] = {2.0e0, 2.0e0};
static float xlb[N] = {-1.0e6, -1.0e6};
static float xub[N] = {1.0e6, 1.0e6};
/* Himmelblau problem 1 */
void fcn(int m, int me, int n, float x[], int active[],
float *f, float g[])
if (active[0])
g[0] = x[0] - 2.0e0 * x[1] + 1.0e0;
if (active[1])
g[1] = -(x[0]*x[0]) / 4.0e0 - x[1]*x[1] + 1.0e0;
return;
}
void grad(int m, int me, int mmax, int n, float x[], int active[],
float f, float g[], float df[], float dg[])
{
if (active[0]) {
dg[0] = 1.0;
dg[1] = -2.0;
}
if (active[1]) {
dg[2] = -0.5 * x[0];
dg[3] = -2.0 * x[1];
}
return;
}
Output
The solution is
1 2
0.8229 0.9114
Warning Errors
IMSL_TOO_MANY_ITN Maximum number of iterations exceeded.
Fatal Errors
IMSL_UPHILL_DIRECTION Search direction uphill.
IMSL_TOO_MANY_LINESEARCH Line search took more than five function calls.
IMSL_NO_PROGRESS_MADE Search direction is close to zero.
IMSL_QP_INCONSISTENT The constraints for the QP subproblem are
inconsistent.
Routines
9.1 Error and Gamma Functions
Error Functions
Error function ....................................................................................... erf 437
Complementary error function ............................................................erfc 438
Inverse error function..............................................................erf_inverse 440
Inverse complementary error function .................................. erfc_inverse 441
Beta function......................................................................................beta 443
Logarithmic beta function............................................................log_beta 445
Incomplete beta function................................................ beta_incomplete 446
Gamma Functions
Gamma function .......................................................................... gamma 447
Logarithmic gamma function .................................................log_gamma 449
Incomplete gamma function ..................................... gamma_incomplete 450
Synopsis
#include <imsl.h>
float imsl_f_erf (float x)
The type double procedure is imsl_d_erf.
Required Arguments
float x (Input)
Point at which the error function is to be evaluated.
Return Value
The value of the error function erf(x).
Description
The error function erf(x) is defined to be
bg
erf x =
2
π z
0
x 2
e − t dt
main()
{
float x = 0.5;
float ans;
ans = imsl_f_erf(x);
printf("erf(%f) = %f\n", x, ans);
}
Output
erf(0.500000) = 0.520500
erfc
Evaluates the real complementary error function erfc(x).
Synopsis
#include <imsl.h>
float imsl_f_erfc (float x)
The type double procedure is imsl_d_erfc.
Required Arguments
float x (Input)
Point at which the complementary error function is to be evaluated.
Return Value
The value of the complementary error function erfc(x).
Description
The complementary error function erfc(x) is defined to be
bg
erfc x =
2
π z
x
∞ 2
e − t dt
The argument x must not be so large that the result underflows. Approximately,
x should be less than
1/ 2
e πsj
− ln
Example
Evaluate the error function at x = 1/2.
#include <imsl.h>
main()
{
float x = 0.5;
float ans;
ans = imsl_f_erfc(x);
printf("erfc(%f) = %f\n", x, ans);
}
Output
erfc(0.500000) = 0.479500
Alert Errors
IMSL_LARGE_ARG_UNDERFLOW The argument x is so large that the result
underflows.
Synopsis
#include <imsl.h>
float imsl_f_erf_inverse (float x)
The type double procedure is imsl_d_erf_inverse.
Required Arguments
float x (Input)
Point at which the inverse error function is to be evaluated. It must be between
−1 and 1.
Return Value
The value of the inverse error function erf-1 (x).
Description
The inverse error function erf-1 (x) is such that x = erf (y), where
bg
erf y = z
2 y −t 2
π 0
e dt
main()
{
float x = 0.5;
float ans;
ans = imsl_f_erf_inverse(x);
printf("inverse erf(%f) = %f\n", x, ans);
}
Output
inverse erf(0.500000) = 0.476936
Warning Errors
IMSL_LARGE_ABS_ARG_WARN The answer is less accurate than half precision
because |x| is too large.
Fatal Errors
IMSL_REAL_OUT_OF_RANGE The inverse error function is defined only for
−1 < x < 1.
erfc_inverse
Evaluates the real inverse complementary error function erfc-1 (x).
Synopsis
#include <imsl.h>
float imsl_f_erfc_inverse (float x)
The type double procedure is imsl_d_erfc_inverse.
Required Arguments
float x (Input)
Point at which the inverse complementary error function is to be evaluated.
The argument x must be in the range 0 < x < 2.
Return Value
The value of the inverse complementary error function.
Description
The inverse complementary error function y = erfc-1 (x) is such that x = erfc (y) where
bg
erfc y =
2
π z
y
∞ 2
e − t dt
Example
Evaluate the inverse complementary error function at x = 1/2.
#include <imsl.h>
main()
{
float x = 0.5;
float ans;
ans = imsl_f_erfc_inverse(x);
printf("inverse erfc(%f) = %f\n", x, ans);
}
Output
inverse erfc(0.500000) = 0.476936
Alert Errors
IMSL_LARGE_ARG_UNDERFLOW The argument x must not be so large that the result
underflows. Very approximately, x should be less
than
b g
2 − ε / 4π
Fatal Errors
IMSL_ERF_ALGORITHM The algorithm failed to converge.
IMSL_SMALL_ARG_OVERFLOW The2
computation of
e x erfc x
must not overflow.
IMSL_REAL_OUT_OF_RANGE The function is defined only for 0 < x < 2.
beta
Evaluates the real beta function β(x, y).
Synopsis
#include <imsl.h>
float imsl_f_beta (float x, float y)
The type double procedure is imsl_d_beta.
Required Arguments
float x (Input)
Point at which the beta function is to be evaluated. It must be positive.
float y (Input)
Point at which the beta function is to be evaluated. It must be positive.
Return Value
The value of the beta function β (x, y). If no result can be computed, NaN is returned.
Description
The beta function, β (x, y), is defined to be
b g ΓΓbbxxgΓ+byygg =
β x, y = z
0
1
b g
t x −1 1 − t
y −1
dt
The beta function requires that x > 0 and y > 0. It underflows for large arguments.
Example
Evaluate the beta function β (0.5, 0.2).
#include <imsl.h>
main()
{
float x = 0.5;
float y = 0.2;
float ans;
Output
beta(0.500000,0.200000) = 6.268653
Alert Errors
IMSL_BETA_UNDERFLOW The arguments must not be so large that the result
underflows.
Fatal Errors
IMSL_ZERO_ARG_OVERFLOW One of the arguments is so close to zero that the
result overflows.
Synopsis
#include <imsl.h>
float imsl_f_log_beta (float x, float y)
The type double procedure is imsl_d_log_beta.
Required Arguments
float x (Input)
Point at which the logarithm of the beta function is to be evaluated. It must be
positive.
float y (Input)
Point at which the logarithm of the beta function is to be evaluated. It must be
positive.
Return Value
The value of the logarithm of the beta function β(x, y).
Description
The beta function, β (x, y), is defined to be
b g ΓΓbbxxgΓ+byygg =
β x, y = z
0
1
b g
t x −1 1 − t
y −1
dt
Example
Evaluate the log of the beta function ln β(0.5, 0.2).
#include <imsl.h>
main()
{
float x = 0.5;
float y = 0.2;
float ans;
Warning Errors
IMSL_X_IS_TOO_CLOSE_TO_NEG_1 The result is accurate to less than one
precision because the expression −x/(x + y)
is too close to −1.
beta_incomplete
Evaluates the real incomplete beta function Ix = βx(a,b)/β(a,b).
Synopsis
#include <imsl.h>
float imsl_f_beta_incomplete (float x, float a, float b)
The type double procedure is imsl_d_beta_incomplete.
Required Arguments
float x (Input)
Point at which the incomplete beta function is to be evaluated.
float a (Input)
Point at which the incomplete beta function is to be evaluated.
float b (Input)
Point at which the incomplete beta function is to be evaluated.
Return Value
The value of the incomplete beta function.
Description
The incomplete beta function is defined to be
b g ββbbaa,b,bgg = βba1,bg
I x a ,b = x
z
0
x
b g
t a −1 1 − t
b −1
dt
The incomplete beta function requires that 0 ≤ x ≤ 1, a > 0, and b > 0. It underflows for
sufficiently small x and large a. This underflow is not reported as an error. Instead, the
value zero is returned.
bg
Γ x = z
0
∞
t x −1e − t dt
main()
{
float x = 1.5;
float ans;
ans = imsl_f_gamma(x);
printf("Gamma(%f) = %f\n", x, ans);
}
Output
Gamma(1.500000) = 0.886227
Alert Errors
IMSL_SMALL_ARG_UNDERFLOW The argument x must be large enough that Γ(x)
does not underflow. The underflow limit occurs
first for arguments close to large negative half
integers. Even though other arguments away from
these half integers may yield machine-
representable values of Γ(x), such arguments are
considered illegal. Users who need such values
should use the logΓ(x) function
imsl_f_log_gamma.
Warning Errors
IMSL_NEAR_NEG_INT_WARN The result is accurate to less than one-half
precision because x is too close to a negative
integer.
Fatal Errors
IMSL_ZERO_ARG_OVERFLOW The argument for the gamma function is too close
to zero.
IMSL_NEAR_NEG_INT_FATAL The argument for the function is too close to a
negative integer.
IMSL_LARGE_ARG_OVERFLOW The function overflows because x is too large.
IMSL_CANNOT_FIND_XMIN The algorithm used to find x$ failed. This error
should never occur.
IMSL_CANNOT_FIND_XMAX The algorithm used to find x" failed. This error
should never occur.
Synopsis
#include <imsl.h>
float imsl_f_log_gamma (float x)
The type double procedure is imsl_d_log_gamma.
Required Arguments
float x (Input)
Point at which the logarithm of the absolute value of the gamma function is to
be evaluated.
Return Value
The value of the logarithm of gamma function, log |Γ(x)|.
Description
The logarithm of the absolute value of the gamma function log |Γ(x)| is computed.
main()
{
float x = 3.5;
float ans;
ans = imsl_f_log_gamma(x);
printf("log gamma(%f) = %f\n", x, ans);
}
Output
log gamma(3.500000) = 1.200974
Warning Errors
IMSL_NEAR_NEG_INT_WARN The result is accurate to less than one-half
precision because x is too close to a negative
integer.
Fatal Errors
IMSL_NEGATIVE_INTEGER The argument for the function cannot be a
negative integer.
IMSL_NEAR_NEG_INT_FATAL The argument for the function is too close to
a negative integer.
IMSL_LARGE_ABS_ARG_OVERFLOW |x| must not be so large that the result
overflows.
gamma_incomplete
Evaluates the incomplete gamma function γ(a, x).
Synopsis
#include <imsl.h>
float imsl_f_gamma_incomplete (float a, float x)
The type double procedure is imsl_d_gamma_incomplete.
Required Arguments
float a (Input)
Parameter of the incomplete gamma function is to be evaluated. It must be
positive.
Return Value
The value of the incomplete gamma function γ(a, x).
Description
The incomplete gamma function, γ(a, x), is defined to be
b g
γ a,x = z0
x
t a −1e − t dt for x > 0
The incomplete gamma function is defined only for a > 0. Although γ(a, x) is well
defined for x > −∞, this algorithm does not calculate γ(a, x) for negative x. For large
a and sufficiently large x, γ(a, x) may overflow. γ(a, x) is bounded by Γ (a), and users
may find this bound a useful guide in determining legal values for a.
Example
Evaluate the incomplete gamma function at a = 1 and x = 3.
#include <stdio.h>
#include <imsl.h>
Output
incomplete gamma(1.000000,3.000000) = 0.950213
Fatal Errors
IMSL_NO_CONV_200_TS_TERMS The function did not converge in 200 terms of
Taylor series.
IMSL_NO_CONV_200_CF_TERMS The function did not converge in 200 terms of the
continued fraction.
bessel_J0
Evaluates the real Bessel function of the first kind of order zero J0(x).
Synopsis
#include <imsl.h>
float imsl_f_bessel_J0 (float x)
The type double procedure is imsl_d_bessel_J0.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
J0 x = z
1 π
π 0
b g
cos x sin θ dθ
Description
Because the Bessel function J0(x) is oscillatory, its computation becomes inaccurate as
|x| increases.
Example
The Bessel function J0(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_J0(x);
printf("J0(%f) = %f\n", x, ans);
}
Output
J0(1.500000) = 0.511828
Warning Errors
IMSL_LARGE_ABS_ARG_WARN |x| should be less than 1 / ε
where ε is the machine precision, to prevent the
answer from being less accurate than half
precision.
Fatal Errors
IMSL_LARGE_ABS_ARG_FATAL |x| should be less than 1/ε where ε is the machine
precision for the answer to have any precision.
Synopsis
#include <imsl.h>
float imsl_f_bessel_J1 (float x)
The type double procedure is imsl_d_bessel_J1.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
J1 x = z
1 π
π 0
b g
cos θ − x sin θ dθ
Description
Because the Bessel function J1(x) is oscillatory, its computation becomes inaccurate as
|x| increases.
Example
The Bessel function J1(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_J1(x);
printf("J1(%f) = %f\n", x, ans);
}
Output
J1(1.500000) = 0.557937
Alert Errors
IMSL_SMALL_ABS_ARG_UNDERFLOW To prevent J1(x) from underflowing, either
x must be zero, or |x| > 2s where s is the
smallest representable positive number.
Fatal Errors
IMSL_LARGE_ABS_ARG_FATAL |x| should be less than 1/ε where ε is the
machine precision for the answer to have
any precision.
bessel_Jx
Evaluates a sequence of Bessel functions of the first kind with real order and complex
arguments.
Synopsis
#include <imsl.h>
f_complex *imsl_c_bessel_Jx (float xnu, f_complex z, int n, …, 0)
The type d_complex function is imsl_z_bessel_Jx.
Required Arguments
float xnu (Input)
The lowest order desired. The argument xnu must be greater than −1/2.
f_complex z (Input)
Argument for which the sequence of Bessel functions is to be evaluated.
int n (Input)
Number of elements in the sequence.
Return Value
A pointer to the n values of the function through the series. Element i contains the value
of the Bessel function of order xnu + i for i = 0, …, n − 1.
Optional Arguments
IMSL_RETURN_USER, f_complex bessel[] (Output)
Store the sequence of Bessel functions in the user-provided array bessel[].
bg
Jν z =
π 0z
1 π
b g
cos z sin θ − νθ dθ −
π
sin νπ
π
b g
z0
∞
e z sinh t − νt dt
This function is based on the code BESSCC of Barnett (1981) and Thompson and
Barnett (1987). This code computes Jn(z) from the modified Bessel function In(z), using
the following relation, with ρ = eip/2:
RρI bz / ρg
b g |Sρ I eρ zj
ν for − π / 2 < arg z ≤ π
Yν z =
|T 3
ν
3
for − π < arg z ≤ π / 2
Example
In this example, J0.3+n-1 (1.2 + 0.5i), ν = 1, …, 4 is computed and printed.
#include <imsl.h>
main()
{
int n = 4;
int i;
float xnu = 0.3;
static f_complex z = {1.2, 0.5};
f_complex *sequence;
Output
I sub 0.30 ((1.20,0.50)) = (0.774,-0.107)
I sub 1.30 ((1.20,0.50)) = (0.400,0.159)
I sub 2.30 ((1.20,0.50)) = (0.087,0.092)
I sub 3.30 ((1.20,0.50)) = (0.008,0.024)
bessel_Y0
Evaluates the real Bessel function of the second kind of order zero Y0(x).
Synopsis
#include <imsl.h>
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
Y0 x = z
1 π
π 0
b g
sin x sin θ dθ
Description
This function is sometimes called the Neumann function, N0(x), or Weber’s function.
Since Y0(x) is complex for negative x and is undefined at x = 0, imsl_f_bessel_Y0 is
defined only for x > 0. Because the Bessel function Y0(x) is oscillatory, its computation
becomes inaccurate as x increases.
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_Y0(x);
printf("Y0(%f) = %f\n", x, ans);
}
Output
Y0(1.500000) = 0.382449
Warning Errors
IMSL_LARGE_ABS_ARG_WARN |x| should be less than 1 / ε where ε is the
machine precision to prevent the answer from
being less accurate than half precision.
Fatal Errors
IMSL_LARGE_ABS_ARG_FATAL |x| should be less than 1/ε where ε is the machine
precision for the answer to have any precision.
bessel_Y1
Evaluates the real Bessel function of the second kind of order one Y1(x).
Synopsis
#include <imsl.h>
float imsl_f_bessel_Y1 (float x)
The type double procedure is imsl_d_bessel_Y1.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
Y1 x = − z
1 π
π 0
b g
sin θ − x sin θ dθ
Example
The Bessel function Y1(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_Y1(x);
printf("Y1(%f) = %f\n", x, ans);
}
Output
Y1(1.500000) = -0.412309
Warning Errors
IMSL_LARGE_ABS_ARG_WARN |x| should be less than 1 / ε where ε is the
machine precision to prevent the answer from
being less accurate than half precision.
Fatal Errors
IMSL_SMALL_ARG_OVERFLOW The argument x must be large enough
(x > max (1/b, s) where s is the smallest
repesentable positive number and b is the largest
repesentable number) that Y1(x) does not
overflow.
IMSL_LARGE_ABS_ARG_FATAL |x| should be less than 1/ε where ε is the machine
precision for the answer to have any precision.
bessel_Yx
Evaluates a sequence of Bessel functions of the second kind with real order and
complex arguments.
Synopsis
#include <imsl.h>
f_complex *imsl_c_bessel_Yx (float xnu, f_complex z, int n, …, 0)
Required Arguments
float xnu (Input)
The lowest order desired. The argument xnu must be greater than −1/2.
f_complex z (Input)
Argument for which the sequence of Bessel functions is to be evaluated.
int n (Input)
Number of elements in the sequence.
Return Value
A pointer to the n values of the function through the series. Element i contains the value
of the Bessel function of order xnu + i for i = 0, …, n − 1.
Optional Arguments
IMSL_RETURN_USER, f_complex bessel[] (Output)
Store the sequence of Bessel functions in the user-provided array bessel[].
Description
The Bessel function Yn(z) is defined to be
bg
Yν z = z
1 π
π 0
b
sin z sin θ − νθ dθ −
π
sin νπ
g
π
b g
z
0
∞
b g
e νt + e − νt cos νt e z sinh t dt
This function is based on the code BESSCC of Barnett (1981) and Thompson and
Barnett (1987). This code computes Yn(z) from the modified Bessel functions In(z) and
Kn(z), using the following relation:
π
Yν z = e b
bg g bg bg
ν +1 πi / 2 2 − νπi / 2
Iν z − e Kν z for − π < arg z ≤
π 2
Example
In this example, Y0.3+n-1 (1.2 + 0.5i), ν = 1, …, 4 is computed and printed.
#include <imsl.h>
main()
{
Output
Y sub 0.30 ((1.20,0.50)) = (-0.013,0.380)
Y sub 1.30 ((1.20,0.50)) = (-0.716,0.338)
Y sub 2.30 ((1.20,0.50)) = (-1.048,0.795)
Y sub 3.30 ((1.20,0.50)) = (-1.625,3.684)
bessel_I0
Evaluates the real modified Bessel function of the first kind of order zero I0(x).
Synopsis
#include <imsl.h>
float imsl_f_bessel_I0 (float x)
The type double procedure is imsl_d_bessel_I0.
Required Arguments
float x (Input)
Point at which the modified Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
I0 x = z
1 π
π 0
b g
cos x cos θ dθ
Description
For large |x|, imsl_f_bessel_I0 will overflow.
Example
The Bessel function I0(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_I0(x);
printf("I0(%f) = %f\n", x, ans);
}
Output
I0(1.500000) = 1.646723
Fatal Errors
IMSL_LARGE_ABS_ARG_FATAL The absolute value of x must not be so large that
e|x| overflows.
bessel_exp_I0
Evaluates the exponentially scaled modified Bessel function of the first kind of order
zero.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the scaled Bessel function e-|x| I0(x). If no solution can be computed, NaN
is returned.
Description
The Bessel function is I0(x) is defined to be
bg
I0 x = z
1 π
π 0
b g
cos x cos θ dθ
Example
The expression e-4.5I0 (4.5) is computed directly by calling imsl_f_bessel_exp_I0
and indirectly by calling imsl_f_bessel_I0. The absolute difference is printed. For
large x, the internal scaling provided by imsl_f_bessel_exp_I0 avoids overflow
that may occur in imsl_f_bessel_I0.
#include <imsl.h>
#include <math.h>
main()
{
float x = 4.5;
float ans;
float error;
Output
(e**(-4.5))I0(4.5) = 0.194198
Error = 4.898845e-09
Synopsis
#include <imsl.h>
float imsl_f_bessel_I1 (float x)
The type double procedure is imsl_d_bessel_I1.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the Bessel function
bg
I1 x =
1
π z
0
π
e x cos θ cos θ dθ
Description
For large |x|, imsl_f_bessel_I1 will overflow. It will underflow near zero.
Example
The Bessel function I1(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_I1(x);
printf("I1(%f) = %f\n", x, ans);
}
Output
I1(1.500000) = 0.981666
Alert Errors
IMSL_SMALL_ABS_ARG_UNDERFLOW The argument should not be so close to zero
that I1(x) ≈ x/2 underflows.
bessel_exp_I1
Evaluates the exponentially scaled modified Bessel function of the first kind of order
one.
Synopsis
#include <imsl.h>
float imsl_f_bessel_exp_I1 (float x)
The type double function is imsl_d_bessel_exp_I1.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the scaled Bessel function e-|x| I1(x). If no solution can be computed, NaN
is returned.
Description
The function imsl_f_bessel_I1 underflows if |x| / 2 underflows. The Bessel function
I1(x) is defined to be
bg
I1 x =
1
π z
0
π
e x cos θ cos θ dθ
Example
The expression e-4.5I0(4.5) is computed directly by calling imsl_f_bessel_exp_I1
and indirectly by calling imsl_f_bessel_I1. The absolute difference is printed. For
large x, the internal scaling provided by imsl_f_bessel_exp_I1 avoids overflow
that may occur in imsl_f_bessel_I1.
#include <imsl.h>
#include <math.h>
main()
{
float x = 4.5;
float ans;
float error;
Output
(e**(-4.5))I1(4.5) = 0.170959
Error = 1.469216e-09
bessel_Ix
Evaluates a sequence of modified Bessel functions of the first kind with real order and
complex arguments.
Synopsis
#include <imsl.h>
f_complex *imsl_c_bessel_Ix (float xnu, f_complex z, int n, …, 0)
The type d_complex function is imsl_z_bessel_Ix.
Required Arguments
float xnu (Input)
The lowest order desired. Argument xnu must be greater than −1/2.
f_complex z (Input)
Argument for which the sequence of Bessel functions is to be evaluated.
int n (Input)
Number of elements in the sequence.
Return Value
A pointer to the n values of the function through the series. Element i contains the value
of the Bessel function of order xnu + i for i = 0, …, n − 1.
Optional Arguments
IMSL_RETURN_USER, f_complex bessel[] (Output)
Store the sequence of Bessel functions in the user-provided array bessel[].
For large arguments, z, Temme’s (1975) algorithm is used to find In(z). The In(z) values
are recurred upward (if this is stable). This involves evaluating a continued fraction. If
this evaluation fails to converge, the answer may not be accurate.
For moderate and small arguments, Miller’s method is used.
Example
In this example, J0.3+n-1 (1.2 + 0.5i), ν = 1, …, 4 is computed and printed.
#include <imsl.h>
main()
{
int n = 4;
int i;
float xnu = 0.3;
static f_complex z = {1.2, 0.5};
f_complex *sequence;
Output
I sub 0.30 ((1.20,0.50)) = (1.163,0.396)
I sub 1.30 ((1.20,0.50)) = (0.447,0.332)
I sub 2.30 ((1.20,0.50)) = (0.082,0.127)
I sub 3.30 ((1.20,0.50)) = (0.006,0.029)
bessel_K0
Evaluates the real modified Bessel function of the third kind of order zero K0(x).
Synopsis
#include <imsl.h>
float imsl_f_bessel_K0 (float x)
The type double procedure is imsl_d_bessel_K0.
Return Value
The value of the modified Bessel function
bg z ∞
b g
K0 x = cos x sin t dt
0
Description
Since K0(x) is complex for negative x and is undefined at x = 0, imsl_f_bessel_K0 is
defined only for x > 0. For large x, imsl_f_bessel_K0 will underflow.
Example
The Bessel function K0(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
Output
K0(1.500000) = 0.213806
Alert Errors
IMSL_LARGE_ARG_UNDERFLOW The argument x must not be so large that the result
(approximately equal to
b g
π / 2x e − x
underflows.
bessel_exp_K0
Evaluates the exponentially scaled modified Bessel function of the third kind of order
zero.
Synopsis
#include <imsl.h>
float imsl_f_bessel_exp_K0 (float x)
The type double function is imsl_d_bessel_exp_K0.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the scaled Bessel function exK0(x). If no solution can be computed, NaN is
returned.
Description
The argument must be greater than zero for the result to be defined. The Bessel
function K0(x) is defined to be
Example
bg z0
∞
b
K0 x = cos x sin t dt g
The expression
eK0 ( 0.5 )
main()
{
float x = 0.5;
float ans;
float error;
Output
(e**0.5)K0(0.5) = 1.524109
Error = 2.028498e-08
bessel_K1
Evaluates the real modified Bessel function of the third kind of order one K1(x).
Synopsis
#include <imsl.h>
float imsl_f_bessel_K1 (float x)
The type double procedure is imsl_d_bessel_K1.
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated. It must be positive.
Return Value
The value of the Bessel function
bg z ∞
b g
K1 x = sin x sin t sin t dt
0
Example
The Bessel function K1(1.5) is evaluated.
#include <imsl.h>
main()
{
float x = 1.5;
float ans;
ans = imsl_f_bessel_K1(x);
printf("K1(%f) = %f\n", x, ans);
}
Output
K1(1.500000) = 0.277388
Alert Errors
IMSL_LARGE_ARG_UNDERFLOW The argument x must not be so large that the
result, approximately equal to,
b g
π / 2x e − x
underflows.
Fatal Errors
IMSL_SMALL_ARG_OVERFLOW The argument x must be large enough
(x > max (1/b, s) where s is the smallest
representable positive number and b is the largest
repesentable number) that K1(x) does not
overflow.
bessel_exp_K1
Evaluates the exponentially scaled modified Bessel function of the third kind of order
one.
Synopsis
#include <imsl.h>
float imsl_f_bessel_exp_K1 (float x)
Required Arguments
float x (Input)
Point at which the Bessel function is to be evaluated.
Return Value
The value of the scaled Bessel function exK1(x). If no solution can be computed, NaN is
returned.
Description
The result
bg
imsl_ f_ bessel_ exp_ K1 = e x K1 x ≈
1
x
bg z ∞
b g
K1 x = sin x sin t sin t dt
0
Example
The expression
eK1 0.5b g
is computed directly by calling imsl_f_bessel_exp_K1 and indirectly by calling
imsl_f_bessel_K1. The absolute difference is printed. For large x, the internal
scaling provided by imsl_f_bessel_exp_K1 avoids underflow that may occur in
imsl_f_bessel_K1.
#include <imsl.h>
#include <math.h>
main()
{
float x = 0.5;
float ans;
float error;
Output
(e**0.5)K1(0.5) = 2.731010
bessel_Kx
Evaluates a sequence of modified Bessel functions of the third kind with real order and
complex arguments.
Synopsis
#include <imsl.h>
f_complex *imsl_c_bessel_Kx (float xnu, f_complex z, int n, …, 0)
The type d_complex function is imsl_z_bessel_Jx.
Required Arguments
float xnu (Input)
The lowest order desired. The argument xnu must be greater than −1/2.
f_complex z (Input)
Argument for which the sequence of Bessel functions is to be evaluated.
int n (Input)
Number of elements in the sequence.
Return Value
A pointer to the n values of the function through the series. Element i contains the value
of the Bessel function of order xnu + i for i = 0, …, n − 1.
Optional Arguments
IMSL_RETURN_USER, f_complex bessel[] (Output)
Store the sequence of Bessel functions in the user-provided array bessel[].
Description
The Bessel function Kn(z) is defined to be
π π
bg 2
bg bg
K ν z = e νπi / 2 iJ ν iz − Yν iz for − π < arg z ≤
2
This function is based on the code BESSCC of Barnett (1981) and Thompson and
Barnett (1987).
Example
In this example, K0.3+n-1 (1.2 + 0.5i), ν = 1, …, 4 is computed and printed.
#include <imsl.h>
main()
{
int n = 4;
int i;
float xnu = 0.3;
static f_complex z = {1.2, 0.5};
f_complex *sequence;
elliptic_integral_K
Evaluates the complete elliptic integral of the kind K(x).
Synopsis
#include <imsl.h>
float imsl_f_elliptic_integral_K (float x)
The type double function is imsl_d_elliptic_integral_K.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The complete elliptic integral K(x).
bg
K x = z
0
π/ 2 dθ
1 − x sin 2 θ
1/ 2
for 0 ≤ x < 1
Example
The integral K(0) is evaluated.
#include <imsl.h>
main()
{
float x = 0.0;
float ans;
x = imsl_f_elliptic_integral_K (x);
Output
K(0.0) = 1.570796
elliptic_integral_E
Evaluates the complete elliptic integral of the second kind E(x).
Synopsis
#include <imsl.h>
float imsl_f_elliptic_integral_E (float x)
The type double function is imsl_d_elliptic_integral_E.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The complete elliptic integral E(x).
bg
E x = z
0
π/ 2
1 − x sin 2 θ
1/ 2
dθ for 0 ≤ x < 1
bg b
E x = RF 0,1 − x ,1 − g x
3
b
RD 0,1 − x ,1 g
Example
The integral E(0.33) is evaluated.
#include <imsl.h>
main()
{
float x = 0.33;
float ans;
x = imsl_f_elliptic_integral_E (x);
Output
E(0.33) = 1.431832
elliptic_integral_RF
Evaluates Carlson’s elliptic integral of the first kind RF(x, y, z).
Synopsis
#include <imsl.h>
float imsl_f_elliptic_integral_RF (float x, float y, float z)
The type double function is imsl_d_elliptic_integral_RF.
Required Arguments
float x (Input)
First variable of the incomplete elliptic integral. It must be nonnegative.
float y (Input)
Second variable of the incomplete elliptic integral. It must be nonnegative.
Return Value
The complete elliptic integral RF(x, y, z)
Description
Carlson’s elliptic integral of the first kind is defined to be
zb
∞
RF b g
x, y,z =
1 dt
2
0 gb gb g
t+x t+ y t+z
1/ 2
The arguments must be nonnegative and less than or equal to b/5. In addition,
x + y, x + z, and y + z must be greater than or equal to 5s. Should any of these
conditions fail, imsl_f_elliptic_integral_RF is set to b. Here,
b = imsl_f_machine(2) is the largest and s = imsl_f_machine(1) is the smallest
representable number.
The function imsl_f_elliptic_integral_RF is based on the code by Carlson and
Notis (1981) and the work of Carlson (1979).
Example
The integral RF(0, 1, 2) is computed.
#include <imsl.h>
main()
{
float x = 0.0;
float y = 1.0;
float z = 2.0;
float ans;
Output
RF(0, 1, 2) = 1.311029
elliptic_integral_RD
Evaluates Carlson’s elliptic integral of the second kind RD(x, y, z).
Synopsis
#include <imsl.h>
Required Arguments
float x (Input)
First variable of the incomplete elliptic integral. It must be nonnegative.
float y (Input)
Second variable of the incomplete elliptic integral. It must be nonnegative.
float z (Input)
Third variable of the incomplete elliptic integral. It must be positive.
Return Value
The complete elliptic integral RD(x, y, z)
Description
Carlson’s elliptic integral of the first kind is define to be
zb
∞
RD b g
x, y,z =
3 dt
2
0 gb gb g
t+x t+ y t+z
3 1/ 2
The arguments must be nonnegative and less than or equal to 0.69(−lnε)1/9s-2/3 where
ε = imsl_f_machine(4) is the machine precision, s = imsl_f_machine(1) is the
smallest representable positive number. Furthermore, x + y and z must be greater than
max{3s2/3, 3/b2/3}, where b = imsl_f_machine(2) is the largest floating point number.
If any of these conditions are false, then imsl_f_elliptic_integral_RD returns b.
The function imsl_f_elliptic_integral_RD is based on the code by Carlson and
Notis (1981) and the work of Carlson (1979).
Example
The integral RD(0, 2, 1) is computed.
#include <imsl.h>
main()
{
float x = 0.0;
float y = 2.0;
float z = 1.0;
float ans;
elliptic_integral_RJ
Evaluates Carlson’s elliptic integral of the third kind RJ (x, y, z, ρ)
Synopsis
#include <imsl.h>
float imsl_f_elliptic_integral_RJ (float x, float y, float z, float rho)
The type double function is imsl_d_elliptic_integral_RJ.
Required Arguments
float x (Input)
First variable of the incomplete elliptic integral. It must be nonnegative.
float y (Input)
Second variable of the incomplete elliptic integral. It must be nonnegative.
float z (Input)
Third variable of the incomplete elliptic integral. It must be positive.
float rho (Input)
Fourth variable of the incomplete elliptic integral. It must be positive.
Return Value
The complete elliptic integral RJ (x, y, z, ρ)
Description
Carlson’s elliptic integral of the third kind is defined to be
zb
∞
b g
R J x , y , z ,ρ =
3 dt
2
0 gb gb gb g
t + x t + y t +z t +ρ
2 1/ 2
main()
{
float x = 2.0;
float y = 3.0;
float z = 4.0;
float rho = 5.0;
float ans;
Output
RJ(2, 3, 4, 5) = 0.142976
elliptic_integral_RC
Evaluates an elementary integral from which inverse circular functions, logarithms and
inverse hyperbolic functions can be computed.
Synopsis
#include <imsl.h>
float imsl_f_elliptic_integral_RC (float x, float y)
The type double function is imsl_d_elliptic_integral_RC.
Required Arguments
float x (Input)
First variable of the incomplete elliptic integral. It must be nonnegative and
must satisfy the conditions given below.
float y (Input)
Second variable of the incomplete elliptic integral. It must be positive and
must satisfy the conditions given below.
Return Value
The elliptic integral RC (x, y).
Description
Carlson’s elliptic integral of the third kind is defined to be
b g
RC x , y =
1 dt
2
0 gb g
t+x t+y
2 1/ 2
The argument x must be nonnegative, y must be positive, and x + y must be less than or
equal to b/5 and greater than or equal to 5s. If any of these conditions are false, the
imsl_f_elliptic_integral_RC is set to b. Here,
b = imsl_f_machine(2) is the largest and s = imsl_f_machine(1) is the smallest
representable floating-point number.
The function imsl_f_elliptic_integral_RC is based on the code by Carlson and
Notis (1981) and the work of Carlson (1979).
Example
The integral RC (2.25, 2) is computed.
#include <imsl.h>
main()
{
float x = 2.25;
float y = 2.0;
float ans;
Output
RC(2.25, 2.0) = 0.693147
fresnel_integral_C
Evaluates the cosine Fresnel integral.
Synopsis
#include <imsl.h>
float imsl_f_fresnel_integral_C (float x)
The type double function is imsl_d_fresnel_integral_C.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The cosine Fresnel integral.
z
x
π 2
C( x ) = cos( t )dt
2
0
Example
The Fresnel integral C(1.75) is evaluated.
#include <imsl.h>
main()
{
float x = 1.75;
float ans;
x = imsl_f_fresnel_integral_C (x);
Output
C(1.75) = 0.321935
fresnel_integral_S
Evaluates the sine Fresnel integral.
Synopsis
#include <imsl.h>
float imsl_f_fresnel_integral_S (float x)
The type double function is imsl_d_fresnel_integral_S.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The sine Fresnel integral.
Description
The sine Fresnel integral is defined to be
Example
The Fresnel integral S(1.75) is evaluated.
#include <imsl.h>
main()
{
float x = 1.75;
float ans;
x = imsl_f_fresnel_integral_S (x);
Output
S(1.75) = 0.499385
airy_Ai
Evaluates the Airy function.
Synopsis
#include <imsl.h>
float imsl_f_airy_Ai (float x)
The type double function is imsl_d_airy_Ai.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The Airy function evaluated at x, Ai(x).
Description
The airy function Ai(x) is defined to be
z
∞
1 1 x 2 3/ 2
Ai( x ) = cos( xt + t 3 )dt = K1/ 3 ( x )
π 3 3π 2
3
0
Example
In this example, Ai(−4.9) is evaluated.
#include <imsl.h>
main()
{
float x = -4.9;
float ans;
x = imsl_f_airy_Ai (x);
Output
Ai(-4.9) = 0.374536
airy_Bi
Evaluates the Airy function of the second kind.
Synopsis
#include <imsl.h>
float imsl_f_airy_Bi (float x)
The type double function is imsl_d_airy_Bi.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The Airy function of the second kind evaluated at x, Bi(x).
Description
The airy function Bi(x) is defined to be
It can also be expressed in terms of modified Bessel functions of the first kind, Iv(x),
and Bessel functions of the first kind Jv(x) (see bessel_Ix and bessel_Jx):
Bi( x ) =
x LM 2 2 OP
I −1/ 3 ( x 3 / 2 ) + I1/ 3 ( x 3 / 2 ) for x > 0
3 N 3 3 Q
and
Bi( x ) =
−x LM 2 2 OP
J −1/ 3 ( | x|3 / 2 ) − J1/ 3 ( | x|3 / 2 ) for x < 0
3 N 3 3 Q
Let ε = imsl_f_machine(4), the machine precision. If x < −1.31ε-2/3, then the answer
will have no precision. If x < −1.31ε-1/3, the answer will be less accurate than half
precision. In addition, x should not be so large that exp[(2/3)x3/2] overflows.
Example
In this example, Bi(−4.9) is evaluated.
#include <imsl.h>
main()
{
float x = -4.9;
float ans;
x = imsl_f_airy_Bi (x);
Output
Bi(-4.9) = -0.057747
airy_Ai_derivative
Evaluates the derivative of the Airy function.
Synopsis
#include <imsl.h>
float imsl_f_airy_Ai_derivative (float x)
The type double function is imsl_d_airy_Ai_derivative.
Return Value
The derivative of the Airy function.
Description
The airy function Ai′(x) is defined to be the derivative of the Airy function,
Ai(x). If x < −1.31ε-2/3, then the answer will have no precision. If
x < −1.31ε-1/3, the answer will be less accurate than half precision. Here
ε = imsl_f_machine(4) is the machine precision. Finally, x should be less than
x" so that the answer does not underflow. Very approximately, x" = {−1.51lns},
where s = imsl_f_machine(1), the smallest representable positive number.
Example
In this example, Ai′(−4.9) is evaluated.
#include <imsl.h>
main()
{
float x = -4.9;
float ans;
x = imsl_f_airy_Ai_derivative (x);
Output
Ai’(-4.9) = 0.146958
airy_Bi_derivative
Evaluates the derivative of the Airy function of the second kind.
Synopsis
#include <imsl.h>
float imsl_f_airy_Bi_derivative (float x)
The type double function is imsl_d_airy_Bi_derivative.
Return Value
The derivative of the Airy function of the second kind.
Description
The airy function Bi′(x) is defined to be the derivative of the Airy function of the
second kind, Bi(x). If x < −1.31ε-2/3, then the answer will have no precision. If
x < −1.31ε-1/3, the answer will be less accurate than half precision. Here
ε = imsl_f_machine(4) is the machine precision. In addition, x should not be so large
that exp[(2/3)x3/2] overflows.
Example
In this example, Bi′(−4.9) is evaluated.
#include <imsl.h>
main()
{
float x = -4.9;
float ans;
x = imsl_f_airy_Bi_derivative (x);
Output
Bi’(-4.9) = 0.827219
kelvin_ber0
Evaluates the Kelvin function of the first kind, ber, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_ber0 (float x)
The type double function is imsl_d_kelvin_ber0.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Description
The Kelvin function ber0(x) is defined to be ℜJ0(xe3pi/4). The Bessel function J0(x) is
defined
bg
J0 x =
1 π
π 0z b g
cos x sin θ dθ
Example
In this example, ber0 (0.4) is evaluated.
#include <imsl.h>
main()
{
float x = 0.4;
float ans;
x = imsl_f_kelvin_ber0 (x);
Output
ber0(0.4) = 0.999600
kelvin_bei0
Evaluates the Kelvin function of the first kind, bei, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_bei0 (float x)
The type double function is imsl_d_kelvin_bei0.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The Kelvin function of the first kind, bei, of order zero evaluated at x.
bg
J0 x =
1 π
π 0z b g
cos x sin θ dθ
Example
In this example, bei0(0.4) is evaluated.
#include <imsl.h>
main()
{
float x = 0.4;
float ans;
x = imsl_f_kelvin_bei0 (x);
Output
bei0(0.4) = 0.039998
kelvin_ker0
Evaluates the Kelvin function of the second kind, ker, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_ker0 (float x)
The type double function is imsl_d_kelvin_ker0.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The Kelvin function of the second kind, ker, of order zero evaluated at x.
bg z ∞
b
K0 x = cos x sin t dt
0
g
The function imsl_f_kelvin_ker0 is based on the work of Burgoyne (1963).
If x < 0, NaN (Not a Number) is returned. If x ≥ 119, then zero is returned.
Example
In this example, ker0(0.4) is evaluated.
#include <imsl.h>
main()
{
float x = 0.4;
float ans;
x = imsl_f_kelvin_ker0 (x);
Output
ker0(0.4) = 1.062624
kelvin_kei0
Evaluates the Kelvin function of the second kind, kei, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_kei0 (float x)
The type double function is imsl_d_kelvin_kei0.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The Kelvin function of the second kind, kei, of order zero evaluated at x.
bg z ∞
b
K0 x = cos x sin t dt
0
g
The function imsl_f_kelvin_kei0 is based on the work of Burgoyne (1963).
If x < 0, NaN (Not a Number) is returned. If x ≥ 119, zero is returned.
Example
In this example, kei0(0.4) is evaluated.
#include <imsl.h>
main()
{
float x = 0.4;
float ans;
x = imsl_f_kelvin_kei0 (x);
Output
kei0(0.4) = -0.703800
kelvin_ber0_derivative
Evaluates the derivative of the Kelvin function of the first kind, ber, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_ber0_derivative (float x)
The type double function is imsl_d_kelvin_ber0_derivative.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The derivative of the Kelvin function of the first kind, ber, of order zero evaluated at x.
Example
In this example, ber0′ (0.6) is evaluated.
#include <imsl.h>
main()
{
float x = 0.6;
float ans;
x = imsl_f_kelvin_ber0_derivative (x);
Output
ber0'(0.6) = -0.013498
kelvin_bei0_derivative
Evaluates the derivative of the Kelvin function of the first kind, bei, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_bei0_derivative (float x)
The type double function is imsl_d_kelvin_bei0_derivative.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The derivative of the Kelvin function of the first kind, bei, of order zero evaluated at x.
Example
In this example, bei0′(0.6) is evaluated.
#include <imsl.h>
main()
{
float x = 0.6;
float ans;
x = imsl_f_kelvin_bei0_derivative (x);
Output
bei0’(0.6) = 0.299798
kelvin_ker0_derivative
Evaluates the derivative of the Kelvin function of the second kind, ker, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_ker0_derivative (float x)
The type double function is imsl_d_kelvin_ker0_derivative.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The derivative of the Kelvin function of the second kind, ker, of order zero evaluated at
x.
Example
In this example, ker0′(0.6) is evaluated.
#include <imsl.h>
main()
{
float x = 0.6;
float ans;
x = imsl_f_kelvin_ker0_derivative (x);
Output
ker0’(0.6) = -1.456538
kelvin_kei0_derivative
Evaluates the derivative of the Kelvin function of the second kind, kei, of order zero.
Synopsis
#include <imsl.h>
float imsl_f_kelvin_kei0_derivative (float x)
The type double function is imsl_d_kelvin_kei0_derivative.
Required Arguments
float x (Input)
Argument for which the function value is desired.
Return Value
The derivative of the Kelvin function of the second kind, kei, of order zero evaluated
at x.
Example
In this example, kei0′(0.6) is evaluated.
#include <imsl.h>
main()
{
float x = 0.6;
float ans;
x = imsl_f_kelvin_kei0_derivative (x);
Output
kei0’(0.6) = 0.348164
normal_cdf
Evaluates the standard normal (Gaussian) distribution function.
Synopsis
#include <imsl.h>
float imsl_f_normal_cdf (float x)
The type double function is imsl_d_normal_cdf.
Required Arguments
float x (Input)
Point at which the normal distribution function is to be evaluated.
Return Value
The probability that a normal random variable takes a value less than or equal to x.
bg
Φ x =
1
2π z
−∞
x
e−t
2
/2
dt
The value of the distribution function at the point x is the probability that the random
variable takes a value less than or equal to x.
The standard normal distribution (for which imsl_f_normal_cdf is the distribution
function) has mean of 0 and variance of 1. The probability that a normal random
variable with mean µ and variance σ2 is less than y is given by imsl_f_normal_cdf
evaluated at (y − µ)/σ.
Φ(x) is evaluated by use of the complementary error function, imsl_f_erfc. The
relationship is:
bg e
Φ x = erfc − x / 2.0 / 2 j
Example
Suppose X is a normal random variable with mean 100 and variance 225. This example
finds the probability that X is less than 90 and the probability that X is between 105 and
110.
#include <imsl.h>
main()
{
float p, x1, x2;
x1 = (105.0-100.0)/15.0;
x2 = (110.0-100.0)/15.0;
p = imsl_f_normal_cdf(x2) - imsl_f_normal_cdf(x1);
printf("The probability that X is between 105 and 110 is %6.4f\n", p);
}
Output
The probability that X is less than 90 is 0.2525
normal_inverse_cdf
Evaluates the inverse of the standard normal (Gaussian) distribution function.
Synopsis
#include <imsl.h>
float imsl_f_normal_inverse_cdf (float p)
The type double procedure is imsl_d_normal_inverse_cdf.
Required Arguments
float p (Input)
Probability for which the inverse of the normal distribution function is to be
evaluated. The argument p must be in the open interval (0.0, 1.0).
Return Value
The inverse of the normal distribution function evaluated at p. The probability that a
standard normal random variable takes a value less than or equal to
imsl_f_normal_inverse_cdf is p.
Description
The function imsl_f_normal_inverse_cdf evaluates the inverse of the distribution
function, Φ, of a standard normal (Gaussian) random variable; that is,
imsl_f_normal_inverse_cdf(p) = Φ-1 (p) where
bg
Φ x =
1
2π z
−∞
x
e−t
2
/2
dt
The value of the distribution function at the point x is the probability that the random
variable takes a value less than or equal to x. The standard normal distribution has a
mean of 0 and a variance of 1.
Example
This example computes the point such that the probability is 0.9 that a standard normal
random variable is less than or equal to this point.
#include <imsl.h>
main()
{
float x;
float p = 0.9;
x = imsl_f_normal_inverse_cdf(p);
printf("The 90th percentile of a standard normal is %6.4f.\n", x);
}
Output
The 90th percentile of a standard normal is 1.2816.
chi_squared_cdf
Evaluates the chi-squared distribution function.
Synopsis
#include <imsl.h>
float imsl_f_chi_squared_cdf (float chi_squared, float df)
The type double function is imsl_d_chi_squared_cdf.
Required Arguments
float chi_squared (Input)
Argument for which the chi-squared distribution function is to be evaluated.
float df (Input)
Number of degrees of freedom of the chi-squared distribution. The argument
df must be greater than or equal to 0.5.
Return Value
The probability that a chi-squared random variable takes a value less than or equal to
chi_squared.
bg gz
1 x
F x = e − t / 2 t ν / 2 −1dt
2 ν/ 2
b
Γ ν/ 2 0
where Γ(⋅) is the gamma function. The value of the distribution function at the point x is
the probability that the random variable takes a value less than or equal to x.
For ν > 65, imsl_f_chi_squared_cdf uses the Wilson-Hilferty approximation
(Abramowitz and Stegun 1964, Equation 26.4.17) to the normal distribution, and
function imsl_f_normal_cdf is used to evaluate the normal distribution function.
For ν ≤ 65, imsl_f_chi_squared_cdf uses series expansions to evaluate the
distribution function. If x < max (ν/2, 26), imsl_f_chi_squared_cdf uses the series
6.5.29 in Abramowitz and Stegun (1964); otherwise, it uses the asymptotic expansion
6.5.32 in Abramowitz and Stegun.
Example
Suppose X is a chi-squared random variable with 2 degrees of freedom. This example
finds the probability that X is less than 0.15 and the probability that X is greater than
3.0.
#include <imsl.h>
void main()
{
float chi_squared = 0.15;
float df = 2.0;
float p;
p = imsl_f_chi_squared_cdf(chi_squared, df);
printf("%s %s %6.4f\n", "The probability that chi-squared",
"with 2 df is less than 0.15 is", p);
chi_squared = 3.0;
p = 1.0 - imsl_f_chi_squared_cdf(chi_squared, df);
printf("%s %s %6.4f\n", "The probability that chi-squared",
"with 2 df is greater than 3.0 is", p);
}
Output
The probability that chi-squared with 2 df is less than 0.15 is 0.0723
The probability that chi-squared with 2 df is greater than 3.0 is 0.2231
Informational Errors
IMSL_ARG_LESS_THAN_ZERO The input argument, chi_squared, is less than
zero.
chi_squared_inverse_cdf
Evaluates the inverse of the chi-squared distribution function.
Synopsis
#include <imsl.h>
float imsl_f_chi_squared_inverse_cdf (float p, float df)
The type double function is imsl_d_chi_squared_inverse_cdf.
Required Arguments
float p (Input)
Probability for which the inverse of the chi-squared distribution function is to
be evaluated. The argument p must be in the open interval (0.0, 1.0).
float df (Input)
Number of degrees of freedom of the chi-squared distribution. The argument
df must be greater than or equal to 0.5.
Return Value
The inverse of the chi-squared distribution function evaluated at p. The probability that
a chi-squared random variable takes a value less than or equal to
imsl_f_chi_squared_inverse_cdf is p.
Description
The function imsl_f_chi_squared_inverse_cdf evaluates the inverse distribution
function of a chi-squared random variable with ν = df and with probability p. That is, it
determines x = imsl_f_chi_squared_inverse_cdf(p,df) such that
gz
1 x
p= e − t / 2 t ν / 2 −1dt
2 ν/ 2
b
Γ ν/ 2 0
where Γ(⋅) is the gamma function. The probability that the random variable takes a
value less than or equal to x is p.
For ν < 40, imsl_f_chi_squared_inverse_cdf uses bisection (if ν ≤ 2 or
p > 0.98) or regula falsi to find the point at which the chi-squared distribution function
is equal to p. The distribution function is evaluated using function
imsl_f_chi_squared_cdf.
For 40 ≤ ν < 100, a modified Wilson-Hilferty approximation (Abramowitz and Stegun
1964, equation 26.4.18) to the normal distribution is used. The function
Example
In this example, the 99-th percentage point is calculated for a chi-squared random
variable with two degrees of freedom. The same calculation is made for a similar
variable with 64 degrees of freedom.
#include <imsl.h>
void main ()
{
float df, x;
float p = 0.99;
df = 2.0;
x = imsl_f_chi_squared_inverse_cdf(p, df);
printf("For p = .99 with 2 df, x = %7.3f.\n", x);
df = 64.0;
x = imsl_f_chi_squared_inverse_cdf(p,df);
printf("For p = .99 with 64 df, x = %7.3f.\n", x);
}
Output
For p = .99 with 2 df, x = 9.210.
For p = .99 with 64 df, x = 93.217.
Warning Errors
IMSL_UNABLE_TO_BRACKET_VALUE The bounds that enclose p could not be
found. An approximation for
imsl_f_chi_squared_inverse_cdf is
returned.
IMSL_CHI_2_INV_CDF_CONVERGENCE The value of the inverse chi-squared could
not be found within a specified number of
iterations. An approximation for
imsl_f_chi_squared_inverse_cdf is
returned.
F_cdf
Evaluates the F distribution function.
Synopsis
#include <imsl.h>
float imsl_f_F_cdf (float f, float df_denominator, float df_numerator)
Required Arguments
float f (Input)
Point at which the F distribution function is to be evaluated.
float df_numerator (Input)
The numerator degrees of freedom. The argument df_numerator must be
positive.
float df_denominator (Input)
The denominator degrees of freedom. The argument df_denominator must
be positive.
Return Value
The probability that an F random variable takes a value less than or equal to the input
point, f.
Description
The function imsl_f_F_cdf evaluates the distribution function of a Snedecor’s F
random variable with df_numerator and df_denominator. The function is
evaluated by making a transformation to a beta random variable and then by evaluating
the incomplete beta function. If X is an F variate with ν1 and ν2 degrees of freedom and
Y = (ν1 X)/(ν2 + ν1 X), then Y is a beta variate with parameters p = ν1/2 and q = ν2/2.
The function imsl_f_F_cdf also uses a relationship between F random variables that
can be expressed as follows:
FF(f, ν1, ν2 ) = 1 − FF(1/f, ν2, ν1 )where FF is the distribution function for an F random
variable.
Example
This example finds the probability that an F random variable with one numerator and
one denominator degree of freedom is greater than 648.
#include <imsl.h>
main()
{
float p;
float F = 648.0;
float df_numerator = 1.0;
float df_denominator = 1.0;
Output
The probability that an F(1,1) variate is greater than 648 is 0.0250.
Synopsis
#include <imsl.h>
float imsl_f_F_inverse_cdf (float p, float df_numerator,
float df_denominator)
The type double procedure is imsl_d_F_inverse_cdf.
Required Arguments
float p (Input)
Probability for which the inverse of the F distribution function is to be
evaluated. The argument p must be in the open interval (0.0, 1.0).
float df_numerator (Input)
Numerator degrees of freedom. Argument df_numerator must be positive.
float df_denominator (Input)
Denominator degrees of freedom. Argument df_denominator must be
positive.
Return Value
The value of the inverse of the F distribution function evaluated at p. The probability
that an F random variable takes a value less than or equal to imsl_f_F_inverse_cdf
is p.
Description
The function imsl_f_F_inverse_cdf evaluates the inverse distribution function of a
Snedecor’s F random variable with ν1 = df_numerator numerator degrees of freedom
and ν2 = df_denominator denominator degrees of freedom. The function is
evaluated by making a transformation to a beta random variable and then by evaluating
the inverse of an incomplete beta function. If X is an F variate with ν1 and ν2 degrees of
freedom and Y = (ν1, X)/(ν2 + ν1 X), then Y is a beta variate with parameters p = ν1/2
and q = ν2/2. If P ≤ 0.5, imsl_f_F_inverse_cdf uses this relationship directly;
otherwise, it also uses a relationship between F random variables that can be expressed
as follows:
Example
In this example, the 99-th percentage point is calculated for an F random variable with
seven degrees of freedom. The same calculation is made for a similar variable with one
degree of freedom.
main()
{
float df_denominator = 1.0;
float df_numerator = 7.0;
float f;
float p = 0.99;
Output
The F(7,1) 0.01 critical value is 5928.370
Fatal Errors
IMSL_F_INVERSE_OVERFLOW Function imsl_f_F_inverse_cdf is set to
machine infinity since overflow would occur upon
modifying the inverse value for the F distribution
with the result obtained from the inverse beta
distribution.
t_cdf
Evaluates the Student’s t distribution function.
Synopsis
#include <imsl.h>
float imsl_f_t_cdf (float t, float df)
The type double function is imsl_d_t_cdf.
Required Arguments
float t (Input)
Argument for which the Student’s t distribution function is to be evaluated.
float df (Input)
Degrees of freedom. Argument df must be greater than or equal to 1.0.
Return Value
The probability that a Student’s t random variable takes a value less than or equal to the
input t.
main ()
{
float p;
float t = 2.447;
float df = 6.0;
p = 2.0*imsl_f_t_cdf(-t,df);
printf("Pr(|t(6)| > 2.447) = %6.4f\n", p);
}
Output
Pr(|t(6)| > 2.447) = 0.0500
Required Arguments
float p (Input)
Probability for which the inverse of the Student’s t distribution function is to
be evaluated. Argument p must be in the open interval (0.0, 1.0).
float df (Input)
Degrees of freedom. Argument df must be greater than or equal to 1.0.
Return Value
The inverse of the Student’s t distribution function evaluated at p. The probability that
a Student’s t random variable takes a value less than or equal to
imsl_f_t_inverse_cdf is p.
Description
The function imsl_f_t_inverse_cdf evaluates the inverse distribution function of a
Student’s t random variable with ν = df degrees of freedom. If ν equals 1 or 2, the
inverse can be obtained in closed form. If ν is between 1 and 2, the relationship of a t to
a beta random variable is exploited, and the inverse of the beta distribution is used to
evaluate the inverse; otherwise, the algorithm of Hill (1970) is used. For small values of
ν greater than 2, Hill’s algorithm inverts an integrated expansion in 1/(1 + t2/ν) of the
t density. For larger values, an asymptotic inverse Cornish-Fisher type expansion about
normal deviates is used.
Example
This example finds the 0.05 critical value for a two-sided t test with six degrees of
freedom.
#include <imsl.h>
void main()
{
float df = 6.0;
float p = 0.975;
float t;
t = imsl_f_t_inverse_cdf(p,df);
Informational Errors
IMSL_OVERFLOW Function imsl_f_t_inverse_cdf is set to machine
infinity since overflow would occur upon modifying
the inverse value for the F distribution with the result
obtained from the inverse beta distribution.
gamma_cdf
Evaluates the gamma distribution function.
Synopsis
#include <imsl.h>
float imsl_f_gamma_cdf (float x, float a)
The type double procedure is imsl_d_gamma_cdf.
Required Arguments
float x (Input)
Argument for which the gamma distribution function is to be evaluated.
float a (Input)
The shape parameter of the gamma distribution. This parameter must be
positive.
Return Value
The probability that a gamma random variable takes a value less than or equal to x.
Description
The function imsl_f_gamma_cdf evaluates the distribution function, F, of a gamma
random variable with shape parameter a, that is,
b g Γb1ag
F x = z0
x
e − t t a −1dt
where Γ(⋅) is the gamma function. (The gamma function is the integral from zero to
infinity of the same integrand as above). The value of the distribution function at the
point x is the probability that the random variable takes a value less than or equal to x.
The gamma distribution is often defined as a two-parameter distribution with a scale
parameter b (which must be positive) or even as a three-parameter distribution in which
the third parameter c is a location parameter.
bg
f t =
1
e b g
− t −c / b
b x − cg a −1
a
b Γa bg
If T is such a random variable with parameters a, b, and c, the probability that
T ≤ t0 can be obtained from imsl_f_gamma_cdf by setting x = (t0 − c)/b.
If x is less than a or if x is less than or equal to 1.0, imsl_f_gamma_cdf uses a series
expansion. Otherwise, a continued fraction expansion is used. (See Abramowitz and
Stegun 1964.)
Example
Let X be a gamma random variable with a shape parameter of four. (In this case, it has
an Erlang distribution since the shape parameter is an integer.) This example finds the
probability that X is less than 0.5 and the probability that X is between 0.5 and 1.0.
#include <imsl.h>
main()
{
float p, x;
float a = 4.0;
x = 0.5;
p = imsl_f_gamma_cdf(x,a);
printf("The probability that X is less than 0.5 is %6.4f\n", p);
x = 1.0;
p = imsl_f_gamma_cdf(x,a) - p;
printf("The probability that X is between 0.5 and 1.0 is %6.4f\n", p);
}
Output
The probability that X is less than 0.5 is 0.0018
The probability that X is between 0.5 and 1.0 is 0.0172
Informational Errors
IMSL_LESS_THAN_ZERO The input argument, x, is less than zero.
Fatal Errors
IMSL_X_AND_A_TOO_LARGE The function overflows because x and a are too
large.
Synopsis
#include <imsl.h>
float imsl_f_binomial_cdf (int k, int n, float p)
The type double procedure is imsl_d_binomial_cdf.
Required Arguments
int k (Input)
Argument for which the binomial distribution function is to be evaluated.
int n (Input)
Number of Bernoulli trials.
float p (Input)
Probability of success on each trial.
Return Value
The probability that k or fewer successes occur in n independent Bernoulli trials, each
of which has a probability p of success.
Description
The function imsl_f_binomial_cdf evaluates the distribution function of a binomial
random variable with parameters n and p. It does this by summing probabilities of the
random variable taking on the specific values in its range. These probabilities are
computed by the recursive relationship
b
Pr X = j =g bn j+b11−− pjgg p Prb X = j − 1g
To avoid the possibility of underflow, the probabilities are computed forward from zero
if k is not greater than n × p; otherwise, they are computed backward from n. The
smallest positive machine number, ε, is used as the starting value for summing the
probabilities, which are rescaled by (1 − p)n ε if forward computation is performed and
by pnε if backward computation is done.
For the special case of p is zero, imsl_f_binomial_cdf is set to 1; and for the case
p is 1, imsl_f_binomial_cdf is set to 1 if k = n and is set to zero otherwise.
Example
Suppose X is a binomial random variable with an n = 5 and a p = 0.95. This example
finds the probability that X is less than or equal to three.
void main()
{
int k = 3;
int n = 5;
float p = 0.95;
float pr;
pr = imsl_f_binomial_cdf(k,n,p);
printf("Pr(x <= 3) = %6.4f\n", pr);
}
Output
Pr(x <= 3) = 0.0226
Informational Errors
IMSL_LESS_THAN_ZERO The input argument, k, is less than zero.
IMSL_GREATER_THAN_N The input argument, k, is greater than the number of
Bernoulli trials, n.
hypergeometric_cdf
Evaluates the hypergeometric distribution function.
Synopsis
#include <imsl.h>
float imsl_f_hypergeometric_cdf (int k, int n, int m, int l)
The type double procedure is imsl_d_hypergeometric_cdf.
Required Arguments
int k (Input)
Argument for which the hypergeometric distribution function is to be
evaluated.
int n (Input)
Sample size n must be greater than or equal to k.
int m (Input)
Number of defectives in the lot.
int l (Input)
Lot size l must be greater than or equal to n and m.
Return Value
The probability that k or fewer defectives occur in a sample of size n drawn from a lot
of size l that contains m defectives.
Pr b x = j g =
e je j
m
j
l −m
n− j
b g
for j = i ,i + 1, K , min n ,m
ejl
n
Example
Suppose X is a hypergeometric random variable with n = 100, l = 1000, and m = 70.
This example evaluates the distribution function at 7.
#include <imsl.h>
void main()
{
int k = 7;
int l = 1000;
int m = 70;
int n = 100;
float p;
p = imsl_f_hypergeometric_cdf(k,n,m,l);
printf("\nPr (x <= 7) = %6.4f", p);
}
Output
Pr (x <= 7) = 0.599
Informational Errors
IMSL_LESS_THAN_ZERO The input argument, k, is less than zero.
IMSL_K_GREATER_THAN_N The input argument, k, is greater than the sample
size.
Fatal Errors
IMSL_LOT_SIZE_TOO_SMALL Lot size must be greater than or equal to n and m.
Synopsis
#include <imsl.h>
float imsl_f_poisson_cdf (int k, float theta)
The type double function is imsl_d_poisson_cdf.
Required Arguments
int k (Input)
Argument for which the Poisson distribution function is to be evaluated.
float theta (Input)
Mean of the Poisson distribution. Argument theta must be positive.
Return Value
The probability that a Poisson random variable takes a value less than or equal to k.
Description
The function imsl_f_poisson_cdf evaluates the distribution function of a Poisson
random variable with parameter theta. The mean of the Poisson random variable,
theta, must be positive. The probability function (with θ = theta) is
Example
Suppose X is a Poisson random variable with θ = 10. This example evaluates the
probability that X ≤ 7.
#include <imsl.h>
void main()
{
int k = 7;
float theta = 10.0;
float p;
p = imsl_f_poisson_cdf(k, theta);
printf("Pr(x <= 7) = %6.4f\n", p);
}
Output
Pr(x <= 7) = 0.2202
Informational Errors
IMSL_LESS_THAN_ZERO The input argument, k, is less than zero.
beta_cdf
Evaluates the beta probability distribution function.
Synopsis
#include <imsl.h>
float imsl_f_beta_cdf (float x, float pin, float qin)
The type double function is imsl_d_beta_cdf.
Return Value
The probability that a beta random variable takes on a value less than or equal to x.
Description
Function imsl_f_beta_cdf evaluates the distribution function of a beta random
variable with parameters pin and qin. This function is sometimes called the
incomplete beta ratio and with p = pin and q = qin, is denoted by Ix (p, q). It is given
by
b g ΓΓbbppgΓ+bqqgg
I x p,q = z
0
x
b g
t p −1 1 − t
q −1
dt
where Γ(⋅) is the gamma function. The value of the distribution function by Ix (p, q) is
the probability that the random variable takes a value less than or equal to x.
The integral in the expression above is called the incomplete beta function and is
denoted by βx (p, q). The constant in the expression is the reciprocal of the beta
function (the incomplete function evaluated at one) and is denoted by β(p, q).
Function beta_cdf uses the method of Bosten and Battiste (1974).
Example
Suppose X is a beta random variable with parameters 12 and 12. (X has a symmetric
distribution.) This example finds the probability that X is less than 0.6 and the
probability that X is between 0.5 and 0.6. (Since X is a symmetric beta random variable,
the probability that it is less than 0.5 is 0.5.)
#include <imsl.h>
main()
{
float p, pin, qin, x;
pin = 12.0;
qin = 12.0;
x = 0.6;
p = imsl_f_beta_cdf(x, pin, qin);
printf(" The probability that X is less than 0.6 is %6.4f\n",
p);
Output
The probability that X is less than 0.6 is 0.8364
The probability that X is between 0.5 and 0.6 is 0.3364
beta_inverse_cdf
Evaluates the inverse of the beta distribution function.
Synopsis
#include <imsl.h>
float imsl_f_beta_inverse_cdf (float p, float pin, float qin)
The type double function is imsl_d_beta_inverse_cdf.
Required Arguments
float p (Input)
Probability for which the inverse of the beta distribution function is to be
evaluated. Argument p must be in the open interval (0.0 ,1.0).
float pin (Input)
First beta distribution parameter. Argument pin must be positive.
float qin (Input)
Second beta distribution parameter. Argument qin must be positive.
Return Value
Function imsl_f_beta_inverse_cdf evaluates the inverse distribution function of a
beta random variable with parameters pin and qin.
Description
With P = p, p = pin, and q = qin, function imsl_f_beta_inverse_cdf returns x such
that
P=
bgbg
Γ pΓq
Γb p + qg z
0
x
b g
t p −1 1 − t
q −1
dt
where Γ(⋅) is the gamma function. The probability that the random variable takes a
value less than or equal to x is P.
main()
{
float p, pin, qin, x;
pin = 12.0;
qin = 12.0;
p = 0.9;
x = imsl_f_beta_inverse_cdf(p, pin, qin);
printf(" X is less than %6.4f with probability 0.9.\n",
x);
}
Output
X is less than 0.6299 with probability 0.9.
bivariate_normal_cdf
Evaluates the bivariate normal distribution function.
Synopsis
#include <imsl.h>
float imsl_f_bivariate_normal_cdf (float x, float y, float rho)
The type double function is imsl_d_bivariate_normal_cdf.
Required Arguments
float x (Input)
The x-coordinate of the point for which the bivariate normal distribution
function is to be evaluated.
float y (Input)
The y-coordinate of the point for which the bivariate normal distribution
function is to be evaluated.
float rho (Input)
Correlation coefficient.
Return Value
The probability that a bivariate normal random variable with correlation rho takes a
value less than or equal to x and less than or equal to y.
This example finds the probability that X is less than −2.0 and Y is less than 0.0.
#include <imsl.h>
main()
{
float p, rho, x, y;
x = -2.0;
y = 0.0;
rho = 0.9;
p = imsl_f_bivariate_normal_cdf(x, y, rho);
printf(" The probability that X is less than -2.0"
" and Y is less than 0.0 is %6.4f\n", p);
Output
The probability that X is less than -2.0 and Y is less than 0.0 is 0.0228
Routines
10.1 Statistics
Univariate summary statistics ........................................ simple_statistics 521
One-way frequency table....................................................table_oneway 526
Chi-squared one-sample goodness-of-fit test............... chi_squared_test 530
Correlation ............................................................................ covariances 538
Multiple linear regression.........................................................regression 543
Polynomial regression..................................................... poly_regression 551
Numerical ranking............................................................................ranks 559
Usage Notes
Statistics
The functions in this section can be used to compute some common univariate summary
statistics, perform a one-sample goodness-of-fit test, produce measures of correlation,
perform multiple and polynomial regression analysis, and compute ranks
(or a transformation of the ranks, such as normal or exponential scores). The user is
referred to the individual functions for additional information.
Each xi is then scaled into the unit interval (0,1). If the multiplier, c, is a primitive root
modulo 231 − 1 (which is a prime), then the generator will have a maximal period of
231 − 2. There are several other considerations, however. See Knuth (1981) for a good
general discussion. The possible values for c in the IMSL generators are 16807,
397204094, and 950706376. The selection is made by the function
imsl_random_ option. The choice of 16807 will result in the fastest execution time,
but other evidence suggests that the performance of 950706376 is best among these three
choices (Fishman and Moore 1982). If no selection is made explicitly, the functions use
the multiplier 16807, which has been in use for some time (Lewis et al. 1969).
The generation of uniform (0,1) numbers is done by the function
imsl_f_random_uniform. This function is portable in the sense that, given the same
seed, it produces the same sequence in all computer/compiler environments.
Shuffled Generators
The user also can select a shuffled version of these generators using
imsl_random_option. The shuffled generators use a scheme due to Learmonth and
Lewis (1973). In this scheme, a table is filled with the first 128 uniform (0,1) numbers
resulting from the simple multiplicative congruential generator. Then, for each xi from
the simple generator, the low-order bits of xi are used to select a random integer, j, from
simple_statistics
Computes basic univariate statistics.
Synopsis
#include <imsl.h>
float *imsl_f_simple_statistics (int n_observations, int n_variables,
float x[] ,…, 0)
The type double procedure is imsl_d_simple_statistics.
Required Arguments
int n_observations (Input)
The number of observations.
int n_variables (Input)
The number of variables.
float x[] (Input)
Array of size n_observations × n_variables containing the data matrix.
Return Value
A pointer to a matrix containing some simple statistics for each of the columns in x. If
MEDIAN and MEDIAN_AND_SCALE are not used as optional arguments, the size of the
matrix is 14 by n_variables. The columns of this matrix correspond to the columns
of x and the rows contain the following statistics:
Optional Arguments
IMSL_CONFIDENCE_MEANS, float confidence_means (Input)
The confidence level for a two-sided interval estimate of the means (assuming
normality) in percent. Argument confidence_means must be between 0.0
and 100.0 and is often 90.0, 95.0, or 99.0. For a one-sided confidence interval
with confidence level c, set confidence_means = 100.0 − 2(100 − c). If
Description
For the data in each column of x, imsl_f_simple_statistics computes the sample
mean, variance, minimum, maximum, and other basic statistics. It also computes
confidence intervals for the mean and variance (under the hypothesis that the sample is
from a normal population).
The definitions of some of the statistics are given below in terms of a single variable
x of which the i-th datum is xi.
x=
åx i
Variance
å bx − xg
2
2 i
s =
n −1
Skewness
å bx − xg / n
3
i
[ å bx − xg / n ]
2 3/ 2
i
Excess or Kurtosis
å bx − xg / n
4
i
−3
[ å bx − xg / n ]
2 2
i
Minimum
xmin = min xi b g
Maximum
xmax = max xi b g
Range
xmax − xmin
Coefficient of Variation
s / x for x ≠ 0
Median
l q RSTaverage
median xi =
middle x after sorting if n is odd
i
of middle two x 's if n is even i
{
MAD = median xi − median x j n s}
Simple Robust Estimate of Scale
b g
MAD / Φ −1 3 / 4
where Φ-1(3/4) ≈ 0.6745 is the inverse of the standard normal distribution function
evaluated at 3/4. This standardizes MAD in order to make the scale estimate consistent at
the normal distribution for estimating the standard deviation (Huber 1981, pp. 107−108).
Example
This example uses data from Draper and Smith (1981). There are five variables and 13
observations.
#include <imsl.h>
#define N_VARIABLES 5
#define N_OBSERVATIONS 13
main()
{
float *simple_statistics;
float x[] = {7., 26., 6., 60., 78.5,
1., 29., 15., 52., 74.3,
11., 56., 8., 20., 104.3,
11., 31., 8., 47., 87.6,
7., 52., 6., 33., 95.9,
11., 55., 9., 22., 109.2,
3., 71., 17., 6., 102.7,
1., 31., 22., 44., 72.5,
2., 54., 18., 22., 93.1,
21., 47., 4., 26., 115.9,
1., 40., 23., 34., 83.8,
11., 66., 9., 12., 113.3,
10., 68., 8., 12., 109.4};
char *row_labels[] = {"means", "variances", "std. dev",
"skewness", "kurtosis", "minima",
"maxima", "ranges", "C.V.", "counts",
"lower mean", "upper mean",
"lower var", "upper var"};
simple_statistics = imsl_f_simple_statistics(N_OBSERVATIONS,
N_VARIABLES, x, 0);
1 2 3 4 5
means 7.462 48.154 11.769 30.000 95.423
variances 34.603 242.141 41.026 280.167 226.314
std. dev 5.882 15.561 6.405 16.738 15.044
skewness 0.688 -0.047 0.611 0.330 -0.195
kurtosis 0.075 -1.323 -1.079 -1.014 -1.342
minima 1.000 26.000 4.000 6.000 72.500
maxima 21.000 71.000 23.000 60.000 115.900
ranges 20.000 45.000 19.000 54.000 43.400
C.V. 0.788 0.323 0.544 0.558 0.158
counts 13.000 13.000 13.000 13.000 13.000
lower mean 3.907 38.750 7.899 19.885 86.332
upper mean 11.016 57.557 15.640 40.115 104.514
lower var 17.793 124.512 21.096 144.065 116.373
upper var 94.289 659.817 111.792 763.434 616.688
table_oneway
Tallies observations into a one-way frequency table.
Synopsis
#include <imsl.h>
float *imsl_f_table_oneway (int n_observations, float x[],
int _intervals, …, 0)
The type double function is imsl_d_table_oneway.
Required Arguments
int n_observations (Input)
Number of observations.
float x[] (Input)
Array of length n_observations containing the observations.
int n_intervals (Input)
Number of intervals (bins).
Return Value
Pointer to an array of length n_intervals containing the counts.
and are open on the left and closed on the right. Argument n_intervals
must be greater than or equal to three for this option. If IMSL_CLASS_MARKS
is specified, equally spaced class marks in ascending order must be provided
in the array class_marks of length n_intervals. The class marks are the
midpoints of each of the n_intervals, and each interval is taken to have
length class_marks[1] − class_marks[0]. The argument n_intervals
must be greater than or equal to two for this option. If
IMSL_ CUTPOINTS is specified, cutpoints (boundaries) must be provided in
the array cutpoints of length n_intervals − 1. This option allows unequal
interval lengths. The initial interval is closed on the right and includes the
initial cutpoint as its right endpoint. The last interval is open on the left and
includes all values greater than the last cutpoint. The remaining n_intervals
− 2 intervals are open on the left and closed on the right. The argument
n_interval must be greater than or equal to three for this option.
Examples
Example 1
The data for this example is from Hinkley (1977) and Velleman and Hoaglin (1981).
They are the measurements (in inches) of precipitation in Minneapolis/St. Paul during
the month of March for 30 consecutive years.
#include <imsl.h>
main()
{
int n_intervals=10;
int n_observations=30;
float *table;
float x[] = {0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43, 3.37,
2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62, 1.31, 0.32,
0.59, 0.81, 2.81, 1.87, 1.18, 1.35, 4.75, 2.48, 0.96,
1.89, 0.90, 2.05};
table = imsl_f_table_oneway (n_observations, x, n_intervals, 0);
imsl_f_write_matrix("counts", 1, n_intervals, table, 0);
}
Output
counts
1 2 3 4 5 6
4 8 5 5 3 1
7 8 9 10
3 0 0 1
Example 2
This example selects IMSL_KNOWN_BOUNDS and sets lower_bound = 0.5 and
upper_bound = 4.5 so that the eight interior intervals each have width
(4.5 − 0.5)/(10 − 2) = 0.5. The 10 intervals are (−∞, 0.5], (0.5, 1.0], …, (4.0, .5],
and (4.5, ∞].
#include <imsl.h>
main()
{
int n_observations=30;
int n_intervals=10;
float *table;
float lower_bound=0.5, upper_bound=4.5;
float x[] = {0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43, 3.37,
2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62, 1.31, 0.32,
0.59, 0.81, 2.81, 1.87, 1.18, 1.35, 4.75, 2.48, 0.96,
1.89, 0.90, 2.05};
table = imsl_f_table_oneway (n_observations, x, n_intervals,
IMSL_KNOWN_BOUNDS, lower_bound,
upper_bound, 0);
imsl_f_write_matrix("counts", 1, n_intervals, table, 0);
}
7 8 9 10
2 0 0 1
Example 3
This example inputs 10 class marks 0.25, 0.75, 1.25, …, 4.75. This defines the class
intervals (0.0, 0.5], (0.5, 1.0], …, (4.0, 4.5], (4.5, 5.0]. Note that unlike the previous
example, the initial and last intervals are the same length as the remaining intervals.
#include <imsl.h>
main()
{
int n_intervals=10;
int n_observations=30;
double *table;
double x[] = {0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43,
3.37, 2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62,
1.31, 0.32, 0.59, 0.81, 2.81, 1.87, 1.18, 1.35,
4.75, 2.48, 0.96, 1.89, 0.90, 2.05};
double class_marks[] = {0.25, 0.75, 1.25, 1.75, 2.25, 2.75,
3.25, 3.75, 4.25, 4.75};
table = imsl_d_table_oneway (n_observations, x, n_intervals,
IMSL_CLASS_MARKS, class_marks,
0);
imsl_d_write_matrix("counts", 1, n_intervals, table, 0);
}
Output
counts
1 2 3 4 5 6
2 7 6 6 4 2
7 8 9 10
2 0 0 1
Example 4
This example inputs nine cutpoints 0.5, 1.0, 1.5, 2.0, …, 4.5 to define the same 10
intervals as in Example 3. Here again, the initial and last intervals are semi-infinite
intervals.
#include <imsl.h>
main()
{
int n_intervals=10;
int n_observations=30;
double *table;
double x[] = {0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43,
3.37, 2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62,
1.31, 0.32, 0.59, 0.81, 2.81, 1.87, 1.18, 1.35,
4.75, 2.48, 0.96, 1.89, 0.90, 2.05};
Output
counts
1 2 3 4 5 6
2 7 6 6 4 2
7 8 9 10
2 0 0 1
chi_squared_test
Performs a chi-squared goodness-of-fit test.
Synopsis
#include <imsl.h>
float imsl_f_chi_squared_test (float user_proc_cdf(),
int n_observations, int n_categories, float x[], …, 0)
The type double function is imsl_d_chi_squared_test.
Required Arguments
float user_proc_cdf (float y) (Input)
User-supplied function that returns the hypothesized, cumulative distribution
function at the point y.
int n_observations (Input)
The number of data elements input in x.
int n_categories (Input)
The number of cells into which the observations are to be tallied.
float x[] (Input)
Array with n_observations components containing the vector of data
elements for this test.
Return Value
The p-value for the goodness-of-fit chi-squared statistic.
Optional Arguments
IMSL_N_PARAMETERS_ESTIMATED, int n_parameters (Input)
The number of parameters estimated in computing the cumulative distribution
function.
IMSL_CUTPOINTS, float **p_cutpoints (Output)
The address of a pointer to the cutpoints array. On return, the pointer is
initialized (through a memory allocation request to malloc), and the array is
stored there. Typically, float *p_cutpoints is declared; &p_cutpoints is
used as an argument to this function; and free(p_cutpoints) is used to
free this array.
IMSL_CUTPOINTS_USER, float cutpoints[] (Input or Output)
Array with n_categories − 1 components containing the vector of cutpoints
defining the cell intervals. The intervals defined by the cutpoints are such that
the lower endpoint is not included, and the upper endpoint is included in any
interval. If IMSL_CUTPOINTS_EQUAL is specified, equal probability cutpoints
are computed and returned in cutpoints.
IMSL_CUTPOINTS_EQUAL
If IMSL_CUTPOINTS_USER is specified, then equal probability cutpoints can
still be used if, in addition, the IMSL_CUTPOINTS_EQUAL option is specified.
If IMSL_CUTPOINTS_USER is not specified, equal probability cutpoints are
used by default.
IMSL_CHI_SQUARED, float *chi_squared (Output)
If specified, the chi-squared test statistic is returned in *chi_squared.
IMSL_DEGREES_OF_FREEDOM, float *df (Output)
If specified, the degrees of freedom for the chi-squared goodness-of-fit test is
returned in *df.
is the function that takes the greatest integer that is no larger than the argument of the
function. Thus, if the computer time required to calculate the cumulative distribution
function is large, user-specified cutpoints may be preferred to reduce the total
computing time.
If the expected count in any cell is less than 1, then a rule of thumb is that the chi-
squared approximation may be suspect. A warning message to this effect is issued in
this case, as well as when an expected value is less than 5.
Programming Notes
The user must supply a function user_proc_cdf with calling sequence
user_proc_cdf(y), that returns the value of the cumulative distribution function at
any point y in the (optionally) specified range. Many of the cumulative distribution
functions in Chapter 9, “Special Functions,” can be used for user_proc_cdf, either
directly, if the calling sequence is correct, or indirectly, if, for example, the sample
means and standard deviations are to be used in computing the theoretical cumulative
distribution function.
Example 1
This example illustrates the use of imsl_f_chi_squared_test on a randomly
generated sample from the normal distribution. One-thousand randomly generated
observations are tallied into 10 equiprobable intervals. The null hypothesis that the
sample is from a normal distribution is specified by use of the imsl_f_normal_cdf
as the hypothesized distribution function. In this example, the null hypothesis is not
rejected.
#include <imsl.h>
main()
{
float *x, p_value;
imsl_random_seed_set(SEED);
/* Generate Normal deviates */
x = imsl_f_random_normal (N_OBSERVATIONS, 0);
/* Perform chi squared test */
p_value = imsl_f_chi_squared_test (imsl_f_normal_cdf, N_OBSERVATIONS,
N_CATEGORIES, x, 0);
/* Print results */
printf ("p value %7.4f\n", p_value);
}
Output
p value 0.1546
Example 2
In this example, some optional arguments are used for the data in the initial example.
#include <imsl.h>
main()
{
float *cell_counts, *cutpoints, *cell_chi_squared;
float chi_squared_statistics[3], *x;
char *stat_row_labels[] = {"chi-squared", "degrees of freedom",
"p-value"};
imsl_random_seed_set(SEED);
/* Generate Normal deviates */
x = imsl_f_random_normal (N_OBSERVATIONS, 0);
/* Perform chi squared test */
chi_squared_statistics[2] =
imsl_f_chi_squared_test (imsl_f_normal_cdf,
N_OBSERVATIONS, N_CATEGORIES, x,
Output
Chi Squared Statistics
chi-squared 13.18
degrees of freedom 9.00
p-value 0.15
Cut Points
1 2 3 4 5 6
-1.282 -0.842 -0.524 -0.253 -0.000 0.253
7 8 9
0.524 0.842 1.282
Cell Counts
1 2 3 4 5 6
106 109 89 92 83 87
7 8 9 10
110 104 121 99
7 8 9 10
1.00 0.16 4.41 0.01
Example 3
In this example, a discrete Poisson random sample of size 1000 with parameter θ = 5.0
is generated via function imsl_f_random_poisson. In the call to
imsl_f_chi_squared_test, function imsl_f_poisson_cdf is used as function
user_proc_cdf.
#include <imsl.h>
float user_proc_cdf(float);
main()
{
int i, *poisson;
float cell_statistics[3][N_CATEGORIES];
float chi_squared_statistics[3], x[N_NUMBERS];
float cutpoints[] = {1.5, 2.5, 3.5, 4.5, 5.5, 6.5,
7.5, 8.5, 9.5};
char *cell_row_labels[] = {"count", "expected count",
"cell chi-squared"};
char *cell_col_labels[] = {"Poisson value", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"};
char *stat_row_labels[] = {"chi-squared", "degrees of freedom",
"p-value"};
imsl_random_seed_set(SEED);
/* Generate the data */
poisson = imsl_random_poisson(N_NUMBERS, THETA, 0);
/* Copy data to a floating point vector*/
for (i = 0; i < N_NUMBERS; i++)
x[i] = poisson[i];
chi_squared_statistics[2] =
imsl_f_chi_squared_test(user_proc_cdf, N_NUMBERS, N_CATEGORIES, x,
IMSL_CUTPOINTS_USER, cutpoints,
IMSL_CELL_COUNTS_USER, &cell_statistics[0][0],
IMSL_CELL_EXPECTED_USER, &cell_statistics[1][0],
IMSL_CELL_CHI_SQUARED_USER, &cell_statistics[2][0],
IMSL_CHI_SQUARED, &chi_squared_statistics[0],
IMSL_DEGREES_OF_FREEDOM, &chi_squared_statistics[1],
0);
/* Print results */
imsl_f_write_matrix("\nChi-squared statistics\n", 3, 1,
&chi_squared_statistics[0],
IMSL_ROW_LABELS, stat_row_labels,
0);
imsl_f_write_matrix("\nCell Statistics\n", 3, N_CATEGORIES,
&cell_statistics[0][0],
IMSL_ROW_LABELS, cell_row_labels,
IMSL_COL_LABELS, cell_col_labels,
0);
}
float user_proc_cdf(float k)
{
float cdf_v;
chi-squared 10.48
degrees of freedom 9.00
p-value 0.31
Cell Statistics
Poisson value 0 1 2 3 4
count 41.0 94.0 138.0 158.0 150.0
expected count 40.4 84.2 140.4 175.5 175.5
cell chi-squared 0.0 1.1 0.0 1.7 3.7
Poisson value 5 6 7 8 9
count 159.0 116.0 75.0 37.0 32.0
expected count 146.2 104.4 65.3 36.3 31.8
cell chi-squared 1.1 1.3 1.4 0.0 0.0
Warning Errors
IMSL_EXPECTED_VAL_LESS_THAN_1 An expected value is less than 1.
IMSL_EXPECTED_VAL_LESS_THAN_5 An expected value is less than 5.
Fatal Errors
IMSL_ALL_OBSERVATIONS_MISSING All observations contain missing values.
IMSL_INCORRECT_CDF_1 The function user_proc_cdf is not a
cumulative distribution function. The
value at the lower bound must be
nonnegative, and the value at the upper
bound must not be greater than one.
IMSL_INCORRECT_CDF_2 The function user_proc_cdf is not a
cumulative distribution function. The
probability of the range of the
distribution is not positive.
IMSL_INCORRECT_CDF_3 The function user_proc_cdf is not a
cumulative distribution function. Its
evaluation at an element in x is
inconsistent with either the evaluation at
the lower or upper bound.
IMSL_INCORRECT_CDF_4 The function user_proc_cdf is not a
cumulative distribution function. Its
evaluation at a cutpoint is inconsistent
with either the evaluation at the lower or
upper bound.
covariances
Computes the sample variance-covariance or correlation matrix.
Synopsis
#include <imsl.h>
float *imsl_f_covariances (int n_observations, int n_variables, float
x[], …, 0)
The type double function is imsl_d_covariances.
Required Arguments
int n_observations (Input)
The number of observations.
int n_variables (Input)
The number of variables.
float x[] (Input)
Array of size n_observations × n_variables containing the matrix of
data.
Return Value
If no optional arguments are used, imsl_f_covariances returns a pointer to an
n_variables × n_variables matrix containing the sample variance-covariance
matrix of the observations. The rows and columns of this matrix correspond to the
columns of x.
Synopsis with Optional Arguments
#include <imsl.h>
float *imsl_f_covariances (int n_observations, int n_variables, float
x[],
IMSL_X_COL_DIM, int x_col_dim,
IMSL_VARIANCE_COVARIANCE_MATRIX,
IMSL_CORRECTED_SSCP_MATRIX,
IMSL_CORRELATION_MATRIX,
IMSL_STDEV_CORRELATION_MATRIX,
IMSL_MEANS, float **p_means,
IMSL_MEANS_USER, float means[],
IMSL_COVARIANCE_COL_DIM, int covariance_col_dim,
IMSL_RETURN_USER, float covariance[],
0)
Description
The function imsl_f_covariances computes estimates of correlations, covariances,
or sums of squares and crossproducts for a data matrix x. The means, (corrected) sums
denote the mean based on i observations for the k-th variable, and let cjki denote the
sum of crossproducts (or sum of squares if j = k) based on i observations. Then, the
method of provisional means finds new means and sums ofcrossproducts as follows:
The means and crossproducts are initialized as:
x k 0 = 0.0 k = 1, K , p
c jk 0 = 0.0 j , k = 1, K , p
where p denotes the number of variables. Letting xk,i+1 denote the k-th variable on
observation i + 1, each new observation leads to the following updates for
x ki
å
n
x
i =1 ki
xk =
n
where n is the number of observations. The following formula defines the sample
covariance, sj k, between variables j and k:
s jk =
å dx
n
i =1 ji ib
− x j x ki − x k g
n −1
Example 1
The first example illustrates the use of imsl_f_covariances for the first 50
observations in the Fisher iris data (Fisher 1936). Note in this example that the first
variable is constant over the first 50 observations.
#include <imsl.h>
#define N_VARIABLES 5
#define N_OBSERVATIONS 50
main()
{
float *covariances;
float x[] = {1.0, 5.1, 3.5, 1.4, .2, 1.0, 4.9, 3.0, 1.4, .2,
1.0, 4.7, 3.2, 1.3, .2, 1.0, 4.6, 3.1, 1.5, .2,
1.0, 5.0, 3.6, 1.4, .2, 1.0, 5.4, 3.9, 1.7, .4,
1.0, 4.6, 3.4, 1.4, .3, 1.0, 5.0, 3.4, 1.5, .2,
1.0, 4.4, 2.9, 1.4, .2, 1.0, 4.9, 3.1, 1.5, .1,
1.0, 5.4, 3.7, 1.5, .2, 1.0, 4.8, 3.4, 1.6, .2,
1.0, 4.8, 3.0, 1.4, .1, 1.0, 4.3, 3.0, 1.1, .1,
1.0, 5.8, 4.0, 1.2, .2, 1.0, 5.7, 4.4, 1.5, .4,
1.0, 5.4, 3.9, 1.3, .4, 1.0, 5.1, 3.5, 1.4, .3,
1.0, 5.7, 3.8, 1.7, .3, 1.0, 5.1, 3.8, 1.5, .3,
1.0, 5.4, 3.4, 1.7, .2, 1.0, 5.1, 3.7, 1.5, .4,
1.0, 4.6, 3.6, 1.0, .2, 1.0, 5.1, 3.3, 1.7, .5,
1.0, 4.8, 3.4, 1.9, .2, 1.0, 5.0, 3.0, 1.6, .2,
1.0, 5.0, 3.4, 1.6, .4, 1.0, 5.2, 3.5, 1.5, .2,
1.0, 5.2, 3.4, 1.4, .2, 1.0, 4.7, 3.2, 1.6, .2,
1.0, 4.8, 3.1, 1.6, .2, 1.0, 5.4, 3.4, 1.5, .4,
1.0, 5.2, 4.1, 1.5, .1, 1.0, 5.5, 4.2, 1.4, .2,
1.0, 4.9, 3.1, 1.5, .2, 1.0, 5.0, 3.2, 1.2, .2,
1.0, 5.5, 3.5, 1.3, .2, 1.0, 4.9, 3.6, 1.4, .1,
1.0, 4.4, 3.0, 1.3, .2, 1.0, 5.1, 3.4, 1.5, .2,
1.0, 5.0, 3.5, 1.3, .3, 1.0, 4.5, 2.3, 1.3, .3,
1.0, 4.4, 3.2, 1.3, .2, 1.0, 5.0, 3.5, 1.6, .6,
1.0, 5.1, 3.8, 1.9, .4, 1.0, 4.8, 3.0, 1.4, .3,
1.0, 5.1, 3.8, 1.6, .2, 1.0, 4.6, 3.2, 1.4, .2,
1.0, 5.3, 3.7, 1.5, .2, 1.0, 5.0, 3.3, 1.4, .2};
#define N_VARIABLES 5
#define N_OBSERVATIONS 50
main()
{
char *title;
float *means, *correlations;
float x[] = {1.0, 5.1, 3.5, 1.4, .2, 1.0, 4.9, 3.0, 1.4, .2,
1.0, 4.7, 3.2, 1.3, .2, 1.0, 4.6, 3.1, 1.5, .2,
1.0, 5.0, 3.6, 1.4, .2, 1.0, 5.4, 3.9, 1.7, .4,
1.0, 4.6, 3.4, 1.4, .3, 1.0, 5.0, 3.4, 1.5, .2,
1.0, 4.4, 2.9, 1.4, .2, 1.0, 4.9, 3.1, 1.5, .1,
1.0, 5.4, 3.7, 1.5, .2, 1.0, 4.8, 3.4, 1.6, .2,
1.0, 4.8, 3.0, 1.4, .1, 1.0, 4.3, 3.0, 1.1, .1,
1.0, 5.8, 4.0, 1.2, .2, 1.0, 5.7, 4.4, 1.5, .4,
1.0, 5.4, 3.9, 1.3, .4, 1.0, 5.1, 3.5, 1.4, .3,
1.0, 5.7, 3.8, 1.7, .3, 1.0, 5.1, 3.8, 1.5, .3,
1.0, 5.4, 3.4, 1.7, .2, 1.0, 5.1, 3.7, 1.5, .4,
1.0, 4.6, 3.6, 1.0, .2, 1.0, 5.1, 3.3, 1.7, .5,
1.0, 4.8, 3.4, 1.9, .2, 1.0, 5.0, 3.0, 1.6, .2,
1.0, 5.0, 3.4, 1.6, .4, 1.0, 5.2, 3.5, 1.5, .2,
1.0, 5.2, 3.4, 1.4, .2, 1.0, 4.7, 3.2, 1.6, .2,
1.0, 4.8, 3.1, 1.6, .2, 1.0, 5.4, 3.4, 1.5, .4,
1.0, 5.2, 4.1, 1.5, .1, 1.0, 5.5, 4.2, 1.4, .2,
1.0, 4.9, 3.1, 1.5, .2, 1.0, 5.0, 3.2, 1.2, .2,
1.0, 5.5, 3.5, 1.3, .2, 1.0, 4.9, 3.6, 1.4, .1,
1.0, 4.4, 3.0, 1.3, .2, 1.0, 5.1, 3.4, 1.5, .2,
1.0, 5.0, 3.5, 1.3, .3, 1.0, 4.5, 2.3, 1.3, .3,
1.0, 4.4, 3.2, 1.3, .2, 1.0, 5.0, 3.5, 1.6, .6,
1.0, 5.1, 3.8, 1.9, .4, 1.0, 4.8, 3.0, 1.4, .3,
1.0, 5.1, 3.8, 1.6, .2, 1.0, 4.6, 3.2, 1.4, .2,
1.0, 5.3, 3.7, 1.5, .2, 1.0, 5.0, 3.3, 1.4, .2};
1 2 3 4
5.006 3.428 1.462 0.246
1 2 3 4
1 0.3525 0.7425 0.2672 0.2781
2 0.3791 0.1777 0.2328
3 0.1737 0.3316
4 0.1054
Warning Errors
IMSL_CONSTANT_VARIABLE Correlations are requested, but the observations
on one or more variables are constant. The
corresponding correlations are set to NaN.
regression
Fits a multiple linear regression model using least squares.
Synopsis
#include <imsl.h>
float *imsl_f_regression (int n_observations, int n_independent, float
x[], float y[], …, 0)
The type double function is imsl_d_regression.
Required Arguments
int n_observations (Input)
The number of observations.
int n_independent (Input)
The number of independent (explanatory) variables.
float x[] (Input)
Array of size n_observations × n_independent containing the matrix of
independent (explanatory) variables.
float y[] (Input)
Array of length n_observations containing the dependent (response)
variable.
Return Value
If the optional argument IMSL_NO_INTERCEPT is not used, imsl_f_regression
returns a pointer to an array of length n_independent + 1 containing a least-squares
solution for the regression coefficients. The estimated intercept is the initial component
of the array.
Optional Arguments
IMSL_X_COL_DIM, int x_col_dim (Input)
The column dimension of x.
Default: x_col_dim = n_independent
IMSL_NO_INTERCEPT
By default, the fitted value for observation i is
β$ 0 + β$ 1 x1 + K + β$ k x k
β 0
Description
The function imsl_f_regression fits a multiple linear regression model with or
without an intercept. By default, the multiple linear regression model is
yi = β0 + β1xi1 +β2xi2 + … + βkxik + εi i = 1, 2, …, n
where the observed values of the yi’s (input in y) are the responses or values of the
dependent variable; the xi1’s, xi2’s, …, xik’s (input in x) are the settings of the k (input
in n_independent) independent variables; β0, β1, …, βk are the regression
coefficients whose estimated values are to be output by imsl_f_regression; and the
εi’s are independently distributed normal errors each with mean zero and variance σ2.
Here, n is the number of rows in the augmented matrix (x,y), i.e., n equals
n_observations. Note that by default, β 0 is included in the model.
for the n observations. This minimum sum of squares (the error sum of squares) is
output as one of the analysis of variance statistics if IMSL_ANOVA_TABLE (or
IMSL_ANOVA_TABLE_USER) is specified and is computed as
n
å b y − y g
2
SSE = i i
i =1
Another analysis of variance statistic is the total sum of squares. By default, the total
sum of squares is the sum of squares of the deviations of yi from its mean
y
åb y − yg
2
SST = i
i =1
When IMSL_NO_INTERCEPT is specified, the total sum of squares is the sum of squares
of yi, the so-called uncorrected total sum of squares. This is computed as
n
SST = åyi =1
2
i
See Draper and Smith (1981) for a good general treatment of the multiple linear
regression model, its analysis, and many examples.
In order to compute a least-squares solution, imsl_f_regression performs an
orthogonal reduction of the matrix of regressors to upper-triangular form. The reduction
is based on one pass through the rows of the augmented matrix (x, y) using fast Givens
transformations. (See Golub and Van Loan 1983, pp. 156−162; Gentleman 1974.) This
method has the advantage that the loss of accuracy resulting from forming the
crossproduct matrix used in the normal equations is avoided.
By default, the current means of the dependent and independent variables are used to
internally center the data for improved accuracy. Let xi be a column vector containing
the j-th row of data for the independent variables. Let xi represent the mean vector for
the independent variables given the data for rows 1, 2, …, i. The current mean vector is
defined to be
å
i
xj
j =1
xi =
i
å b x − x gb x − x g = å i − 1b x − x gb x − x g
iT T
i n i n i i i i
i =1 i =2
Examples
Example 1
A regression model
yi = β 0 + β1 xi1 + β 2 xi 2 + β 3 xi 3 + ε i i = 1,2 , K , 9
main()
{
float *coefficients;
float x[][N_INDEPENDENT] = {7.0, 5.0, 6.0,
2.0,-1.0, 6.0,
7.0, 3.0, 5.0,
-3.0, 1.0, 4.0,
2.0,-1.0, 0.0,
2.0, 1.0, 7.0,
-3.0,-1.0, 3.0,
2.0, 1.0, 1.0,
2.0, 1.0, 4.0};
float y[] = {7.0,-5.0, 6.0, 5.0, 5.0, -2.0, 0.0, 8.0, 3.0};
Example 2
A weighted least-squares fit is computed using the model
yi = β0xi0 +β1xi1 + β2xi2 + εi i = 1, 2, …, 4
and weights 1/i2 discussed by Maindonald (1984, pp. 67 −68). In order to compute the
weighted least-squares fit, using an ordinary least-squares function
(imsl_f_regression), the regressors (including the column of ones for the intercept
term) and the responses must be transformed prior to invocation of
imsl_f_regression. Specifically, the i-th response and regressors are multiplied by
a square root of the i-th weight. IMSL_NO_INTERCEPT must be specified since the
column of ones corresponding to the intercept term in the untransformed model is
transformed by the weights and is regarded as an additional independent variable.
In the example, IMSL_ANOVA_TABLE is specified. The minimum sum of squares for
error in terms of the original untransformed regressors and responses for this weighted
regression is
4
å w b y − y g
2
SSE = i i i
i =1
#include <imsl.h>
#include <math.h>
#define N_INDEPENDENT 3
#define N_COEFFICIENTS N_INDEPENDENT
#define N_OBSERVATIONS 4
main()
{
int i, j;
float *coefficients, w, anova_table[15], power;
float x[][N_INDEPENDENT] = {1.0, -2.0, 0.0,
1.0, -1.0, 2.0,
1.0, 2.0, 5.0,
1.0, 7.0, 3.0};
float y[] = {-3.0, 1.0, 2.0, 6.0};
char *anova_row_labels[] = {
"degrees of freedom for regression",
"degrees of freedom for error",
"total (uncorrected) degrees of freedom",
"sum of squares for regression",
"sum of squares for error",
"total (uncorrected) sum of squares",
"regression mean square",
"error mean square", "F-statistic",
"p-value", "R-squared (in percent)",
"adjusted R-squared (in percent)",
"est. standard deviation of model error",
"overall mean of y",
"coefficient of variation (in percent)"};
power = 0.0;
for (i = 0; i < N_OBSERVATIONS; i++) {
power += 1.0;
/* The square root of the weight */
w = sqrt(1.0 / (power*power));
/* Transform response */
y[i] *= w;
/* Transform regressors */
for (j = 0; j < N_INDEPENDENT; j++)
x[i][j] *= w;
}
imsl_f_write_matrix("Least-Squares Coefficients", 1,
N_COEFFICIENTS, coefficients, 0);
imsl_f_write_matrix("* * * Analysis of Variance * * *\n", 15, 1,
anova_table, IMSL_ROW_LABELS, anova_row_labels,
* * * Analysis of Variance * * *
Warning Errors
IMSL_RANK_DEFICIENT The model is not full rank. There is not a unique
least-squares solution.
poly_regression
Performs a polynomial least-squares regression.
Synopsis
#include <imsl.h>
float *imsl_f_poly_regression (int n_observations, float x[], float y[],
int degree, …, 0)
The type double procedure is imsl_d_poly_regression.
Required Arguments
int n_observations (Input)
The number of observations.
float x[] (Input)
Array of length n_observations containing the independent variable.
float y[] (Input)
Array of length n_observations containing the dependent variable.
int degree (Input)
The degree of the polynomial.
Optional Arguments
IMSL_WEIGHTS, float weights[] (Input)
Array with n_observations components containing the vector of weights
for the observation. If this option is not specified, all observations have equal
weights of one.
IMSL_SSQ_POLY, float **p_ssq_poly (Output)
The address of a pointer to the array containing the sequential sums of squares
and other statistics. On return, the pointer is initialized (through a memory
allocation request to malloc), and the array is stored there. Typically, float
*p_ssq_poly is declared; &p_ssq_poly is used as an argument to this
function; and free(p_ssq_poly) is used to free this array. Row i
corresponds to xi, i = 1, …, degree, and the columns are described as follows:
Column Description
1 degrees of freedom
2 sums of squares
3 F-statistic
Column Description
1 degrees of freedom
2 lack-of-fit sums of squares
3 F-statistic for testing lack-of-fit for a
polynomial model of degree i
4 p-value for the test
å b y − y g
2
2 i
R = 100%
åb y − yg
2
1
where yi is the fitted y value at xi and y is the mean of y. This statistic is useful in
assessing the overall fit of the curve to the data. R2 must be between 0% and 100%,
inclusive. R2 = 100% indicates a perfect fit to the data.
Estimates of the regression coefficients in a polynomial model are computed using
orthogonal polynomials as the regressor variables. This reparameterization of the
polynomial model in terms of orthogonal polynomials has the advantage that the loss of
accuracy resulting from forming powers of the x-values is avoided. All results are
returned to the user for the original model (power form).
The function imsl_f_poly_regression is based on the algorithm of Forsythe
(1957). A modification to Forsythe’s algorithm suggested by Shampine (1975) is used
for computing the polynomial coefficients. A discussion of Forsythe’s algorithm and
Shampine’s modification appears in Kennedy and Gentle (1980, pp. 342−347).
Examples
Example 1
A polynomial model is fitted to data discussed by Neter and Wasserman (1974, pp.
279−285). The data set contains the response variable y measuring coffee sales (in
hundred gallons) and the number of self-service coffee dispensers. Responses for
14 similar cafeterias are in the data set. A graph of the results also is given.
#include <imsl.h>
#define DEGREE 2
#define NOBS 14
main()
{
float *coefficients;
float x[] = {0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 4.0,
4.0, 5.0, 5.0, 6.0, 6.0, 7.0, 7.0};
float y[] = {508.1, 498.4, 568.2, 577.3, 651.7, 657.0, 755.3,
758.9, 787.6, 792.1, 841.4, 831.8, 854.7, 871.4};
Output
Least-Squares Polynomial Coefficients
0 503.3
1 78.9
2 -4.0
Example 2
This example is a continuation of the initial example. Here, many optional arguments
are used.
#include <stdio.h>
#include <imsl.h>
#define DEGREE 2
#define NOBS 14
void main()
{
int iset = 1, dfpe;
float *coefficients, *anova, sspe, *sspoly, *sslof;
float x[] = {0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 4.0,
4.0, 5.0, 5.0, 6.0, 6.0, 7.0, 7.0};
float y[] = {508.1, 498.4, 568.2, 577.3, 651.7, 657.0, 755.3,
758.9, 787.6, 792.1, 841.4, 831.8, 854.7, 871.4};
Output
Least-Squares Polynomial Coefficients
intercept linear quadratic
503.3 78.9 -4.0
Sequential Statistics
Degrees of Sum of
Freedom Squares F-Statistic p-value
Lack-of-Fit Statistics
Degrees of Sum of
Freedom Squares F-Statistic p-value
linear 5.0 4793.7 22.0 0.0004
quadratic 4.0 405.9 2.3 0.1548
* * * Analysis of Variance * * *
Warning Errors
IMSL_CONSTANT_YVALUES The y values are constant. A zero-order
polynomial is fit. High order coefficients
are set to zero.
IMSL_FEW_DISTINCT_XVALUES There are too few distinct x values to fit
the desired degree polynomial. High
order coefficients are set to zero.
IMSL_PERFECT_FIT A perfect fit was obtained with a
polynomial of degree less than degree.
High order coefficients are set to zero.
Fatal Errors
IMSL_NONNEG_WEIGHT_REQUEST_2 All weights must be nonnegative.
IMSL_ALL_OBSERVATIONS_MISSING Each (x, y) point contains NaN (not a
number). There are no valid data.
IMSL_CONSTANT_XVALUES The x values are constant.
Synopsis
#include <imsl.h>
float *imsl_f_ranks (int n_observations, float x[], …, 0)
The type double function is imsl_d_ranks.
Required Arguments
int n_observations (Input)
The number of observations.
float x[] (Input)
Array of length n_observations containing the observations to be ranked.
Return Value
A pointer to a vector of length n_observations containing the rank (or optionally, a
transformation of the rank) of each observation.
Optional Arguments
IMSL_AVERAGE_TIE, or
IMSL_HIGHEST, or
IMSL_LOWEST, or
Keyword Method
IMSL_AVERAGE_TIE average of the scores of the tied
observations (default)
IMSL_HIGHEST highest score in the group of ties
IMSL_LOWEST lowest score in the group of ties
IMSL_RANDOM_SPLIT tied observations are randomly split
using a random number generator.
Keyword Result
IMSL_RANKS ranks (default)
IMSL_BLOM_SCORES Blom version of normal scores
IMSL_TUKEY_SCORES Tukey version of normal scores
IMSL_VAN_DER_WAERDEN_SCORES Van der Waerden version of normal
scores
IMSL_EXPECTED_NORMAL_SCORES expected value of normal order
statistics (For tied observations, the
average of the expected normal
scores.)
IMSL_SAVAGE_SCORES Savage scores (the expected value of
exponential order statistics)
Ties
In data without ties, the output values are the ordinary ranks (or a transformation of the
ranks) of the data in x. If x[i] has the smallest value among the values in x and there is
no other element in x with this value, then ranks[i] = 1. If both x[i] and x[j] have the
same smallest value, then the output value depends upon the option used to break ties.
Keyword Result
IMSL_AVERAGE_TIE ranks[i] = ranks[j] = 1.5
IMSL_HIGHEST ranks[i] = ranks[j] = 2.0
IMSL_LOWEST ranks[i] = ranks [j] = 1.0
IMSL_RANDOM_SPLIT ranks[i] = 1.0 and ranks[j] = 2.0
or, randomly,
ranks[i] = 2.0 and ranks[j] = 1.0
When the ties are resolved randomly, the function imsl_f_random_uniform is used
to generate random numbers. Different results may occur from different executions of
the program unless the “seed” of the random number generator is set explicitly by use
of the function imsl_random_seed_set.
The Scores
Normal and other functions of the ranks can optionally be returned. Normal scores can
be defined as the expected values, or approximations to the expected values, of order
statistics from a normal distribution. The simplest approximations are obtained by
evaluating the inverse cumulative normal distribution function,
imsl_f_normal_inverse_cdf, at the ranks scaled into the open interval (0,1). In the
Blom version (see Blom 1958), the scaling transformation for the rank
ri (1 ≤ ri ≤ n where n is the sample size, n_observations) is (ri − 3/8)/(n + 1/4).
The Blom normal score corresponding to the observation with rank ri is
ri − 3 / 8
Φ −1 ( )
n +1/ 4
Ties are handled in the same way as for the Blom normal scores.
In the Van der Waerden version (see Lehmann 1975, p. 97), the scaling transformation
for the rank ri is ri/(n + 1). The Van der Waerden normal score corresponding to the
observation with rank ri is
ri
Φ −1 ( )
n +1
Ties are handled in the same way as for the Blom normal scores.
When option IMSL_EXPECTED_NORMAL_SCORES is used, the output values are the
expected values of the normal order statistics from a sample of size n_observations.
If the value in x[i] is the k-th smallest, then the value output in ranks[i] is E(zk) where
E(⋅) is the expectation operator, and zk is the k-th order statistic in a sample of size
n_observations from a standard normal distribution. Ties are handled in the same
way as for the Blom normal scores.
Savage scores are the expected values of the exponential order statistics from a sample
of size n_observations. These values are called Savage scores because of their use
in a test discussed by Savage (1956) (see Lehmann 1975). If the value in x[i] is the
k-th smallest, then the value output in ranks[i] is E(yk) where yk is the k-th order
statistic in a sample of size n_observations from a standard exponential distribution.
The expected value of the k-th order statistic from an exponential sample of size n
(n_observations) is
1 1 1
+ +K+
n n −1 n − k +1
Ties are handled in the same way as for the Blom normal scores.
Examples
Example 1
The data for this example, from Hinkley (1977), contains 30 observations. Note that the
fourth and sixth observations are tied, and that the third and twentieth observations are
tied.
#include <imsl.h>
#define N_OBSERVATIONS 30
main()
{
Output
Ranks
1 2 3 4 5 6
5.0 18.0 6.5 11.5 21.0 11.5
7 8 9 10 11 12
2.0 15.0 29.0 24.0 27.0 28.0
13 14 15 16 17 18
16.0 23.0 3.0 17.0 13.0 1.0
19 20 21 22 23 24
4.0 6.5 26.0 19.0 10.0 14.0
25 26 27 28 29 30
30.0 25.0 9.0 20.0 8.0 22.0
Example 2
This example uses all of the score options with the same data set, which contains some
ties. Ties are handled in several different ways in this example.
#include <imsl.h>
#define N_OBSERVATIONS 30
void main()
{
float fuzz_value=0.0, score[4][N_OBSERVATIONS], *ranks;
float x[] = {0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43,
3.37, 2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62,
1.31, 0.32, 0.59, 0.81, 2.81, 1.87, 1.18, 1.35,
4.75, 2.48, 0.96, 1.89, 0.90, 2.05};
char *row_labels[] = {"Blom", "Tukey", "Van der Waerden",
"Expected Value"};
Output
Normal Order Statistics
1 2 3 4 5
Blom -1.024 0.209 -0.776 -0.294 0.473
Tukey -1.020 0.208 -0.890 -0.381 0.471
Van der Waerden -0.989 0.204 -0.753 -0.287 0.460
Expected Value -1.026 0.209 -0.836 -0.338 0.473
6 7 8 9 10
Blom -0.294 -1.610 -0.041 1.610 0.776
Tukey -0.381 -1.599 -0.041 1.599 0.773
Van der Waerden -0.372 -1.518 -0.040 1.518 0.753
Expected Value -0.338 -1.616 -0.041 1.616 0.777
11 12 13 14 15
Blom 1.176 1.361 0.041 0.668 -1.361
Tukey 1.171 1.354 0.041 0.666 -1.354
Van der Waerden 1.131 1.300 0.040 0.649 -1.300
Expected Value 1.179 1.365 0.041 0.669 -1.365
16 17 18 19 20
Blom 0.125 -0.209 -2.040 -1.176 -0.776
Tukey 0.124 -0.208 -2.015 -1.171 -0.890
Van der Waerden 0.122 -0.204 -1.849 -1.131 -0.865
Expected Value 0.125 -0.209 -2.043 -1.179 -0.836
26 27 28 29 30
Blom 0.893 -0.568 0.382 -0.668 0.568
Tukey 0.890 -0.566 0.381 -0.666 0.566
Van der Waerden 0.865 -0.552 0.372 -0.649 0.552
Expected Value 0.894 -0.568 0.382 -0.669 0.568
7 8 9 10 11 12
0.068 0.677 2.995 1.545 2.162 2.495
13 14 15 16 17 18
0.743 1.402 0.104 0.815 0.555 0.033
19 20 21 22 23 24
0.141 0.240 1.912 0.975 0.397 0.614
25 26 27 28 29 30
3.995 1.712 0.350 1.066 0.304 1.277
random_seed_get
Retrieves the current value of the seed used in the IMSL random number generators.
Synopsis
#include <imsl.h>
int imsl_random_seed_get ( )
Return Value
The value of the seed.
Description
The function imsl_random_seed_get retrieves the current value of the “seed” used
in the random number generators. A reason for doing this would be to restart a
simulation, using imsl_random_seed_set to reset the seed.
Example
This example illustrates the statements required to restart a simulation using
imsl_random_seed_get and imsl_random_seed_set. Also, the example shows
that restarting the sequence of random numbers at the value of the seed last generated is
the same as generating the random numbers all at once.
#define N_RANDOM 5
main()
{
int seed = 123457;
float *r1, *r2, *r;
imsl_random_seed_set(seed);
r1 = imsl_f_random_uniform(N_RANDOM, 0);
imsl_f_write_matrix ("First Group of Random Numbers", 1,
N_RANDOM, r1, 0);
seed = imsl_random_seed_get();
imsl_random_seed_set(seed);
r2 = imsl_f_random_uniform(N_RANDOM, 0);
imsl_f_write_matrix ("Second Group of Random Numbers", 1,
N_RANDOM, r2, 0);
imsl_random_seed_set(123457);
r = imsl_f_random_uniform(2*N_RANDOM, 0);
imsl_f_write_matrix ("Both Groups of Random Numbers", 1,
2*N_RANDOM, r, 0);
}
Output
First Group of Random Numbers
1 2 3 4 5
0.9662 0.2607 0.7663 0.5693 0.8448
7 8 9 10
0.9872 0.6014 0.8964 0.3809
random_seed_set
Initializes a random seed for use in the IMSL random number generators.
Synopsis
#include <imsl.h>
void imsl_random_seed_set (int seed)
Description
The function imsl_random_seed_set is used to initialize the seed used in the IMSL
random number generators. The form of the generators is
The value of x0 is the seed. If the seed is not initialized prior to invocation of any of the
routines for random number generation by calling imsl_random_seed_set, the seed
is initialized via the system clock. The seed can be reinitialized to a clock-dependent
value by calling imsl_random_seed_set with seed set to 0.
The effect of imsl_random_seed_set is to set some global values used by the
random number generators.
A common use of imsl_random_seed_set is in conjunction with
imsl_random_seed_get to restart a simulation.
Example
See function imsl_random_seed_get.
random_option
Selects the uniform (0,1) multiplicative congruential pseudorandom number generator.
Synopsis
#include <imsl.h>
void imsl_random_option (int generator_option)
Required Arguments
int generator_option (Input)
Indicator of the generator. The random number generator is a multiplicative
congruential generator with modulus 231 − 1. Argument generator_option
is used to choose the multiplier and whether or not shuffling is done.
Description
The IMSL uniform pseudorandom number generators use a multiplicative congruential
method, with or without shuffling. The value of the multiplier and whether or not to use
shuffling are determined by imsl_random_option. The description of function
imsl_f_random_uniform may provide some guidance in the choice of the form of
the generator. If no selection is made explicitly, the generators use the multiplier 16807
without shuffling. This form of the generator has been in use for some time (Lewis et al.
1969).
Example
The C statement
imsl_random_option(1)
selects the simple multiplicative congruential generator with multiplier 16807. Since
this is the same as the default, this statement has no effect unless
imsl_random_option had previously been called in the same program to select a
different generator.
random_uniform
Generates pseudorandom numbers from a uniform (0,1) distribution.
Synopsis
#include <imsl.h>
float *imsl_f_random_uniform (int n_random, …, 0)
The type double function is imsl_d_random_uniform.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
Optional Arguments
IMSL_RETURN_USER, float r[] (Output)
If specified, the array of length n_random containing the random uniform
(0, 1) deviates is returned in the user-provided array r.
Description
The function imsl_f_random_uniform generates pseudorandom numbers from a
uniform (0, 1) distribution using a multiplicative congruential method. The form of the
generator is
Each xi is then scaled into the unit interval (0,1). The possible values for c in the
generators are 16807, 397204094, and 950706376. The selection is made by the
function imsl_random_option. The choice of 16807 will result in the fastest
execution time. If no selection is made explicitly, the functions use the multiplier
16807.
The function imsl_random_seed_set can be used to initialize the seed of the
random number generator. The function imsl_random_option can be used to select
the form of the generator.
The user can select a shuffled version of these generators. In this scheme, a table is
filled with the first 128 uniform (0, 1) numbers resulting from the simple multiplicative
congruential generator. Then, for each xi from the simple generator, the low-order bits
of xi are used to select a random integer, j, from 1 to 128. The j-th entry in the table is
then delivered as the random number; and xi, after being scaled into the unit interval, is
inserted into the j-th position in the table.
The values returned by imsl_f_random_uniform are positive and less than 1.0.
Some values returned may be smaller than the smallest relative spacing, however.
Hence, it may be the case that some value, for example r[i], is such that
1.0 − r[i] = 1.0.
Deviates from the distribution with uniform density over the interval (a, b) can be
obtained by scaling the output from imsl_f_random_uniform. The following
Example
In this example, imsl_f_random_uniform is used to generate five pseudorandom
uniform numbers. Since imsl_random_option is not called, the generator used is a
simple multiplicative congruential one with a multiplier of 16807.
#include <imsl.h>
#include <stdio.h>
#define N_RANDOM 5
void main()
{
float *r;
imsl_random_seed_set(123457);
r = imsl_f_random_uniform(N_RANDOM, 0);
random_normal
Generates pseudorandom numbers from a standard normal distribution using an inverse
CDF method.
Synopsis
#include <imsl.h>
float *imsl_f_random_normal (int n_random, …, 0)
The type double function is imsl_d_random_normal.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
Return Value
A pointer to a vector of length n_random containing the random standard normal
deviates. To release this space, use free.
Optional Arguments
IMSL_RETURN_USER, float r[] (Output)
Pointer to a vector of length n_random that will contain the generated random
standard normal deviates.
Description
Function imsl_f_random_normal generates pseudorandom numbers from a standard
normal (Gaussian) distribution using an inverse CDF technique. In this method, a
uniform (0, 1) random deviate is generated. Then, the inverse of the normal distribution
function is evaluated at that point, using the function imsl_f_normal_inverse_cdf.
Deviates from the normal distribution with mean mean and standard deviation
std_dev can be obtained by scaling the output from imsl_f_random_normal. The
following statements (in single precision) would yield random deviates from a normal
(mean, std_dev2) distribution.
float *r;
r = imsl_f_random_normal (n_random, 0);
for (i=0; i<n_random; i++)
r[i] = r[i]*std_dev + mean;
Example
In this example, imsl_f_random_normal is used to generate five pseudorandom
deviates from a standard normal distribution.
#include <imsl.h>
#define N_RANDOM 5
void main()
{
int seed = 123457;
int n_random = N_RANDOM;
float *r;
imsl_random_seed_set (seed);
r = imsl_f_random_normal(n_random, 0);
printf("%s: %8.4f%8.4f%8.4f%8.4f%8.4f\n",
"Standard normal random deviates",
r[0], r[1], r[2], r[3], r[4]);
}
Output
Standard normal random deviates: 1.8279 -0.6412 0.7266 0.1747 1.0145
random_poisson
Generates pseudorandom numbers from a Poisson distribution.
Synopsis
#include <imsl.h>
int *imsl_random_poisson (int n_random, float theta, …, 0)
Required Arguments
int n_random (Input)
Number of random numbers to generate.
float theta (Input)
Mean of the Poisson distribution. The argument theta must be positive.
Return Value
If no optional arguments are used, imsl_random_poisson returns a pointer to a
vector of length n_random containing the random Poisson deviates. To release this
space, use free.
Optional Arguments
IMSL_RETURN_USER, int r[] (Output)
If specified, the vector of length n_random of random Poisson deviates is
returned in the user-provided array r.
Description
The function imsl_random_poisson generates pseudorandom numbers from
a Poisson distribution with positive mean theta. The probability function
(with θ = theta) is
f(x) = (e-qθx)/x!, for x = 0, 1,2, …
Example
In this example, imsl_random_poisson is used to generate five pseudorandom
deviates from a Poisson distribution with mean equal to 0.5.
#include <imsl.h>
#define N_RANDOM 5
void main()
{
int *r;
int seed = 123457;
float theta = 0.5;
imsl_random_seed_set (seed);
r = imsl_random_poisson (N_RANDOM, theta, 0);
imsl_i_write_matrix ("Poisson(0.5) random deviates", 1, 5, r, 0);
}
Output
Poisson(0.5) random deviates
1 2 3 4 5
2 0 1 0 1
random_gamma
Generates pseudorandom numbers from a standard gamma distribution.
Synopsis
#include <imsl.h>
float *imsl_f_random_gamma (int n_random, float a, …, 0)
The type double procedure is imsl_d_random_gamma.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
Return Value
If no optional arguments are used, imsl_f_random_gamma returns a pointer to a
vector of length n_random containing the random standard gamma deviates. To release
this space, use free.
Optional Arguments
IMSL_USER_RETURN, float r[] (Output)
If specified, the vector of length n_random containing the random standard
gamma deviates is returned in the user-provided array r.
Description
The function imsl_f_random_gamma generates pseudorandom numbers from a
gamma distribution with shape parameter a and unit scale parameter. The probability
density function is
b g Γb1ag x
f x = a −1 − x
e for x ≥ 0
Various computational algorithms are used depending on the value of the shape
parameter a. For the special case of a = 0.5, squared and halved normal deviates are
used; and for the special case of a = 1.0, exponential deviates are generated. Otherwise,
if a is less than 1.0, an acceptance-rejection method due to Ahrens, described in Ahrens
and Dieter (1974), is used. If a is greater than 1.0, a ten-region rejection procedure
developed by Schmeiser and Lal (1980) is used.
Deviates from the two-parameter gamma distribution with shape parameter a and scale
parameter b can be generated by using imsl_f_random_gamma and then multiplying
each entry in r by b. The following statements (in single precision) would yield random
deviates from a gamma (a, b) distribution.
float *r;
r = imsl_f_random_gamma(n_random, a, 0);
for (i=0; i<n_random; i++) *(r+i) *= b;
The Erlang distribution is a standard gamma distribution with the shape parameter
having a value equal to a positive integer; hence, imsl_f_random_gamma generates
pseudorandom deviates from an Erlang distribution with no modifications required.
Example
In this example, imsl_f_random_gamma is used to generate five pseudorandom
deviates from a gamma (Erlang) distribution with shape parameter equal to 3.0.
#include <imsl.h>
void main()
{
int seed = 123457;
int n_random = 5;
float a = 3.0;
float *r;
imsl_random_seed_set(seed);
r = imsl_f_random_gamma(n_random, a, 0);
imsl_f_write_matrix("Gamma(3) random deviates", 1, n_random, r, 0);
}
Output
Gamma(3) random deviates
1 2 3 4 5
6.843 3.445 1.853 3.999 0.779
random_beta
Generates pseudorandom numbers from a beta distribution.
Synopsis
#include <imsl.h>
float *imsl_f_random_beta (float n_random, float pin, float qin, …, 0)
The type double function is imsl_d_random_beta.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
float pin (Input)
First beta distribution parameter. Argument pin must be positive.
float qin (Input)
Second beta distribution parameter. Argument qin must be positive.
Optional Arguments
IMSL_RETURN_USER, float r[] (Output)
If specified, the vector of length n_random containing the random standard
beta deviates is returned in r.
Description
The function imsl_f_random_beta generates pseudorandom numbers from a beta
distribution with parameters pin and qin, both of which must be positive. With
p = pin and q = qin, the probability density function is
b g ΓΓbbppgΓ+bqqgg x b1 − xg
f x = p −1 q −1
for 0 ≤ x ≤ 1
main()
{
int n_random = 5;
int seed = 123457;
float pin = 3.0;
float qin = 2.0;
float *r;
imsl_random_seed_set (seed);
r = imsl_f_random_beta (n_random, pin, qin, 0);
imsl_f_write_matrix("Beta (3,2) random deviates", 1, n_random, r, 0);
}
Output
Beta (3,2) random deviates
1 2 3 4 5
0.2814 0.9483 0.3984 0.3103 0.8296
random_exponential
Generates pseudorandom numbers from a standard exponential distribution.
Synopsis
#include <imsl.h>
float *imsl_f_random_exponential (int n_random, …, 0)
The type double function is imsl_d_random_exponential.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
Return Value
A pointer to an array of length n_random containing the random standard exponential
deviates.
Description
Function imsl_f_random_exponential generates pseudorandom numbers from a
standard exponential distribution. The probability density function is f(x) = e-x, for
x > 0. Function imsl_random_exponential uses an antithetic inverse CDF
technique; that is, a uniform random deviate U is generated, and the inverse of the
exponential cumulative distribution function is evaluated at 1.0 − U to yield the
exponential deviate.
Deviates from the exponential distribution with mean θ can be generated by using
imsl_f_random_exponential and then multiplying each entry in r by θ.
Example
In this example, imsl_f_random_exponential is used to generate five
pseudorandom deviates from a standard exponential distribution.
#include <imsl.h>
#define N_RANDOM 5
main()
{
int seed = 123457;
int n_random = N_RANDOM;
float *r;
imsl_random_seed_set(seed);
r = imsl_f_random_exponential(n_random, 0);
printf("%s: %8.4f%8.4f%8.4f%8.4f%8.4f\n",
"Exponential random deviates",
r[0], r[1], r[2], r[3], r[4]);
}
Output
Exponential random deviates: 0.0344 1.3443 0.2662 0.5633 0.1686
Routines
Print a matrix or vector.......................................................... write_matrix 579
Set the page width and length ..........................................................page 585
Set the printing options ....................................................... write_options 586
write_matrix
Prints a rectangular matrix (or vector) stored in contiguous memory locations.
Synopsis
#include <imsl.h>
void imsl_f_write_matrix (char *title, int nra, int nca, float a[], …, 0)
For int a[], use imsl_i_write_matrix.
For double a[], use imsl_d_write_matrix.
For f_complex a[], use imsl_c_write_matrix.
For d_complex a[], use imsl_z_write_matrix.
Required Arguments
char *title (Input)
The matrix title. Use \n within a title to create a new line. Long titles are
automatically wrapped.
int nra (Input)
The number of rows in the matrix.
int nca (Input)
The number of columns in the matrix.
float a[] (Input)
Array of size nra × nca containing the matrix to be printed.
Optional Arguments
IMSL_TRANSPOSE
Print aT.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of a.
Default: a_col_dim = nca
IMSL_PRINT_ALL, or
IMSL_PRINT_LOWER, or
IMSL_PRINT_UPPER, or
IMSL_PRINT_LOWER_NO_DIAG, or
IMSL_PRINT_UPPER_NO_DIAG
Exactly one of these optional arguments can be specified in order to indicate
that either a triangular part of the matrix or the entire matrix is to be printed.
If omitted, the entire matrix is printed.
Keyword Action
IMSL_PRINT_ALL The entire matrix is printed (the default).
IMSL_PRINT_LOWER The lower triangle of the matrix is printed,
including the diagonal.
Description
The function imsl_write_matrix prints a real rectangular matrix (stored in a) with
optional row and column labels (specified by rlabel and clabel, respectively,
Examples
Example 1
This example is representative of the most common situation in which no optional
arguments are given.
#include <imsl.h>
#define NRA 3
#define NCA 4
main()
{
int i, j;
f_complex a[NRA][NCA];
4
1 ( 1.4, 98.6)
2 ( 2.4, 97.6)
3 ( 3.4, 96.6)
Example 2
In this example, some of the optional arguments available in the write_matrix
functions are demonstrated.
#include <imsl.h>
#define NRA 3
#define NCA 4
main()
{
int i, j;
float a[NRA][NCA];
char *fmt = "%10.6W";
char *rlabel[] = {"row 1", "row 2", "row 3"};
char *clabel[] = { "", "col 1", "col 2", "col 3", "col 4"};
Output
matrix
a
col 2 col 3 col 4
row 1 1.2 1.3 1.4
row 2 2.3 2.4
row 3 3.4
Example 3
In this example, a row vector of length four is printed.
#define NRA 1
#define NCA 4
main()
{
int i;
float a[NCA];
char *clabel[] = {"", "col 1", "col 2", "col 3", "col 4"};
page
Sets or retrieves the page width or length.
Synopsis
#include <imsl.h>
void imsl_page (Imsl_page_options option, int *page_attribute)
Required Arguments
Imsl_page_options option (Input)
Option giving which page attribute is to be set or retrieved. The possible
values are:
option Description
IMSL_SET_PAGE_WIDTH Set the page width.
IMSL_GET_PAGE_WIDTH Retrieve the page width.
IMSL_SET_PAGE_LENGTH Set the page length.
IMSL_GET_PAGE_LENGTH Retrieve the page length.
#define NRA 3
#define NCA 4
main()
{
int i, j, page_attribute;
float a[NRA][NCA];
Output
a
1 2 3
1 1.1 1.2 1.3
2 2.1 2.2 2.3
3 3.1 3.2 3.3
4
1 1.4
2 2.4
3 3.4
write_options
Sets or retrieves an option for printing a matrix.
Synopsis
#include <imsl.h>
void imsl_write_options (Imsl_write_options option, int* option_value)
Description
The function imsl_write_options allows the user to set or retrieve an option for
printing a matrix. Options controlled by imsl_write_options are horizontal
centering, method for printing large matrices, paging, method for printing NaN
(not a number), method for printing titles, and the default format for real and complex
numbers. (NaN can be retrieved by functions imsl_f_machine and
imsl_d_machine, Chapter 12, “Utilities.”)
The w conversion character used by the FORMAT option is a special conversion character
that can be used to automatically select a pretty C conversion specification ending in
Example
The following example illustrates the effect of imsl_write_options when printing a
3 × 4 real matrix A with IMSL function imsl_f_write_matrix, where aij = i + j/10.
The first call to imsl_write_options sets horizontal centering so that the matrix is
printed centered horizontally on the page. In the next invocation of
imsl_f_write_matrix, the left-justification option has been set via function
imsl_write_options, so the matrix is left justified when printed.
#include <imsl.h>
#define NRA 4
#define NCA 3
main()
{
int i, j, option_value;
float a[NRA][NCA];
Output
a
1 2 3
1 1.1 1.2 1.3
2 2.1 2.2 2.3
3 3.1 3.2 3.3
4 4.1 4.2 4.3
a
1 2 3
1 1.1 1.2 1.3
2 2.1 2.2 2.3
3 3.1 3.2 3.3
4 4.1 4.2 4.3
Routines
12.1 Set Output Files
Set output files................................................................. output_file 594
Get library version and license number ................................ version 598
12.2 Time and Date
CPU time used ........................................................................ ctime 599
Date to days since epoch ........................................... date_to_days 599
Days since epoch to date ........................................... days_to_date 601
12.3 Error Handling
Error message options ............................................... error_options 602
Get error code ................................................................ error_code 608
12.4 Constants
Natural and mathematical constants .................................. constant 609
Integer machine constants ...................................machine (integer) 613
Float machine constants...........................................machine (float) 615
12.5 Sorting
Sort float vector ..........................................................................sort 618
Sort integer vector ....................................................... sort (integer) 620
12.6 Computing Vector Norms
Compute various norms ...............................................vector_norm 623
12.7 Linear Algebra Support
Vector-Vector, Matrix-Vector, and Matrix-Matrix-Multiplication
Real Matrix..................................................................mat_mul_rect 625
Complex matrix..........................................mat_mul_rect (complex) 628
Real band matrix ..............................................mat_mul_rect_band 632
Complex band matrix.......................mat_mul_rect_band (complex) 636
Real coordinate matrix.............................mat_mul_rect_coordinate 641
Complex coordinate matrix.....mat_mul_rect_coordinate (complex) 645
output_file
Sets the output file or the error message output file.
Optional Arguments
IMSL_SET_OUTPUT_FILE, FILE *ofile (Input)
Set the output file to ofile.
Default: ofile = stdout
IMSL_GET_OUTPUT_FILE, FILE **pfile (Output)
Set the FILE pointed to by pfile to the current output file.
IMSL_SET_ERROR_FILE, FILE *efile (Input)
Set the error message output file to efile.
Default: efile = stderr
IMSL_GET_ERROR_FILE, FILE **pefile (Output)
Set the FILE pointed to by pefile to the error message output file.
Description
This function allows the file used for printing by IMSL routines to be changed.
Examples
Example 1
This example opens the file myfile and changes the output file to this new file.
The function imsl_f_write_matrix then writes to this file.
#include <stdio.h>
#include <imsl.h>
main()
{
FILE *ofile;
float x[] = {3.0, 2.0, 1.0};
Output
x (default file)
1 2 3
3 2 1
File myfile
x (myfile)
1 2 3
3 2 1
Example 2
The following example illustrates how to direct output from IMSL routines that
run in separate threads to different files. First, two threads are created, each
calling a different IMSL function, then the results are printed by calling
imsl_f_write_matrix from within each thread. Note that
imsl_output_file is called from within each thread to change the default
output file.
#include <pthread.h>
#include <stdio.h>
#include "imsl.h"
if (rand_nums) free(rand_nums);
fclose(file_ptr);
if (x) free(x);
fclose(file_ptr);
}
Output
[Link]
Random Numbers
1 0.0966
2 0.8340
3 0.9477
4 0.0359
5 0.0115
[Link]
Solution, x, of Ax = b
1 2 3
-2 -2 3
Synopsis
#include <imsl.h>
char* imsl_version (Imsl_keyword code)
Required Arguments
Imsl_keyword code (Input)
Index indicating which value is to be returned. It must be
IMSL_LIBRARY_VERSION, IMSL_OS_VERSION,
IMSL_COMPILER_VERSION, or IMSL_LICENSE_NUMBER.
Return Value
The requested value is returned. If code is out of range, then NULL is returned.
Use free to release the returned string.
Description
The function imsl_version returns information describing the version of this
library, the version of the operating system under which it was compiled, the
compiler used, and the IMSL number.
Example
This example prints all the values returned by imsl_version on a particular
machine. The output is omitted because the results are system dependent.
#include <imsl.h>
main()
{
char *library_version, *os_version;
char *compiler_version, *license_number;
library_version = imsl_version(IMSL_LIBRARY_VERSION);
os_version = imsl_version(IMSL_OS_VERSION);
compiler_version = imsl_version(IMSL_COMPILER_VERSION);
license_number = imsl_version(IMSL_LICENSE_NUMBER);
Synopsis
#include <imsl.h>
double imsl_ctime ( )
Return Value
The number of CPU seconds used so far by the program.
Example
The CPU time needed to compute
å
1,000 ,000
k
k =0
is obtained and printed. The time needed is, of course, machine dependent. The
CPU time needed will also vary slightly from run to run on the same machine.
#include <imsl.h>
main()
{
int k;
double sum, time;
/* Sum 1 million values */
for (sum=0, k=1; k<=1000000; k++)
sum += k;
/* Get amount of CPU time used */
time = imsl_ctime();
printf("sum = %f\n", sum);
printf("time = %f\n", time);
}
Output
sum = 500000500000.000000
time = 2.260000
date_to_days
Computes the number of days from January 1, 1900, to the given date.
Synopsis
#include <imsl.h>
Required Arguments
int day (Input)
Day of the input date.
int month (Input)
Month of the input date.
int year (Input)
Year of the input date. The year 1950 would correspond to the year
1950 A.D., and the year 50 would correspond to year 50 A.D.
Return Value
Number of days from January 1, 1900, to the given date. If negative, it indicates
the number of days prior to January 1, 1900.
Description
The function imsl_date_to_days returns the number of days from January 1,
1900, to the given date. The function imsl_date_to_days returns negative
values for days prior to January 1, 1900. A negative year can be used to specify
B.C. Input dates in year 0 and for October 5, 1582, through October 14, 1582,
inclusive, do not exist; consequently, in these cases, imsl_date_to_days
issues a terminal error.
The beginning of the Gregorian calendar was the first day after October 4, 1582,
which became October 15, 1582. Prior to that, the Julian calendar was in use.
Example
The following example uses imsl_date_to_days to compute the number of
days from January 15, 1986, to February 28, 1986.
#include <imsl.h>
main()
{
int day0, day1;
Output
Number of days = 44
Synopsis
#include <imsl.h>
void imsl_days_to_date (int days, int *day, int *month, int *year)
Required Arguments
int days (Input)
Number of days since January 1, 1900.
int *day (Output)
Day of the output date.
int *month (Output)
Month of the output date.
int *year (Output)
Year of the output date. The year 1950 would correspond to the year
1950 A.D., and the year 50 would correspond to year 50 A.D.
Description
The function imsl_days_to_date computes the date corresponding to the
number of days since January 1, 1900. For a negative input value of days, the
date computed is prior to January 1, 1900. This function is the inverse of function
imsl_date_to_days.
The beginning of the Gregorian calendar was the first day after October 4, 1582,
which became October 15, 1582. Prior to that, the Julian calendar was in use.
Example
The following example uses imsl_days_to_date to compute the date for the
100th day of 1986. This is accomplished by first using IMSL function
imsl_date_to_ days to get the “day number” for December 31, 1985.
#include <imsl.h>
main()
{
int day0, day, month, year;
error_options
Sets various error handling options.
Synopsis with Optional Arguments
#include <imsl.h>
void imsl_error_options (
IMSL_SET_PRINT, Imsl_error type, int setting,
IMSL_SET_STOP, Imsl_error type, int setting,
IMSL_SET_TRACEBACK, Imsl_error type, int setting,
IMSL_FULL_TRACEBACK, int setting,
IMSL_GET_PRINT, Imsl_error type, int *psetting,
IMSL_GET_STOP, Imsl_error type, int *psetting,
IMSL_GET_TRACEBACK, Imsl_error type, int *psetting,
IMSL_SET_ERROR_FILE, FILE *file,
IMSL_GET_ERROR_FILE, FILE **pfile,
IMSL_ERROR_MSG_PATH, char *path,
IMSL_ERROR_MSG_NAME, char *name,
IMSL_ERROR_PRINT_PROC, Imsl_error_print_proc print_proc,
IMSL_SET_SIGNAL_TRAPPING, int setting,
0)
Optional Arguments
IMSL_SET_PRINT, Imsl_error type, int setting (Output)
Printing of type type error messages is turned off if setting is 0;
otherwise, printing is turned on.
Default: Printing turned on for IMSL_WARNING, IMSL_FATAL,
IMSL_TERMINAL, IMSL_FATAL_IMMEDIATE, and
IMSL_WARNING_IMMEDIATE messages
IMSL_SET_STOP, Imsl_error type, int setting (Input)
Stopping on type type error messages is turned off if setting is 0;
otherwise, stopping is turned on.
Default: Stopping turned on for IMSL_FATAL, IMSL_TERMINAL, and
IMSL_FATAL_IMMEDIATE messages
IMSL_SET_TRACEBACK, Imsl_error type, int setting (Input)
Printing of a traceback on type type error messages is turned off if
setting is 0; otherwise, printing of the traceback turned on.
Default: Traceback turned off for all message types
IMSL_FULL_TRACEBACK, int setting (Input)
Only documented functions are listed in the traceback if setting is 0;
Description
This function allows the error handling system to be customized.
If multiple threads are used then default settings are valid for each thread but can
be altered for each individual thread. When using threads it is necessary to set
options (excluding IMSL_SET_SIGNAL_TRAPPING ) for each thread by calling
imsl_error_options from within each thread.
The IMSL signal-trapping mechanism must be disabled when multiple threads are
used. The IMSL signal-trapping mechanism can be disabled by making the
following call before any threads are created:
imsl_error_options(IMSL_SET_SIGNAL_TRAPPING, 0, 0);
See Examples 3 and 4 for multithreaded examples.
Examples
Example 1
In this example, the IMSL_TERMINAL print setting is retrieved. Next, stopping on
IMSL_TERMINAL errors is turned off, then output to standard output is redirected,
and an error is deliberately caused by calling imsl_error_options with an
illegal value.
#include <imsl.h>
#include <stdio.h>
main()
{
int setting;
/* Turn off stopping on IMSL_TERMINAL */
/* error messages and write error */
/* messages to standard output */
imsl_error_options(IMSL_SET_STOP, IMSL_TERMINAL, 0,
IMSL_SET_ERROR_FILE, stdout,
0);
/* Call imsl_error_options() with */
/* an illegal value */
imsl_error_options(-1);
/* Get setting for IMSL_TERMINAL */
imsl_error_options(IMSL_GET_PRINT, IMSL_TERMINAL, &setting,
0);
printf("IMSL_TERMINAL error print setting = %d\n", setting);
}
Output
*** TERMINAL Error from imsl_error_options. There is an error with
*** argument number 1. This may be caused by an incorrect number of
Example 2
In this example, IMSL’s error printing function has been substituted for the
standard function. Only the first four lines are printed below.
#include <imsl.h>
#include <stdio.h>
main()
{
/* Turn off tracebacks on IMSL_TERMINAL */
/* error messages and use a custom */
/* print function */
imsl_error_options(IMSL_ERROR_PRINT_PROC, print_proc,
0);
/* Call imsl_error_options() with an */
/* illegal value */
imsl_error_options(-1);
}
Output
Error message type 5
Error code 103
From function imsl_error_options
There is an error with argument number 1. This may be caused by an
incorrect number of values following a previous optional argument name.
Example 3
In this example, two threads are created and error options is called within each
thread to set the error handling options differently for each thread. Since we
expect to generate terminal errors in each thread, we must turn off stopping on
terminal errors for each thread. Also notice that imsl_error_options is called
from main to disable the IMSL signal-trapping mechanism. See Example 4 for a
similar example using WIN32 threads. Note since multiple threads are executing,
the order of the errors output may differ on some systems.
#include <pthread.h>
void main()
{
pthread_t thread1;
pthread_t thread2;
res = imsl_f_gamma(-1.0);
}
*** TERMINAL Error from imsl_f_gamma. The argument for the function can not
*** be a negative integer. Argument "x" = -1.000000e+00.
Example 4
In this example the WIN32 API is used to demonstrate the same functionality as
shown in Example 3 above. Note since multiple threads are executing, the order
of the errors output may differ on some systems.
#include <windows.h>
#include <stdio.h>
#include "imsl.h"
imsl_error_options(IMSL_SET_SIGNAL_TRAPPING, 0, 0);
}
DWORD WINAPI ex1(void *arg)
{
float res;
/*
* Call imsl_error_options to set the error handling
* options for this thread.
*/
imsl_error_options(IMSL_SET_STOP, IMSL_TERMINAL, 0, 0);
res = imsl_f_beta(-1.0, .5);
return(0);
}
DWORD WINAPI ex2(void *arg)
{
float res;
/*
Output
*** TERMINAL Error from imsl_f_gamma. The argument for the function can not
*** be a negative integer. Argument "x" = -1.000000e+00.
*** TERMINAL Error from imsl_f_beta. Both "x" = -1.000000e+00 and "y" =
*** 5.000000e-01 must be greater than zero.
error_code
Gets the code corresponding to the error message from the last function called.
Synopsis
#include <imsl.h>
long imsl_error_code ( )
Return Value
This function returns the error message code from the last IMSL function called.
The include file imsl.h defines a name for each error code.
Example
This example turns off stopping on IMSL_TERMINAL error messages and
generates an error by calling imsl_error_options with an illegal value for
IMSL_SET_PRINT. The error message code number is retrieved and printed. In
imsl.h, IMSL_INTEGER_OUT_OF_RANGE is defined to be 132.
#include <imsl.h>
#include <stdio.h>
main()
{
Output
*** TERMINAL Error from imsl_error_options."type" must be between 1 and 5,
*** but "type" = 100.
constant
Returns the value of various mathematical and physical constants.
Synopsis
#include <imsl.h>
float imsl_f_constant (char name, char unit)
The type double function is imsl_d_constant.
Required Arguments
char *name (Input)
Character string containing the name of the desired constant. The case of
the character string name does not matter. The names “PI”, “Pi”, “pI”,
and “pi” are equivalent. Spaces and underscores are allowed and
ignored.
char *unit (Input)
Character string containing the units of the desired constant. If NULL,
then Système International d’Unités (SI) units are assumed. The case of
the character string unit does not matter. The names “METER”,
“Meter” and “meter” are equivalent. unit has the form U1*U2*...
*Um/V1/.../Vn, where Ui and Vi are the names of basic units or are
the names of basic units raised to a power. Basic units must be separated
by * or /. Powers are indicated by ^, as in “m^2” for m2. Examples are,
“METER*KILOGRAM/SECOND”, “M*KG/S”, “METER”, or “M/KG^2”.
Description
The names allowed are listed in the following table. Values marked with a ‡ are exact
(to machine precision). The references in the right-hand column are indicated by the
code numbers: [1] for Cohen and Taylor (1986), [2] for Liepman (1964), and [3] for
precomputed mathematical constants.
Unit Description
Time day, hour = hr, min, minute, s = sec = second, year
Frequency Hertz = Hz
Mass AMU, g = gram, lb = pound, ounce = oz, slug
Distance Angstrom, AU, feet = foot, in = inch, m = meter = metre, micron, mile,
mill, parsec, yard
Area acre
Volume 1 = liter=litre
Force dyne, N = Newton
Energy BTU, Erg, J = Joule
Work W = watt
Pressure ATM = atmosphere, bar
Temperature degC = Celsius, degF = Fahrenheit, degK = Kelvin
Viscosity poise, stoke
Charge Abcoulomb, C = Coulomb, statcoulomb
Current A = ampere, abampere, statampere
Voltage Abvolt, V = volt
Magnetic induction T = Telsa, Wb = Weber
Other units I, farad, mole, Gauss, Henry, Maxwell, Ohm
The following metric prefixes may be used with the above units. The one or two
letter prefixes may only be used with one letter unit abbreviations.
Examples
Example 1
In this example, Euler’s constant γ is obtained and printed. Euler’s constant is
defined to be
LM 1 − ln nOP
n −1
γ = lim
n →∞ MNå k PQ
k =1
#include <stdio.h>
#include <imsl.h>
main()
{
float gamma;
/* Get gamma */
gamma = imsl_f_constant("gamma", 0);
/* Print gamma */
printf("gamma = %f\n", gamma);
}
Output
gamma = 0.577216
Example 2
In this example, the speed of light is obtained using several different units.
#include <stdio.h>
#include <imsl.h>
main()
{
float speed_light;
/* Get speed of light in meters/second */
speed_light = imsl_f_constant("Speed Light", "meter/second");
printf("speed of light = %g meter/second\n", speed_light);
Output
speed of light = 2.99792e+08 meter/second
speed of light = 186282 mile/second
speed of light = 29.9793 cm/ns
Warning Errors
IMSL_MASS_TO_FORCE A conversion of units of mass to units of force
was required for consistency.
machine (integer)
Returns integer information describing the computer’s arithmetic.
Synopsis
#include <imsl.h>
int imsl_i_machine (int n)
Required Arguments
int n (Input)
Index indicating which value is to be returned. It must be between 0 and
12.
Return Value
The requested value is returned. If n is out of range, then NaN is returned.
Description
The function imsl_i_machine returns information describing the computer’s
arithmetic. This can be used to make programs machine independent.
imsl_1_machine(0) = Number of bits per byte
Assume that integers are represented in M-digit, base-A form as
å
M
σ x Ak
k =0 k
å
N −k
σB E x B
k =1 k
where σ is the sign and 0 ≤ xk < B for k = 1, …, N for and E$ ≤ E ≤ E". Then,
n Definition
6 B, the base
7 Nf, the number of base-B digits in float
8 E min f , the smallest float exponent
main()
{
int n, ans;
Output
imsl_i_machine(0) = 8
imsl_i_machine(1) = 2
imsl_i_machine(2) = 15
imsl_i_machine(3) = 32767
imsl_i_machine(4) = 31
imsl_i_machine(5) = 2147483647
imsl_i_machine(6) = 2
imsl_i_machine(7) = 24
imsl_i_machine(8) = -125
imsl_i_machine(9) = 128
imsl_i_machine(10) = 53
imsl_i_machine(11) = -1021
imsl_i_machine(12) = 1024
machine (float)
Returns information describing the computer’s floating-point arithmetic.
Synopsis
#include <imsl.h>
float imsl_f_machine (int n)
The type double function is imsl_d_machine.
Required Arguments
int n (Input)
Index indicating which value is to be [Link] index must be
between 1 and 8.
Return Value
The requested value is returned. If n is out of range, then NaN is returned.
å
Nf
σB E x B−k
k =1 k
and
E max f = imsl_ i_ machine(9)
The ANSI/IEEE Std 754-1985 standard for binary arithmetic uses NaN (not a
number) as the result of various otherwise illegal operations, such as computing
0/0. On computers that do not support NaN, a value larger than
imsl_d_machine(2) is returned for imsl_f_machine(6). On computers that do
not have a special representation for infinity, imsl_f_machine(2) returns the
same value as imsl_f_machine(7).
The function imsl_f_machine is defined by the following table:
n Definition
1 Emin f −1
B , the smallest positive number
2 B
Emax f
(1− B
-N f
), the largest number
3 −N f
B , the smallest relative spacing
4 1− N f
B , the largest relative spacing
5 log10(B)
6 NaN (not a number)
7 positive machine infinity
8 negative machine infinity
and
E max f = imsl_ i_ machine(12)
Missing values in IMSL functions are always indicated by NaN (Not a Number).
This is imsl_f_machine(6) in single precision and imsl_d_machine(6) in
double. There is no missing-value indicator for integers. Users will almost always
have to convert from their missing value indicators to NaN.
Example
This example prints all eight values returned by imsl_f_machine and by
imsl_d_machine on a machine with IEEE arithmetic.
#include <imsl.h>
main()
{
int n;
float fans;
double dans;
Output
imsl_f_machine(1) = 1.17549e-38
imsl_f_machine(2) = 3.40282e+38
imsl_f_machine(3) = 5.96046e-08
imsl_f_machine(4) = 1.19209e-07
imsl_f_machine(5) = 0.30103
imsl_f_machine(6) = NaN
imsl_f_machine(7) = Inf
imsl_f_machine(8) = -Inf
imsl_d_machine(1) = 2.22507e-308
imsl_d_machine(2) = 1.79769e+308
imsl_d_machine(3) = 1.11022e-16
imsl_d_machine(4) = 2.22045e-16
imsl_d_machine(5) = 0.30103
imsl_d_machine(6) = NaN
sort
Sorts a vector by algebraic value. Optionally, a vector can be sorted by absolute
value, and a sort permutation can be returned.
Synopsis
#include <imsl.h>
float *imsl_f_sort (int n, float *x, …, 0)
The type double function is imsl_d_sort.
Required Arguments
int n (Input)
The length of the input vector.
float *x (Input)
Input vector to be sorted.
Return Value
A vector of length n containing the values of the input vector x sorted into
ascending order. If an error occurs, then NULL is returned.
Optional Arguments
IMSL_ABSOLUTE
Sort x by absolute value.
IMSL_PERMUTATION, int **perm (Output)
Return a pointer to the sort permutation.
IMSL_PERMUTATION_USER, int perm_user[] (Output)
Return the sort permutation in user-supplied space.
Description
By default, imsl_f_sort sorts the elements of x into ascending order by
algebraic value. The vector is divided into two parts by choosing a central
element T of the vector. The first and last elements of x are compared with T and
exchanged until the three values appear in the vector in ascending order. The
elements of the vector are rearranged until all elements greater than or equal to
the central elements appear in the second part of the vector and all those less than
or equal to the central element appear in the first part. The upper and lower
subscripts of one of the segments are saved, and the process continues iteratively
on the other segment. When one segment is finally sorted, the process begins
again by retrieving the subscripts of another unsorted portion of the vector. On
completion, xj ≤ xi for j < i. If the option IMSL_ABSOLUTE is selected, the
elements of x are sorted into ascending order by absolute value. If we denote the
return vector by y, on completion, |yj| ≤ |yi| for j < i.
If the option IMSL_PERMUTATION is chosen, a record of the permutations to the
array x is returned. That is, after the initialization of permi = i, the elements of
perm are moved in the same manner as are the elements of x.
Examples
Example 1
In this example, an input vector is sorted algebraically.
#include <stdio.h>
#include <imsl.h>
main()
{
float x[] = {1.0, 3.0, -2.0, 4.0};
float *sorted_result;
int n;
n = 4;
sorted_result = imsl_f_sort (n, x, 0);
Output
Sorted vector
1 2 3 4
-2 1 3 4
main()
{
float x[] = {1.0, 3.0, -2.0, 4.0};
float sorted_result[4];
int n;
n = 4;
imsl_f_sort (n, x,
IMSL_ABSOLUTE,
IMSL_RETURN_USER, sorted_result,
0);
Output
Sorted vector
1 2 3 4
1 -2 3 4
sort (integer)
Sorts an integer vector by algebraic value. Optionally, a vector can be sorted by
absolute value, and a sort permutation can be returned.
Synopsis
#include <imsl.h>
int *imsl_i_sort (int n, int *x, …, 0)
Required Arguments
int n (Input)
The length of the input vector.
int *x (Input)
Input vector to be sorted.
Return Value
A vector of length n containing the values of the input vector x sorted into
ascending order. If an error occurs, then NULL is returned.
Optional Arguments
IMSL_ABSOLUTE
Sort x by absolute value.
IMSL_PERMUTAION, int **perm (Output)
Return a pointer to the sort permutation.
IMSL_PERMUTATION_USER, int perm_user[] (Output)
Return the sort permutation in user-supplied space.
IMSL_RETURN_USER, int y[] (Output)
Return the sorted data in user-supplied space.
Description
By default, imsl_i_sort sorts the elements of x into ascending order by
algebraic value. The vector is divided into two parts by choosing a central
element T of the vector. The first and last elements of x are compared with T and
exchanged until the three values appear in the vector in ascending order. The
elements of the vector are rearranged until all elements greater than or equal to
the central elements appear in the second part of the vector and all those less than
or equal to the central element appear in the first part. The upper and lower
subscripts of one of the segments are saved, and the process continues iteratively
on the other segment. When one segment is finally sorted, the process begins
again by retrieving the subscripts of another unsorted portion of the vector. On
completion, xj ≤ xi for j < i. If the option IMSL_ABSOLUTE is selected, the
elements of x are sorted into ascending order by absolute value. If we denote the
return vector by y, on completion, |yj| ≤ |yi| for j < i.
If the option IMSL_PERMUTATION is chosen, a record of the permutations to the
array
x is returned. That is, after the initialization of permi = i, the elements of perm
are moved in the same manner as are the elements of x.
Example 1
In this example, an input vector is sorted algebraically.
#include <stdio.h>
#include <imsl.h>
main()
{
int x[] = {1, 3, -2, 4};
int *sorted_result;
int n;
n = 4;
sorted_result = imsl_i_sort (n, x, 0);
Output
Sorted vector
1 2 3 4
-2 1 3 4
Example 2
This example sorts an input vector by absolute value and prints the result stored in
user-allocated space.
#include <stdio.h>
#include <imsl.h>
main()
{
int x[] = {1, 3, -2, 4};
int sorted_result[4];
int n;
n = 4;
imsl_i_sort (n, x,
IMSL_ABSOLUTE,
IMSL_RETURN_USER, sorted_result,
0);
Synopsis
#include <imsl.h>
float imsl_f_vector_norm (int n, float *x, …., 0)
The type double function is imsl_d_vector_norm.
Required Arguments
int n (Input)
The length of the input vector(s).
float *x (Input)
Input vector for which the norm is to be computed
Return Value
The requested norm of the input vector. If the norm cannot be computed, NaN is
returned.
Synopsis with Optional Arguments
#include <imsl.h>
float imsl_f_vector_norm (int n, float *x,
IMSL_ONE_NORM,
IMSL_INF_NORM,
IMSL_SECOND_VECTOR, float *y,
0)
Description
By default, imsl_f_vector_norm computes the Euclidean norm
1
F xI
n −1 2
GH å JK
i =0
2
i
åx
i =0
i
Examples
Example 1
In this example, the Euclidean norm of an input vector is computed.
#include <stdio.h>
#include "imsl.h"
main()
{
float x[] = {1.0, 3.0, -2.0, 4.0};
float norm;
int n;
n = sizeof(x)/sizeof(*x);
norm = imsl_f_vector_norm (n, x, 0);
Output
Euclidean norm of x = 5.477226
Example 2
This example computes max |xi − yi| and prints the norm and index.
#include <stdio.h>
#include "imsl.h"
main()
{
float x[] = {1.0, 3.0, -2.0, 4.0};
float y[] = {4.0, 2.0, -1.0, -5.0};
float norm;
int index;
int n;
n = sizeof(x)/sizeof(*x);
norm = imsl_f_vector_norm (n, x,
IMSL_SECOND_VECTOR, y,
IMSL_INF_NORM, &index, 0);
Output
Infinity norm of x-y = 9.000000 at location 3
Synopsis
#include <imsl.h>
float *imsl_f_mat_mul_rect (char *string, …, 0)
The type double procedure is imsl_d_mat_mul_rect.
Required Arguments
char *string (Input)
String indicating matrix multiplication to be performed.
Return Value
The result of the multiplication. This is always a pointer to a float, even if the
result is a single number. To release this space, use free. If no answer was
computed, then NULL is returned.
Optional Arguments
IMSL_A_MATRIX, int nrowa, int ncola, float a[] (Input)
The nrowa × ncola matrix A.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of A.
Default: a_col_dim = ncola
IMSL_B_MATRIX, int nrowb, int ncolb, float b[] (Input)
The nrowb × ncolb matrix A.
Description
This function computes a matrix-vector product, a matrix-matrix product, a
bilinear form of a matrix, or a triple product according to the specification given
by string. For example, if “A*x” is given, Ax is computed. In string, the
matrices A and B and the vectors x and y can be used. Any of these four names
can be used with trans, indicating transpose. The vectors x and y are treated as
n × 1 matrices.
If string contains only one item, such as “x” or “trans(A)”, then a copy of the
array, or its transpose, is returned. If string contains one multiplication, such as
“A*x” or “B*A”, then the indicated product is returned. Some other legal values
for string are “trans(y)*A”, “A*trans(B)”, “x*trans(y)”, or
“trans(x)*y”.
The matrices and/or vectors referred to in string must be given as optional
arguments. If string is “B*x”, then IMSL_B_MATRIX and IMSL_X_VECTOR
must be given.
Example
Let
main()
{
float A[] = {1, 2, 9,
ans = imsl_f_mat_mul_rect("trans(A)",
IMSL_A_MATRIX, 2, 3, A,
0);
imsl_f_write_matrix("trans(A)", 3, 2, ans, 0);
ans = imsl_f_mat_mul_rect("A*x",
IMSL_A_MATRIX, 2, 3, A,
IMSL_X_VECTOR, 3, x,
0);
imsl_f_write_matrix("A*x", 1, 2, ans, 0);
ans = imsl_f_mat_mul_rect("trans(x)*trans(A)",
IMSL_A_MATRIX, 2, 3, A,
IMSL_X_VECTOR, 3, x,
0);
imsl_f_write_matrix("trans(x)*trans(A)", 1, 2, ans, 0);
ans = imsl_f_mat_mul_rect("A*B",
IMSL_A_MATRIX, 2, 3, A,
IMSL_B_MATRIX, 3, 2, B,
0);
imsl_f_write_matrix("A*B", 2, 2, ans, 0);
ans = imsl_f_mat_mul_rect("trans(B)*trans(A)",
IMSL_A_MATRIX, 2, 3, A,
IMSL_B_MATRIX, 3, 2, B,
0);
imsl_f_write_matrix("trans(B)*trans(A)", 2, 2, ans, 0);
ans = imsl_f_mat_mul_rect("trans(x)*y",
IMSL_X_VECTOR, 3, x,
IMSL_Y_VECTOR, 3, y,
0);
imsl_f_write_matrix("trans(x)*y", 1, 1, ans, 0);
ans = imsl_f_mat_mul_rect("x*trans(y)",
IMSL_X_VECTOR, 3, x,
IMSL_Y_VECTOR, 3, y,
0);
imsl_f_write_matrix("x*trans(y)", 3, 3, ans, 0);
ans = imsl_f_mat_mul_rect("trans(x)*A*y",
IMSL_A_MATRIX, 2, 3, A,
/* use only the first 2 components of x */
IMSL_X_VECTOR, 2, x,
IMSL_Y_VECTOR, 3, y,
0);
imsl_f_write_matrix("trans(x)*A*y", 1, 1, ans, 0);
}
A*x
1 2
20 50
trans(x)*trans(A)
1 2
20 50
A*B
1 2
1 98 19
2 106 33
trans(B)*trans(A)
1 2
1 98 106
2 19 33
trans(x)*y
31
x*trans(y)
1 2 3
1 21 28 14
2 6 8 4
3 3 4 2
trans(x)*A*y
293
mat_mul_rect (complex)
Computes the transpose of a matrix, the conjugate-transpose of a matrix, a matrix-
vector product, a matrix-matrix product, the bilinear form, or any triple product.
Synopsis
#include <imsl.h>
f_complex *imsl_c_mat_mul_rect (char *string, …, 0)
The type d_complex function is imsl_z_mat_mul_rect.
Return Value
The result of the multiplication. This is always a pointer to a f_complex, even if
the result is a single number. To release this space, use free. If no answer was
computed, then NULL is returned.
Optional Arguments
IMSL_A_MATRIX, int nrowa, int ncola, f_complex *a (Input)
The nrowa × ncola matrix A.
IMSL_A_COL_DIM, int a_col_dim (Input)
The column dimension of A.
Default: a_col_dim = ncola
IMSL_B_MATRIX, int nrowb, int ncolb, f_complex *b (Input)
The nrowb × ncolb matrix B.
IMSL_B_COL_DIM, int b_col_dim (Input)
The column dimension of B.
Default: b_col_dim = ncolb
IMSL_X_VECTOR, int nx, f_complex *x (Input)
The vector x of size nx.
IMSL_Y_VECTOR, int ny, f_complex *y (Input)
The vector y of size ny.
IMSL_RETURN_USER, f_complex ans[] (Output)
A user-allocated array containing the result.
Description
This function computes a matrix-vector product, a matrix-matrix product, a
bilinear form of a matrix, or a triple product according to the specification given
by string. For example, if “A*x” is given, Ax is computed. In string, the
matrices A and B and the vectors x and y can be used. Any of these four names
can be used with trans, indicating transpose, or with ctrans, indicating
conjugate (or Hermitian) transpose. The vectors x and y are treated as n × 1
matrices.
If string contains only one item, such as “x” or “trans(A)”, then a copy of
the array, or its transpose, is returned. If string contains one multiplication, such
as “A*x” or “B*A”, then the indicated product is returned. Some other legal values
for string are “trans(y)*A”, “A*ctrans(B)”, “x*trans(y)”, or
“ctrans(x)*y”.
The matrices and/or vectors referred to in string must be given as optional
arguments. If string is “B*x”, then IMSL_B_MATRIX and IMSL_X_VECTOR
must be given.
Example
Let
L1 + 4i 2 + 3i 9 + 6i OP LM3 − 6i 2 + 4i OP
A=M B = M7 + 3i 4 − 5i P
N5 + 2i 4 − 3i 7+i Q
MN9 + 2i 1 + 3i PQ
LM7 + 4i OP LM3 + 4i OP
x = M2 + 2i P y = M4 − 2i P
MN 1 − 5i PQ MN2 + 3i PQ
The arrays AH, Ax, xTAT, AB, BHAT, xTy, and xyH are computed and printed.
#include <imsl.h>
main()
{
f_complex A[] = {{1,4}, {2, 3}, {9,6},
{5,2}, {4,-3}, {7,1}};
ans = imsl_c_mat_mul_rect("ctrans(A)",
IMSL_A_MATRIX, 2, 3, A,
0);
imsl_c_write_matrix("ctrans(A)", 3, 2, ans, 0);
ans = imsl_c_mat_mul_rect("A*x",
IMSL_A_MATRIX, 2, 3, A,
IMSL_X_VECTOR, 3, x,
0);
imsl_c_write_matrix("A*x", 1, 2, ans, 0);
ans = imsl_c_mat_mul_rect("trans(x)*trans(A)",
IMSL_A_MATRIX, 2, 3, A,
IMSL_X_VECTOR, 3, x,
0);
imsl_c_write_matrix("trans(x)*trans(A)", 1, 2, ans, 0);
ans = imsl_c_mat_mul_rect("A*B",
IMSL_A_MATRIX, 2, 3, A,
IMSL_B_MATRIX, 3, 2, B,
0);
imsl_c_write_matrix("A*B", 2, 2, ans, 0);
ans = imsl_c_mat_mul_rect("ctrans(B)*trans(A)",
IMSL_A_MATRIX, 2, 3, A,
IMSL_B_MATRIX, 3, 2, B,
0);
imsl_c_write_matrix("ctrans(B)*trans(A)", 2, 2, ans, 0);
ans = imsl_c_mat_mul_rect("trans(x)*y",
IMSL_X_VECTOR, 3, x,
IMSL_Y_VECTOR, 3, y,
0);
imsl_c_write_matrix("trans(x)*y", 1, 1, ans, 0);
ans = imsl_c_mat_mul_rect("x*ctrans(y)",
IMSL_X_VECTOR, 3, x,
IMSL_Y_VECTOR, 3, y,
0);
imsl_c_write_matrix("x*ctrans(y)", 3, 3, ans, 0);
}
Output
ctrans(A)
1 2
1 ( 1, -4) ( 5, -2)
2 ( 2, -3) ( 4, 3)
3 ( 9, -6) ( 7, -1)
A*x
1 2
( 28, 3) ( 53, 2)
trans(x)*trans(A)
A*B
1 2
1 ( 101, 105) ( 0, 47)
2 ( 125, -10) ( 7, 14)
ctrans(B)*trans(A)
1 2
1 ( 95, 69) ( 87, -2)
2 ( 38, 5) ( 59, -28)
trans(x)*y
( 34, 37)
x*ctrans(y)
1 2 3
1 ( 37, -16) ( 20, 30) ( 26, -13)
2 ( 14, -2) ( 4, 12) ( 10, -2)
3 ( -17, -19) ( 14, -18) ( -13, -13)
mat_mul_rect_band
Computes the transpose of a matrix, a matrix-vector product, or a matrix-matrix
product, all matrices stored in band form.
Synopsis
#include <imsl.h>
float *imsl_f_mat_mul_rect_band (char *string, ..., 0)
The equivalent double function is imsl_d_mat_mul_rect_band.
Required Arguments
char *string (Input)
String indicating matrix multiplication to be performed.
Return Value
The result of the multiplication is returned. To release this space, use free.
Optional Arguments
IMSL_A_MATRIX, int nrowa, int ncola, int nlca, int nuca, float *a
(Input)
The sparse matrix
A ∈ℜ nrowa × ncola
IMSL_B_MATRIX, int nrowb, int ncolb, int nlcb, int nucb, float *b
(Input)
The sparse matrix
B ∈ℜ nrowb × xnolb
IMSL_X_VECTOR, int nx, float *x, (Input)
The vector x of length nx.
IMSL_RETURN_MATRIX_CODIAGONALS, int *nlc_result,
int *nuc_result, (Output)
If the function imsl_f_mat_mul_rect_band returns data for a band
matrix, use this option to retrieve the number of lower and upper
codiagonals of the return matrix.
IMSL_RETURN_USER_VECTOR, float vector_user[], (Output)
If the result of the computation in a vector, return the answer in the user
supplied sparse vector_user.
Description
The function imsl_f_mat_mul_rect_band computes a matrix-matrix product
or a matrix-vector product, where the matrices are specified in band format. The
operation performed is specified by string. For example, if “A*x” is given, Ax
is computed. In string, the matrices A and B and the vector x can be used. Any
of these names can be used with trans, indicating transpose. The vector x is
treated as a dense n × 1 matrix. If string contains only one item, such as “x” or
“trans(A)”, then a copy of the array, or its transpose is returned.
The matrices and/or vector referred to in string must be given as optional
arguments. Therefore, if string is “A*x”, then IMSL_A_MATRIX and
IMSL_X_VECTOR must be given.
Example 1
Consider the matrix
LM 2 −1 0 0OP
A=M P
−3 1 −2 0
MM 0 0 −1 2P
P
N0 0 2 1Q
After storing A in band format, multiply A by x = (1, 2, 3, 4) T and print the result.
#include <imsl.h>
main()
{
float a[] = {0.0, -1.0, -2.0, 2.0,
2.0, 1.0, -1.0, 1.0,
-3.0, 0.0, 2.0, 0.0};
/* Set b = A*x */
b = imsl_f_mat_mul_rect_band ("A*x",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
0);
Output
Product, Ax
1 2 3 4
0 -7 5 10
Example 2
This example uses the power method to determine the dominant eigenvector of
E(100, 10). The same computation is performed by using imsl_f_eig_sym. The
iteration stops when the component-wise absolute difference between the
dominant eigenvector found by imsl_f_eig_sym and the eigenvector at the
current iteration is less than the square root of machine unit roundoff.
#include <imsl.h>
#include <math.h>
n = 100;
c = 10;
tolerance = sqrt(imsl_f_machine(4));
error = 1.0;
start = c;
for (i=0; i<c; i++, start--)
for (k=0, j=start; j<n; j++, k++)
dense_a[k*n + j] = a[i*n + j];
/* Convert diagonal */
/* Normalize */
/* Do power method */
/* Normalize */
Output
Maximum absolute error = 3.367960e-04
mat_mul_rect_band (complex)
Computes the transpose of a matrix, a matrix-vector product, or a matrix-matrix
product for all matrices of complex type and stored in band form.
Synopsis
#include <imsl.h>
f_complex *imsl_c_mat_mul_rect_band (char *string, ..., 0)
The equivalent d_complex function is imsl_z_mat_mul_rect_band.
Return Value
The result of the multiplication is returned. To release this space, use free.
Optional Arguments
IMSL_A_MATRIX, int nrowa, int ncola, int nlca, int nuca,
f_complex *a (Input)
The sparse matrix
A ∈ℜ nrowa × ncola
IMSL_B_MATRIX, int nrowb, int ncolb, int nlcb, int nucb,
f_complex *b (Input)
The sparse matrix
B ∈ℜ nrowb × xnolb
IMSL_X_VECTOR, int nx, f_complex *x, (Input)
The vector x of length nx.
IMSL_RETURN_MATRIX_CODIAGONALS, int *nlc_result,
int *nuc_result, (Output)
If the function imsl_c_mat_mul_rect_band returns data for a band
matrix, use this option to retrieve the number of lower and upper
codiagonals of the return matrix.
IMSL_RETURN_USER_VECTOR, f_complex vector_user[], (Output)
If the result of the computation in a vector, return the answer in the user
supplied sparse vector_user.
Examples
Example 1
Let
LM −2 4 0 0 OP
A=M
6+i −0.5 + 3i −2 + 2i 0 P
MM 0 1+ i 3 − 3i −4 − i P
P
N0 0 2i 1− i Q
and
LM 3 OP
x=M
MM 3 PPP
−1 + i
N −1 + i Q
This example computes the product Ax.
#include <imsl.h>
main()
{
int n = 4;
int nlca = 1;
int nuca = 1;
f_complex *b;
f_complex a[] =
{{0.0, 0.0}, {4.0, 0.0}, {-2.0, 2.0}, {-4.0, -1.0},
{-2.0, -3.0}, {-0.5, 3.0}, {3.0, -3.0}, {1.0, -1.0},
{6.0, 1.0}, {1.0, 1.0}, {0.0, 2.0}, {0.0, 0.0}};
f_complex x[] =
/* Set b = A*x */
b = imsl_c_mat_mul_rect_band ("A*x",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
0);
Output
Product, Ax
1 2 3
( -10.0, -5.0) ( 9.5, 5.5) ( 12.0, -12.0)
4
( 0.0, 8.0)
Example 2
Using the same matrix A and vector x given in the last example, the products Ax,
ATx, AHx and AAH are computed.
#include <imsl.h>
#include <stdlib.h>
main()
{
int n = 4;
int nlca = 1;
int nuca = 1;
f_complex *b;
f_complex *z;
int nlca_z;
int nuca_z;
f_complex a[] =
{{0.0, 0.0}, {4.0, 0.0}, {-2.0, 2.0}, {-4.0, -1.0},
{-2.0, -3.0}, {-0.5, 3.0}, {3.0, -3.0}, {1.0, -1.0},
{6.0, 1.0}, {1.0, 1.0}, {0.0, 2.0}, {0.0, 0.0}};
f_complex x[] =
{{3.0, 0.0}, {-1.0, 1.0}, {3.0, 0.0}, {-1.0, 1.0}};
/* Set b = A*x */
b = imsl_c_mat_mul_rect_band ("A*x",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
0);
/* Set b = trans(A)*x */
b = imsl_c_mat_mul_rect_band ("trans(A)*x",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
0);
/* Set b = ctrans(A)*x */
b = imsl_c_mat_mul_rect_band ("ctrans(A)*x",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
0);
/* Set z = A*ctrans(A) */
z = imsl_c_mat_mul_rect_band ("A*ctrans(A)",
IMSL_A_MATRIX, n, n, nlca, nuca, a,
IMSL_X_VECTOR, n, x,
IMSL_RETURN_MATRIX_CODIAGONALS, &nlca_z, &nuca_z,
0);
Output
Ax
1 2 3
( -10.0, -5.0) ( 9.5, 5.5) ( 12.0, -12.0)
4
( 0.0, 8.0)
trans(A)x
1 2 3
( -13.0, -4.0) ( 12.5, -0.5) ( 7.0, -15.0)
4
( -12.0, -1.0)
ctrans(A)x
1 2 3
( -11.0, 16.0) ( 18.5, -0.5) ( 15.0, 11.0)
4
( -14.0, 3.0)
4
1 ( 4.00, 4.00)
2 ( -9.00, -11.00)
3 ( 6.00, 0.00)
4 ( 0.00, 0.00)
5 ( 0.00, 0.00)
mat_mul_rect_coordinate
Computes the transpose of a matrix, a matrix-vector product, or a matrix-matrix
product for all matrices stored in sparse coordinate form.
Synopsis
#include <imsl.h>
void *imsl_f_mat_mul_rect_coordinate (char *string, ..., 0)
The equivalent double function is imsl_d_mat_mul_rect_coordinate.
Required Arguments
char *string (Input)
String indicating matrix multiplication to be performed.
Return Value
The result of the multiplication. If the result is a vector, the return type is pointer
to float. If the result of the multiplication is a sparse matrix, the return type is
pointer to Imsl_f_sparse_elem. To release this space, use free.
Optional Arguments
IMSL_A_MATRIX, int nrowa, int ncola, int nza, Imsl_f_sparse_elem *a
(Input)
The sparse matrix
A ∈ℜ nrowa × ncola
with nza nonzero elements.
IMSL_B_MATRIX, int nrowb, int ncolb, int nzb, Imsl_f_sparse_elem *b
(Input)
The sparse matrix
B ∈ℜ nrowb × xnolb
with nzb nonzero elements.
IMSL_X_VECTOR, int nx, float *x, (Input)
The vector x of length nx.
IMSL_RETURN_MATRIX_SIZE, int *size, (Output)
If the function imsl_f_mat_mul_rect_coordinate returns a vector
of type Imsl_f_sparse_elem, use this option to retrieve the length of the
return vector, i.e. the number of nonzero elements in the sparse matrix
generated by the requested computations.
IMSL_RETURN_USER_VECTOR, float vector_user[], (Output)
If the result of the computation in a vector, return the answer in the user
supplied sparse vector_user. It’s size depends on the computation.
Description
The function imsl_f_mat_mul_rect_coordinate computes a matrix-matrix
product or a matrix-vector product, where the matrices are specified in coordinate
representation. The operation performed is specified by string. For example, if
“A*x” is given, Ax is computed. In string, the matrices A and B and the vector x
can be used. Any of these names can be used with trans, indicating transpose.
The vector x is treated as a dense n × 1 matrix.
If string contains only one item, such as “x” or “trans(A)”, then a copy of the
array, or its transpose is returned. Some multiplications, such as “A*trans(A)”
or “trans(x)*B”, will produce a sparse matrix in coordinate format as a result.
Other products such as “B*x” will produce a pointer to a floating type, containing
the resulting vector.
The matrices and/or vector referred to in string must be given as optional
arguments. Therefore, if string is “A*x”, then IMSL_A_MATRIX and
IMSL_X_VECTOR must be given.
Example 1
In this example, a sparse matrix in coordinate form is multipled by a vector.
#include <imsl.h>
main()
{
Imsl_f_sparse_elem a[] = {0, 0, 10.0,
1, 1, 10.0,
1, 2, -3.0,
1, 3, -1.0,
2, 2, 15.0,
3, 0, -2.0,
3, 3, 10.0,
3, 4, -1.0,
4, 0, -1.0,
4, 3, -5.0,
4, 4, 1.0,
4, 5, -3.0,
5, 0, -1.0,
5, 1, -2.0,
5, 5, 6.0};
/* Set x = A*b */
x = imsl_f_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, b,
0);
Output
Product Ab
1 2 3 4 5 6
100 -98 675 344 -302 162
Example 2
This example uses the power method to determine the dominant eigenvector of
E(100, 10). The same computation is performed by using imsl_f_eig_sym. The
iteration stops when the component-wise absolute difference between the
dominant eigenvector found by imsl_f_eig_sym and the eigenvector at the
current iteration is less than the square root of machine unit roundoff.
#include <imsl.h>
#include <math.h>
n = 100;
c = 10;
tolerance = sqrt(imsl_f_machine(4));
error = 1.0;
/* Normalize */
/* Do power method */
mat_mul_rect_coordinate (complex)
Computes the transpose of a matrix, a matrix-vector produce, or a matrix-matrix
product for all matrices stored in sparse coordinate form.
Synopsis
#include <imsl.h>
void *imsl_c_mat_mul_rect_coordinate (char *string, ..., 0)
The equivalent double function is imsl_d_mat_mul_rect_coordinate.
Required Arguments
char *string (Input)
String indicating matrix multiplication to be performed.
Return Value
The result of the multiplication. If the result is a vector, the return type is pointer
to f_complex. If the result of the multiplication is a sparse matrix, the return type
is pointer to Imsl_c_sparse_elem.
Description
The function imsl_c_mat_mul_rect_coordinate computes a matrix-matrix
product or a matrix-vector product, where the matrices are specified in coordinate
representation. The operation performed is specified by string. For example, if
“A*x” is given, Ax is computed. In string, the matrices A and B and the vector x
can be used. Any of these names can be used with trans or ctrans, indicating
transpose and conjugate transpose, respectively. The vector x is treated as a dense
n × 1 matrix.
If string contains only one item, such as “x” or “trans(A)”, then a copy of the
array, or its transpose is returned. Some multiplications, such as “A*ctrans(A)”
or “trans(x)*B”, will produce a sparse matrix in coordinate format as a result.
Other products such as “B*x” will produce a pointer to a complex type,
containing the resulting vector.
The matrix and/or vector referred to in string must be given as optional
arguments. Therefore, if string is “A*x”, IMSL_A_MATRIX and
IMSL_X_VECTOR must be given.
Examples
Example 1
Let
LM 10 + 7i 0 0 0 0 0 OP
MM 0 3 + 2i −3 −1 + 2i 0 0 P
0 0 4 + 2i 0 0 0 P
A=M P
MM −2 − 4i 0 0 1 + 6i −1 + 3i 0 P
−7 + 7i P
MM−−15++124ii 0 0 −5 12 + 2i
3 + 7i PQ
P
N −2 + 8i 0 0 0
and
main()
{
Imsl_c_sparse_elem a[] = {0, 0, {10.0, 7.0},
1, 1, {3.0, 2.0},
1, 2, {-3.0, 0.0},
1, 3, {-1.0, 2.0},
2, 2, {4.0, 2.0},
3, 0, {-2.0, -4.0},
3, 3, {1.0, 6.0},
3, 4, {-1.0, 3.0},
4, 0, {-5.0, 4.0},
4, 3, {-5.0, 0.0},
4, 4, {12.0, 2.0},
4, 5, {-7.0, 7.0},
5, 0, {-1.0, 12.0},
5, 1, {-2.0, 8.0},
5, 5, {3.0, 7.0}};
f_complex b[] = {{1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0},
{4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}};
int n = 6;
int nz = 15;
f_complex *x;
/* Set x = A*b */
x = imsl_c_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, nz, a,
IMSL_X_VECTOR, n, b,
0);
Output
Product Ab
1 2 3
( 3, 17) ( -19, 5) ( 6, 18)
4 5 6
( -38, 32) ( -63, 49) ( -57, 83)
Example 2
Using the same matrix A and vector x given in the last example, the products Ax,
ATx, AHx and AAH are computed.
#include <imsl.h>
main()
{
Imsl_c_sparse_elem *z;
Imsl_c_sparse_elem a[] = {0, 0, {10.0, 7.0},
1, 1, {3.0, 2.0},
1, 2, {-3.0, 0.0},
1, 3, {-1.0, 2.0},
2, 2, {4.0, 2.0},
3, 0, {-2.0, -4.0},
3, 3, {1.0, 6.0},
3, 4, {-1.0, 3.0},
4, 0, {-5.0, 4.0},
4, 3, {-5.0, 0.0},
4, 4, {12.0, 2.0},
4, 5, {-7.0, 7.0},
5, 0, {-1.0, 12.0},
5, 1, {-2.0, 8.0},
5, 5, {3.0, 7.0}};
f_complex x[] = {{1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0},
{4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}};
int n = 6;
int nz = 15;
int nz_z;
int i;
f_complex *b;
/* Set b = A*x */
b = imsl_c_mat_mul_rect_coordinate ("A*x",
IMSL_A_MATRIX, n, nz, a,
IMSL_X_VECTOR, n, x,
0);
/* Set b = trans(A)*x */
/* Set b = ctrans(A)*x */
b = imsl_c_mat_mul_rect_coordinate ("ctrans(A)*x",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, x,
0);
/* Set z = A*ctrans(A) */
z = imsl_c_mat_mul_rect_coordinate ("A*ctrans(A)",
IMSL_A_MATRIX, n, n, nz, a,
IMSL_X_VECTOR, n, x,
IMSL_RETURN_MATRIX_SIZE, &nz_z,
0);
printf("\n\n\t\t\t z = A*ctrans(A)\n\n");
Output
Ax
1 2 3
( 3, 17) ( -19, 5) ( 6, 18)
4 5 6
( -38, 32) ( -63, 49) ( -57, 83)
trans(A)x
1 2 3
( -112, 54) ( -58, 46) ( 0, 12)
4 5 6
( -51, 5) ( 34, 78) ( -94, 60)
ctrans(A)x
1 2 3
( 54, -112) ( 46, -58) ( 12, 0)
z = A*ctrans(A)
mat_add_band
Adds two band matrices, both in band storage mode, C ← αA + βB.
Synopsis
#include <imsl.h>
float *imsl_f_mat_add_band (int n, int nlca, int nuca, float alpha,
float a[], int nlcb, int nucb, float beta, float b[], int *nlcc,
int *nucc, ..., 0)
The type double function is imsl_d_mat_add_band.
Required Arguments
int n (Input)
The order of the matrices A and B.
int nlca (Input)
Number of lower codiagonals of A.
Return Value
A pointer to an array of type float containing the computed sum. NULL is returned
in the event of an error or if the return matrix has no nonzero elements.
Optional Arguments
IMSL_A_TRANSPOSE,
Replace A with AT in the expression αA + βB.
IMSL_B_TRANSPOSE,
Replace B with BT in the expression αA + βB.
Description
The function imsl_f_mat_add_band forms the sum αA + βB, given the scalars
α and β, and, the matrices A and B in band format. The transpose of
A and/or B may be used during the computation if optional arguments are
specified. Symmetric storage mode may be used if the optional argument is
specified.
If IMSL_SYMMETRIC is specified, the return value for the number of lower
codiagonals, nlcc, will be equal to 0.
If the return matrix equals NULL, the return value for the number of lower
codiagonals, nlcc, will be equal to −1 and the number of upper codiagonals, nucc,
will be equal to 0.
Examples
Example 1
Add two real matrices of order 4 stored in band mode. Matrix A has one upper
codiagonal and one lower codiagonal. Matrix B has no upper codiagonals and two
lower codiagonals.
#include <imsl.h>
void main()
{
float a[] = {0.0, 2.0, 3.0, -1.0,
1.0, 1.0, 1.0, 1.0,
0.0, 3.0, 4.0, 0.0};
float b[] = {3.0, 3.0, 3.0, 3.0,
1.0, -2.0, 1.0, 0.0,
-1.0, 2.0, 0.0, 0.0};
int nucb = 0, nlcb = 2;
int nuca = 1, nlca = 1;
int nucc, nlcc;
int n = 4, m;
float alpha = 1.0, beta = 1.0;
float *c;
m = nlcc + nucc + 1;
imsl_f_write_matrix("C = A + B", m, n, c, 0);
free(c);
}
C = A + B
1 2 3 4
Example 2
Compute 4*A + 2*B, where
LM3 4 0 0 OP LM5 2 0 0 OP
A=M
0P
P1P and B = MMM0
4 2 3 2 1 3 0P
MM0 3 1 3 2 1P
P
N0 0 1 2Q N0 0 1 2Q
#include <imsl.h>
void main()
{
float a[] = {0.0, 4.0, 3.0, 1.0,
3.0, 2.0, 1.0, 2.0};
float b[] = {0.0, 2.0, 3.0, 1.0,
5.0, 1.0, 2.0, 2.0};
int nuca = 1, nlca = 1;
int nucb = 1, nlcb = 1;
int n = 4, m, nlcc, nucc;
float alpha = 4.0, beta = 2.0;
float *c;
m = nucc + nlcc + 1;
imsl_f_write_matrix("C = 4*A + 2*B\n", m, n, c, 0);
free(c);
}
Output
C = 4*A + 2*B
1 2 3 4
1 0 20 18 6
2 22 10 8 12
mat_add_band (complex)
Adds two band matrices, both in band storage mode, C ← αA + βB.
Required Arguments
int n (Input)
The order of the matrices A and B.
int nlca (Input)
Number of lower codiagonals of A.
int nuca (Input)
Number of upper codiagonals of A.
f_complex alpha (Input)
Scalar multiplier for A.
f_complex a[] (Input)
An n by n band matrix with nlca lower codiagonals and nuca upper
codiagonals stored in band mode with dimension (nlca + nuca + 1) by n.
int nlcb (Input)
Number of lower codiagonals of B.
int nucb (Input)
Number of upper codiagonals of B.
f_complex beta (Input)
Scalar multiplier for B.
f_complex b[] (Input)
An n by n band matrix with nlcb lower codiagonals and nucb upper
codiagonals stored in band mode with dimension (nlcb + nucb + 1) by n.
int *nlcc (Output)
Number of lower codiagonals of C.
int *nucc (Output)
Number of upper codiagonals of C.
Return Value
A pointer to an array of type f_complex containing the computed sum. In the
event of an error or if the return matrix has no nonzero elements, NULL is
returned.
Optional Arguments
IMSL_A_TRANSPOSE,
Replace A with AT in the expression αA + βB.
IMSL_B_TRANSPOSE,
Replace B with BT in the expression αA + βB.
IMSL_A_CONJUGATE_TRANSPOSE,
Replace A with AH in the expression αA + βB.
IMSL_B_CONJUGATE_TRANSPOSE,
Replace B with BH in the expression αA + βB.
IMSL_SYMMETRIC,
Matrix A, B, and C are stored in band symmetric storage mode.
Description
The function imsl_c_mat_add_band forms the sum αA + βB, given the scalars
α and β, and the matrices A and B in band format. The transpose or conjugate
transpose of
A and/or B may be used during the computation if optional arguments are
specified. Symmetric storage mode may be used if the optional argument is
specified.
If IMSL_SYMMETRIC is specified, the return value for the number of lower
codiagonals, nlcc, will be equal to 0.
If the return matrix equals NULL, the return value for the number of lower
codiagonals, nlcc, will be equal to −1 and the number of upper codiagonals, nucc,
will be equal to 0.
Example 1
Add two complex matrices of order 4 stored in band mode. Matrix A has one
upper codiagonal and one lower codiagonal. Matrix B has no upper codiagonals
and two lower codiagonals.
#include <imsl.h>
void main()
{
f_complex a[] =
{{0.0, 0.0}, {2.0, 1.0}, {3.0, 3.0}, {-1.0, 0.0},
{1.0, 1.0}, {1.0, 3.0}, {1.0, -2.0}, {1.0, 5.0},
{0.0, 0.0}, {3.0, -2.0}, {4.0, 0.0}, {0.0, 0.0}};
f_complex b[] =
{{3.0, 1.0}, {3.0, 5.0}, {3.0, -1.0}, {3.0, 1.0},
{1.0, -3.0}, {-2.0, 0.0}, {1.0, 2.0}, {0.0, 0.0},
{-1.0, 4.0}, {2.0, 1.0}, {0.0, 0.0}, {0.0, 0.0}};
int nucb = 0, nlcb = 2;
int nuca = 1, nlca = 1;
int nucc, nlcc;
int n = 4, m;
f_complex *c;
f_complex alpha = {1.0, 0.0};
f_complex beta = {1.0, 0.0};
m = nlcc + nucc + 1;
imsl_c_write_matrix("C = A + B", m, n, c, 0);
free(c);
}
Output
C = A + B
1 2 3
1 ( 0, 0) ( 2, 1) ( 3, 3)
2 ( 4, 2) ( 4, 8) ( 4, -3)
3 ( 1, -3) ( 1, -2) ( 5, 2)
4 ( -1, 4) ( 2, 1) ( 0, 0)
4
1 ( -1, 0)
2 ( 4, 6)
3 ( 0, 0)
4 ( 0, 0)
Example 2
Compute
(3 + 2i)AH + (4 + i) BH
void main()
{
f_complex a[] =
{{0.0, 0.0}, {1.0, 3.0}, {3.0, 1.0}, {2.0, 5.0},
{2.0, 3.0}, {6.0, 2.0}, {4.0, 1.0}, {1.0, 2.0}};
f_complex b[] =
{{0.0, 0.0}, {5.0, 1.0}, {2.0, 3.0}, {4.0, 2.0},
{1.0, 2.0}, {1.0, 3.0}, {3.0, 2.0}, {1.0, 4.0},
{4.0, 1.0}, {2.0, 3.0}, {2.0, 6.0}, {0.0, 0.0}};
int nuca = 1, nlca = 0;
int nucb = 1, nlcb = 1;
int n = 4, m, nlcc, nucc;
f_complex *c;
f_complex alpha = {3.0, 2.0};
f_complex beta = {4.0, 1.0};
c = imsl_c_mat_add_band(n, nlca, nuca, alpha, a,
nlcb, nucb, beta, b,
&nlcc, &nucc,
IMSL_A_CONJUGATE_TRANSPOSE,
IMSL_B_CONJUGATE_TRANSPOSE, 0);
m = nlcc + nucc + 1;
imsl_c_write_matrix("C = (3+2i)*ctrans(A) + (4+i)*ctrans(B)\n",
m, n, c, 0);
free(c);
}
Output
C = (3+2i)*ctrans(A) + (4+i)*ctrans(B)
1 2 3
1 ( 0, 0) ( 17, 0) ( 11, -10)
2 ( 18, -12) ( 29, -5) ( 28, 0)
3 ( 30, -6) ( 22, -7) ( 34, -15)
4
1 ( 14, -22)
2 ( 15, -19)
3 ( 0, 0)
mat_add_coordinate
Performs element-wise addition on two real matrices stored in coordinate format,
C ← αA + βB.
Required Arguments
int n (Input)
The order of the matrices A and B.
int nz_a (Input)
Number of nonzeros in the matrix A.
float alpha (Input)
Scalar multiplier for A.
Imsl_f_sparse_elem a[] (Input)
Vector of length nz_a containing the location and value of each nonzero
entry in the matrix A.
int nz_b (Input)
Number of nonzeros in the matrix B.
float beta (Input)
Scalar multiplier for B.
Imsl_f_sparse_elem b[] (Input)
Vector of length nz_b containing the location and value of each nonzero
entry in the matrix B.
int *nz_c (Output)
The number of nonzeros in the sum αA + βB.
Return Value
A pointer to an array of type Imsl_f_sparse_elem containing the computed sum.
In the event of an error or if the return matrix has no nonzero elements, NULL is
returned.
Optional Arguments
IMSL_A_TRANSPOSE,
Replace A with AT in the expression αA + βB.
IMSL_B_TRANSPOSE,
Replace B with BT in the expression αA + βB.
Description
The function imsl_f_mat_add_coordinate forms the sum αA + βB, given the
scalars α and β, and the matrices A and B in coordinate format. The transpose of
A and/or B may be used during the computation if optional arguments are
specified. The method starts by storing A in a linked list data structure, and
performs the multiply by
α. Next the data in matrix B is traversed and if the coordinates of a nonzero
element correspond to those of a nonzero element in A, that entry in the linked list
is updated. Otherwise, a new node in the linked list is created. The multiply by β
occurs at this time. Lastly, the linked list representation of C is converted to
coordinate representation, omitting any elements that may have become zero
through cancellation.
Examples
Example 1
Add two real matrices of order 4 stored in coordinate format. Matrix A has five
nonzero elements. Matrix B has seven nonzero elements.
#include <imsl.h>
void main ()
{
Imsl_f_sparse_elem a[] = {0, 0, 3,
0, 3, -1,
1, 2, 5,
2, 0, 1,
3, 1, 3};
Imsl_f_sparse_elem b[] = {0, 1, -2,
0, 3, 1,
1, 0, 3,
2, 2, 5,
2, 3, 1,
3, 0, 4,
3, 1, 3};
int nz_a = 5, nz_b = 7, nz_c;
int n = 4, i;
float alpha = 1.0, beta = 1.0;
Imsl_f_sparse_elem *c;
free(c);
}
Output
row column value
0 0 3.00
0 1 -2.00
1 0 3.00
1 2 5.00
2 0 1.00
2 2 5.00
2 3 1.00
3 0 4.00
3 1 6.00
Example 2
void main ()
{
Imsl_f_sparse_elem a[] = {0, 0, 3,
0, 3, -1,
1, 2, 5,
2, 0, 1,
3, 1, 3};
Imsl_f_sparse_elem b[] = {0, 1, -2,
0, 3, 1,
1, 0, 3,
2, 2, 5,
2, 3, 1,
3, 0, 4,
3, 1, 3};
int nz_a = 5, nz_b = 7, nz_c;
int n = 4, i;
float alpha = 2.0, beta = 2.0;
Imsl_f_sparse_elem *c;
free(c);
}
Output
row column value
0 0 6.00
0 1 6.00
0 2 2.00
0 3 8.00
1 0 -4.00
1 3 12.00
2 1 10.00
2 2 10.00
3 2 2.00
mat_add_coordinate (complex)
Performs element-wise addition on two complex matrices stored in coordinate
format, C ← αA + βB.
Synopsis
#include <imsl.h>
Imsl_c_sparse_elem *imsl_c_mat_add_coordinate (int n, int nz_a,
f_complex alpha, Imsl_c_sparse_elem a[], int nz_b,
f_complex beta, Imsl_c_sparse_elem b[], int *nz_c, ..., 0)
The type double function is imsl_z_mat_add_coordinate.
Required Arguments
int n (Input)
The order of the matrices A and B.
int nz_a (Input)
Number of nonzeros in the matrix A.
f_complex alpha (Input)
Scalar multiplier for A.
Imsl_c_sparse_elem a[] (Input)
Vector of length nz_a containing the location and value of each nonzero
entry in the matrix A.
Return Value
A pointer to an array of type Imsl_c_sparse_elem containing the computed sum.
In the event of an error or if the return matrix has no nonzero elements, NULL is
returned.
Optional Arguments
IMSL_A_TRANSPOSE,
Replace A with AT in the expression αA + βB.
IMSL_B_TRANSPOSE,
Replace B with BT in the expression αA + βB.
IMSL_A_CONJUGATE_TRANSPOSE,
Replace A with AH in the expression αA + βB.
IMSL_B_CONJUGATE_TRANSPOSE,
Replace B with BH in the expression αA + βB.
Description
The function imsl_c_mat_add_coordinate forms the sum αA + βB, given the
scalars α and β, and the matrices A and B in coordinate format. The transpose or
Examples
Example 1
Add two complex matrices of order 4 stored in coordinate format. Matrix A has
five nonzero elements. Matrix B has seven nonzero elements.
#include <imsl.h>
void main ()
{
Imsl_c_sparse_elem a[] = {0, 0, 3, 4,
0, 3, -1, 2,
1, 2, 5, -1,
2, 0, 1, 2,
3, 1, 3, 0};
Imsl_c_sparse_elem b[] = {0, 1, -2, 1,
0, 3, 1, -2,
1, 0, 3, 0,
2, 2, 5, 2,
2, 3, 1, 4,
3, 0, 4, 0,
3, 1, 3, -2};
int nz_a = 5, nz_b = 7, nz_c;
int n = 4, i;
f_complex alpha = {1.0, 0.0}, beta = {1.0, 0.0};
Imsl_c_sparse_elem *c;
free(c);
}
Output
row column value
0 0 3.00 4.00
0 1 -2.00 1.00
1 0 3.00 0.00
1 2 5.00 -1.00
Example 2
void main ()
{
Imsl_c_sparse_elem a[] = {0, 0, 3, 4,
0, 3, -1, 2,
1, 2, 5, -1,
2, 0, 1, 2,
3, 1, 3, 0};
Imsl_c_sparse_elem b[] = {0, 1, -2, 1,
0, 3, 1, -2,
1, 0, 3, 0,
2, 2, 5, 2,
2, 3, 1, 4,
3, 0, 4, 0,
3, 1, 3, -2};
int nz_a = 5, nz_b = 7, nz_c;
int n = 4, i;
f_complex alpha = {2.0, 3.0}, beta = {2.0, -1.0};
Imsl_c_sparse_elem *c;
free(c);
}
Output
row column value
0 0 -6.00 17.00
0 1 6.00 -3.00
0 2 -4.00 7.00
matrix_norm
Computes various norms of a rectangular matrix.
Synopsis
#include <imsl.h>
float imsl_f_matrix_norm (int m, int n, float a[], ..., 0)
The type double function is imsl_d_matrix_norm.
Required Arguments
int m (Input)
The number of rows in matrix A.
int n (Input)
The number of columns in matrix A.
float a[] (Input)
Matrix for which the norm will be computed.
Return Value
The requested norm of the input matrix. If the norm cannot be computed, NaN is
returned.
Description
By default, imsl_f_matrix_norm computes the Frobenius norm
is returned.
Example
Compute the Frobenius norm, infinity norm, and one norm of matrix A.
#include <imsl.h>
void main()
{
float a[] = {1.0, 2.0, -2.0, 3.0,
-2.0, 1.0, 3.0, 0.0,
0.0, 3.0, 1.0, -7.0,
5.0, -2.0, 7.0, 6.0,
4.0, 3.0, 4.0, 0.0};
int m = 5, n = 4;
float frobenius_norm, inf_norm, one_norm;
Output
Frobenius norm = 15.684387
Infinity norm = 20.000000
One norm = 17.000000
matrix_norm_band
Computes various norms of a matrix stored in band storage mode.
Required Arguments
int n (Input)
The order of matrix A.
float a[] (Input)
Matrix for which the norm will be computed.
int nlc (Input)
Number of lower codiagonals of A.
int nuc (Input)
Number of upper codiagonals of A.
Return Value
The requested norm of the input matrix, by default, the Frobenius norm. If the
norm cannot be computed, NaN is returned.
Optional Arguments
IMSL_ONE_NORM,
Compute the 1-norm of matrix A,
IMSL_INF_NORM,
Compute the infinity norm of matrix A,
IMSL_SYMMETRIC,
Matrix A is stored in band symmetric storage mode.
Description
By default, imsl_f_matrix_norm_band computes the Frobenius norm
is returned.
Examples
Example 1
Compute the Frobenius norm, infinity norm, and one norm of matrix A. Matrix A
is stored in band storage mode.
#include <imsl.h>
void main()
{
float a[] = {0.0, 2.0, 3.0, -1.0,
1.0, 1.0, 1.0, 1.0,
0.0, 3.0, 4.0, 0.0};
int nlc = 1, nuc = 1;
int n = 4;
float frobenius_norm, inf_norm, one_norm;
Output
Frobenius norm = 6.557438
Infinity norm = 5.000000
One norm = 8.000000
void main()
{
float a[] = {0.0, 0.0, 7.0, 3.0, 1.0, 4.0,
0.0, 5.0, 1.0, 2.0, 1.0, 2.0,
1.0, 2.0, 4.0, 6.0, 3.0, 1.0};
int nlc = 2, nuc = 2;
int n = 6;
float frobenius_norm, inf_norm, one_norm;
Output
Frobenius norm = 16.941074
Infinity norm = 16.000000
One norm = 16.000000
matrix_norm_coordinate
Computes various norms of a matrix stored in coordinate format.
Synopsis
#include <imsl.h>
float imsl_f_matrix_norm_coordinate (int m, int n, int nz,
Imsl_f_sparse_elem a[], ..., 0)
The type double function is imsl_d_matrix_norm_coordinate.
Required Arguments
int m (Input)
The number of rows in matrix A.
Return Value
The requested norm of the input matrix, by default, the Frobenius norm. If the
norm cannot be computed, NaN is returned.
Optional Arguments
IMSL_ONE_NORM,
Compute the 1-norm of matrix A.
IMSL_INF_NORM,
Compute the infinity norm of matrix A.
IMSL_SYMMETRIC,
Matrix A is stored in symmetric coordinate format.
Description
By default, imsl_f_matrix_norm_coordinate computes the Frobenius norm
1
L m −1 n −1 OP
= Må å A
2
2
A 2
MN i =0 j =0
ij
PQ
If the option IMSL_ONE_NORM is selected, the 1-norm
m −1
A1= max
0 ≤ j ≤ n −1
åA
i =0
ij
is returned.
Examples
Example 1
Compute the Frobenius norm, infinity norm, and one norm of matrix A. Matrix A
is stored in coordinate format.
#include <imsl.h>
void main()
{
Imsl_f_sparse_elem a[] = {0, 0, 10.0,
1, 1, 10.0,
1, 2, -3.0,
1, 3, -1.0,
2, 2, 15.0,
3, 0, -2.0,
3, 3, 10.0,
3, 4, -1.0,
4, 0, -1.0,
4, 3, -5.0,
4, 4, 1.0,
4, 5, -3.0,
5, 0, -1.0,
5, 1, -2.0,
5, 5, 6.0};
int m = 6, n = 6;
int nz = 15;
float frobenius_norm, inf_norm, one_norm;
Output
Frobenius norm = 24.839485
Infinity norm = 15.000000
One norm = 18.000000
void main()
{
Imsl_f_sparse_elem a[] = {0, 0, 10.0,
0, 2, -1.0,
0, 5, 5.0,
1, 3, 2.0,
1, 4, 3.0,
2, 2, 3.0,
2, 5, 4.0,
4, 4, -1.0,
4, 5, 4.0};
int m = 6, n = 6;
int nz = 9;
float frobenius_norm, inf_norm, one_norm;
generate_test_band
Generates test matrices of class and E(n, c). Returns in band or band symmetric
format.
Synopsis
#include <imsl.h>
float *imsl_f_generate_test_band (int n, int c, ..., 0)
The function imsl_d_generate_test_band is the double precision analogue.
Return Value
A pointer to a vector of type float. To release this space, use free. If no test was
generated, then NULL is returned.
Optional Arguments
IMSL_SYMMETRIC_STORAGE,
Return matrix stored in band symmetric format.
Description
The same nomenclature as Østerby and Zlatev (1982) is used. Test matrices of
class E(n, c), to which we will generally refer to as E-matrices, are symmetric,
positive definite matrices of order n with 4 in the diagonal and −1 in the
superdiagonal and subdiagonal. In addition there are two bands with −1 at a
distance c from the diagonal. More precisely:
ai,i = 4 0≤i<n
ai,i+1 = −1 0≤i<n−1
ai+1,1 = −1 0≤i<n−1
ai,i+c = −1 0≤i<n−c
ai+c,i = −1 0≤i<n−c
main()
{
int n = 5;
int c = 3;
float *a;
generate_test_band (complex)
Generates test matrices of class Ec(n, c). Returns in band or band symmetric
format.
Synopsis
#include <imsl.h>
f_complex *imsl_c_generate_test_band (int n, int c, ..., 0)
The function imsl_z_generate_test_band is the double precision analogue.
Required Arguments
int n (Input)
Number of rows in the matrix.
Return Value
A pointer to a vector of type f_complex. To release this space, use free. If no test
was generated, then NULL is returned.
Optional Arguments
IMSL_SYMMETRIC_STORAGE,
Return matrix stored in band symmetric format.
Description
We use the same nomenclature as Østerby and Zlatev (1982). Test matrices of
class E(n, c), to which we will generally refer to as E-matrices, are symmetric,
positive definite matrices of order n with (6.0, 0.0) in the diagonal, (−1.0, 1.0) in
the superdiagonal and (−1.0, −1.0) subdiagonal. In addition there are two bands at
a distance c from the diagonal with (−1.0, 1.0) in the upper codiagonal and
(−1.0, −1.0) in the lower codiagonal. More precisely:
ai,i = 6 0≤i<n
ai,i+1 = −1 − i 0≤i<n−1
ai+1,1 = −1 − i 0≤i<n−1
ai,i+c = −1 + i 0≤i<n−c
ai+c,i = −1 + i 0≤i<n−c
Example
This example generates the following matrix and prints the result:
main()
{
int i;
int n = 5;
int c = 3;
f_complex *a;
4 5
1 ( -1, 1) ( -1, 1)
2 ( 0, 0) ( 0, 0)
3 ( -1, 1) ( -1, 1)
4 ( 6, 0) ( 6, 0)
5 ( -1, -1) ( 0, 0)
6 ( 0, 0) ( 0, 0)
7 ( 0, 0) ( 0, 0)
generate_test_coordinate
Generates test matrices of class D(n, c) and E(n, c). Returns in either coordinate
format.
Synopsis
#include <imsl.h>
Imsl_f_sparse_elem *imsl_f_generate_test_coordinate (int n, int c,
int *nz, ..., 0)
Required Arguments
int n (Input)
Number of rows in the matrix.
int c (Input)
Parameter used to alter structure.
int *nz (Output)
Length of the return vector.
Return Value
A pointer to a vector of length nz of type Imsl_f_sparse_elem. To release this
space, use free. If no test was generated, then NULL is returned.
Optional Arguments
IMSL_D_MATRIX
Return a matrix of class D(n, c).
Default: Return a matrix of class E(n, c).
IMSL_SYMMETRIC_STORAGE,
For coordinate representation, return only values for the diagonal and
lower triangle. This option is not allowed if IMSL_D_MATRIX is
specified.
Description
We use the same nomenclature as Østerby and Zlatev (1982).Test matrices of
class E(n, c), to which we will generally refer to as E-matrices, are symmetric,
positive definite matrices of order n with 4 in the diagonal and −1 in the
superdiagonal and subdiagonal. In addition there are two bands with −1 at a
distance c from the diagonal. More precisely
ai,i = 1 0≤i<n
ai,i+c = i + 2 0≤i<n−c
ai,i-n+c = i + 2 n−c≤i<n
ai,i+c+1 = −(i + 1) 0≤i<n−c−1
ai,i-n+c+1 = −(i + 1) n−c−1≤i<n
ai,i+c+2 = 16 0≤i<n−c−2
ai,i-n+c+2 = 16 n−c−2≤i<n
ai,n-11+i+j = 100j 1 ≤ i< 11 − j, 0 ≤ j < 10
for any n ≥ 14 and 1 ≤ c ≤ n − 13.
x x x x x x x x x x x x x x
x x x x x x x x x x x x x
x x x x x x x x x x x x
x x x x x x x x x x x
x x x x x x x x x x
x x x x x x x x x
x x x x x x x x
x x x x x x x
x x x x x x
x x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
main()
{
int i;
int n = 5;
int c = 3;
int nz;
Imsl_f_sparse_elem *a;
Output
row col val
0 0 4.0
1 1 4.0
2 2 4.0
3 3 4.0
4 4 4.0
1 0 -1.0
2 1 -1.0
3 2 -1.0
4 3 -1.0
0 1 -1.0
1 2 -1.0
2 3 -1.0
3 4 -1.0
3 0 -1.0
4 1 -1.0
0 3 -1.0
1 4 -1.0
Example 2
In this example, the matrix E(5, 3) is returned in symmetric storage and printed.
#include <imsl.h>
main()
{
Output
row col val
0 0 4.0
1 1 4.0
2 2 4.0
3 3 4.0
4 4 4.0
1 0 -1.0
2 1 -1.0
3 2 -1.0
4 3 -1.0
3 0 -1.0
4 1 -1.0
generate_test_coordinate (complex)
Generates test matrices of class D(n, c) and E(n, c). Returns in either coordinate
or band storage format, where possible.
Synopsis
#include <imsl.h>
void *imsl_c_generate_test_coordinate (int n, int c, int *nz, ..., 0)
The function is imsl_z_generate_test_coordinate is the double precision
analogue.
Required Arguments
int n (Input)
Number of rows in the matrix.
int c (Input)
Parameter used to alter structure.
Return Value
A pointer to a vector of length nz of type imsl_c_sparse_elem. To release this
space, use free. If no test was generated, then NULL is returned.
Optional Arguments
IMSL_D_MATRIX
Return a matrix of class D(n, c).
Default: Return a matrix of class E(n, c).
IMSL_SYMMETRIC_STORAGE,
For coordinate representation, return only values for the diagonal and
lower triangle. This option is not allowed if IMSL_D_MATRIX is
specified.
Description
The same nomenclature as Østerby and Zlatev (1982) is used. Test matrices of
class E(n, c), to which we will generally refer to as E-matrices, are symmetric,
positive definite matrices of order n with (6.0, 0.0) in the diagonal, (−1.0, 1.0) in
the superdiagonal and (−1.0, −1.0) subdiagonal. In addition there are two bands at
a distance c from the diagonal with (−1.0, 1.0) in the upper codiagonal and
(−1.0, −1.0) in the lower codiagonal. More precisely:
ai,i = 6 0≤i<n
ai,i+1 = −1 − i 0≤i<n−1
ai+1,1 = −1 − i 0≤i<n−1
ai,i+c = −1 + i 0≤i<n−c
ai+c,i = −1 + i 0≤i<n−c
x x x x x x x x x x x x x x
x x x x x x x x x x x x x
x x x x x x x x x x x x
x x x x x x x x x x x
x x x x x x x x x x
x x x x x x x x x
x x x x x x x x
x x x x x x x
x x x x x x
x x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
Examples
Example 1
This example generates the matrix
LM 6 −1 − i 0 −1 + i 0 OP
MM−1 − i 6 −1 − i 0 −1 + i PP
E b5,3g = −1 − i −1 − i
c
MM−10− i 0
6
−1 − i 6
0
−1 + i
PP
MN 0 −1 − i 0 −1 − i 6 PQ
and prints the result.
#include "imsl.h"
main()
{
int i;
int n = 5;
int c = 3;
int nz;
Imsl_c_sparse_elem *a;
Example 2
In this example, the matrix E(5, 3) is returned in symmetric storage and printed.
#include <imsl.h>
main()
{
int i;
int n = 5;
int c = 3;
int nz;
Imsl_c_sparse_elem *a;
Output
row col val
0 0 ( 6.0, 0.0)
1 1 ( 6.0, 0.0)
2 2 ( 6.0, 0.0)
3 3 ( 6.0, 0.0)
4 4 ( 6.0, 0.0)
1 0 ( -1.0, -1.0)
2 1 ( -1.0, -1.0)
3 2 ( -1.0, -1.0)
4 3 ( -1.0, -1.0)
3 0 ( -1.0, -1.0)
4 1 ( -1.0, -1.0)
User Errors
IMSL functions attempt to detect user errors and handle them in a way that provides as
much information to the user as possible. To do this, we recognize various levels of
severity of errors, and we also consider the extent of the error in the context of the
purpose of the function; a trivial error in one situation may be serious in another.
Functions attempt to report as many errors as they can reasonably detect. Multiple
errors present a difficult problem in error detection because input is interpreted in an
uncertain context after the first error is detected.
Additional Examples
See functions imsl_error_options and imsl_error_code in Chapter 12, “Utilities”
for additional examples.
x= =ya
z = imsl_c_eq(x,y) int f_complex (both)
Drop
Precision
a Result has the value 1 if x and y are valid numbers with real and imaginary parts identical; otherwise, result has the value 0.
–π < a ≤ π
z= x z = imsl_c_sqrt(z) f_complex f_complex
z = xa
z = imsl_cf_power(x,a) f_complex f_complex, float
c = ak
c = imsl_fi_power(a,k) float float, int
x==yb
z = imsl_z_eq(x,y) int d_complex (both)
Drop Precision
z = a + ib z = imsl_zd_convert(a,b) d_complex double (both)
Ascend Data
b Result has the value 1 if x and y are valid numbers with real and imaginary parts identical; otherwise, result has the value 0.
–π < a ≤ π
z= x z = imsl_z_sqrt(z) d_complex d_complex
z = xa
z = imsl_zd_power(x,a) d_complex d_complex, double
z = xy
z = imsl_zz_power(x,y) d_complex d_complex (both)
c = ak
c = imsl_di_power(a,k) double double, int
c = ab
c = imsl_dd_power(a,b) double double (both)
m = jk
m = imsl_ii_power(j,k) int int (both)
The following sample code computes and prints several quantities associated with
complex numbers. Note that the quantity
w = 3 + 4i
has a rounding error associated with it. Also the quotient z = (1 + 2i) / (3 + 4i) has a
rounding error. The result is acceptable in both cases because the relative errors
|w – (2 + 2i)|/ |w| and |z * (3 + 4i) – (1 + 2i)|/ |(1 + 2i)| are approximately the size of
machine precision.
#include <imsl.h>
main()
{
f_complex x = {1,2};
f_complex y = {3,4};
f_complex z;
f_complex w;
int isame;
float eps = imsl_f_machine(4);
/* Echo inputs x and y */
printf("Data: x = (%g, %g)\n y = (%g, %g)\n\n",
[Link], [Link], [Link], [Link]);
/* Add inputs */
z = imsl_c_add(x,y);
printf("Sum: z = x + y = (%g, %g)\n\n", [Link], [Link]);
/* Compute square root of y */
Output
Data: x = (1, 2)
y = (3, 4)
Sum: z = x + y = (4, 6)
Akima
Akima, H. (1970), A new method of interpolation and smooth curve
fitting based on local procedures, Journal of the ACM, 17, 589–602.
Akima, H. (1978), A method of bivariate interpolation and smooth
surface fitting for irregularly distributed data points, ACM Transactions
on Mathematical Software, 4, 148–159.
Ashcraft
Ashcraft, C. (1987), A vector implementation of the multifrontal method
for large sparse symmetric positive definite systems, Technical Report
ETA-TR-51, Engineering Technology Applications Division, Boeing
Computer Services, Seattle, Washington.
Ashcraft et al.
Ashcraft, C., R. Grimes, J. Lewis, B. Peyton, and H. Simon (1987),
Progress in sparse matrix methods for large linear systems on vector
supercomputers. Intern. J. Supercomputer Applic., 1(4), 10–29.
Atkinson (1979)
Atkinson, A.C. (1979), A family of switching algorithms for the computer
generation of beta random variates, Biometrika, 66, 141–145.
Atkinson (1978)
Atkinson, Ken (1978), An Introduction to Numerical Analysis, John
Wiley & Sons, New York.
IMSL C/Math/Library Appendix A: References • A-1
Barnett
Barnett, A.R. (1981), An algorithm for regular and irregular Coulomb
and Bessel functions of real order to machine accuracy, Computer
Physics Communication, 21, 297–314.
Blom
Blom, Gunnar (1958), Statistical Estimates and Transformed Beta-
Variables, John Wiley & Sons, New York.
Boisvert
Boisvert, Ronald (1984), A fourth order accurate fast direct method of
the Helmholtz equation, Elliptic Problem solvers II, (edited by G.
Birkhoff and A. Schoenstadt), Academic Press, Orlando, Florida, 35–44.
Brent
Brent, Richard P. (1973), Algorithms for Minimization without
Derivatives, Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
Brigham
Brigham, E. Oran (1974), The Fast Fourier Transform, Prentice-Hall,
Englewood Cliffs, New Jersey.
Burgoyne
Burgoyne, F.D. (1963), Approximations to Kelvin functions,
Mathematics of Computation, 83, 295-298.
Carlson
Carlson, B.C. (1979), Computing elliptic integrals by duplication,
Numerische Mathematik, 33, 1–16.
Cheng
Cheng, R.C.H. (1978), Generating beta variates with nonintegral shape
parameters, Communications of the ACM, 21, 317–322.
Cooper
Cooper, B.E. (1968), Algorithm AS4, An auxiliary function for
distribution integrals, Applied Statistics, 17, 190–192.
Crowe et al.
Crowe, Keith, Yuan-An Fan, Jing Li, Dale Neaderhouser, and Phil Smith
(1990), A direct sparse linear equation solver using linked list storage ,
IMSL Technical Report 9006, IMSL, Houston.
Dongarra et al.
Dongarra, J.J., J.R. Bunch, C.B. Moler, and G.W. Stewart (1979),
LINPACK User’s Guide, SIAM, Philadelphia.
DuCroz et al.
Du Croz, Jeremy, P. Mayes, and G. Radicati (1990), Factorization of
band matrices using Level-3 BLAS, Proceedings of CONPAR 90-VAPP
IV, Lecture Notes in Computer Science, Springer, Berlin, 222.
Duff et al.
Duff, I. S., A. M. Erisman, and J. K. Reid (1986), Direct Methods for
Sparse Matrices, Clarendon Press, Oxford.
Forsythe
Forsythe, G.E. (1957), Generation and use of orthogonal polynomials for
fitting data with a digital computer, SIAM Journal on Applied
Mathematics, 5, 74–88.
Franke
Franke, R. (1982), Scattered data interpolation: Tests of some methods,
Mathematics of Computation, 38, 181–200.
Garbow et al.
Garbow, B.S., J.M. Boyle, K.J. Dongarra, and C.B. Moler (1977), Matrix
Eigensystem Routines - EISPACK Guide Extension, Springer–Verlag,
New York.
Garbow, B.S., G. Giunta, J.N. Lyness, and A. Murli (1988), Software for
an implementation of Weeks’ method for the inverse Laplace transform
problem, ACM Transactions on Mathematical Software, 14, 163–170.
Gautschi
Gautschi, Walter (1968), Construction of Gauss-Christoffel quadrature
formulas, Mathematics of Computation, 22, 251–270.
Gear
Gear, C.W. (1971), Numerical Initial Value Problems in Ordinary
Differential Equations, Prentice-Hall, Englewood Cliffs, New Jersey.
Gentleman
Gentleman, W. Morven (1974), Basic procedures for large, sparse or
weighted linear least squares problems, Applied Statistics, 23, 448–454.
Gill et al.
Gill, P.E., W. Murray, M.A. Saunders, and M.H. Wright (1985), Model
building and practical aspects of nonlinear programming, in
Computational Mathematical Programming, (edited by K. Schittkowski),
NATO ASI Series, 15, Springer-Verlag, Berlin, Germany.
Golub
Golub, G.H. (1973), Some modified matrix eigenvalue problems, SIAM
Review, 15, 318–334.
Grosse
Grosse, Eric (1980), Tensor spline approximation, Linear Algebra and its
Applications, 34, 29–41.
Hanson
Hanson, Richard J. (1986), Least squares with bounds and linear
constraints, SIAM Journal Sci. Stat. Computing, 7, #3.
Hardy
Hardy, R.L. (1971), Multiquadric equations of topography and other
irregular surfaces, Journal of Geophysical Research, 76, 1905–1915.
Hart et al.
Hart, John F., E.W. Cheney, Charles L. Lawson, Hans [Link], Charles
K. Mesztenyi, John R. Rice, Henry G. Thacher, Jr., and Christoph
Witzgall (1968), Computer Approximations, John Wiley & Sons, New
York.
Healy
Healy, M.J.R. (1968), Algorithm AS 6: Triangular decomposition of a
symmetric matrix, Applied Statistics, 17, 195–197.
Herraman
Herraman, C. (1968), Sums of squares and products matrix, Applied
Statistics, 17, 289–292.
Higham
Higham, Nicholas J. (1988), FORTRAN Codes for estimating the one-
norm of a real or complex matrix, with applications to condition
estimation, ACM Transactions on Mathematical Software, 14, 381-396.
Hill
Hill, G.W. (1970), Student’s t-distribution, Communications of the ACM,
13, 617–619.
Hindmarsh
Hindmarsh, A.C. (1974), GEAR: Ordinary Differential Equation System
Solver, Lawrence Livermore National Laboratory Report UCID-30001,
Revision 3, Lawrence Livermore National Laboratory, Livermore, Calif.
Huber
Huber, Peter J. (1981), Robust Statistics, John Wiley & Sons, New York.
Hull et al.
Hull, T.E., W.H. Enright, and K.R. Jackson (1976), User’s guide for
DVERK — A subroutine for solving non-stiff ODEs, Department of
Computer Science Technical Report 100, University of Toronto.
Irvine et al.
Irvine, Larry D., Samuel P. Marin, and Philip W. Smith (1986),
Constrained interpolation and smoothing, Constructive Approximation, 2,
129–151.
Jackson et al.
Jackson, K.R., W.H. Enright, and T.E. Hull (1978), A theoretical
criterion for comparing Runge-Kutta formulas, SIAM Journal of
Numerical Analysis, 15, 618–641.
Jenkins
Jenkins, M.A. (1975), Algorithm 493: Zeros of a real polynomial, ACM
Transactions on Mathematical Software, 1, 178–189.
Jöhnk
Jöhnk, M.D. (1964), Erzeugung von Betaverteilten und Gammaverteilten
Zufalls-zahlen, Metrika, 8, 5–15.
Knuth
Knuth, Donald E. (1981), The Art of Computer Programming, Volume 2:
Seminumerical Algorithms, 2nd. ed., Addison-Wesley, Reading, Mass.
Lehmann
Lehmann, E.L. (1975), Nonparametrics: Statistical Methods Based on
Ranks, Holden-Day, San Francisco.
Levenberg
Levenberg, K. (1944), A method for the solution of certain problems in
least squares, Quarterly of Applied Mathematics, 2, 164–168.
Leavenworth
Leavenworth, B. (1960), Algorithm 25: Real zeros of an arbitrary
function, Communications of the ACM, 3, 602.
Lewis et al.
Lewis, P.A.W., A.S. Goodman, and J.M. Miller (1969), A pseudorandom
number generator for the System/ 360, IBM Systems Journal, 8, 136–146.
Liepman
Liepman, David S. (1964), Mathematical constants, in Handbook of
Mathematical Functions, Dover Publications, New York.
Maindonald
Maindonald, J.H. (1984), Statistical Computation, John Wiley & Sons,
New York.
Marquardt
Marquardt, D. (1963), An algorithm for least-squares estimation of
nonlinear parameters, SIAM Journal on Applied Mathematics, 11, 431–
441.
Michelli et al.
Micchelli, C.A., T.J. Rivlin, and S. Winograd (1976), The optimal
recovery of smooth functions, Numerische Mathematik, 26, 279–285.
Micchelli, C.A., Philip W. Smith, John Swetits, and Joseph D. Ward
(1985), Constrained Lp approximation, Constructive Approximation, 1,
93–102.
Moré et al.
Moré, Jorge, Burton Garbow, and Kenneth Hillstrom (1980), User Guide
for MINPACK-1, Argonne National Laboratory Report ANL-80-74,
Argonne, Illinois.
Müller
Müller, D.E. (1956), A method for solving algebraic equations using an
automatic computer, Mathematical Tables and Aids to Computation , 10,
208–215.
Murtagh
Murtagh, Bruce A. (1981), Advanced Linear Programming: Computation
and Practice, McGraw-Hill, New York.
Murty
Murty, Katta G. (1983), Linear Programming, John Wiley and Sons,
New York.
Neter et al.
Neter, John, William Wasserman, and Michael H. Kutner (1983), Applied
Linear Regression Models, Richard D. Irwin, Homewood, Illinois.
Owen
Owen, D.B. (1962), Handbook of Statistical Tables, Addison-Wesley
Publishing Company, Reading, Mass.
Owen, D.B. (1965), A special case of the bivariate non-central t
distribution, Biometrika, 52, 437–446.
Parlett
Parlett, B.N. (1980), The Symmetric Eigenvalue Problem, Prentice-Hall,
Inc., Englewood Cliffs, New Jersey.
Petro
Petro, R. (1970), Remark on Algorithm 347: An efficient algorithm for
sorting with minimal storage, Communications of the ACM, 13, 624.
Piessens et al.
Piessens, R., E. deDoncker-Kapenga, C.W. Überhuber, and D.K.
Kahaner (1983), QUADPACK, Springer-Verlag, New York.
Powell
Powell, M.J.D. (1978), A fast algorithm for nonlinearly constrained
optimization calculations, Numerical Analysis Proceedings, Dundee
1977, Lecture Notes in Mathematics, (edited by G. A. Watson), 630,
Springer-Verlag, Berlin, Germany, 144–157.
Powell, M.J.D. (1985), On the quadratic programming algorithm of
Goldfarb and Idnani, Mathematical Programming Study, 25, 46–61.
Powell, M.J.D. (1988), A tolerant algorithm for linearly constrained
optimizations calculations, DAMTP Report NA17, University of
Cambridge, England.
Powell, M.J.D. (1989), TOLMIN: A fortran package for linearly
constrained optimizations calculations, DAMTP Report NA2, University
of Cambridge, England.
Powell, M.J.D. (1983), ZQPCVX a FORTRAN subroutine for convex
quadratic programming, DAMTP Report 1983/NA17, University of
Cambridge, Cambridge, England.
Reinsch
Reinsch, Christian H. (1967), Smoothing by spline functions, Numerische
Mathematik, 10, 177–183.
Savage
Savage, I. Richard (1956), Contributions to the theory of rank order
statistics—the two-sample case, Annals of Mathematical Statistics, 27,
590–615.
Schittkowski
Schittkowski, K. (1987), More test examples for nonlinear programming
codes, Springer-Verlag, Berlin, 74.
Schittkowski, K. (1986), NLPQL: A FORTRAN subroutine solving
constrained nonlinear programming problems, (edited by Clyde L.
Monma), Annals of Operations Research, 5, 485–500.
Schittkowski, K. (1980), Nonlinear programming codes, Lecture Notes in
Economics and Mathematical Systems, 183, Springer-Verlag, Berlin,
Germany.
Schittkowski, K. (1983), On the convergence of a sequential quadratic
programming method with an augmented Lagrangian line search function,
Mathematik Operationsforschung und Statistik, Serie Optimization, 14,
197–216.
Schmeiser
Schmeiser, Bruce (1983), Recent advances in generating observations
from discrete random variates, in Computer Science and Statistics:
Proceedings of the Fifteenth Symposium on the Interface , (edited by
James E. Gentle), North-Holland Publishing Company, Amsterdam, 154–
160.
Shampine
Shampine, L.F. (1975), Discrete least squares polynomial fits,
Communications of the ACM, 18, 179–180.
Singleton
Singleton, T.C. (1969), Algorithm 347: An efficient algorithm for sorting
with minimal storage, Communications of the ACM, 12, 185–187.
Smith et al.
Smith, B.T., J.M. Boyle, J.J. Dongarra, B.S. Garbow, Y. Ikebe, V.C.
Klema, and C.B. Moler (1976), Matrix Eigensystem Routines —
EISPACK Guide, Springer-Verlag, New York.
Smith
Smith, P.W. (1990), On knots and nodes for spline interpolation,
Algorithms for Approximation II, J.C. Mason and M.G. Cox, Eds.,
Chapman and Hall, New York.
Stewart
Stewart, G.W. (1973), Introduction to Matrix Computations, Academic
Press, New York.
Stoer
Stoer, J. (1985), Principles of sequential quadratic programming methods
for solving nonlinear programs, in Computational Mathematical
Strecok
Strecok, Anthony J. (1968), On the calculation of the inverse of the error
function, Mathematics of Computation, 22, 144–158.
Temme
Temme, N.M (1975), On the numerical evaluation of the modified Bessel
Function of the third kind, Journal of Computational Physics, 19, 324–
337.
Tukey
Tukey, John W. (1962), The future of data analysis, Annals of
Mathematical Statistics, 33, 1–67.
Walker
Walker, H.F. (1988), Implementation of the GMRES method using
Householder transformations, SIAM Journal of Scientific and Statistical
Computing, 9, 152-163.
Watkins
Watkins, David S., L. Elsner (1991), Convergence of algorithm of
decomposition type for the eigenvalue problem, Linear Algebra
Applications, 143, pp. 29–47.
Weeks
Weeks, W.T. (1966), Numerical inversion of Laplace transforms using
Laguerre functions, J. ACM, 13, 419–429.
z
a x−c
b
Index
condition numbers 116
conjugate gradient method 79
convolution 346, 352
coordinate format 655, 659, 667
correlation 346, 352
correlation matrix 538
cosine factor 256
cosine Fresnel integrals 481
CPU time 597
cubic Hermite polynomials 299
A cubic spline interpolant 217
Adams-Gear method 292 cubic splines 145, 152, 157, 160,
Airy functions 483, 484, 485, 486 205
algebraic-logarithmic singularities current value of the seed 565
249
ANSI C vii D
approximation 225
arithmetic 688 data types 688
dates and days 597, 599
decay rates 286
B derivatives 281
backward differentiation formulas discrete Fourier cosine
296 transformation 334, 336
band matrices 648, 651 discrete Fourier sine transformation
band storage mode 648, 651, 664 338, 340
Bauer and Fike theorem 116 distribution functions 495, 497, 498,
Bessel functions 452, 454, 455, 456, 500, 501, 504, 505, 507, 508,
458, 459, 461, 462, 464, 465, 510, 511, 513, 514, 516, 517
466, 467, 469, 470, 471, 473
beta distributions 575 E
beta functions 443, 445, 446, 514,
516 eigenvalues 115, 116, 117, 118, 120,
binomial functions 510 123, 126, 129, 132, 135
bivariate functions 517 eigenvectors 115, 116, 117, 118,
Blom scores 559 120, 123, 126, 129, 132, 135
elementary functions 688
elementary integrals 480
C element-wise addition 655, 659
Cauchy principal 264 elliptic integrals 474, 475, 476, 477,
chi-squared functions 498, 500 479
chi-squared goodness-of-fit test 530 equality/inequality constraints 414
Cholesky factorization 17, 22, 35, equilibrium 286
39, 107, 130 error detection 216
column pivoting 88 error functions 437, 438, 440, 441
complex arithmetic xxii, 688 error handling xxi, 600, 606
complex general band system 31 error messages 592
complex Hermitian positive definite errors 685
system 39 Euler’s constant 610
F K
U
uncertainty 4
underflow xxi
uniform mesh 315
univariate 249
univariate statistics 521
V
vectors 579
Verner, J.H. 289
version 596
Z
zero of a system 377
zeros of a function 372
• Clarity of documentation
Consultation
Contact Visual Numerics Product Support by faxing 713/781-9260 or by
emailing:
Electronic addresses are not handled uniformly across the major networks, and
some local conventions for specifying electronic addresses might cause further
variations to occur; contact your E-mail postmaster for further details.
The following describes the procedure for consultation with Visual Numerics:
4. Include the name of the routine for which assistance is needed and a
description of the problem
The function imsl_f_lin_sol_gen_band is used to solve a system of linear equations, Ax = b, where A is a real general band matrix. It provides flexible optional arguments for various computations. Key optional arguments include IMSL_TRANSPOSE for solving ATx = b instead of Ax = b, IMSL_RETURN_USER for using a user-allocated array to return the solution, IMSL_FACTOR for returning the pivot sequence and LU factorization with allocated space, and IMSL_CONDITION for estimating the condition number of A. These options enhance the capability to factorize, solve, and manage computations related to the input matrix and its properties .
Functions like t_cdf evaluate probabilities by computing the cumulative distribution function for t-distributed random variables based on the degrees of freedom (df). These parameters dictate the shape of the distribution, as a lower df leads to heavier tails, reflecting a higher probability of extreme values compared to distributions with more degrees of freedom, which resemble the normal distribution as df increases. The evaluation relies on the mathematical definition of the t-distribution, and uses series expansion methods or relationships with beta distributions depending on the magnitude of t and the range of df, thereby accurately reflecting the probability and variability associated with the specified df .
imsl_f_int_fcn_smooth is intended for integrating smooth functions using nonadaptive quadrature based on nested Paterson rules, which may not be robust for functions with singularities. Its focus is on functions that are consistently smooth over the interval. In contrast, imsl_f_int_fcn_sing_pts is geared towards functions with known singular points, employing a globally adaptive integration scheme which focuses on reducing errors around these singularities. Errors in imsl_f_int_fcn_sing_pts primarily arise from the mismanagement of singular points or reaching the maximum number of subintervals, while imsl_f_int_fcn_smooth might suffer from inadequate precision for functions lacking sufficient smoothness or where sharp variations occur .
Interpolation error in cubic spline methods depends significantly on the smoothness of the original function being approximated, the density and distribution of the interpolation points, and the choice of boundary conditions. The error is generally influenced by how well the splines can approximate the original function's curvature. If the function is smooth and well-behaved, the interpolation error will be minimal. The 'not-a-knot' condition, or other imposed boundary conditions, also affect error distribution. Properly selected knots can minimize error, as splines are piecewise polynomials that precisely match the given data points but approximate the regions in between, primarily driven by the function's nature at interpolation locations .
The IMSL_CONDITION option provides an estimated L1 norm condition number of the matrix A, enhancing the utility of imsl_f_lin_sol_gen_band by offering insight into the sensitivity and stability of the numerical solution. A high condition number suggests that the matrix is close to singular or ill-conditioned, which implies that small changes in the matrix or right-hand side vector could lead to large variations in the solution. This allows users to gauge the reliability of computed solutions and potentially adjust their strategy for solving accurate results based on the isolation of numerical errors .
The function imsl_f_int_fcn_cauchy is effective at integrating functions that possess singularities typical of the Cauchy distribution, utilizing adaptive schemes to handle singular points intelligently. The reliability hinges on its capability to minimize errors by focusing computational resources on problematic regions. However, potential limitations include its sensitivity to the exact placement of singularities, the potential for roundoff errors, and the degradation of precision when the integrand varies rapidly around singular points. The method's efficiency may decline, necessitating refined techniques for effectively isolating and processing singular behavior .
Using Kelvin function derivatives in numerical algorithms, such as imsl_f_kelvin_ker0_derivative, is crucial for problems related to applications involving cylindrical waveguides, signal processing, or solving differential equations that model physical phenomena requiring Bessel and Kelvin function solutions. The derivative, particularly for the second kind, provides insight into the behavior of these specialized functions under differentiation, which impacts their application in modeling and simulation tasks across engineering fields. It highlights an advanced understanding of physical systems described by these functions, especially in contexts where asymptotic properties or singular behavior is involved .
The example of evaluating Kelvin function derivatives, such as with imsl_f_kelvin_kei0_derivative, illustrates numerical differentiation by calculating the gradient of a function that exhibits rapid oscillations or singular behavior near certain points. For the Kelvin functions, derivative computation exemplifies handling such complexities by accurate numerical schemes that stabilize and enhance calculation precision around singular or asymptotic points. It showcases how specialized functions can extend standard differentiation approaches, accommodating edge cases and maximizing precision in challenging computational settings .
The imsl_c_lin_sol_posdef_band function is specifically designed to solve systems of linear equations with real symmetric positive definite band matrices, employing the RHR Cholesky factorization. This contrasts with imsl_c_lin_sol_gen_band, which handles general complex band matrices with LU factorization. imsl_c_lin_sol_posdef_band uses an RHR factorization that is more efficient for positive definite matrices as it assumes symmetry and positive-definiteness, which simplifies computations and enhances numerical stability. In addition, it can provide an L1 norm condition number estimate using Higham’s modifications to Hager’s method to assess the sensitivity of the solution .
Solving linear equations with Hermitian matrices leverages their property of having real diagonal elements and complex conjugate symmetry, allowing the use of specialized algorithms that assume these characteristics. This can enhance numerical efficiency and stability, as indicated by functions like those that check Hermitian diagonal properties. For general matrices, algorithms need to accommodate a wider array of possibilities, involving a broader set of operations like LU factorization without assumptions about symmetry or definiteness. Special error cases, such as singularity or positivity issues, need particular attention in the context of Hermitian matrices .