BLAS++ 2024.05.31
BLAS C++ API
Loading...
Searching...
No Matches
her.hh
1// Copyright (c) 2017-2023, University of Tennessee. All rights reserved.
2// SPDX-License-Identifier: BSD-3-Clause
3// This program is free software: you can redistribute it and/or modify it under
4// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
5
6#ifndef BLAS_HER_HH
7#define BLAS_HER_HH
8
9#include "blas/util.hh"
10#include "blas/syr.hh"
11
12#include <limits>
13
14namespace blas {
15
16// =============================================================================
57
58template <typename TA, typename TX>
59void her(
60 blas::Layout layout,
61 blas::Uplo uplo,
62 int64_t n,
63 blas::real_type<TA, TX> alpha, // zher takes double alpha; use real
64 TX const *x, int64_t incx,
65 TA *A, int64_t lda )
66{
67 typedef blas::scalar_type<TA, TX> scalar_t;
68 typedef blas::real_type<TA, TX> real_t;
69
70 #define A(i_, j_) A[ (i_) + (j_)*lda ]
71
72 // constants
73 const real_t zero = 0;
74
75 // check arguments
76 blas_error_if( layout != Layout::ColMajor &&
77 layout != Layout::RowMajor );
78 blas_error_if( uplo != Uplo::Lower &&
79 uplo != Uplo::Upper );
80 blas_error_if( n < 0 );
81 blas_error_if( incx == 0 );
82 blas_error_if( lda < n );
83
84 // quick return
85 if (n == 0 || alpha == zero)
86 return;
87
88 // for row major, swap lower <=> upper
89 if (layout == Layout::RowMajor) {
90 uplo = (uplo == Uplo::Lower ? Uplo::Upper : Uplo::Lower);
91 }
92
93 int64_t kx = (incx > 0 ? 0 : (-n + 1)*incx);
94 if (uplo == Uplo::Upper) {
95 if (incx == 1) {
96 // unit stride
97 for (int64_t j = 0; j < n; ++j) {
98 // note: NOT skipping if x[j] is zero, for consistent NAN handling
99 scalar_t tmp = alpha * conj( x[j] );
100 for (int64_t i = 0; i <= j-1; ++i) {
101 A(i, j) += x[i] * tmp;
102 }
103 A(j, j) = real( A(j, j) ) + real( x[j] * tmp );
104 }
105 }
106 else {
107 // non-unit stride
108 int64_t jx = kx;
109 for (int64_t j = 0; j < n; ++j) {
110 scalar_t tmp = alpha * conj( x[jx] );
111 int64_t ix = kx;
112 for (int64_t i = 0; i <= j-1; ++i) {
113 A(i, j) += x[ix] * tmp;
114 ix += incx;
115 }
116 A(j, j) = real( A(j, j) ) + real( x[jx] * tmp );
117 jx += incx;
118 }
119 }
120 }
121 else {
122 // lower triangle
123 if (incx == 1) {
124 // unit stride
125 for (int64_t j = 0; j < n; ++j) {
126 scalar_t tmp = alpha * conj( x[j] );
127 A(j, j) = real( A(j, j) ) + real( tmp * x[j] );
128 for (int64_t i = j+1; i < n; ++i) {
129 A(i, j) += x[i] * tmp;
130 }
131 }
132 }
133 else {
134 // non-unit stride
135 int64_t jx = kx;
136 for (int64_t j = 0; j < n; ++j) {
137 scalar_t tmp = alpha * conj( x[jx] );
138 A(j, j) = real( A(j, j) ) + real( tmp * x[jx] );
139 int64_t ix = jx;
140 for (int64_t i = j+1; i < n; ++i) {
141 ix += incx;
142 A(i, j) += x[ix] * tmp;
143 }
144 jx += incx;
145 }
146 }
147 }
148
149 #undef A
150}
151
152} // namespace blas
153
154#endif // #ifndef BLAS_HER_HH
void her(blas::Layout layout, blas::Uplo uplo, int64_t n, blas::real_type< TA, TX > alpha, TX const *x, int64_t incx, TA *A, int64_t lda)
Hermitian matrix rank-1 update:
Definition her.hh:59