atl_trinvert.c

来自「基于Blas CLapck的.用过的人知道是干啥的」· C语言 代码 · 共 437 行

C
437
字号
/* *             Automatically Tuned Linear Algebra Software v3.8.0 *                    (C) Copyright 1997 R. Clint Whaley * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *   1. Redistributions of source code must retain the above copyright *      notice, this list of conditions and the following disclaimer. *   2. Redistributions in binary form must reproduce the above copyright *      notice, this list of conditions, and the following disclaimer in the *      documentation and/or other materials provided with the distribution. *   3. The name of the ATLAS group or the names of its contributers may *      not be used to endorse or promote products derived from this *      software without specific written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ATLAS GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */#include "atlas_kern3.h"#ifdef TREAL#ifdef Upper_#define ATL_trmv_scal Mjoin(ATL_dtrmv_scalUN,UnitNM)static void ATL_trmv_scal(const int N, const SCALAR alpha0, const TYPE *A,                          const int lda, TYPE *X)/* * X <- alpha * A * X */{   int i, j;   const int n = (N>>2)<<2;   const int incAd = (lda+1)<<2;   register TYPE y0, y1, y2, y3, x0;   const register TYPE alpha=alpha0;   const TYPE *Ad=A, *Ac;   TYPE *x, *stX = X + N;   for (i=0; i != n; i += 4)   {      Ac = Ad;      Ad += incAd;      x0 = *X;      #ifdef UnitDiag_         y0 = x0;      #else         y0 = *Ac * x0;      #endif      Ac += lda;      x0 = X[1];      #ifdef UnitDiag_         y1 = x0;      #else         y1 = Ac[1] * x0;      #endif      y0 += *Ac * x0;      Ac += lda;      x0 = X[2];      #ifdef UnitDiag_         y2 = x0;      #else         y2 = Ac[2] * x0;      #endif      y1 += Ac[1] * x0;      y0 += *Ac * x0;      Ac += lda;      x0 = X[3];      #ifdef UnitDiag_         y3 = x0;      #else         y3 = Ac[3] * x0;      #endif      y2 += Ac[2] * x0;      y1 += Ac[1] * x0;      y0 += *Ac * x0;      Ac += lda;      x = X + 4;      if (x != stX)      {         do         {            x0 = *x++;            y0 += *Ac * x0;            y1 += Ac[1] * x0;            y2 += Ac[2] * x0;            y3 += Ac[3] * x0;            Ac += lda;         }         while (x != stX);      }      y0 *= alpha;      y1 *= alpha;      y2 *= alpha;      y3 *= alpha;      *X = y0;      X[1] = y1;      X[2] = y2;      X[3] = y3;      X += 4;   }   i = N - n;   switch(N-n)  /* ixi trmv */   {   case 1:      #ifdef UnitDiag_         *X *= alpha;      #else         *X *= alpha * *Ad;      #endif      break;   case 2:      #ifdef UnitDiag_         *X = alpha * (*X + Ad[lda] * X[1]);         X[1] *= alpha;      #else         *X = alpha * (*Ad * *X + Ad[lda] * X[1]);         X[1] = alpha * (Ad[lda+1] * X[1]);      #endif      break;   case 3:         i = lda << 1;      #ifdef UnitDiag_         *X = alpha * (*X + Ad[lda] * X[1] + Ad[i] * X[2]);         X[1] = alpha * (X[1] + Ad[i+1] * X[2]);         X[2] *= alpha;      #else         *X = alpha * (*Ad * *X + Ad[lda] * X[1] + Ad[i] * X[2]);         X[1] = alpha * (Ad[lda+1] * X[1] + Ad[i+1] * X[2]);         X[2] *= alpha * Ad[i+2];      #endif      break;   default:;   }}void Mjoin(Mjoin(PATL,trinvertU),UnitNM)(const int N, TYPE *A, const int lda){   int j;   register int i;   const int ione=1;   #ifdef UnitDiag_      #define DIAG "U"      #define Ajj -1.0   #else      #define DIAG "N"      TYPE Ajj;      const int ldap1 = lda + 1;      TYPE one=1.0;   #endif   TYPE *Ac=A;   if (N > 0)   {      for (j=0; j != N; j++)      {         #ifndef UnitDiag_            Ajj = one / Ac[j];            Ac[j] = Ajj;            Ajj = -Ajj;         #endif         #ifdef OldDtrmv            dtrmv_("U", "N", DIAG, &j, A, &lda, Ac, &ione);            for (i=0; i != j; i++) Ac[i] *= Ajj;         #else            ATL_trmv_scal(j, Ajj, A, lda, Ac);         #endif         Ac += lda;      }   }}#else#define ATL_trmv_scal Mjoin(ATL_dtrmv_scalLN,UnitNM)static void ATL_trmv_scal(const int N, const SCALAR alpha0, const TYPE *A,                          const int lda, TYPE *X){   int i;   const int n = (N>>2)<<2;   TYPE *x = X, *stX = X+N-4;   const TYPE *Ac, *a=A;   const register TYPE alpha=alpha0;   register TYPE y0, y1, y2, y3, x0;   if (n)   {      A += N-4;      for (i=0; i != n; i += 4)      {         Ac = A;         y0 = y1 = y2 = y3 = 0.0;         if (X != stX)         {            do            {               x0 = *X;               y0 += *Ac * x0;               y1 += Ac[1] * x0;               y2 += Ac[2] * x0;               y3 += Ac[3] * x0;               Ac += lda;            }            while(++X != stX);         }         x0 = *X;         #ifdef UnitDiag_            y0 += x0;         #else            y0 += *Ac * x0;         #endif         y1 += Ac[1] * x0;         y2 += Ac[2] * x0;         y3 += Ac[3] * x0;         x0 = X[1];         Ac += lda;         y0 *= alpha;         #ifdef UnitDiag_            y1 += x0;         #else            y1 += Ac[1] * x0;         #endif         y2 += Ac[2] * x0;         y3 += Ac[3] * x0;         x0 = X[2];         Ac += lda;         y1 *= alpha;         #ifdef UnitDiag_            y2 += x0;         #else            y2 += Ac[2] * x0;         #endif         y3 += Ac[3] * x0;         Ac += lda;         y2 *= alpha;         #ifdef UnitDiag_            y3 += X[3];         #else            y3 += Ac[3] * X[3];         #endif         y3 *= alpha;         *stX = y0;         stX[1] = y1;         stX[2] = y2;         stX[3] = y3;         stX -= 4;         X = x;         A -= 4;      }      A += N-n;   }   A = a;   switch(N-n)   {   case 1:      #ifdef UnitDiag_         *x *= alpha;      #else         *x *= alpha * *A;      #endif      break;   case 2:      #ifdef UnitDiag_	 x[1] = alpha * (*x * A[1] + x[1]);         *x *= alpha;      #else	 x[1] = alpha * (*x * A[1] + x[1] * A[lda+1]);         *x *= alpha * *A;      #endif      break;   case 3:      Ac = A + lda;      #ifdef UnitDiag_         x[2] = alpha * (*x * A[2] + x[1] * Ac[2] + x[2]);	 x[1] = alpha * (*x * A[1] + x[1]);         *x *= alpha;      #else         x[2] = alpha * (*x * A[2] + x[1] * Ac[2] + x[2] * Ac[lda+2]);	 x[1] = alpha * (*x * A[1] + x[1] * Ac[1]);         *x *= alpha * *A;      #endif      break;   }}#ifndef NoUsevoid Mjoin(Mjoin(PATL,trinvertL),UnitNM)(const int N, TYPE *A, const int lda){   int j;   register int i;   const int ione=1;   const int ldap1=lda+1;   #ifdef UnitDiag_      #define DIAG "U"      #define Ajj -1.0   #else      #define DIAG "N"      register TYPE Ajj;      TYPE one=1.0;   #endif   TYPE *Ad = A + (N-1)*ldap1;   for (j=0; j != N; j++)   {      #ifndef UnitDiag_         Ajj = one / *Ad;         *Ad = Ajj;         Ajj = -Ajj;      #endif      #ifndef OldDtrmv         ATL_trmv_scal(j, Ajj, Ad+ldap1, lda, Ad+1);      #else         dtrmv_("L", "N", DIAG, &j, Ad+ldap1, &lda, Ad+1, &ione);         #ifdef UnitDiag_            for (i=1; i <= j; i++) Ad[i] = -Ad[i];         #else            for (i=1; i <= j; i++) Ad[i] *= Ajj;         #endif      #endif      Ad -= ldap1;   }}#endif#endif#else /* complex code */#ifdef Upper_void Mjoin(Mjoin(PATL,trinvertU),UnitNM)(const int N, TYPE *A, const int lda){   int j;   register int i;   const int ione=1, lda2=lda<<1;   #ifdef UnitDiag_      #define DIAG "U"      const TYPE Ajj[2] = {-1.0, 0.0};   #else      #define DIAG "N"      const int ldap1 = lda2+2;      TYPE Ajj[2], *Ad=A;   #endif   TYPE *Ac=A;   TYPE rtmp, itmp, t0;   if (N > 0)   {      #ifndef UnitDiag_         Mjoin(PATL,cplxinvert)(N, A, ldap1, A, ldap1);/* invert diag entries */      #endif      for (j=0; j != N; j++)      {         #ifndef UnitDiag_            *Ajj = -(*Ad);            Ajj[1] = -Ad[1];         #endif         #if 0            Mjoin(PRE,trmv_)("U", "N", DIAG, &j, A, &lda, Ac, &ione);            Mjoin(PRE,scal_)(&j, Ajj, Ac, &ione);         #else            #ifdef UnitDiag_               Mjoin(PATL,trmv_scalUNU_an1)(j, Ajj, A, lda, Ac);            #else               Mjoin(PATL,trmv_scalUNN_aX)(j, Ajj, A, lda, Ac);            #endif         #endif         #ifndef UnitDiag_            Ad += ldap1;         #endif         Ac += lda2;      }   }}#elsevoid Mjoin(Mjoin(PATL,trinvertL),UnitNM)(const int N, TYPE *A, const int lda){   int j;   register int i;   const int ione=1;   const int ldap1=(lda<<1)+2;   #ifdef UnitDiag_      #define DIAG "U"      const TYPE Ajj[2] = {-1.0, 0.0};   #else      #define DIAG "N"      TYPE Ajj[2];   #endif   TYPE *Ad = A + (N-1)*ldap1;   #ifndef UnitDiag_      Mjoin(PATL,cplxinvert)(N, A, ldap1, A, ldap1);  /* invert diag entries */   #endif   for (j=0; j != N; j++)   {      #ifndef UnitDiag_         *Ajj = -(*Ad);         Ajj[1] = -Ad[1];      #endif      #if 1         #ifdef UnitDiag_            Mjoin(PATL,trmv_scalLNU_an1)(j, Ajj, Ad+ldap1, lda, Ad+2);         #else            Mjoin(PATL,trmv_scalLNN_aX)(j, Ajj, Ad+ldap1, lda, Ad+2);         #endif      #else         Mjoin(PRE,trmv_)("L", "N", DIAG, &j, Ad+ldap1, &lda, Ad+2, &ione);         Mjoin(PRE,scal_)(&j, Ajj, Ad+2, &ione);      #endif      Ad -= ldap1;   }}#endif#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?