$search
00001 /* 00002 * OpenNL: Numerical Library 00003 * Copyright (C) 2004 Bruno Levy 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * 00019 * If you modify this software, you should include a notice giving the 00020 * name of the person performing the modification, the date of modification, 00021 * and the reason for such modification. 00022 * 00023 * Contact: Bruno Levy 00024 * 00025 * levy@loria.fr 00026 * 00027 * ISA Project 00028 * LORIA, INRIA Lorraine, 00029 * Campus Scientifique, BP 239 00030 * 54506 VANDOEUVRE LES NANCY CEDEX 00031 * FRANCE 00032 * 00033 * Note that the GNU General Public License does not permit incorporating 00034 * the Software into proprietary programs. 00035 */ 00036 00037 #include <NL/nl_blas.h> 00038 00039 #ifdef NL_USE_ATLAS 00040 int NL_FORTRAN_WRAP(xerbla)(char *srname, int *info) { 00041 printf("** On entry to %6s, parameter number %2d had an illegal value\n", 00042 srname, *info 00043 ); 00044 return 0; 00045 } 00046 #ifndef NL_USE_BLAS 00047 #define NL_USE_BLAS 00048 #endif 00049 #endif 00050 00051 #ifdef NL_USE_SUPERLU 00052 #ifndef NL_USE_BLAS 00053 #define NL_USE_BLAS 00054 /* 00055 * The BLAS included in SuperLU does not have DTPSV, 00056 * we use the DTPSV embedded in OpenNL. 00057 */ 00058 #define NEEDS_DTPSV 00059 #endif 00060 #endif 00061 00062 #ifndef NL_USE_BLAS 00063 #define NEEDS_DTPSV 00064 #endif 00065 00066 00067 /************************************************************************/ 00068 /* BLAS routines */ 00069 /* copy-pasted from CBLAS (i.e. generated from f2c) */ 00070 00071 /* 00072 * lsame 00073 * xerbla 00074 * daxpy 00075 * ddot 00076 * dscal 00077 * dnrm2 00078 * dcopy 00079 * dgemv 00080 * dtpsv 00081 */ 00082 00083 00084 00085 typedef NLint integer ; 00086 typedef NLdouble doublereal ; 00087 typedef NLboolean logical ; 00088 typedef NLint ftnlen ; 00089 00090 00091 #ifndef max 00092 #define max(x,y) ((x) > (y) ? (x) : (y)) 00093 #endif 00094 00095 #ifndef NL_USE_BLAS 00096 00097 int NL_FORTRAN_WRAP(lsame)(char *ca, char *cb) 00098 { 00099 /* -- LAPACK auxiliary routine (version 2.0) -- 00100 Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., 00101 Courant Institute, Argonne National Lab, and Rice University 00102 September 30, 1994 00103 00104 Purpose 00105 ======= 00106 00107 LSAME returns .TRUE. if CA is the same letter as CB regardless of case. 00108 00109 Arguments 00110 ========= 00111 00112 CA (input) CHARACTER*1 00113 CB (input) CHARACTER*1 00114 CA and CB specify the single characters to be compared. 00115 00116 ===================================================================== 00117 */ 00118 00119 /* System generated locals */ 00120 int ret_val; 00121 00122 /* Local variables */ 00123 int inta, intb, zcode; 00124 00125 ret_val = *(unsigned char *)ca == *(unsigned char *)cb; 00126 if (ret_val) { 00127 return ret_val; 00128 } 00129 00130 /* Now test for equivalence if both characters are alphabetic. */ 00131 00132 zcode = 'Z'; 00133 00134 /* Use 'Z' rather than 'A' so that ASCII can be detected on Prime 00135 machines, on which ICHAR returns a value with bit 8 set. 00136 ICHAR('A') on Prime machines returns 193 which is the same as 00137 ICHAR('A') on an EBCDIC machine. */ 00138 00139 inta = *(unsigned char *)ca; 00140 intb = *(unsigned char *)cb; 00141 00142 if (zcode == 90 || zcode == 122) { 00143 /* ASCII is assumed - ZCODE is the ASCII code of either lower or 00144 upper case 'Z'. */ 00145 if (inta >= 97 && inta <= 122) inta += -32; 00146 if (intb >= 97 && intb <= 122) intb += -32; 00147 00148 } else if (zcode == 233 || zcode == 169) { 00149 /* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or 00150 upper case 'Z'. */ 00151 if ((inta >= 129 && inta <= 137) || 00152 (inta >= 145 && inta <= 153) || 00153 (inta >= 162 && inta <= 169) 00154 ) 00155 inta += 64; 00156 if ( 00157 (intb >= 129 && intb <= 137) || 00158 (intb >= 145 && intb <= 153) || 00159 (intb >= 162 && intb <= 169) 00160 ) 00161 intb += 64; 00162 } else if (zcode == 218 || zcode == 250) { 00163 /* ASCII is assumed, on Prime machines - ZCODE is the ASCII code 00164 plus 128 of either lower or upper case 'Z'. */ 00165 if (inta >= 225 && inta <= 250) inta += -32; 00166 if (intb >= 225 && intb <= 250) intb += -32; 00167 } 00168 ret_val = inta == intb; 00169 return ret_val; 00170 00171 } /* lsame_ */ 00172 00173 /* Subroutine */ int NL_FORTRAN_WRAP(xerbla)(char *srname, int *info) 00174 { 00175 /* -- LAPACK auxiliary routine (version 2.0) -- 00176 Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., 00177 Courant Institute, Argonne National Lab, and Rice University 00178 September 30, 1994 00179 00180 00181 Purpose 00182 ======= 00183 00184 XERBLA is an error handler for the LAPACK routines. 00185 It is called by an LAPACK routine if an input parameter has an 00186 invalid value. A message is printed and execution stops. 00187 00188 Installers may consider modifying the STOP statement in order to 00189 call system-specific exception-handling facilities. 00190 00191 Arguments 00192 ========= 00193 00194 SRNAME (input) CHARACTER*6 00195 The name of the routine which called XERBLA. 00196 00197 INFO (input) INT 00198 The position of the invalid parameter in the parameter list 00199 00200 of the calling routine. 00201 00202 ===================================================================== 00203 */ 00204 00205 printf("** On entry to %6s, parameter number %2d had an illegal value\n", 00206 srname, *info); 00207 00208 /* End of XERBLA */ 00209 00210 return 0; 00211 } /* xerbla_ */ 00212 00213 00214 /* Subroutine */ int NL_FORTRAN_WRAP(daxpy)(integer *n, doublereal *da, doublereal *dx, 00215 integer *incx, doublereal *dy, integer *incy) 00216 { 00217 00218 00219 /* System generated locals */ 00220 integer i__1; 00221 00222 /* Local variables */ 00223 static integer i, m, ix, iy, mp1; 00224 00225 00226 /* constant times a vector plus a vector. 00227 uses unrolled loops for increments equal to one. 00228 jack dongarra, linpack, 3/11/78. 00229 modified 12/3/93, array(1) declarations changed to array(*) 00230 00231 00232 00233 Parameter adjustments 00234 Function Body */ 00235 #define DY(I) dy[(I)-1] 00236 #define DX(I) dx[(I)-1] 00237 00238 00239 if (*n <= 0) { 00240 return 0; 00241 } 00242 if (*da == 0.) { 00243 return 0; 00244 } 00245 if (*incx == 1 && *incy == 1) { 00246 goto L20; 00247 } 00248 00249 /* code for unequal increments or equal increments 00250 not equal to 1 */ 00251 00252 ix = 1; 00253 iy = 1; 00254 if (*incx < 0) { 00255 ix = (-(*n) + 1) * *incx + 1; 00256 } 00257 if (*incy < 0) { 00258 iy = (-(*n) + 1) * *incy + 1; 00259 } 00260 i__1 = *n; 00261 for (i = 1; i <= *n; ++i) { 00262 DY(iy) += *da * DX(ix); 00263 ix += *incx; 00264 iy += *incy; 00265 /* L10: */ 00266 } 00267 return 0; 00268 00269 /* code for both increments equal to 1 00270 00271 00272 clean-up loop */ 00273 00274 L20: 00275 m = *n % 4; 00276 if (m == 0) { 00277 goto L40; 00278 } 00279 i__1 = m; 00280 for (i = 1; i <= m; ++i) { 00281 DY(i) += *da * DX(i); 00282 /* L30: */ 00283 } 00284 if (*n < 4) { 00285 return 0; 00286 } 00287 L40: 00288 mp1 = m + 1; 00289 i__1 = *n; 00290 for (i = mp1; i <= *n; i += 4) { 00291 DY(i) += *da * DX(i); 00292 DY(i + 1) += *da * DX(i + 1); 00293 DY(i + 2) += *da * DX(i + 2); 00294 DY(i + 3) += *da * DX(i + 3); 00295 /* L50: */ 00296 } 00297 return 0; 00298 } /* daxpy_ */ 00299 #undef DY 00300 #undef DX 00301 00302 00303 doublereal NL_FORTRAN_WRAP(ddot)(integer *n, doublereal *dx, integer *incx, doublereal *dy, 00304 integer *incy) 00305 { 00306 00307 /* System generated locals */ 00308 integer i__1; 00309 doublereal ret_val; 00310 00311 /* Local variables */ 00312 static integer i, m; 00313 static doublereal dtemp; 00314 static integer ix, iy, mp1; 00315 00316 00317 /* forms the dot product of two vectors. 00318 uses unrolled loops for increments equal to one. 00319 jack dongarra, linpack, 3/11/78. 00320 modified 12/3/93, array(1) declarations changed to array(*) 00321 00322 00323 00324 Parameter adjustments 00325 Function Body */ 00326 #define DY(I) dy[(I)-1] 00327 #define DX(I) dx[(I)-1] 00328 00329 ret_val = 0.; 00330 dtemp = 0.; 00331 if (*n <= 0) { 00332 return ret_val; 00333 } 00334 if (*incx == 1 && *incy == 1) { 00335 goto L20; 00336 } 00337 00338 /* code for unequal increments or equal increments 00339 not equal to 1 */ 00340 00341 ix = 1; 00342 iy = 1; 00343 if (*incx < 0) { 00344 ix = (-(*n) + 1) * *incx + 1; 00345 } 00346 if (*incy < 0) { 00347 iy = (-(*n) + 1) * *incy + 1; 00348 } 00349 i__1 = *n; 00350 for (i = 1; i <= *n; ++i) { 00351 dtemp += DX(ix) * DY(iy); 00352 ix += *incx; 00353 iy += *incy; 00354 /* L10: */ 00355 } 00356 ret_val = dtemp; 00357 return ret_val; 00358 00359 /* code for both increments equal to 1 00360 00361 00362 clean-up loop */ 00363 00364 L20: 00365 m = *n % 5; 00366 if (m == 0) { 00367 goto L40; 00368 } 00369 i__1 = m; 00370 for (i = 1; i <= m; ++i) { 00371 dtemp += DX(i) * DY(i); 00372 /* L30: */ 00373 } 00374 if (*n < 5) { 00375 goto L60; 00376 } 00377 L40: 00378 mp1 = m + 1; 00379 i__1 = *n; 00380 for (i = mp1; i <= *n; i += 5) { 00381 dtemp = dtemp + DX(i) * DY(i) + DX(i + 1) * DY(i + 1) + DX(i + 2) * 00382 DY(i + 2) + DX(i + 3) * DY(i + 3) + DX(i + 4) * DY(i + 4); 00383 /* L50: */ 00384 } 00385 L60: 00386 ret_val = dtemp; 00387 return ret_val; 00388 } /* ddot_ */ 00389 #undef DY 00390 #undef DX 00391 00392 /* Subroutine */ int NL_FORTRAN_WRAP(dscal)(integer *n, doublereal *da, doublereal *dx, 00393 integer *incx) 00394 { 00395 00396 00397 /* System generated locals */ 00398 integer i__1, i__2; 00399 00400 /* Local variables */ 00401 static integer i, m, nincx, mp1; 00402 00403 00404 /* scales a vector by a constant. 00405 uses unrolled loops for increment equal to one. 00406 jack dongarra, linpack, 3/11/78. 00407 modified 3/93 to return if incx .le. 0. 00408 modified 12/3/93, array(1) declarations changed to array(*) 00409 00410 00411 00412 Parameter adjustments 00413 Function Body */ 00414 #ifdef DX 00415 #undef DX 00416 #endif 00417 #define DX(I) dx[(I)-1] 00418 00419 00420 if (*n <= 0 || *incx <= 0) { 00421 return 0; 00422 } 00423 if (*incx == 1) { 00424 goto L20; 00425 } 00426 00427 /* code for increment not equal to 1 */ 00428 00429 nincx = *n * *incx; 00430 i__1 = nincx; 00431 i__2 = *incx; 00432 for (i = 1; *incx < 0 ? i >= nincx : i <= nincx; i += *incx) { 00433 DX(i) = *da * DX(i); 00434 /* L10: */ 00435 } 00436 return 0; 00437 00438 /* code for increment equal to 1 00439 00440 00441 clean-up loop */ 00442 00443 L20: 00444 m = *n % 5; 00445 if (m == 0) { 00446 goto L40; 00447 } 00448 i__2 = m; 00449 for (i = 1; i <= m; ++i) { 00450 DX(i) = *da * DX(i); 00451 /* L30: */ 00452 } 00453 if (*n < 5) { 00454 return 0; 00455 } 00456 L40: 00457 mp1 = m + 1; 00458 i__2 = *n; 00459 for (i = mp1; i <= *n; i += 5) { 00460 DX(i) = *da * DX(i); 00461 DX(i + 1) = *da * DX(i + 1); 00462 DX(i + 2) = *da * DX(i + 2); 00463 DX(i + 3) = *da * DX(i + 3); 00464 DX(i + 4) = *da * DX(i + 4); 00465 /* L50: */ 00466 } 00467 return 0; 00468 } /* dscal_ */ 00469 #undef DX 00470 00471 doublereal NL_FORTRAN_WRAP(dnrm2)(integer *n, doublereal *x, integer *incx) 00472 { 00473 00474 00475 /* System generated locals */ 00476 integer i__1, i__2; 00477 doublereal ret_val, d__1; 00478 00479 /* Builtin functions */ 00480 double sqrt(doublereal); 00481 00482 /* Local variables */ 00483 static doublereal norm, scale, absxi; 00484 static integer ix; 00485 static doublereal ssq; 00486 00487 00488 /* DNRM2 returns the euclidean norm of a vector via the function 00489 name, so that 00490 00491 DNRM2 := sqrt( x'*x ) 00492 00493 00494 00495 -- This version written on 25-October-1982. 00496 Modified on 14-October-1993 to inline the call to DLASSQ. 00497 Sven Hammarling, Nag Ltd. 00498 00499 00500 00501 Parameter adjustments 00502 Function Body */ 00503 #ifdef X 00504 #undef X 00505 #endif 00506 #define X(I) x[(I)-1] 00507 00508 00509 if (*n < 1 || *incx < 1) { 00510 norm = 0.; 00511 } else if (*n == 1) { 00512 norm = fabs(X(1)); 00513 } else { 00514 scale = 0.; 00515 ssq = 1.; 00516 /* The following loop is equivalent to this call to the LAPACK 00517 00518 auxiliary routine: 00519 CALL DLASSQ( N, X, INCX, SCALE, SSQ ) */ 00520 00521 i__1 = (*n - 1) * *incx + 1; 00522 i__2 = *incx; 00523 for (ix = 1; *incx < 0 ? ix >= (*n-1)**incx+1 : ix <= (*n-1)**incx+1; ix += *incx) { 00524 if (X(ix) != 0.) { 00525 absxi = (d__1 = X(ix), fabs(d__1)); 00526 if (scale < absxi) { 00527 /* Computing 2nd power */ 00528 d__1 = scale / absxi; 00529 ssq = ssq * (d__1 * d__1) + 1.; 00530 scale = absxi; 00531 } else { 00532 /* Computing 2nd power */ 00533 d__1 = absxi / scale; 00534 ssq += d__1 * d__1; 00535 } 00536 } 00537 /* L10: */ 00538 } 00539 norm = scale * sqrt(ssq); 00540 } 00541 00542 ret_val = norm; 00543 return ret_val; 00544 00545 /* End of DNRM2. */ 00546 00547 } /* dnrm2_ */ 00548 #undef X 00549 00550 /* Subroutine */ int NL_FORTRAN_WRAP(dcopy)(integer *n, doublereal *dx, integer *incx, 00551 doublereal *dy, integer *incy) 00552 { 00553 00554 /* System generated locals */ 00555 integer i__1; 00556 00557 /* Local variables */ 00558 static integer i, m, ix, iy, mp1; 00559 00560 00561 /* copies a vector, x, to a vector, y. 00562 uses unrolled loops for increments equal to one. 00563 jack dongarra, linpack, 3/11/78. 00564 modified 12/3/93, array(1) declarations changed to array(*) 00565 00566 00567 00568 Parameter adjustments 00569 Function Body */ 00570 #define DY(I) dy[(I)-1] 00571 #define DX(I) dx[(I)-1] 00572 00573 00574 if (*n <= 0) { 00575 return 0; 00576 } 00577 if (*incx == 1 && *incy == 1) { 00578 goto L20; 00579 } 00580 00581 /* code for unequal increments or equal increments 00582 not equal to 1 */ 00583 00584 ix = 1; 00585 iy = 1; 00586 if (*incx < 0) { 00587 ix = (-(*n) + 1) * *incx + 1; 00588 } 00589 if (*incy < 0) { 00590 iy = (-(*n) + 1) * *incy + 1; 00591 } 00592 i__1 = *n; 00593 for (i = 1; i <= *n; ++i) { 00594 DY(iy) = DX(ix); 00595 ix += *incx; 00596 iy += *incy; 00597 /* L10: */ 00598 } 00599 return 0; 00600 00601 /* code for both increments equal to 1 00602 00603 00604 clean-up loop */ 00605 00606 L20: 00607 m = *n % 7; 00608 if (m == 0) { 00609 goto L40; 00610 } 00611 i__1 = m; 00612 for (i = 1; i <= m; ++i) { 00613 DY(i) = DX(i); 00614 /* L30: */ 00615 } 00616 if (*n < 7) { 00617 return 0; 00618 } 00619 L40: 00620 mp1 = m + 1; 00621 i__1 = *n; 00622 for (i = mp1; i <= *n; i += 7) { 00623 DY(i) = DX(i); 00624 DY(i + 1) = DX(i + 1); 00625 DY(i + 2) = DX(i + 2); 00626 DY(i + 3) = DX(i + 3); 00627 DY(i + 4) = DX(i + 4); 00628 DY(i + 5) = DX(i + 5); 00629 DY(i + 6) = DX(i + 6); 00630 /* L50: */ 00631 } 00632 return 0; 00633 } /* dcopy_ */ 00634 00635 #undef DX 00636 #undef DY 00637 00638 /* Subroutine */ int NL_FORTRAN_WRAP(dgemv)(char *trans, integer *m, integer *n, doublereal * 00639 alpha, doublereal *a, integer *lda, doublereal *x, integer *incx, 00640 doublereal *beta, doublereal *y, integer *incy) 00641 { 00642 00643 00644 /* System generated locals */ 00645 /* integer a_dim1, a_offset ; */ 00646 integer i__1, i__2; 00647 00648 /* Local variables */ 00649 static integer info; 00650 static doublereal temp; 00651 static integer lenx, leny, i, j; 00652 /* extern logical lsame_(char *, char *); */ 00653 static integer ix, iy, jx, jy, kx, ky; 00654 /* extern int xerbla_(char *, integer *); */ 00655 00656 00657 /* Purpose 00658 ======= 00659 00660 DGEMV performs one of the matrix-vector operations 00661 00662 y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, 00663 00664 where alpha and beta are scalars, x and y are vectors and A is an 00665 m by n matrix. 00666 00667 Parameters 00668 ========== 00669 00670 TRANS - CHARACTER*1. 00671 On entry, TRANS specifies the operation to be performed as 00672 follows: 00673 00674 TRANS = 'N' or 'n' y := alpha*A*x + beta*y. 00675 00676 TRANS = 'T' or 't' y := alpha*A'*x + beta*y. 00677 00678 TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. 00679 00680 Unchanged on exit. 00681 00682 M - INTEGER. 00683 On entry, M specifies the number of rows of the matrix A. 00684 M must be at least zero. 00685 Unchanged on exit. 00686 00687 N - INTEGER. 00688 On entry, N specifies the number of columns of the matrix A. 00689 00690 N must be at least zero. 00691 Unchanged on exit. 00692 00693 ALPHA - DOUBLE PRECISION. 00694 On entry, ALPHA specifies the scalar alpha. 00695 Unchanged on exit. 00696 00697 A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). 00698 Before entry, the leading m by n part of the array A must 00699 contain the matrix of coefficients. 00700 Unchanged on exit. 00701 00702 LDA - INTEGER. 00703 On entry, LDA specifies the first dimension of A as declared 00704 00705 in the calling (sub) program. LDA must be at least 00706 max( 1, m ). 00707 Unchanged on exit. 00708 00709 X - DOUBLE PRECISION array of DIMENSION at least 00710 ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' 00711 and at least 00712 ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. 00713 Before entry, the incremented array X must contain the 00714 vector x. 00715 Unchanged on exit. 00716 00717 INCX - INTEGER. 00718 On entry, INCX specifies the increment for the elements of 00719 X. INCX must not be zero. 00720 Unchanged on exit. 00721 00722 BETA - DOUBLE PRECISION. 00723 On entry, BETA specifies the scalar beta. When BETA is 00724 supplied as zero then Y need not be set on input. 00725 Unchanged on exit. 00726 00727 Y - DOUBLE PRECISION array of DIMENSION at least 00728 ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' 00729 and at least 00730 ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. 00731 Before entry with BETA non-zero, the incremented array Y 00732 must contain the vector y. On exit, Y is overwritten by the 00733 00734 updated vector y. 00735 00736 INCY - INTEGER. 00737 On entry, INCY specifies the increment for the elements of 00738 Y. INCY must not be zero. 00739 Unchanged on exit. 00740 00741 00742 Level 2 Blas routine. 00743 00744 -- Written on 22-October-1986. 00745 Jack Dongarra, Argonne National Lab. 00746 Jeremy Du Croz, Nag Central Office. 00747 Sven Hammarling, Nag Central Office. 00748 Richard Hanson, Sandia National Labs. 00749 00750 00751 00752 Test the input parameters. 00753 00754 00755 Parameter adjustments 00756 Function Body */ 00757 #define X(I) x[(I)-1] 00758 #define Y(I) y[(I)-1] 00759 00760 #define A(I,J) a[(I)-1 + ((J)-1)* ( *lda)] 00761 00762 info = 0; 00763 if (! NL_FORTRAN_WRAP(lsame)(trans, "N") && ! NL_FORTRAN_WRAP(lsame)(trans, "T") && ! 00764 NL_FORTRAN_WRAP(lsame)(trans, "C")) { 00765 info = 1; 00766 } else if (*m < 0) { 00767 info = 2; 00768 } else if (*n < 0) { 00769 info = 3; 00770 } else if (*lda < max(1,*m)) { 00771 info = 6; 00772 } else if (*incx == 0) { 00773 info = 8; 00774 } else if (*incy == 0) { 00775 info = 11; 00776 } 00777 if (info != 0) { 00778 NL_FORTRAN_WRAP(xerbla)("DGEMV ", &info); 00779 return 0; 00780 } 00781 00782 /* Quick return if possible. */ 00783 00784 if (*m == 0 || *n == 0 || (*alpha == 0. && *beta == 1.)) { 00785 return 0; 00786 } 00787 00788 /* Set LENX and LENY, the lengths of the vectors x and y, and set 00789 00790 up the start points in X and Y. */ 00791 00792 if (NL_FORTRAN_WRAP(lsame)(trans, "N")) { 00793 lenx = *n; 00794 leny = *m; 00795 } else { 00796 lenx = *m; 00797 leny = *n; 00798 } 00799 if (*incx > 0) { 00800 kx = 1; 00801 } else { 00802 kx = 1 - (lenx - 1) * *incx; 00803 } 00804 if (*incy > 0) { 00805 ky = 1; 00806 } else { 00807 ky = 1 - (leny - 1) * *incy; 00808 } 00809 00810 /* Start the operations. In this version the elements of A are 00811 accessed sequentially with one pass through A. 00812 00813 First form y := beta*y. */ 00814 00815 if (*beta != 1.) { 00816 if (*incy == 1) { 00817 if (*beta == 0.) { 00818 i__1 = leny; 00819 for (i = 1; i <= leny; ++i) { 00820 Y(i) = 0.; 00821 /* L10: */ 00822 } 00823 } else { 00824 i__1 = leny; 00825 for (i = 1; i <= leny; ++i) { 00826 Y(i) = *beta * Y(i); 00827 /* L20: */ 00828 } 00829 } 00830 } else { 00831 iy = ky; 00832 if (*beta == 0.) { 00833 i__1 = leny; 00834 for (i = 1; i <= leny; ++i) { 00835 Y(iy) = 0.; 00836 iy += *incy; 00837 /* L30: */ 00838 } 00839 } else { 00840 i__1 = leny; 00841 for (i = 1; i <= leny; ++i) { 00842 Y(iy) = *beta * Y(iy); 00843 iy += *incy; 00844 /* L40: */ 00845 } 00846 } 00847 } 00848 } 00849 if (*alpha == 0.) { 00850 return 0; 00851 } 00852 if (NL_FORTRAN_WRAP(lsame)(trans, "N")) { 00853 00854 /* Form y := alpha*A*x + y. */ 00855 00856 jx = kx; 00857 if (*incy == 1) { 00858 i__1 = *n; 00859 for (j = 1; j <= *n; ++j) { 00860 if (X(jx) != 0.) { 00861 temp = *alpha * X(jx); 00862 i__2 = *m; 00863 for (i = 1; i <= *m; ++i) { 00864 Y(i) += temp * A(i,j); 00865 /* L50: */ 00866 } 00867 } 00868 jx += *incx; 00869 /* L60: */ 00870 } 00871 } else { 00872 i__1 = *n; 00873 for (j = 1; j <= *n; ++j) { 00874 if (X(jx) != 0.) { 00875 temp = *alpha * X(jx); 00876 iy = ky; 00877 i__2 = *m; 00878 for (i = 1; i <= *m; ++i) { 00879 Y(iy) += temp * A(i,j); 00880 iy += *incy; 00881 /* L70: */ 00882 } 00883 } 00884 jx += *incx; 00885 /* L80: */ 00886 } 00887 } 00888 } else { 00889 00890 /* Form y := alpha*A'*x + y. */ 00891 00892 jy = ky; 00893 if (*incx == 1) { 00894 i__1 = *n; 00895 for (j = 1; j <= *n; ++j) { 00896 temp = 0.; 00897 i__2 = *m; 00898 for (i = 1; i <= *m; ++i) { 00899 temp += A(i,j) * X(i); 00900 /* L90: */ 00901 } 00902 Y(jy) += *alpha * temp; 00903 jy += *incy; 00904 /* L100: */ 00905 } 00906 } else { 00907 i__1 = *n; 00908 for (j = 1; j <= *n; ++j) { 00909 temp = 0.; 00910 ix = kx; 00911 i__2 = *m; 00912 for (i = 1; i <= *m; ++i) { 00913 temp += A(i,j) * X(ix); 00914 ix += *incx; 00915 /* L110: */ 00916 } 00917 Y(jy) += *alpha * temp; 00918 jy += *incy; 00919 /* L120: */ 00920 } 00921 } 00922 } 00923 00924 return 0; 00925 00926 /* End of DGEMV . */ 00927 00928 } /* dgemv_ */ 00929 00930 #undef X 00931 #undef Y 00932 #undef A 00933 00934 00935 00936 00937 #else 00938 00939 extern void NL_FORTRAN_WRAP(daxpy)( 00940 int *n, double *alpha, double *x, 00941 int *incx, double *y, int *incy 00942 ) ; 00943 00944 extern double NL_FORTRAN_WRAP(ddot)( 00945 int *n, double *x, int *incx, double *y, 00946 int *incy 00947 ) ; 00948 00949 extern double NL_FORTRAN_WRAP(dnrm2)( int *n, double *x, int *incx ) ; 00950 00951 extern int NL_FORTRAN_WRAP(dcopy)(int* n, double* dx, int* incx, double* dy, int* incy) ; 00952 00953 extern void NL_FORTRAN_WRAP(dscal)(int* n, double* alpha, double *x, int* incx) ; 00954 00955 #ifndef NEEDS_DTPSV 00956 extern void NL_FORTRAN_WRAP(dtpsv)( 00957 char *uplo, char *trans, char *diag, 00958 int *n, double *AP, double *x, int *incx 00959 ) ; 00960 #endif 00961 00962 extern void NL_FORTRAN_WRAP(dgemv)( 00963 char *trans, int *m, int *n, 00964 double *alpha, double *A, int *ldA, 00965 double *x, int *incx, 00966 double *beta, double *y, int *incy 00967 ) ; 00968 00969 #endif 00970 00971 #ifdef NEEDS_DTPSV 00972 00973 /* DECK DTPSV */ 00974 /* Subroutine */ int NL_FORTRAN_WRAP(dtpsv)(uplo, trans, diag, n, ap, x, incx, uplo_len, 00975 trans_len, diag_len) 00976 char *uplo, *trans, *diag; 00977 integer *n; 00978 doublereal *ap, *x; 00979 integer *incx; 00980 ftnlen uplo_len; 00981 ftnlen trans_len; 00982 ftnlen diag_len; 00983 { 00984 /* System generated locals */ 00985 integer i__1, i__2; 00986 00987 /* Local variables */ 00988 static integer info; 00989 static doublereal temp; 00990 static integer i__, j, k; 00991 /* extern logical lsame_(); */ 00992 static integer kk, ix, jx, kx; 00993 /* extern int xerbla_(); */ 00994 static logical nounit; 00995 00996 /* ***BEGIN PROLOGUE DTPSV */ 00997 /* ***PURPOSE Solve one of the systems of equations. */ 00998 /* ***LIBRARY SLATEC (BLAS) */ 00999 /* ***CATEGORY D1B4 */ 01000 /* ***TYPE DOUBLE PRECISION (STPSV-S, DTPSV-D, CTPSV-C) */ 01001 /* ***KEYWORDS LEVEL 2 BLAS, LINEAR ALGEBRA */ 01002 /* ***AUTHOR Dongarra, J. J., (ANL) */ 01003 /* Du Croz, J., (NAG) */ 01004 /* Hammarling, S., (NAG) */ 01005 /* Hanson, R. J., (SNLA) */ 01006 /* ***DESCRIPTION */ 01007 01008 /* DTPSV solves one of the systems of equations */ 01009 01010 /* A*x = b, or A'*x = b, */ 01011 01012 /* where b and x are n element vectors and A is an n by n unit, or */ 01013 /* non-unit, upper or lower triangular matrix, supplied in packed form. */ 01014 01015 /* No test for singularity or near-singularity is included in this */ 01016 /* routine. Such tests must be performed before calling this routine. */ 01017 01018 /* Parameters */ 01019 /* ========== */ 01020 01021 /* UPLO - CHARACTER*1. */ 01022 /* On entry, UPLO specifies whether the matrix is an upper or */ 01023 /* lower triangular matrix as follows: */ 01024 01025 /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ 01026 01027 /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ 01028 01029 /* Unchanged on exit. */ 01030 01031 /* TRANS - CHARACTER*1. */ 01032 /* On entry, TRANS specifies the equations to be solved as */ 01033 /* follows: */ 01034 01035 /* TRANS = 'N' or 'n' A*x = b. */ 01036 01037 /* TRANS = 'T' or 't' A'*x = b. */ 01038 01039 /* TRANS = 'C' or 'c' A'*x = b. */ 01040 01041 /* Unchanged on exit. */ 01042 01043 /* DIAG - CHARACTER*1. */ 01044 /* On entry, DIAG specifies whether or not A is unit */ 01045 /* triangular as follows: */ 01046 01047 /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ 01048 01049 /* DIAG = 'N' or 'n' A is not assumed to be unit */ 01050 /* triangular. */ 01051 01052 /* Unchanged on exit. */ 01053 01054 /* N - INTEGER. */ 01055 /* On entry, N specifies the order of the matrix A. */ 01056 /* N must be at least zero. */ 01057 /* Unchanged on exit. */ 01058 01059 /* AP - DOUBLE PRECISION array of DIMENSION at least */ 01060 /* ( ( n*( n + 1))/2). */ 01061 /* Before entry with UPLO = 'U' or 'u', the array AP must */ 01062 /* contain the upper triangular matrix packed sequentially, */ 01063 /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ 01064 /* AP( 2 ) and AP( 3 ) contain a( 1, 2 ) and a( 2, 2 ) */ 01065 /* respectively, and so on. */ 01066 /* Before entry with UPLO = 'L' or 'l', the array AP must */ 01067 /* contain the lower triangular matrix packed sequentially, */ 01068 /* column by column, so that AP( 1 ) contains a( 1, 1 ), */ 01069 /* AP( 2 ) and AP( 3 ) contain a( 2, 1 ) and a( 3, 1 ) */ 01070 /* respectively, and so on. */ 01071 /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ 01072 /* A are not referenced, but are assumed to be unity. */ 01073 /* Unchanged on exit. */ 01074 01075 /* X - DOUBLE PRECISION array of dimension at least */ 01076 /* ( 1 + ( n - 1 )*abs( INCX ) ). */ 01077 /* Before entry, the incremented array X must contain the n */ 01078 /* element right-hand side vector b. On exit, X is overwritten */ 01079 /* with the solution vector x. */ 01080 01081 /* INCX - INTEGER. */ 01082 /* On entry, INCX specifies the increment for the elements of */ 01083 /* X. INCX must not be zero. */ 01084 /* Unchanged on exit. */ 01085 01086 /* ***REFERENCES Dongarra, J. J., Du Croz, J., Hammarling, S., and */ 01087 /* Hanson, R. J. An extended set of Fortran basic linear */ 01088 /* algebra subprograms. ACM TOMS, Vol. 14, No. 1, */ 01089 /* pp. 1-17, March 1988. */ 01090 /* ***ROUTINES CALLED LSAME, XERBLA */ 01091 /* ***REVISION HISTORY (YYMMDD) */ 01092 /* 861022 DATE WRITTEN */ 01093 /* 910605 Modified to meet SLATEC prologue standards. Only comment */ 01094 /* lines were modified. (BKS) */ 01095 /* ***END PROLOGUE DTPSV */ 01096 /* .. Scalar Arguments .. */ 01097 /* .. Array Arguments .. */ 01098 /* .. Parameters .. */ 01099 /* .. Local Scalars .. */ 01100 /* .. External Functions .. */ 01101 /* .. External Subroutines .. */ 01102 /* ***FIRST EXECUTABLE STATEMENT DTPSV */ 01103 01104 /* Test the input parameters. */ 01105 01106 /* Parameter adjustments */ 01107 --x; 01108 --ap; 01109 01110 /* Function Body */ 01111 info = 0; 01112 if (!NL_FORTRAN_WRAP(lsame)(uplo, "U") && 01113 !NL_FORTRAN_WRAP(lsame)(uplo, "L") 01114 ) { 01115 info = 1; 01116 } else if ( 01117 !NL_FORTRAN_WRAP(lsame)(trans, "N") && 01118 !NL_FORTRAN_WRAP(lsame)(trans, "T") && 01119 !NL_FORTRAN_WRAP(lsame)(trans, "C") 01120 ) { 01121 info = 2; 01122 } else if ( 01123 !NL_FORTRAN_WRAP(lsame)(diag, "U") && 01124 !NL_FORTRAN_WRAP(lsame)(diag, "N") 01125 ) { 01126 info = 3; 01127 } else if (*n < 0) { 01128 info = 4; 01129 } else if (*incx == 0) { 01130 info = 7; 01131 } 01132 if (info != 0) { 01133 NL_FORTRAN_WRAP(xerbla)("DTPSV ", &info); 01134 return 0; 01135 } 01136 01137 /* Quick return if possible. */ 01138 01139 if (*n == 0) { 01140 return 0; 01141 } 01142 01143 nounit = NL_FORTRAN_WRAP(lsame)(diag, "N"); 01144 01145 /* Set up the start point in X if the increment is not unity. This */ 01146 /* will be ( N - 1 )*INCX too small for descending loops. */ 01147 01148 if (*incx <= 0) { 01149 kx = 1 - (*n - 1) * *incx; 01150 } else if (*incx != 1) { 01151 kx = 1; 01152 } 01153 01154 /* Start the operations. In this version the elements of AP are */ 01155 /* accessed sequentially with one pass through AP. */ 01156 01157 if (NL_FORTRAN_WRAP(lsame)(trans, "N")) { 01158 01159 /* Form x := inv( A )*x. */ 01160 01161 if (NL_FORTRAN_WRAP(lsame)(uplo, "U")) { 01162 kk = *n * (*n + 1) / 2; 01163 if (*incx == 1) { 01164 for (j = *n; j >= 1; --j) { 01165 if (x[j] != 0.) { 01166 if (nounit) { 01167 x[j] /= ap[kk]; 01168 } 01169 temp = x[j]; 01170 k = kk - 1; 01171 for (i__ = j - 1; i__ >= 1; --i__) { 01172 x[i__] -= temp * ap[k]; 01173 --k; 01174 /* L10: */ 01175 } 01176 } 01177 kk -= j; 01178 /* L20: */ 01179 } 01180 } else { 01181 jx = kx + (*n - 1) * *incx; 01182 for (j = *n; j >= 1; --j) { 01183 if (x[jx] != 0.) { 01184 if (nounit) { 01185 x[jx] /= ap[kk]; 01186 } 01187 temp = x[jx]; 01188 ix = jx; 01189 i__1 = kk - j + 1; 01190 for (k = kk - 1; k >= i__1; --k) { 01191 ix -= *incx; 01192 x[ix] -= temp * ap[k]; 01193 /* L30: */ 01194 } 01195 } 01196 jx -= *incx; 01197 kk -= j; 01198 /* L40: */ 01199 } 01200 } 01201 } else { 01202 kk = 1; 01203 if (*incx == 1) { 01204 i__1 = *n; 01205 for (j = 1; j <= i__1; ++j) { 01206 if (x[j] != 0.) { 01207 if (nounit) { 01208 x[j] /= ap[kk]; 01209 } 01210 temp = x[j]; 01211 k = kk + 1; 01212 i__2 = *n; 01213 for (i__ = j + 1; i__ <= i__2; ++i__) { 01214 x[i__] -= temp * ap[k]; 01215 ++k; 01216 /* L50: */ 01217 } 01218 } 01219 kk += *n - j + 1; 01220 /* L60: */ 01221 } 01222 } else { 01223 jx = kx; 01224 i__1 = *n; 01225 for (j = 1; j <= i__1; ++j) { 01226 if (x[jx] != 0.) { 01227 if (nounit) { 01228 x[jx] /= ap[kk]; 01229 } 01230 temp = x[jx]; 01231 ix = jx; 01232 i__2 = kk + *n - j; 01233 for (k = kk + 1; k <= i__2; ++k) { 01234 ix += *incx; 01235 x[ix] -= temp * ap[k]; 01236 /* L70: */ 01237 } 01238 } 01239 jx += *incx; 01240 kk += *n - j + 1; 01241 /* L80: */ 01242 } 01243 } 01244 } 01245 } else { 01246 01247 /* Form x := inv( A' )*x. */ 01248 01249 if (NL_FORTRAN_WRAP(lsame)(uplo, "U")) { 01250 kk = 1; 01251 if (*incx == 1) { 01252 i__1 = *n; 01253 for (j = 1; j <= i__1; ++j) { 01254 temp = x[j]; 01255 k = kk; 01256 i__2 = j - 1; 01257 for (i__ = 1; i__ <= i__2; ++i__) { 01258 temp -= ap[k] * x[i__]; 01259 ++k; 01260 /* L90: */ 01261 } 01262 if (nounit) { 01263 temp /= ap[kk + j - 1]; 01264 } 01265 x[j] = temp; 01266 kk += j; 01267 /* L100: */ 01268 } 01269 } else { 01270 jx = kx; 01271 i__1 = *n; 01272 for (j = 1; j <= i__1; ++j) { 01273 temp = x[jx]; 01274 ix = kx; 01275 i__2 = kk + j - 2; 01276 for (k = kk; k <= i__2; ++k) { 01277 temp -= ap[k] * x[ix]; 01278 ix += *incx; 01279 /* L110: */ 01280 } 01281 if (nounit) { 01282 temp /= ap[kk + j - 1]; 01283 } 01284 x[jx] = temp; 01285 jx += *incx; 01286 kk += j; 01287 /* L120: */ 01288 } 01289 } 01290 } else { 01291 kk = *n * (*n + 1) / 2; 01292 if (*incx == 1) { 01293 for (j = *n; j >= 1; --j) { 01294 temp = x[j]; 01295 k = kk; 01296 i__1 = j + 1; 01297 for (i__ = *n; i__ >= i__1; --i__) { 01298 temp -= ap[k] * x[i__]; 01299 --k; 01300 /* L130: */ 01301 } 01302 if (nounit) { 01303 temp /= ap[kk - *n + j]; 01304 } 01305 x[j] = temp; 01306 kk -= *n - j + 1; 01307 /* L140: */ 01308 } 01309 } else { 01310 kx += (*n - 1) * *incx; 01311 jx = kx; 01312 for (j = *n; j >= 1; --j) { 01313 temp = x[jx]; 01314 ix = kx; 01315 i__1 = kk - (*n - (j + 1)); 01316 for (k = kk; k >= i__1; --k) { 01317 temp -= ap[k] * x[ix]; 01318 ix -= *incx; 01319 /* L150: */ 01320 } 01321 if (nounit) { 01322 temp /= ap[kk - *n + j]; 01323 } 01324 x[jx] = temp; 01325 jx -= *incx; 01326 kk -= *n - j + 1; 01327 /* L160: */ 01328 } 01329 } 01330 } 01331 } 01332 01333 return 0; 01334 01335 /* End of DTPSV . */ 01336 01337 } /* dtpsv_ */ 01338 01339 #endif 01340 01341 01342 /***********************************************************************************/ 01343 /* C wrappers for BLAS routines */ 01344 01345 /* x <- a*x */ 01346 void dscal( int n, double alpha, double *x, int incx ) { 01347 NL_FORTRAN_WRAP(dscal)(&n,&alpha,x,&incx); 01348 } 01349 01350 /* y <- x */ 01351 void dcopy( 01352 int n, double *x, int incx, double *y, int incy 01353 ) { 01354 NL_FORTRAN_WRAP(dcopy)(&n,x,&incx,y,&incy); 01355 } 01356 01357 /* y <- a*x+y */ 01358 void daxpy( 01359 int n, double alpha, double *x, int incx, double *y, 01360 int incy 01361 ) { 01362 NL_FORTRAN_WRAP(daxpy)(&n,&alpha,x,&incx,y,&incy); 01363 } 01364 01365 /* returns x^T*y */ 01366 double ddot( 01367 int n, double *x, int incx, double *y, int incy 01368 ) { 01369 return NL_FORTRAN_WRAP(ddot)(&n,x,&incx,y,&incy); 01370 } 01371 01373 double dnrm2( int n, double *x, int incx ) { 01374 return NL_FORTRAN_WRAP(dnrm2)(&n,x,&incx); 01375 } 01376 01378 void dtpsv( 01379 MatrixTriangle uplo, MatrixTranspose trans, 01380 MatrixUnitTriangular diag, int n, double *AP, 01381 double *x, int incx 01382 ) { 01383 static char *UL[2] = { "U", "L" }; 01384 static char *T[3] = { "N", "T", 0 }; 01385 static char *D[2] = { "U", "N" }; 01386 NL_FORTRAN_WRAP(dtpsv)(UL[(int)uplo],T[(int)trans],D[(int)diag],&n,AP,x,&incx); 01387 } 01388 01390 void dgemv( 01391 MatrixTranspose trans, int m, int n, double alpha, 01392 double *A, int ldA, double *x, int incx, 01393 double beta, double *y, int incy 01394 ) { 01395 static char *T[3] = { "N", "T", 0 }; 01396 NL_FORTRAN_WRAP(dgemv)(T[(int)trans],&m,&n,&alpha,A,&ldA,x,&incx,&beta,y,&incy); 01397 } 01398 01399 /************************************************************************/ 01400 /* End of BLAS routines */ 01401 /************************************************************************/