/*
 * Roby Joehanes
 * 
 * Copyright 2007 Roby Joehanes
 * This file is distributed under the GNU General Public License version 3.0.
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
/**
 * 
 */
package jdistlib.math;

import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sqrt;

/**
 * 

Routines that I took from LINPACK library. So far, only dpbfa and dpbsl * are taken. I hand-translated them from FORTRAN. I don't change the method * names, just in case if you people are familiar with it already. Also, please * pay attention to the parameter names. I removed all superfluous indices. * *

See: http://www.netlib.org/linpack/ * * @author Roby Joehanes * */ public class LinPack { /** *

dpbsl solves the double precision symmetric positive definite band system a*x = b * using the factors computed by dpbco or dpbfa. * *

(Taken from LINPACK_D) * *

on entry * * @param abd double precision(lda, n), the output from dpbco or dpbfa. * @param lda integer, the leading dimension of the array abd * @param n integer, the order of the matrix a * @param m integer, the number of diagonals above the main diagonal. * @param b double precision(n), the right hand side vector. * *

On return * @return b the solution vector x * *

error condition
	 * a division by zero will occur if the input factor contains
	 * a zero on the diagonal.  technically this indicates singularity
	 * but it is usually caused by improper subroutine arguments.
	 * it will not occur if the subroutines are called correctly and  info == 0 .
	 * 
	 * to compute  inverse(a) * c  where  c  is a matrix with  p  columns
	 * 
	 * call dpbco(abd,lda,n,rcond,z,info)
	 * if (rcond is too small .or. info .ne. 0) go to ...
	 *    do 10 j = 1, p
	 *       call dpbsl(abd,lda,n,c(1,j))
	 *    10 continue
	 * 
	 * linpack.  this version dated 08/14/78
	 * cleve moler, university of new mexico, argonne national lab.
	 * 
* @param abd Banded matrix. * @param m Band width * @param b the Y vector. Holds the output after the routine ends. */ public static final void dpbsl(double[][] abd, int m, double[] b) { double t; int n = abd[0].length, la, lb, lm; // solve trans(r)*y = b for (int k = 0; k < n; ++k) { lm = min(k, m); la = m - lm; lb = k - lm; t = 0; for (int i = 0; i < lm; i++) t += abd[la + i][k] * b[lb + i]; b[k] = (b[k] - t) / abd[m][k]; } // solve r*x = y for (int kb = 0; kb < n; ++kb) { int k = n - kb - 1; lm = min(k, m); la = m - lm; lb = k - lm; b[k] /= abd[m][k]; t = -b[k]; for (int i = 0; i < lm; i++) b[lb + i] += t * abd[la + i][k]; } } /** *

dpbfa factors a double precision symmetric positive definite * matrix stored in band form. * *

dpbfa is usually called by dpbco, but it can be called * directly with a saving in time if rcond is not needed. * *

(Taken from LINPACK_D) * *

	 * on entry
	 * abd     double precision(lda, n)
	 *         the matrix to be factored.  the columns of the upper
	 *         triangle are stored in the columns of abd and the
	 *         diagonals of the upper triangle are stored in the
	 *         rows of abd .  see the comments below for details.
	 * 
	 * lda     integer
	 *         the leading dimension of the array abd. lda must be >= m + 1
	 * 
	 * n       integer
	 *         the order of the matrix  a .
	 * 
	 * m       integer
	 *         the number of diagonals above the main diagonal. 0 <= m < n
	 * 
	 * on return
	 * abd     an upper triangular matrix  r , stored in band form, so that a = trans(r)*r .
	 * info    integer
	 *         = 0  for normal return.
	 *         = k  if the leading minor of order  k  is not positive definite.
	 * 
	 * band storage
	 * if  a  is a symmetric positive definite band matrix,
	 * the following program segment will set up the input.
	 *     m = (band width above diagonal)
	 *     do 20 j = 1, n
	 *        i1 = max0(1, j-m)
	 *        do 10 i = i1, j
	 *           k = i-j+m+1
	 *           abd(k,j) = a(i,j)
	 *        10    continue
	 *     20 continue
	 * linpack.  this version dated 08/14/78 .
	 * cleve moler, university of new mexico, argonne national lab.
	 * begin block with ...exits to 40
	 * 
* @param abd Banded matrix * @param m Band width */ public static final int dpbfa(double[][] abd, int m) { int n = abd[0].length; for (int j = 0; j < n; ++j) { double s = 0; for (int mu = max(m - j, 0), k = mu, ik = m, jk = max(j - m, 0); k < m; ++k, --ik, ++jk) { double sum = 0; int length = k - mu; for (int l = 0; l < length; l++) sum += abd[ik + l][jk] * abd[mu + l][j]; double t = (abd[k][j] - sum) / abd[m][jk]; abd[k][j] = t; s += t * t; } s = abd[m][j] - s; if (s <= 0) return j; abd[m][j] = sqrt(s); } return 0; } }

Ads help maintain this website.