00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef MORE_MATH_SPINOR_H
00031 #define MORE_MATH_SPINOR_H
00032
00033 #include <iosfwd>
00034 #include <more/math/math.h>
00035 #include <more/math/complex.h>
00036 #include <more/bits/mathbits.h>
00037 #include <more/math/qtypes.h>
00038 #include <more/io/fwd.h>
00039
00040 namespace more {
00041 namespace math {
00042
00043 struct alpha_tag {};
00044 struct beta_tag {};
00045
00046 extern alpha_tag alpha;
00047 extern beta_tag beta;
00048
00049 struct sigma_x_tag {};
00050 struct sigma_y_tag {};
00051 struct sigma_z_tag {};
00052 extern sigma_x_tag sigma_x;
00053 extern sigma_y_tag sigma_y;
00054 extern sigma_z_tag sigma_z;
00055
00056
00057 template<typename T> struct spinopr;
00058
00059 template<typename T>
00060 struct spinor {
00061 template<typename U> friend class spinor;
00062 spinor() {}
00063 spinor(zero_tag) : u(0), d(0) {}
00064 spinor(alpha_tag) : u(1), d(0) {}
00065 spinor(beta_tag) : u(0), d(1) {}
00066 template<typename U>
00067 spinor(const spinor<U>& x) : u(x.u), d(x.d) {}
00068
00069 T operator()(half_tag) const { return u; }
00070 T operator()(minus_half_tag) const { return d; }
00071 T& operator()(half_tag) { return u; }
00072 T& operator()(minus_half_tag) { return d; }
00073 T operator()(pm_half i) const { return i==half? u : d; }
00074 T& operator()(pm_half i) { return i==half? u : d; }
00075
00076 template<typename U>
00077 spinor& operator=(const spinor<U>& rhs) {
00078 u = rhs.u;
00079 d = rhs.d;
00080 return *this;
00081 }
00082 template<typename U>
00083 spinor& operator+=(const spinor<U>& rhs) {
00084 u += rhs.u;
00085 d += rhs.d;
00086 return *this;
00087 }
00088 template<typename U>
00089 spinor& operator-=(const spinor<U>& rhs) {
00090 u -= rhs.u;
00091 d -= rhs.d;
00092 return *this;
00093 }
00094 template<typename U>
00095 spinor& operator*=(const U& rhs) {
00096 u *= rhs;
00097 d *= rhs;
00098 return *this;
00099 }
00100 template<typename U>
00101 spinor& operator/=(const U& rhs) {
00102 u /= rhs;
00103 d /= rhs;
00104 return *this;
00105 }
00106 template<typename U>
00107 spinor& left_multiply(const spinopr<U>&);
00108
00109 spinor& negate() { u = -u; d = -d; return *this; }
00110
00111 void sync(io::syncstream&);
00112
00113 private:
00114 T u, d;
00115 };
00116
00117 template<typename T>
00118 struct spinopr {
00119 template<typename U> friend class spinopr;
00120 spinopr() {}
00121 spinopr(zero_tag) : uu(0), du(0), ud(0), dd(0) {}
00122 spinopr(one_tag) : uu(1), du(0), ud(0), dd(1) {}
00123 spinopr(sigma_x_tag) : uu(0), du(1), ud(1), dd(0) {}
00124 spinopr(sigma_y_tag)
00125 : uu(0), du(T(1)*onei), ud(-T(1)*onei), dd(0) {}
00126 spinopr(sigma_z_tag) : uu(1), du(0), ud(0), dd(-1) {}
00127 spinopr(T x, sigma_x_tag) : uu(0), du(x), ud(x), dd(0) {}
00128 spinopr(T x, sigma_y_tag)
00129 : uu(0), du(x*onei), ud(-x*onei), dd(0) {}
00130 spinopr(T x, sigma_z_tag) : uu(x), du(0), ud(0), dd(-x) {}
00131 template<typename U>
00132 spinopr(const U& x) : uu(x), du(0), ud(0), dd(x) {}
00133 template<typename U>
00134 spinopr(const spinopr<U>& x)
00135 : uu(x.uu), du(x.du), ud(x.ud), dd(x.dd) {}
00136 template<typename U, typename V>
00137 spinopr(const spinor<U>& x, const spinor<V>& y)
00138 : uu(x(half)*conj(y( half))), du(x(-half)*conj(y( half))),
00139 ud(x(half)*conj(y(-half))), dd(x(-half)*conj(y(-half))) {}
00140
00141 T operator()(half_tag, half_tag) const { return uu; }
00142 T operator()(half_tag, minus_half_tag) const { return ud; }
00143 T operator()(minus_half_tag, half_tag) const { return du; }
00144 T operator()(minus_half_tag, minus_half_tag) const { return dd; }
00145 T& operator()(half_tag, half_tag) { return uu; }
00146 T& operator()(half_tag, minus_half_tag) { return ud; }
00147 T& operator()(minus_half_tag, half_tag) { return du; }
00148 T& operator()(minus_half_tag, minus_half_tag) { return dd; }
00149 T operator()(pm_half i, pm_half j) const {
00150 return i == half? (j == half? uu : ud)
00151 : (j == half? du : dd);
00152 }
00153 T& operator()(pm_half i, pm_half j) {
00154 return i == half? (j == half? uu : ud)
00155 : (j == half? du : dd);
00156 }
00157
00158 spinopr& operator=(const zero_tag& rhs) {
00159 uu = ud = du = dd = T(0);
00160 return *this;
00161 }
00162 spinopr& operator=(const one_tag& rhs) {
00163 uu = dd = T(1);
00164 ud = du = T(0);
00165 return *this;
00166 }
00167 template<typename U>
00168 spinopr& operator=(const spinopr<U>& rhs) {
00169 uu = rhs.uu;
00170 du = rhs.du;
00171 ud = rhs.ud;
00172 dd = rhs.dd;
00173 return *this;
00174 }
00175 template<typename U>
00176 spinopr& operator+=(const spinopr<U>& rhs) {
00177 uu += rhs.uu;
00178 du += rhs.du;
00179 ud += rhs.ud;
00180 dd += rhs.dd;
00181 return *this;
00182 }
00183 template<typename U>
00184 spinopr& operator-=(const spinopr<U>& rhs) {
00185 uu -= rhs.uu;
00186 du -= rhs.du;
00187 ud -= rhs.ud;
00188 dd -= rhs.dd;
00189 return *this;
00190 }
00191 template<typename U>
00192 spinopr& operator*=(const spinopr<U>& rhs) {
00193 T uus = uu, dus = du;
00194 uu = uu*rhs.uu + ud*rhs.du;
00195 du = du*rhs.uu + dd*rhs.du;
00196 ud = uus*rhs.ud + ud*rhs.dd;
00197 dd = dus*rhs.ud + dd*rhs.dd;
00198 return *this;
00199 }
00200
00201 template<typename U>
00202 spinopr& operator=(const U& rhs) {
00203 uu = rhs;
00204 du = 0;
00205 ud = 0;
00206 dd = rhs;
00207 return *this;
00208 }
00209 template<typename U>
00210 spinopr& operator+=(const U& rhs) {
00211 uu += rhs;
00212 dd += rhs;
00213 return *this;
00214 }
00215 template<typename U>
00216 spinopr& operator-=(const U& rhs) {
00217 uu -= rhs;
00218 dd -= rhs;
00219 return *this;
00220 }
00221 template<typename U>
00222 spinopr& operator*=(const U& rhs) {
00223 uu *= rhs;
00224 du *= rhs;
00225 ud *= rhs;
00226 dd *= rhs;
00227 return *this;
00228 }
00229 template<typename U>
00230 spinopr& operator/=(const U& rhs) {
00231 return *this *= 1.0/rhs;
00232 }
00233 spinopr& operator*=(sigma_x_tag) {
00234 T uus = uu, dus = du;
00235 uu = ud;
00236 du = dd;
00237 ud = uus;
00238 dd = dus;
00239 return *this;
00240 }
00241 spinopr& operator*=(sigma_y_tag) {
00242 T uus = uu, dus = du;
00243 uu = onei*ud;
00244 du = onei*dd;
00245 ud = -onei*uus;
00246 dd = -onei*dus;
00247 return *this;
00248 }
00249 spinopr& operator*=(sigma_z_tag) {
00250 ud = -ud;
00251 dd = -dd;
00252 return *this;
00253 }
00254 spinopr& left_multiply(sigma_x_tag) {
00255 T uus = uu, uds = ud;
00256 uu = du;
00257 du = uus;
00258 ud = dd;
00259 dd = uds;
00260 return *this;
00261 }
00262 spinopr& left_multiply(sigma_y_tag) {
00263 T uus = uu, uds = ud;
00264 uu = -onei*du;
00265 du = onei*uus;
00266 ud = -onei*dd;
00267 dd = onei*uds;
00268 return *this;
00269 }
00270 spinopr& left_multiply(sigma_z_tag) {
00271 du = -du;
00272 dd = -dd;
00273 return *this;
00274 }
00275 spinopr& negate() {
00276 uu = -uu;
00277 du = -du;
00278 ud = -ud;
00279 dd = -dd;
00280 return *this;
00281 }
00282 spinopr& adj() {
00283 T dus = du;
00284 uu = conj(uu);
00285 du = conj(ud);
00286 ud = conj(dus);
00287 dd = conj(dd);
00288 return *this;
00289 }
00290
00291 void sync(io::syncstream&);
00292
00293 private:
00294 T uu, du, ud, dd;
00295 };
00296
00297
00298
00299
00300 template<typename T>
00301 inline spinor<T>
00302 operator*(T x, alpha_tag) {
00303 spinor<T> z;
00304 z( half) = x;
00305 z(-half) = 0;
00306 return z;
00307 }
00308 template<typename T>
00309 inline spinor<T>
00310 operator*(T x, beta_tag) {
00311 spinor<T> z;
00312 z( half) = 0;
00313 z(-half) = x;
00314 return z;
00315 }
00316
00317
00318
00319
00320 template<typename T>
00321 inline spinopr<T> operator*(T x, sigma_x_tag) {
00322 return spinopr<T>(x, sigma_x_tag());
00323 }
00324 template<typename T>
00325 inline spinopr<T> operator*(sigma_x_tag, T y) {
00326 return spinopr<T>(y, sigma_x_tag());
00327 }
00328 template<typename T>
00329 inline spinopr<T> operator*(T x, sigma_y_tag) {
00330 return spinopr<T>(x, sigma_y_tag());
00331 }
00332 template<typename T>
00333 inline spinopr<T> operator*(sigma_y_tag, T y) {
00334 return spinopr<T>(y, sigma_y_tag());
00335 }
00336 template<typename T>
00337 inline spinopr<T> operator*(T x, sigma_z_tag) {
00338 return spinopr<T>(x, sigma_z_tag());
00339 }
00340 template<typename T>
00341 inline spinopr<T> operator*(sigma_z_tag, T y) {
00342 return spinopr<T>(y, sigma_z_tag());
00343 }
00344
00345 template<typename T>
00346 inline spinopr<T>
00347 operator*(const spinopr<T>& x, sigma_x_tag) {
00348 return spinopr<T>(x) *= sigma_x_tag();
00349 }
00350 template<typename T>
00351 inline spinopr<T>
00352 operator*(sigma_x_tag, const spinopr<T>& y) {
00353 return spinopr<T>(y).left_multiply(sigma_x_tag());
00354 }
00355 template<typename T>
00356 inline spinopr<T>
00357 operator*(const spinopr<T>& x, sigma_y_tag) {
00358 return spinopr<T>(x) *= sigma_y_tag();
00359 }
00360 template<typename T>
00361 inline spinopr<T>
00362 operator*(sigma_y_tag, const spinopr<T>& y) {
00363 return spinopr<T>(y).left_multiply(sigma_y_tag());
00364 }
00365 template<typename T>
00366 inline spinopr<T>
00367 operator*(const spinopr<T>& x, sigma_z_tag) {
00368 return spinopr<T>(x) *= sigma_z_tag();
00369 }
00370 template<typename T>
00371 inline spinopr<T>
00372 operator*(sigma_z_tag, const spinopr<T>& y) {
00373 return spinopr<T>(y).left_multiply(sigma_z_tag());
00374 }
00375
00376 template<typename T>
00377 inline spinopr<T> operator+(const spinopr<T>& x, sigma_x_tag) {
00378 return x + spinopr<T>(sigma_x_tag());
00379 }
00380 template<typename T>
00381 inline spinopr<T> operator+(sigma_x_tag, const spinopr<T>& y) {
00382 return spinopr<T>(sigma_x_tag()) + y;
00383 }
00384 template<typename T>
00385 inline spinopr<T> operator+(const spinopr<T>& x, sigma_y_tag) {
00386 return x + spinopr<T>(sigma_y_tag());
00387 }
00388 template<typename T>
00389 inline spinopr<T> operator+(sigma_y_tag, const spinopr<T>& y) {
00390 return spinopr<T>(sigma_y_tag()) + y;
00391 }
00392 template<typename T>
00393 inline spinopr<T> operator+(const spinopr<T>& x, sigma_z_tag) {
00394 return x + spinopr<T>(sigma_z_tag());
00395 }
00396 template<typename T>
00397 inline spinopr<T> operator+(sigma_z_tag, const spinopr<T>& y) {
00398 return spinopr<T>(sigma_z_tag()) + y;
00399 }
00400
00401
00402
00403
00404 template<typename T>
00405 inline spinor<T>
00406 operator+(const spinor<T>& x) {
00407 return x;
00408 }
00409 template<typename T>
00410 inline spinor<T>
00411 operator-(const spinor<T>& x) {
00412 return spinor<T>(x).negate();
00413 }
00414 template<typename T, typename U>
00415 inline spinor< typename plus_type_<T, U>::eval >
00416 operator+(const spinor<T>& x, const spinor<U>& y) {
00417 return spinor< typename plus_type_<T, U>::eval >(x) += y;
00418 }
00419 template<typename T, typename U>
00420 inline spinor< typename minus_type_<T, U>::eval >
00421 operator-(const spinor<T>& x, const spinor<U>& y) {
00422 return spinor< typename minus_type_<T, U>::eval >(x) -= y;
00423 }
00424 #if 0
00425 template<typename T, typename U>
00426 inline spinor< typename times_type_<T, U>::eval >
00427 operator*(const spinor<T>& x, U y) {
00428 return spinor< typename times_type_<T, U>::eval >(x) *= y;
00429 }
00430 template<typename T, typename U>
00431 inline spinor< typename times_type_<T, U>::eval >
00432 operator*(T x, const spinor<U>& y) {
00433 return spinor< typename times_type_<T, U>::eval >(y) *= x;
00434 }
00435 template<typename T, typename U>
00436 inline spinor< typename divides_type_<T, U>::eval >
00437 operator/(const spinor<T>& x, U y) {
00438 return spinor< typename divides_type_<T, U>::eval >(x) /= y;
00439 }
00440 #else
00441 template<typename T>
00442 inline spinor<T>
00443 operator*(const spinor<T>& x, T y) {
00444 return spinor<T>(x) *= y;
00445 }
00446 template<typename T>
00447 inline spinor<T>
00448 operator*(T x, const spinor<T>& y) {
00449 return spinor<T>(y) *= x;
00450 }
00451 template<typename T>
00452 inline spinor<T>
00453 operator/(const spinor<T>& x, T y) {
00454 return spinor<T>(x) /= y;
00455 }
00456 template<typename T>
00457 inline spinor< std::complex<T> >
00458 operator*(const spinor< std::complex<T> >& x, T y) {
00459 return spinor< std::complex<T> >(x) *= y;
00460 }
00461 template<typename T>
00462 inline spinor< std::complex<T> >
00463 operator*(T x, const spinor< std::complex<T> >& y) {
00464 return spinor< std::complex<T> >(y) *= x;
00465 }
00466 template<typename T>
00467 inline spinor< std::complex<T> >
00468 operator/(const spinor< std::complex<T> >& x, T y) {
00469 return spinor< std::complex<T> >(x) /= y;
00470 }
00471 template<typename T>
00472 inline spinor<T>
00473 operator*(const spinor<T>& x, const std::complex<T>& y) {
00474 return spinor<T>(x) *= y;
00475 }
00476 template<typename T>
00477 inline spinor<T>
00478 operator*(const std::complex<T>& x, const spinor<T>& y) {
00479 return spinor<T>(y) *= x;
00480 }
00481 template<typename T>
00482 inline spinor<T>
00483 operator/(const spinor<T>& x, const std::complex<T>& y) {
00484 return spinor<T>(x) /= y;
00485 }
00486 #endif
00487
00488
00489
00490
00491 template<typename T>
00492 inline spinopr<T>
00493 operator+(const spinopr<T>& x) {
00494 return x;
00495 }
00496 template<typename T>
00497 inline spinopr<T>
00498 operator-(const spinopr<T>& x) {
00499 return spinopr<T>(x).negate();
00500 }
00501
00502 template<typename T, typename U>
00503 inline spinopr<typename plus_type_<T, U>::eval>
00504 operator+(const spinopr<T>& x, const spinopr<U>& y) {
00505 return spinopr<typename plus_type_<T, U>::eval>(x) += y;
00506 }
00507 template<typename T, typename U>
00508 inline spinopr<typename minus_type_<T, U>::eval>
00509 operator-(const spinopr<T>& x, const spinopr<U>& y) {
00510 return spinopr<typename minus_type_<T, U>::eval>(x) -= y;
00511 }
00512 template<typename T, typename U>
00513 inline spinopr<typename times_type_<T, U>::eval>
00514 operator*(const spinopr<T>& x, const spinopr<U>& y) {
00515 return spinopr<typename times_type_<T, U>::eval>(x) *= y;
00516 }
00517
00518 template<typename T, typename U>
00519 inline spinopr<typename plus_type_<T, U>::eval>
00520 operator+(const spinopr<T>& x, U y) {
00521 return spinopr<typename plus_type_<T, U>::eval>(x) += y;
00522 }
00523 template<typename T, typename U>
00524 inline spinopr<typename plus_type_<T, U>::eval>
00525 operator+(T x, const spinopr<U>& y) {
00526 return spinopr<typename plus_type_<T, U>::eval>(y) += x;
00527 }
00528 template<typename T, typename U>
00529 inline spinopr<typename minus_type_<T, U>::eval>
00530 operator-(const spinopr<T>& x, U y) {
00531 return spinopr<typename minus_type_<T, U>::eval>(x) -= y;
00532 }
00533 template<typename T, typename U>
00534 inline spinopr<typename minus_type_<T, U>::eval>
00535 operator-(T x, const spinopr<U>& y) {
00536 return spinopr<typename minus_type_<T, U>::eval>(y).negate() += x;
00537 }
00538 template<typename T, typename U>
00539 inline spinopr<typename times_type_<T, U>::eval>
00540 operator*(const spinopr<T>& x, U y) {
00541 return spinopr<typename times_type_<T, U>::eval>(x) *= y;
00542 }
00543 template<typename T, typename U>
00544 inline spinopr<typename times_type_<T, U>::eval>
00545 operator*(T x, const spinopr<U>& y) {
00546 return spinopr<typename times_type_<T, U>::eval>(y) *= x;
00547 }
00548 template<typename T, typename U>
00549 inline spinopr<typename divides_type_<T, U>::eval>
00550 operator/(const spinopr<T>& x, U y) {
00551 return spinopr<typename divides_type_<T, U>::eval>(x) /= y;
00552 }
00553
00554
00555
00556
00557 template<typename T>
00558 template<typename U>
00559 inline spinor<T>&
00560 spinor<T>::left_multiply(const spinopr<U>& lhs) {
00561 T us = u;
00562 u = lhs( half, half)*u + lhs( half, -half)*d;
00563 d = lhs(-half, half)*us + lhs(-half, -half)*d;
00564
00565
00566 return *this;
00567 }
00568 template<typename T>
00569 inline spinor<T>
00570 operator*(const spinopr<T>& x, const spinor<T>& y) {
00571 return spinor<T>(y).left_multiply(x);
00572 }
00573
00574
00575
00576
00577 template<typename T>
00578 std::ostream& operator<<(std::ostream&, const spinor<T>&);
00579 template<typename T>
00580 std::ostream& operator<<(std::ostream&, const spinopr<T>&);
00581 template<typename T>
00582 std::istream& operator>>(std::istream&, spinor<T>&);
00583 template<typename T>
00584 std::istream& operator>>(std::istream&, spinopr<T>&);
00585
00586
00587
00588
00589
00590
00591
00592 template<typename T> struct norm_type_< spinor<T> >
00593 { typedef typename norm_type_<T>::eval eval; };
00594 template<typename T> struct norm_type_< spinopr<T> >
00595 { typedef typename norm_type_<T>::eval eval; };
00596 template<typename T> struct scalar_type_< spinor<T> >
00597 { typedef typename scalar_type_<T>::eval eval; };
00598 template<typename T>
00599 struct scalar_type_< spinopr<T> > { typedef T eval; };
00600
00601 template<> struct norm_type_<alpha_tag> { typedef one_tag eval; };
00602 template<> struct norm_type_<beta_tag> { typedef one_tag eval; };
00603 template<typename T>
00604 struct outer_product_type_< spinor<T> > { typedef spinopr<T> eval; };
00605
00606 template<typename T>
00607 inline typename norm_type_<T>::eval
00608 norm(const spinor<T>& x) { return norm(x(half)) + norm(x(-half)); }
00609 template<typename T>
00610 inline typename norm_type_<T>::eval
00611 abs(const spinor<T>& x) { return sqrt(norm(x)); }
00612 template<typename T>
00613 inline typename norm_type_<T>::eval
00614 norm(const spinopr<T>& x) {
00615 return norm(x( half, half)) + norm(x( half, -half))
00616 + norm(x(-half, half)) + norm(x(-half, -half));
00617 }
00618 template<typename T>
00619 inline typename norm_type_<T>::eval
00620 abs(const spinopr<T>& x) { return sqrt(norm(x)); }
00621
00622 template<typename T>
00623 inline T
00624 dot(const spinor<T>& x, const spinor<T>& y) {
00625 return conj(x(-half))*y(-half) + conj(x(half))*y(half);
00626 }
00627 template<typename T>
00628 inline T
00629 real_dot(const spinor< std::complex<T> >& x,
00630 const spinor< std::complex<T> >& y) {
00631 return real(x(-half))*real(y(-half)) + imag(x(-half))*imag(y(-half))
00632 + real(x( half))*real(y( half)) + imag(x( half))*imag(y( half));
00633 }
00634 template<typename T>
00635 inline spinopr<T>
00636 outer_prod(const spinor<T>& x, const spinor<T>& y) {
00637 return spinopr<T>(x, y);
00638 }
00639
00640 template<typename T>
00641 inline spinopr<T>
00642 adj(const spinopr<T>& x) { return spinopr<T>(x).adj(); }
00643
00644 template<typename T>
00645 inline T
00646 trace(const spinopr<T>& x) {
00647 return x(half, half) + x(-half, -half);
00648 }
00649 template<typename T>
00650 inline T
00651 det(const spinopr<T>& x) {
00652 return x(half, half)*x(-half, -half) - x(half, -half)*x(-half, half);
00653 }
00654 template<typename T>
00655 inline T
00656 sum(const spinor<T>& x) {
00657 return x(half) + x(-half);
00658 }
00659
00660 template<typename T>
00661 inline bool
00662 finite(const spinor<T>& x) {
00663 return finite(x(half)) && finite(x(-half));
00664 }
00665 template<typename T>
00666 inline bool
00667 finite(const spinopr<T>& x) {
00668 return finite(x( half, half)) && finite(x( half, -half))
00669 && finite(x(-half, half)) && finite(x(-half, -half));
00670 }
00671 template<typename T>
00672 spinopr<T>
00673 sin(spinopr<T> const& x);
00674 template<typename T>
00675 spinopr<T>
00676 cos(spinopr<T> const& x);
00677 template<typename T>
00678 spinopr<T>
00679 tan(spinopr<T> const& x);
00680 template<typename T>
00681 spinopr<T>
00682 sinh(spinopr<T> const& x);
00683 template<typename T>
00684 spinopr<T>
00685 cosh(spinopr<T> const& x);
00686 template<typename T>
00687 spinopr<T>
00688 tanh(spinopr<T> const& x);
00689 template<typename T>
00690 spinopr<T>
00691 exp(spinopr<T> const& x);
00692 template<typename T>
00693 spinopr<T>
00694 log(spinopr<T> const& x);
00695 template<typename T>
00696 spinopr<T>
00697 sqrt(spinopr<T> const& x);
00698 }
00699 using namespace math;
00700 }
00701
00702 #endif