34double sqr(
double x) {
return x*x; }
36int sign(
double x) {
return x >= 0.0 ? 1 : -1; }
62 const std::complex<double> eID(std::polar(1.0,
delta));
63 const double s12 = std::sin(
theta_12);
64 const double s13 = std::sin(
theta_13);
65 const double s23 = std::sin(
theta_23);
66 const double c12 = std::cos(
theta_12);
67 const double c13 = std::cos(
theta_13);
68 const double c23 = std::cos(
theta_23);
72 const int pf =
sign(std::real(eID));
74 Eigen::Matrix<double,3,3> pmns_matrix;
75 pmns_matrix(0, 0) = c12 * c13;
76 pmns_matrix(0, 1) = s12 * c13;
77 pmns_matrix(0, 2) = pf * s13;
78 pmns_matrix(1, 0) = -s12 * c23 - pf * c12 * s23 * s13;
79 pmns_matrix(1, 1) = c12 * c23 - pf * s12 * s23 * s13;
80 pmns_matrix(1, 2) = s23 * c13;
81 pmns_matrix(2, 0) = s12 * s23 - pf * c12 * c23 * s13;
82 pmns_matrix(2, 1) = -c12 * s23 - pf * s12 * c23 * s13;
83 pmns_matrix(2, 2) = c23 * c13;
90 const std::complex<double> eID(std::polar(1.0,
delta));
91 const std::complex<double> eIAlpha1(std::polar(1.0, 0.5*
alpha_1));
92 const std::complex<double> eIAlpha2(std::polar(1.0, 0.5*
alpha_2));
93 const double s12 = std::sin(
theta_12);
94 const double s13 = std::sin(
theta_13);
95 const double s23 = std::sin(
theta_23);
96 const double c12 = std::cos(
theta_12);
97 const double c13 = std::cos(
theta_13);
98 const double c23 = std::cos(
theta_23);
100 Eigen::Matrix<std::complex<double>,3,3> pmns_matrix;
101 pmns_matrix(0, 0) = c12 * c13 * eIAlpha1;
102 pmns_matrix(0, 1) = s12 * c13 * eIAlpha2;
103 pmns_matrix(0, 2) = s13 / eID;
104 pmns_matrix(1, 0) = (-s12 * c23 - c12 * s23 * s13 * eID) * eIAlpha1;
105 pmns_matrix(1, 1) = (c12 * c23 - s12 * s23 * s13 * eID) * eIAlpha2;
106 pmns_matrix(1, 2) = s23 * c13;
107 pmns_matrix(2, 0) = (s12 * s23 - c12 * c23 * s13 * eID) * eIAlpha1;
108 pmns_matrix(2, 1) = (-c12 * s23 - s12 * c23 * s13 * eID) * eIAlpha2;
109 pmns_matrix(2, 2) = c23 * c13;
115 Eigen::Matrix<double,3,3>& Ve,
116 Eigen::Matrix<double,3,3>& Ue)
118 Eigen::Matrix<double,3,3> pmns(Ve*Vv.adjoint());
123 Eigen::Matrix<double,3,3>& Vv,
124 Eigen::Matrix<double,3,3>& Ve,
125 Eigen::Matrix<double,3,3>& Ue)
127 Eigen::Matrix<double,3,3> signs_E(Eigen::Matrix<double,3,3>::Identity());
128 Eigen::Matrix<double,3,3> signs_V(Eigen::Matrix<double,3,3>::Identity());
131 if (pmns(2, 2) < 0.) {
133 for (
int j = 0; j < 3; ++j) {
139 if (pmns(1, 2) < 0.) {
142 for (
int j = 0; j < 3; ++j) {
154 Eigen::Matrix<std::complex<double>,3,3>& Vv,
155 Eigen::Matrix<std::complex<double>,3,3>& Ve,
156 Eigen::Matrix<std::complex<double>,3,3>& Ue)
158 Eigen::Matrix<std::complex<double>,3,3> pmns(Ve*Vv.adjoint());
165std::complex<T>
phase(
const std::complex<T>& z)
noexcept
172 const Eigen::Matrix<std::complex<double>,3,3>& pmns,
173 const std::complex<double>& p,
174 std::complex<double>& o,
175 Eigen::DiagonalMatrix<std::complex<double>,3>& l)
178 l.diagonal().bottomRightCorner<2,1>() = (o * pmns.bottomRightCorner<2,1>()).
179 unaryExpr([] (
const std::complex<double>& z) {
return phase<double>(z); }).conjugate();
185 if (sc < -1.) { sc = -1.0; }
186 if (sc > 1.) { sc = 1.0; }
193 Eigen::Matrix<std::complex<double>,3,3>& pmns,
194 Eigen::Matrix<std::complex<double>,3,3>& Vv,
195 Eigen::Matrix<std::complex<double>,3,3>& Ve,
196 Eigen::Matrix<std::complex<double>,3,3>& Ue)
198 std::complex<double> o;
199 Eigen::DiagonalMatrix<std::complex<double>,3> l(1,1,1);
202 const double c13_sq = 1. -
sqr(s13);
206 const auto rel_phase = std::sqrt(
phase(pmns(1,0) * pmns(2,1)));
207 const auto p =
std::conj(rel_phase * rel_phase)
208 *
phase(pmns(1,0) * pmns(1,1));
209 l.diagonal()[1] =
std::conj(o * rel_phase);
210 l.diagonal()[2] =
std::conj(o * rel_phase) * p;
212 const double c13 = std::sqrt(c13_sq);
214 const double c12 = std::sqrt(1 -
sqr(s12));
216 const double c23 = std::sqrt(1 -
sqr(s23));
217 const double jcp = std::imag(pmns(1,2) *
std::conj(pmns(0,2))
219 const double side1 = s12*s23;
220 const double side2 = c12*c23*s13;
224 const double sindelta = std::sqrt(1 -
sqr(cosdelta));
225 const std::complex<double> p(cosdelta, sindelta);
228 const auto a1 =
phase(o*pmns(0,0));
229 const auto a2 =
phase(o*pmns(0,1));
231 Eigen::Matrix<std::complex<double>,2,2> pmnsBL{
232 (o * l * pmns).bottomLeftCorner<2,2>()};
233 Eigen::Array<std::complex<double>,2,2> maj_phases;
234 maj_phases << a1, a2, a1, a2;
235 const Eigen::Array<double,2,2> imagBL{
236 (maj_phases.conjugate() * pmnsBL.array()).imag()};
237 if (!((imagBL <= 0).all() || (imagBL >= 0).all())) {
242 Ve.transpose() *= l * o;
243 Ue.transpose() *= (l * o).diagonal().conjugate().asDiagonal();
244 pmns = Ve * Vv.adjoint();
double sanitize_hypot(double sc) noexcept
restrict sin or cos to interval [-1,1]
std::complex< T > phase(const std::complex< T > &z) noexcept
void calc_phase_factors(const Eigen::Matrix< std::complex< double >, 3, 3 > &pmns, const std::complex< double > &p, std::complex< double > &o, Eigen::DiagonalMatrix< std::complex< double >, 3 > &l)
constexpr T norm(const Complex< T > &z) noexcept
std::enable_if_t< std::is_unsigned< T >::value, bool > is_zero(T a, T prec=std::numeric_limits< T >::epsilon()) noexcept
compares a number for being close to zero
constexpr Complex< T > conj(const Complex< T > &z) noexcept
static void to_pdg_convention(Eigen::Matrix< double, 3, 3 > &, Eigen::Matrix< double, 3, 3 > &, Eigen::Matrix< double, 3, 3 > &, Eigen::Matrix< double, 3, 3 > &)
void reset_to_observation()
Eigen::Matrix< std::complex< double >, 3, 3 > get_complex_pmns() const
Eigen::Matrix< double, 3, 3 > get_real_pmns() const