cblas128.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. // Copyright ©2015 The Gonum Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package cblas128
  5. import (
  6. "gonum.org/v1/gonum/blas"
  7. "gonum.org/v1/gonum/blas/gonum"
  8. )
  9. var cblas128 blas.Complex128 = gonum.Implementation{}
  10. // Use sets the BLAS complex128 implementation to be used by subsequent BLAS calls.
  11. // The default implementation is
  12. // gonum.org/v1/gonum/blas/gonum.Implementation.
  13. func Use(b blas.Complex128) {
  14. cblas128 = b
  15. }
  16. // Implementation returns the current BLAS complex128 implementation.
  17. //
  18. // Implementation allows direct calls to the current the BLAS complex128 implementation
  19. // giving finer control of parameters.
  20. func Implementation() blas.Complex128 {
  21. return cblas128
  22. }
  23. // Vector represents a vector with an associated element increment.
  24. type Vector struct {
  25. N int
  26. Inc int
  27. Data []complex128
  28. }
  29. // General represents a matrix using the conventional storage scheme.
  30. type General struct {
  31. Rows, Cols int
  32. Stride int
  33. Data []complex128
  34. }
  35. // Band represents a band matrix using the band storage scheme.
  36. type Band struct {
  37. Rows, Cols int
  38. KL, KU int
  39. Stride int
  40. Data []complex128
  41. }
  42. // Triangular represents a triangular matrix using the conventional storage scheme.
  43. type Triangular struct {
  44. N int
  45. Stride int
  46. Data []complex128
  47. Uplo blas.Uplo
  48. Diag blas.Diag
  49. }
  50. // TriangularBand represents a triangular matrix using the band storage scheme.
  51. type TriangularBand struct {
  52. N, K int
  53. Stride int
  54. Data []complex128
  55. Uplo blas.Uplo
  56. Diag blas.Diag
  57. }
  58. // TriangularPacked represents a triangular matrix using the packed storage scheme.
  59. type TriangularPacked struct {
  60. N int
  61. Data []complex128
  62. Uplo blas.Uplo
  63. Diag blas.Diag
  64. }
  65. // Symmetric represents a symmetric matrix using the conventional storage scheme.
  66. type Symmetric struct {
  67. N int
  68. Stride int
  69. Data []complex128
  70. Uplo blas.Uplo
  71. }
  72. // SymmetricBand represents a symmetric matrix using the band storage scheme.
  73. type SymmetricBand struct {
  74. N, K int
  75. Stride int
  76. Data []complex128
  77. Uplo blas.Uplo
  78. }
  79. // SymmetricPacked represents a symmetric matrix using the packed storage scheme.
  80. type SymmetricPacked struct {
  81. N int
  82. Data []complex128
  83. Uplo blas.Uplo
  84. }
  85. // Hermitian represents an Hermitian matrix using the conventional storage scheme.
  86. type Hermitian Symmetric
  87. // HermitianBand represents an Hermitian matrix using the band storage scheme.
  88. type HermitianBand SymmetricBand
  89. // HermitianPacked represents an Hermitian matrix using the packed storage scheme.
  90. type HermitianPacked SymmetricPacked
  91. // Level 1
  92. const (
  93. negInc = "cblas128: negative vector increment"
  94. badLength = "cblas128: vector length mismatch"
  95. )
  96. // Dotu computes the dot product of the two vectors without
  97. // complex conjugation:
  98. // xᵀ * y.
  99. // Dotu will panic if the lengths of x and y do not match.
  100. func Dotu(x, y Vector) complex128 {
  101. if x.N != y.N {
  102. panic(badLength)
  103. }
  104. return cblas128.Zdotu(x.N, x.Data, x.Inc, y.Data, y.Inc)
  105. }
  106. // Dotc computes the dot product of the two vectors with
  107. // complex conjugation:
  108. // xᴴ * y.
  109. // Dotc will panic if the lengths of x and y do not match.
  110. func Dotc(x, y Vector) complex128 {
  111. if x.N != y.N {
  112. panic(badLength)
  113. }
  114. return cblas128.Zdotc(x.N, x.Data, x.Inc, y.Data, y.Inc)
  115. }
  116. // Nrm2 computes the Euclidean norm of the vector x:
  117. // sqrt(\sum_i x[i] * x[i]).
  118. //
  119. // Nrm2 will panic if the vector increment is negative.
  120. func Nrm2(x Vector) float64 {
  121. if x.Inc < 0 {
  122. panic(negInc)
  123. }
  124. return cblas128.Dznrm2(x.N, x.Data, x.Inc)
  125. }
  126. // Asum computes the sum of magnitudes of the real and imaginary parts of
  127. // elements of the vector x:
  128. // \sum_i (|Re x[i]| + |Im x[i]|).
  129. //
  130. // Asum will panic if the vector increment is negative.
  131. func Asum(x Vector) float64 {
  132. if x.Inc < 0 {
  133. panic(negInc)
  134. }
  135. return cblas128.Dzasum(x.N, x.Data, x.Inc)
  136. }
  137. // Iamax returns the index of an element of x with the largest sum of
  138. // magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|).
  139. // If there are multiple such indices, the earliest is returned.
  140. //
  141. // Iamax returns -1 if n == 0.
  142. //
  143. // Iamax will panic if the vector increment is negative.
  144. func Iamax(x Vector) int {
  145. if x.Inc < 0 {
  146. panic(negInc)
  147. }
  148. return cblas128.Izamax(x.N, x.Data, x.Inc)
  149. }
  150. // Swap exchanges the elements of two vectors:
  151. // x[i], y[i] = y[i], x[i] for all i.
  152. // Swap will panic if the lengths of x and y do not match.
  153. func Swap(x, y Vector) {
  154. if x.N != y.N {
  155. panic(badLength)
  156. }
  157. cblas128.Zswap(x.N, x.Data, x.Inc, y.Data, y.Inc)
  158. }
  159. // Copy copies the elements of x into the elements of y:
  160. // y[i] = x[i] for all i.
  161. // Copy will panic if the lengths of x and y do not match.
  162. func Copy(x, y Vector) {
  163. if x.N != y.N {
  164. panic(badLength)
  165. }
  166. cblas128.Zcopy(x.N, x.Data, x.Inc, y.Data, y.Inc)
  167. }
  168. // Axpy computes
  169. // y = alpha * x + y,
  170. // where x and y are vectors, and alpha is a scalar.
  171. // Axpy will panic if the lengths of x and y do not match.
  172. func Axpy(alpha complex128, x, y Vector) {
  173. if x.N != y.N {
  174. panic(badLength)
  175. }
  176. cblas128.Zaxpy(x.N, alpha, x.Data, x.Inc, y.Data, y.Inc)
  177. }
  178. // Scal computes
  179. // x = alpha * x,
  180. // where x is a vector, and alpha is a scalar.
  181. //
  182. // Scal will panic if the vector increment is negative.
  183. func Scal(alpha complex128, x Vector) {
  184. if x.Inc < 0 {
  185. panic(negInc)
  186. }
  187. cblas128.Zscal(x.N, alpha, x.Data, x.Inc)
  188. }
  189. // Dscal computes
  190. // x = alpha * x,
  191. // where x is a vector, and alpha is a real scalar.
  192. //
  193. // Dscal will panic if the vector increment is negative.
  194. func Dscal(alpha float64, x Vector) {
  195. if x.Inc < 0 {
  196. panic(negInc)
  197. }
  198. cblas128.Zdscal(x.N, alpha, x.Data, x.Inc)
  199. }
  200. // Level 2
  201. // Gemv computes
  202. // y = alpha * A * x + beta * y if t == blas.NoTrans,
  203. // y = alpha * Aᵀ * x + beta * y if t == blas.Trans,
  204. // y = alpha * Aᴴ * x + beta * y if t == blas.ConjTrans,
  205. // where A is an m×n dense matrix, x and y are vectors, and alpha and beta are
  206. // scalars.
  207. func Gemv(t blas.Transpose, alpha complex128, a General, x Vector, beta complex128, y Vector) {
  208. cblas128.Zgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc)
  209. }
  210. // Gbmv computes
  211. // y = alpha * A * x + beta * y if t == blas.NoTrans,
  212. // y = alpha * Aᵀ * x + beta * y if t == blas.Trans,
  213. // y = alpha * Aᴴ * x + beta * y if t == blas.ConjTrans,
  214. // where A is an m×n band matrix, x and y are vectors, and alpha and beta are
  215. // scalars.
  216. func Gbmv(t blas.Transpose, alpha complex128, a Band, x Vector, beta complex128, y Vector) {
  217. cblas128.Zgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc)
  218. }
  219. // Trmv computes
  220. // x = A * x if t == blas.NoTrans,
  221. // x = Aᵀ * x if t == blas.Trans,
  222. // x = Aᴴ * x if t == blas.ConjTrans,
  223. // where A is an n×n triangular matrix, and x is a vector.
  224. func Trmv(t blas.Transpose, a Triangular, x Vector) {
  225. cblas128.Ztrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc)
  226. }
  227. // Tbmv computes
  228. // x = A * x if t == blas.NoTrans,
  229. // x = Aᵀ * x if t == blas.Trans,
  230. // x = Aᴴ * x if t == blas.ConjTrans,
  231. // where A is an n×n triangular band matrix, and x is a vector.
  232. func Tbmv(t blas.Transpose, a TriangularBand, x Vector) {
  233. cblas128.Ztbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc)
  234. }
  235. // Tpmv computes
  236. // x = A * x if t == blas.NoTrans,
  237. // x = Aᵀ * x if t == blas.Trans,
  238. // x = Aᴴ * x if t == blas.ConjTrans,
  239. // where A is an n×n triangular matrix in packed format, and x is a vector.
  240. func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) {
  241. cblas128.Ztpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc)
  242. }
  243. // Trsv solves
  244. // A * x = b if t == blas.NoTrans,
  245. // Aᵀ * x = b if t == blas.Trans,
  246. // Aᴴ * x = b if t == blas.ConjTrans,
  247. // where A is an n×n triangular matrix and x is a vector.
  248. //
  249. // At entry to the function, x contains the values of b, and the result is
  250. // stored in-place into x.
  251. //
  252. // No test for singularity or near-singularity is included in this
  253. // routine. Such tests must be performed before calling this routine.
  254. func Trsv(t blas.Transpose, a Triangular, x Vector) {
  255. cblas128.Ztrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc)
  256. }
  257. // Tbsv solves
  258. // A * x = b if t == blas.NoTrans,
  259. // Aᵀ * x = b if t == blas.Trans,
  260. // Aᴴ * x = b if t == blas.ConjTrans,
  261. // where A is an n×n triangular band matrix, and x is a vector.
  262. //
  263. // At entry to the function, x contains the values of b, and the result is
  264. // stored in-place into x.
  265. //
  266. // No test for singularity or near-singularity is included in this
  267. // routine. Such tests must be performed before calling this routine.
  268. func Tbsv(t blas.Transpose, a TriangularBand, x Vector) {
  269. cblas128.Ztbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc)
  270. }
  271. // Tpsv solves
  272. // A * x = b if t == blas.NoTrans,
  273. // Aᵀ * x = b if t == blas.Trans,
  274. // Aᴴ * x = b if t == blas.ConjTrans,
  275. // where A is an n×n triangular matrix in packed format and x is a vector.
  276. //
  277. // At entry to the function, x contains the values of b, and the result is
  278. // stored in-place into x.
  279. //
  280. // No test for singularity or near-singularity is included in this
  281. // routine. Such tests must be performed before calling this routine.
  282. func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) {
  283. cblas128.Ztpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc)
  284. }
  285. // Hemv computes
  286. // y = alpha * A * x + beta * y,
  287. // where A is an n×n Hermitian matrix, x and y are vectors, and alpha and
  288. // beta are scalars.
  289. func Hemv(alpha complex128, a Hermitian, x Vector, beta complex128, y Vector) {
  290. cblas128.Zhemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc)
  291. }
  292. // Hbmv performs
  293. // y = alpha * A * x + beta * y,
  294. // where A is an n×n Hermitian band matrix, x and y are vectors, and alpha
  295. // and beta are scalars.
  296. func Hbmv(alpha complex128, a HermitianBand, x Vector, beta complex128, y Vector) {
  297. cblas128.Zhbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc)
  298. }
  299. // Hpmv performs
  300. // y = alpha * A * x + beta * y,
  301. // where A is an n×n Hermitian matrix in packed format, x and y are vectors,
  302. // and alpha and beta are scalars.
  303. func Hpmv(alpha complex128, a HermitianPacked, x Vector, beta complex128, y Vector) {
  304. cblas128.Zhpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc)
  305. }
  306. // Geru performs a rank-1 update
  307. // A += alpha * x * yᵀ,
  308. // where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar.
  309. func Geru(alpha complex128, x, y Vector, a General) {
  310. cblas128.Zgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride)
  311. }
  312. // Gerc performs a rank-1 update
  313. // A += alpha * x * yᴴ,
  314. // where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar.
  315. func Gerc(alpha complex128, x, y Vector, a General) {
  316. cblas128.Zgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride)
  317. }
  318. // Her performs a rank-1 update
  319. // A += alpha * x * yᵀ,
  320. // where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar.
  321. func Her(alpha float64, x Vector, a Hermitian) {
  322. cblas128.Zher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride)
  323. }
  324. // Hpr performs a rank-1 update
  325. // A += alpha * x * xᴴ,
  326. // where A is an n×n Hermitian matrix in packed format, x is a vector, and
  327. // alpha is a scalar.
  328. func Hpr(alpha float64, x Vector, a HermitianPacked) {
  329. cblas128.Zhpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data)
  330. }
  331. // Her2 performs a rank-2 update
  332. // A += alpha * x * yᴴ + conj(alpha) * y * xᴴ,
  333. // where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar.
  334. func Her2(alpha complex128, x, y Vector, a Hermitian) {
  335. cblas128.Zher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride)
  336. }
  337. // Hpr2 performs a rank-2 update
  338. // A += alpha * x * yᴴ + conj(alpha) * y * xᴴ,
  339. // where A is an n×n Hermitian matrix in packed format, x and y are vectors,
  340. // and alpha is a scalar.
  341. func Hpr2(alpha complex128, x, y Vector, a HermitianPacked) {
  342. cblas128.Zhpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data)
  343. }
  344. // Level 3
  345. // Gemm computes
  346. // C = alpha * A * B + beta * C,
  347. // where A, B, and C are dense matrices, and alpha and beta are scalars.
  348. // tA and tB specify whether A or B are transposed or conjugated.
  349. func Gemm(tA, tB blas.Transpose, alpha complex128, a, b General, beta complex128, c General) {
  350. var m, n, k int
  351. if tA == blas.NoTrans {
  352. m, k = a.Rows, a.Cols
  353. } else {
  354. m, k = a.Cols, a.Rows
  355. }
  356. if tB == blas.NoTrans {
  357. n = b.Cols
  358. } else {
  359. n = b.Rows
  360. }
  361. cblas128.Zgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride)
  362. }
  363. // Symm performs
  364. // C = alpha * A * B + beta * C if s == blas.Left,
  365. // C = alpha * B * A + beta * C if s == blas.Right,
  366. // where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and
  367. // alpha and beta are scalars.
  368. func Symm(s blas.Side, alpha complex128, a Symmetric, b General, beta complex128, c General) {
  369. var m, n int
  370. if s == blas.Left {
  371. m, n = a.N, b.Cols
  372. } else {
  373. m, n = b.Rows, a.N
  374. }
  375. cblas128.Zsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride)
  376. }
  377. // Syrk performs a symmetric rank-k update
  378. // C = alpha * A * Aᵀ + beta * C if t == blas.NoTrans,
  379. // C = alpha * Aᵀ * A + beta * C if t == blas.Trans,
  380. // where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans
  381. // and a k×n matrix otherwise, and alpha and beta are scalars.
  382. func Syrk(t blas.Transpose, alpha complex128, a General, beta complex128, c Symmetric) {
  383. var n, k int
  384. if t == blas.NoTrans {
  385. n, k = a.Rows, a.Cols
  386. } else {
  387. n, k = a.Cols, a.Rows
  388. }
  389. cblas128.Zsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride)
  390. }
  391. // Syr2k performs a symmetric rank-2k update
  392. // C = alpha * A * Bᵀ + alpha * B * Aᵀ + beta * C if t == blas.NoTrans,
  393. // C = alpha * Aᵀ * B + alpha * Bᵀ * A + beta * C if t == blas.Trans,
  394. // where C is an n×n symmetric matrix, A and B are n×k matrices if
  395. // t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars.
  396. func Syr2k(t blas.Transpose, alpha complex128, a, b General, beta complex128, c Symmetric) {
  397. var n, k int
  398. if t == blas.NoTrans {
  399. n, k = a.Rows, a.Cols
  400. } else {
  401. n, k = a.Cols, a.Rows
  402. }
  403. cblas128.Zsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride)
  404. }
  405. // Trmm performs
  406. // B = alpha * A * B if tA == blas.NoTrans and s == blas.Left,
  407. // B = alpha * Aᵀ * B if tA == blas.Trans and s == blas.Left,
  408. // B = alpha * Aᴴ * B if tA == blas.ConjTrans and s == blas.Left,
  409. // B = alpha * B * A if tA == blas.NoTrans and s == blas.Right,
  410. // B = alpha * B * Aᵀ if tA == blas.Trans and s == blas.Right,
  411. // B = alpha * B * Aᴴ if tA == blas.ConjTrans and s == blas.Right,
  412. // where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is
  413. // a scalar.
  414. func Trmm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) {
  415. cblas128.Ztrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride)
  416. }
  417. // Trsm solves
  418. // A * X = alpha * B if tA == blas.NoTrans and s == blas.Left,
  419. // Aᵀ * X = alpha * B if tA == blas.Trans and s == blas.Left,
  420. // Aᴴ * X = alpha * B if tA == blas.ConjTrans and s == blas.Left,
  421. // X * A = alpha * B if tA == blas.NoTrans and s == blas.Right,
  422. // X * Aᵀ = alpha * B if tA == blas.Trans and s == blas.Right,
  423. // X * Aᴴ = alpha * B if tA == blas.ConjTrans and s == blas.Right,
  424. // where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and
  425. // alpha is a scalar.
  426. //
  427. // At entry to the function, b contains the values of B, and the result is
  428. // stored in-place into b.
  429. //
  430. // No check is made that A is invertible.
  431. func Trsm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) {
  432. cblas128.Ztrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride)
  433. }
  434. // Hemm performs
  435. // C = alpha * A * B + beta * C if s == blas.Left,
  436. // C = alpha * B * A + beta * C if s == blas.Right,
  437. // where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and
  438. // alpha and beta are scalars.
  439. func Hemm(s blas.Side, alpha complex128, a Hermitian, b General, beta complex128, c General) {
  440. var m, n int
  441. if s == blas.Left {
  442. m, n = a.N, b.Cols
  443. } else {
  444. m, n = b.Rows, a.N
  445. }
  446. cblas128.Zhemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride)
  447. }
  448. // Herk performs the Hermitian rank-k update
  449. // C = alpha * A * Aᴴ + beta*C if t == blas.NoTrans,
  450. // C = alpha * Aᴴ * A + beta*C if t == blas.ConjTrans,
  451. // where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans
  452. // and a k×n matrix otherwise, and alpha and beta are scalars.
  453. func Herk(t blas.Transpose, alpha float64, a General, beta float64, c Hermitian) {
  454. var n, k int
  455. if t == blas.NoTrans {
  456. n, k = a.Rows, a.Cols
  457. } else {
  458. n, k = a.Cols, a.Rows
  459. }
  460. cblas128.Zherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride)
  461. }
  462. // Her2k performs the Hermitian rank-2k update
  463. // C = alpha * A * Bᴴ + conj(alpha) * B * Aᴴ + beta * C if t == blas.NoTrans,
  464. // C = alpha * Aᴴ * B + conj(alpha) * Bᴴ * A + beta * C if t == blas.ConjTrans,
  465. // where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans
  466. // and k×n matrices otherwise, and alpha and beta are scalars.
  467. func Her2k(t blas.Transpose, alpha complex128, a, b General, beta float64, c Hermitian) {
  468. var n, k int
  469. if t == blas.NoTrans {
  470. n, k = a.Rows, a.Cols
  471. } else {
  472. n, k = a.Cols, a.Rows
  473. }
  474. cblas128.Zher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride)
  475. }