1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2018 Wave Computing, Inc. 5 // Written by: 6 // Chris Larsen 7 // Alexey Frunze (afrunze@wavecomp.com) 8 // 9 // This Source Code Form is subject to the terms of the Mozilla 10 // Public License v. 2.0. If a copy of the MPL was not distributed 11 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 12 13 #ifndef EIGEN_COMPLEX_MSA_H 14 #define EIGEN_COMPLEX_MSA_H 15 16 #include <iostream> 17 18 namespace Eigen { 19 20 namespace internal { 21 22 //---------- float ---------- 23 struct Packet2cf { Packet2cfPacket2cf24 EIGEN_STRONG_INLINE Packet2cf() { 25 } Packet2cfPacket2cf26 EIGEN_STRONG_INLINE explicit Packet2cf(const std::complex<float>& a, 27 const std::complex<float>& b) { 28 Packet4f t = { std::real(a), std::imag(a), std::real(b), std::imag(b) }; 29 v = t; 30 } Packet2cfPacket2cf31 EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) { 32 } Packet2cfPacket2cf33 EIGEN_STRONG_INLINE Packet2cf(const Packet2cf& a) : v(a.v) { 34 } 35 EIGEN_STRONG_INLINE Packet2cf& operator=(const Packet2cf& b) { 36 v = b.v; 37 return *this; 38 } conjugatePacket2cf39 EIGEN_STRONG_INLINE Packet2cf conjugate(void) const { 40 return Packet2cf((Packet4f)__builtin_msa_bnegi_d((v2u64)v, 63)); 41 } 42 EIGEN_STRONG_INLINE Packet2cf& operator*=(const Packet2cf& b) { 43 Packet4f v1, v2; 44 45 // Get the real values of a | a1_re | a1_re | a2_re | a2_re | 46 v1 = (Packet4f)__builtin_msa_ilvev_w((v4i32)v, (v4i32)v); 47 // Get the imag values of a | a1_im | a1_im | a2_im | a2_im | 48 v2 = (Packet4f)__builtin_msa_ilvod_w((v4i32)v, (v4i32)v); 49 // Multiply the real a with b 50 v1 = pmul(v1, b.v); 51 // Multiply the imag a with b 52 v2 = pmul(v2, b.v); 53 // Conjugate v2 54 v2 = Packet2cf(v2).conjugate().v; 55 // Swap real/imag elements in v2. 56 v2 = (Packet4f)__builtin_msa_shf_w((v4i32)v2, EIGEN_MSA_SHF_I8(1, 0, 3, 2)); 57 // Add and return the result 58 v = padd(v1, v2); 59 return *this; 60 } 61 EIGEN_STRONG_INLINE Packet2cf operator*(const Packet2cf& b) const { 62 return Packet2cf(*this) *= b; 63 } 64 EIGEN_STRONG_INLINE Packet2cf& operator+=(const Packet2cf& b) { 65 v = padd(v, b.v); 66 return *this; 67 } 68 EIGEN_STRONG_INLINE Packet2cf operator+(const Packet2cf& b) const { 69 return Packet2cf(*this) += b; 70 } 71 EIGEN_STRONG_INLINE Packet2cf& operator-=(const Packet2cf& b) { 72 v = psub(v, b.v); 73 return *this; 74 } 75 EIGEN_STRONG_INLINE Packet2cf operator-(const Packet2cf& b) const { 76 return Packet2cf(*this) -= b; 77 } 78 EIGEN_STRONG_INLINE Packet2cf& operator/=(const Packet2cf& b) { 79 *this *= b.conjugate(); 80 Packet4f s = pmul<Packet4f>(b.v, b.v); 81 s = padd(s, (Packet4f)__builtin_msa_shf_w((v4i32)s, EIGEN_MSA_SHF_I8(1, 0, 3, 2))); 82 v = pdiv(v, s); 83 return *this; 84 } 85 EIGEN_STRONG_INLINE Packet2cf operator/(const Packet2cf& b) const { 86 return Packet2cf(*this) /= b; 87 } 88 EIGEN_STRONG_INLINE Packet2cf operator-(void) const { 89 return Packet2cf(pnegate(v)); 90 } 91 92 Packet4f v; 93 }; 94 95 inline std::ostream& operator<<(std::ostream& os, const Packet2cf& value) { 96 os << "[ (" << value.v[0] << ", " << value.v[1] 97 << "i)," 98 " (" 99 << value.v[2] << ", " << value.v[3] << "i) ]"; 100 return os; 101 } 102 103 template <> 104 struct packet_traits<std::complex<float> > : default_packet_traits { 105 typedef Packet2cf type; 106 typedef Packet2cf half; 107 enum { 108 Vectorizable = 1, 109 AlignedOnScalar = 1, 110 size = 2, 111 HasHalfPacket = 0, 112 113 HasAdd = 1, 114 HasSub = 1, 115 HasMul = 1, 116 HasDiv = 1, 117 HasNegate = 1, 118 HasAbs = 0, 119 HasAbs2 = 0, 120 HasMin = 0, 121 HasMax = 0, 122 HasSetLinear = 0, 123 HasBlend = 1 124 }; 125 }; 126 127 template <> 128 struct unpacket_traits<Packet2cf> { 129 typedef std::complex<float> type; 130 enum { size = 2, alignment = Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false }; 131 typedef Packet2cf half; 132 }; 133 134 template <> 135 EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) { 136 EIGEN_MSA_DEBUG; 137 138 float f0 = from.real(), f1 = from.imag(); 139 Packet4f v0 = { f0, f0, f0, f0 }; 140 Packet4f v1 = { f1, f1, f1, f1 }; 141 return Packet2cf((Packet4f)__builtin_msa_ilvr_w((Packet4i)v1, (Packet4i)v0)); 142 } 143 144 template <> 145 EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 146 EIGEN_MSA_DEBUG; 147 148 return a + b; 149 } 150 151 template <> 152 EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 153 EIGEN_MSA_DEBUG; 154 155 return a - b; 156 } 157 158 template <> 159 EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { 160 EIGEN_MSA_DEBUG; 161 162 return -a; 163 } 164 165 template <> 166 EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { 167 EIGEN_MSA_DEBUG; 168 169 return a.conjugate(); 170 } 171 172 template <> 173 EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 174 EIGEN_MSA_DEBUG; 175 176 return a * b; 177 } 178 179 template <> 180 EIGEN_STRONG_INLINE Packet2cf pand<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 181 EIGEN_MSA_DEBUG; 182 183 return Packet2cf(pand(a.v, b.v)); 184 } 185 186 template <> 187 EIGEN_STRONG_INLINE Packet2cf por<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 188 EIGEN_MSA_DEBUG; 189 190 return Packet2cf(por(a.v, b.v)); 191 } 192 193 template <> 194 EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 195 EIGEN_MSA_DEBUG; 196 197 return Packet2cf(pxor(a.v, b.v)); 198 } 199 200 template <> 201 EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 202 EIGEN_MSA_DEBUG; 203 204 return Packet2cf(pandnot(a.v, b.v)); 205 } 206 207 template <> 208 EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) { 209 EIGEN_MSA_DEBUG; 210 211 EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>((const float*)from)); 212 } 213 214 template <> 215 EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { 216 EIGEN_MSA_DEBUG; 217 218 EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>((const float*)from)); 219 } 220 221 template <> 222 EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { 223 EIGEN_MSA_DEBUG; 224 225 return pset1<Packet2cf>(*from); 226 } 227 228 template <> 229 EIGEN_STRONG_INLINE void pstore<std::complex<float> >(std::complex<float>* to, 230 const Packet2cf& from) { 231 EIGEN_MSA_DEBUG; 232 233 EIGEN_DEBUG_ALIGNED_STORE pstore<float>((float*)to, from.v); 234 } 235 236 template <> 237 EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float>* to, 238 const Packet2cf& from) { 239 EIGEN_MSA_DEBUG; 240 241 EIGEN_DEBUG_UNALIGNED_STORE pstoreu<float>((float*)to, from.v); 242 } 243 244 template <> 245 EIGEN_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>( 246 const std::complex<float>* from, Index stride) { 247 EIGEN_MSA_DEBUG; 248 249 return Packet2cf(from[0 * stride], from[1 * stride]); 250 } 251 252 template <> 253 EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, 254 const Packet2cf& from, 255 Index stride) { 256 EIGEN_MSA_DEBUG; 257 258 *to = std::complex<float>(from.v[0], from.v[1]); 259 to += stride; 260 *to = std::complex<float>(from.v[2], from.v[3]); 261 } 262 263 template <> 264 EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float>* addr) { 265 EIGEN_MSA_DEBUG; 266 267 prefetch(reinterpret_cast<const float*>(addr)); 268 } 269 270 template <> 271 EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a) { 272 EIGEN_MSA_DEBUG; 273 274 return std::complex<float>(a.v[0], a.v[1]); 275 } 276 277 template <> 278 EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) { 279 EIGEN_MSA_DEBUG; 280 281 return Packet2cf((Packet4f)__builtin_msa_shf_w((v4i32)a.v, EIGEN_MSA_SHF_I8(2, 3, 0, 1))); 282 } 283 284 template <> 285 EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& a) { 286 EIGEN_MSA_DEBUG; 287 288 return Packet2cf((Packet4f)__builtin_msa_shf_w((v4i32)a.v, EIGEN_MSA_SHF_I8(1, 0, 3, 2))); 289 } 290 291 template <> 292 EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a) { 293 EIGEN_MSA_DEBUG; 294 295 Packet4f value = (Packet4f)preverse((Packet2d)a.v); 296 value += a.v; 297 return std::complex<float>(value[0], value[1]); 298 } 299 300 template <> 301 EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a) { 302 EIGEN_MSA_DEBUG; 303 304 return std::complex<float>((a.v[0] * a.v[2]) - (a.v[1] * a.v[3]), 305 (a.v[0] * a.v[3]) + (a.v[1] * a.v[2])); 306 } 307 308 EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f) 309 310 template <> 311 EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { 312 EIGEN_MSA_DEBUG; 313 314 return a / b; 315 } 316 317 inline std::ostream& operator<<(std::ostream& os, const PacketBlock<Packet2cf, 2>& value) { 318 os << "[ " << value.packet[0] << ", " << std::endl << " " << value.packet[1] << " ]"; 319 return os; 320 } 321 322 EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2cf, 2>& kernel) { 323 EIGEN_MSA_DEBUG; 324 325 Packet4f tmp = 326 (Packet4f)__builtin_msa_ilvl_d((v2i64)kernel.packet[1].v, (v2i64)kernel.packet[0].v); 327 kernel.packet[0].v = 328 (Packet4f)__builtin_msa_ilvr_d((v2i64)kernel.packet[1].v, (v2i64)kernel.packet[0].v); 329 kernel.packet[1].v = tmp; 330 } 331 332 template <> 333 EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket, 334 const Packet2cf& elsePacket) { 335 return (Packet2cf)(Packet4f)pblend<Packet2d>(ifPacket, (Packet2d)thenPacket.v, 336 (Packet2d)elsePacket.v); 337 } 338 339 //---------- double ---------- 340 341 struct Packet1cd { 342 EIGEN_STRONG_INLINE Packet1cd() { 343 } 344 EIGEN_STRONG_INLINE explicit Packet1cd(const std::complex<double>& a) { 345 v[0] = std::real(a); 346 v[1] = std::imag(a); 347 } 348 EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) { 349 } 350 EIGEN_STRONG_INLINE Packet1cd(const Packet1cd& a) : v(a.v) { 351 } 352 EIGEN_STRONG_INLINE Packet1cd& operator=(const Packet1cd& b) { 353 v = b.v; 354 return *this; 355 } 356 EIGEN_STRONG_INLINE Packet1cd conjugate(void) const { 357 static const v2u64 p2ul_CONJ_XOR = { 0x0, 0x8000000000000000 }; 358 return (Packet1cd)pxor(v, (Packet2d)p2ul_CONJ_XOR); 359 } 360 EIGEN_STRONG_INLINE Packet1cd& operator*=(const Packet1cd& b) { 361 Packet2d v1, v2; 362 363 // Get the real values of a | a1_re | a1_re 364 v1 = (Packet2d)__builtin_msa_ilvev_d((v2i64)v, (v2i64)v); 365 // Get the imag values of a | a1_im | a1_im 366 v2 = (Packet2d)__builtin_msa_ilvod_d((v2i64)v, (v2i64)v); 367 // Multiply the real a with b 368 v1 = pmul(v1, b.v); 369 // Multiply the imag a with b 370 v2 = pmul(v2, b.v); 371 // Conjugate v2 372 v2 = Packet1cd(v2).conjugate().v; 373 // Swap real/imag elements in v2. 374 v2 = (Packet2d)__builtin_msa_shf_w((v4i32)v2, EIGEN_MSA_SHF_I8(2, 3, 0, 1)); 375 // Add and return the result 376 v = padd(v1, v2); 377 return *this; 378 } 379 EIGEN_STRONG_INLINE Packet1cd operator*(const Packet1cd& b) const { 380 return Packet1cd(*this) *= b; 381 } 382 EIGEN_STRONG_INLINE Packet1cd& operator+=(const Packet1cd& b) { 383 v = padd(v, b.v); 384 return *this; 385 } 386 EIGEN_STRONG_INLINE Packet1cd operator+(const Packet1cd& b) const { 387 return Packet1cd(*this) += b; 388 } 389 EIGEN_STRONG_INLINE Packet1cd& operator-=(const Packet1cd& b) { 390 v = psub(v, b.v); 391 return *this; 392 } 393 EIGEN_STRONG_INLINE Packet1cd operator-(const Packet1cd& b) const { 394 return Packet1cd(*this) -= b; 395 } 396 EIGEN_STRONG_INLINE Packet1cd& operator/=(const Packet1cd& b) { 397 *this *= b.conjugate(); 398 Packet2d s = pmul<Packet2d>(b.v, b.v); 399 s = padd(s, preverse<Packet2d>(s)); 400 v = pdiv(v, s); 401 return *this; 402 } 403 EIGEN_STRONG_INLINE Packet1cd operator/(const Packet1cd& b) const { 404 return Packet1cd(*this) /= b; 405 } 406 EIGEN_STRONG_INLINE Packet1cd operator-(void) const { 407 return Packet1cd(pnegate(v)); 408 } 409 410 Packet2d v; 411 }; 412 413 inline std::ostream& operator<<(std::ostream& os, const Packet1cd& value) { 414 os << "[ (" << value.v[0] << ", " << value.v[1] << "i) ]"; 415 return os; 416 } 417 418 template <> 419 struct packet_traits<std::complex<double> > : default_packet_traits { 420 typedef Packet1cd type; 421 typedef Packet1cd half; 422 enum { 423 Vectorizable = 1, 424 AlignedOnScalar = 0, 425 size = 1, 426 HasHalfPacket = 0, 427 428 HasAdd = 1, 429 HasSub = 1, 430 HasMul = 1, 431 HasDiv = 1, 432 HasNegate = 1, 433 HasAbs = 0, 434 HasAbs2 = 0, 435 HasMin = 0, 436 HasMax = 0, 437 HasSetLinear = 0 438 }; 439 }; 440 441 template <> 442 struct unpacket_traits<Packet1cd> { 443 typedef std::complex<double> type; 444 enum { size = 1, alignment = Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false }; 445 typedef Packet1cd half; 446 }; 447 448 template <> 449 EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) { 450 EIGEN_MSA_DEBUG; 451 452 EIGEN_DEBUG_ALIGNED_LOAD return Packet1cd(pload<Packet2d>((const double*)from)); 453 } 454 455 template <> 456 EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) { 457 EIGEN_MSA_DEBUG; 458 459 EIGEN_DEBUG_UNALIGNED_LOAD return Packet1cd(ploadu<Packet2d>((const double*)from)); 460 } 461 462 template <> 463 EIGEN_STRONG_INLINE Packet1cd pset1<Packet1cd>(const std::complex<double>& from) { 464 EIGEN_MSA_DEBUG; 465 466 return Packet1cd(from); 467 } 468 469 template <> 470 EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 471 EIGEN_MSA_DEBUG; 472 473 return a + b; 474 } 475 476 template <> 477 EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 478 EIGEN_MSA_DEBUG; 479 480 return a - b; 481 } 482 483 template <> 484 EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { 485 EIGEN_MSA_DEBUG; 486 487 return -a; 488 } 489 490 template <> 491 EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) { 492 EIGEN_MSA_DEBUG; 493 494 return a.conjugate(); 495 } 496 497 template <> 498 EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 499 EIGEN_MSA_DEBUG; 500 501 return a * b; 502 } 503 504 template <> 505 EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 506 EIGEN_MSA_DEBUG; 507 508 return Packet1cd(pand(a.v, b.v)); 509 } 510 511 template <> 512 EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 513 EIGEN_MSA_DEBUG; 514 515 return Packet1cd(por(a.v, b.v)); 516 } 517 518 template <> 519 EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 520 EIGEN_MSA_DEBUG; 521 522 return Packet1cd(pxor(a.v, b.v)); 523 } 524 525 template <> 526 EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 527 EIGEN_MSA_DEBUG; 528 529 return Packet1cd(pandnot(a.v, b.v)); 530 } 531 532 template <> 533 EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) { 534 EIGEN_MSA_DEBUG; 535 536 return pset1<Packet1cd>(*from); 537 } 538 539 template <> 540 EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, 541 const Packet1cd& from) { 542 EIGEN_MSA_DEBUG; 543 544 EIGEN_DEBUG_ALIGNED_STORE pstore<double>((double*)to, from.v); 545 } 546 547 template <> 548 EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, 549 const Packet1cd& from) { 550 EIGEN_MSA_DEBUG; 551 552 EIGEN_DEBUG_UNALIGNED_STORE pstoreu<double>((double*)to, from.v); 553 } 554 555 template <> 556 EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) { 557 EIGEN_MSA_DEBUG; 558 559 prefetch(reinterpret_cast<const double*>(addr)); 560 } 561 562 template <> 563 EIGEN_DEVICE_FUNC inline Packet1cd pgather<std::complex<double>, Packet1cd>( 564 const std::complex<double>* from, Index stride __attribute__((unused))) { 565 EIGEN_MSA_DEBUG; 566 567 Packet1cd res; 568 res.v[0] = std::real(from[0]); 569 res.v[1] = std::imag(from[0]); 570 return res; 571 } 572 573 template <> 574 EIGEN_DEVICE_FUNC inline void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to, 575 const Packet1cd& from, 576 Index stride 577 __attribute__((unused))) { 578 EIGEN_MSA_DEBUG; 579 580 pstore(to, from); 581 } 582 583 template <> 584 EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a) { 585 EIGEN_MSA_DEBUG; 586 587 return std::complex<double>(a.v[0], a.v[1]); 588 } 589 590 template <> 591 EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) { 592 EIGEN_MSA_DEBUG; 593 594 return a; 595 } 596 597 template <> 598 EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) { 599 EIGEN_MSA_DEBUG; 600 601 return pfirst(a); 602 } 603 604 template <> 605 EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) { 606 EIGEN_MSA_DEBUG; 607 608 return pfirst(a); 609 } 610 611 EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d) 612 613 template <> 614 EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { 615 EIGEN_MSA_DEBUG; 616 617 return a / b; 618 } 619 620 EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) { 621 EIGEN_MSA_DEBUG; 622 623 return Packet1cd(preverse(Packet2d(x.v))); 624 } 625 626 inline std::ostream& operator<<(std::ostream& os, const PacketBlock<Packet1cd, 2>& value) { 627 os << "[ " << value.packet[0] << ", " << std::endl << " " << value.packet[1] << " ]"; 628 return os; 629 } 630 631 EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd, 2>& kernel) { 632 EIGEN_MSA_DEBUG; 633 634 Packet2d v1, v2; 635 636 v1 = (Packet2d)__builtin_msa_ilvev_d((v2i64)kernel.packet[0].v, (v2i64)kernel.packet[1].v); 637 // Get the imag values of a 638 v2 = (Packet2d)__builtin_msa_ilvod_d((v2i64)kernel.packet[0].v, (v2i64)kernel.packet[1].v); 639 640 kernel.packet[0].v = v1; 641 kernel.packet[1].v = v2; 642 } 643 644 } // end namespace internal 645 646 } // end namespace Eigen 647 648 #endif // EIGEN_COMPLEX_MSA_H 649