File indexing completed on 2024-04-06 12:04:43
0001 #define SMATRIX_USE_CONSTEXPR
0002 #include "Math/SMatrix.h"
0003 #include <cmath>
0004 #include <cstddef>
0005 #include <random>
0006
0007 typedef unsigned int IndexType;
0008
0009
0010 namespace ROOT {
0011
0012 namespace Math {
0013
0014
0015
0016
0017
0018
0019
0020
0021 struct AssignAsSym {
0022
0023 template <class T, IndexType D, class A, class R>
0024 static void Evaluate(SMatrix<T, D, D, MatRepStd<T, D> >& lhs, const Expr<A, T, D, D, R>& rhs) {
0025
0026
0027
0028 for (IndexType i = 0; i < D; ++i)
0029
0030 for (IndexType j = 0; j <= i; ++j)
0031 lhs(i, j) = rhs(i, j);
0032
0033 for (IndexType i = 0; i != D - 1; ++i)
0034 for (IndexType j = i + 1; j != D; ++j)
0035 lhs(i, j) = lhs(j, i);
0036 }
0037
0038 template <class T, IndexType D, class R>
0039 static void Evaluate(SMatrix<T, D, D, MatRepStd<T, D> >& lhs, const SMatrix<T, D, D, R>& rhs) {
0040 for (IndexType i = 0; i != D * D; ++i)
0041 lhs.fRep[i] = rhs.apply(i);
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 }
0053 };
0054
0055 template <class T, IndexType D1, IndexType D2, class R>
0056 inline SMatrix<T, D1, D1, MatRepSym<T, D1> > Similarity1(const SMatrix<T, D1, D2, R>& lhs,
0057 const SMatrix<T, D2, D2, MatRepStd<T, D2> >& rhs) {
0058 SMatrix<T, D1, D2, MatRepStd<T, D1, D2> > tmp = lhs * rhs;
0059 typedef SMatrix<T, D1, D1, MatRepSym<T, D1> > SMatrixSym;
0060 SMatrixSym mret{SMatrixNoInit{}};
0061 AssignSym::Evaluate(mret, tmp * Transpose(lhs));
0062 return mret;
0063 }
0064
0065 template <class T, IndexType D1, IndexType D2>
0066 inline SMatrix<T, D1, D1, MatRepStd<T, D1> > Similarity2(const SMatrix<T, D1, D2, MatRepStd<T, D1, D2> >& lhs,
0067 const SMatrix<T, D2, D2, MatRepStd<T, D2> >& rhs) {
0068 SMatrix<T, D1, D2, MatRepStd<T, D1, D2> > tmp = lhs * rhs;
0069 typedef SMatrix<T, D1, D1, MatRepStd<T, D1> > SMatrixSym;
0070 SMatrixSym mret = SMatrixNoInit();
0071 AssignAsSym::Evaluate(mret, tmp * Transpose(lhs));
0072 return mret;
0073 }
0074 }
0075 }
0076
0077
0078 template <typename T, IndexType D1, IndexType D2>
0079 inline void similarity(ROOT::Math::SMatrix<T, D1, D1, ROOT::Math::MatRepStd<T, D1> >& b,
0080 ROOT::Math::SMatrix<T, D1, D2, ROOT::Math::MatRepStd<T, D1, D2> > const& u,
0081 ROOT::Math::SMatrix<T, D2, D2, ROOT::Math::MatRepStd<T, D2> > const& a) {
0082
0083 for (IndexType i = 0; i != D1; ++i)
0084 for (IndexType j = 0; j <= i; ++j)
0085 for (IndexType k = 0; k != D2; ++k)
0086 for (IndexType l = 0; l != D2; ++l)
0087 b(i, j) += u(i, k) * a(k, l) * u(j, l);
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 for (IndexType i = 0; i != D1 - 1; ++i)
0123 for (IndexType j = i + 1; j != D1; ++j)
0124 b(i, j) = b(j, i);
0125 }
0126
0127 template <typename M1, typename M2>
0128 double eps(M1 const& m1, M2 const& m2) {
0129 IndexType N = M1::kRows;
0130 double ret = 0.;
0131 for (IndexType i = 0; i != N; ++i)
0132 for (IndexType j = 0; j != N; ++j)
0133 ret = std::max(ret, std::abs(m1(i, j) - m2(i, j)));
0134 return ret;
0135 }
0136
0137 template <typename M>
0138 bool isSym(M const& m) {
0139 IndexType N = M::kRows;
0140 for (IndexType i = 0; i != N; ++i)
0141 for (IndexType j = 0; j <= i; ++j)
0142 if (m(i, j) != m(j, i))
0143 return false;
0144 return true;
0145 }
0146
0147 #include <iostream>
0148 #include "FWCore/Utilities/interface/HRRealTime.h"
0149
0150 namespace {
0151 std::mt19937 eng;
0152 std::uniform_real_distribution<double> rgen(-5., 5.);
0153
0154 inline double rr() { return rgen(eng); }
0155
0156 template <typename T, IndexType D1, IndexType D2>
0157 inline void fillRandom(ROOT::Math::SMatrix<T, D1, D2, ROOT::Math::MatRepStd<T, D1, D2> >& a) {
0158 for (IndexType i = 0; i != D1; ++i) {
0159 for (IndexType j = 0; j != D2; ++j)
0160 a(i, j) = rr();
0161 }
0162 }
0163 template <typename T, IndexType N>
0164 inline void fillRandomSym(ROOT::Math::SMatrix<T, N, N, ROOT::Math::MatRepStd<T, N> >& a) {
0165 for (IndexType i = 0; i != N; ++i) {
0166 for (IndexType j = 0; j <= i; ++j)
0167 a(i, j) = rr();
0168 }
0169 for (IndexType i = 0; i != N - 1; ++i)
0170 for (IndexType j = i + 1; j != N; ++j)
0171 a(i, j) = a(j, i);
0172 }
0173 }
0174
0175 bool ok = true;
0176
0177 template <typename T, IndexType D1, IndexType D2>
0178 void go(edm::HRTimeType& s1, edm::HRTimeType& s2, edm::HRTimeType& s3, edm::HRTimeType& s4, bool print) {
0179 typedef ROOT::Math::SMatrix<T, D1, D2, ROOT::Math::MatRepStd<T, D1, D2> > JMatrix;
0180 typedef ROOT::Math::SMatrix<T, D1, D1, ROOT::Math::MatRepStd<T, D1, D1> > Matrix1;
0181 typedef ROOT::Math::SMatrix<T, D1, D1, ROOT::Math::MatRepSym<T, D1> > SymMatrix1;
0182 typedef ROOT::Math::SMatrix<T, D2, D2, ROOT::Math::MatRepStd<T, D2, D2> > Matrix2;
0183 typedef ROOT::Math::SMatrix<T, D2, D2, ROOT::Math::MatRepSym<T, D2> > SymMatrix2;
0184
0185 JMatrix lh;
0186 fillRandom(lh);
0187 Matrix2 rh;
0188 fillRandomSym(rh);
0189
0190 SymMatrix2 srh;
0191 ROOT::Math::AssignSym::Evaluate(srh, rh);
0192
0193 SymMatrix1 res1;
0194 s1 = edm::hrRealTime();
0195 res1 = ROOT::Math::Similarity(lh, srh);
0196 s1 = edm::hrRealTime() - s1;
0197
0198 SymMatrix1 res2;
0199 s2 = edm::hrRealTime();
0200 res2 = ROOT::Math::Similarity1(lh, rh);
0201 s2 = edm::hrRealTime() - s2;
0202
0203 Matrix1 res3;
0204 s3 = edm::hrRealTime();
0205 res3 = ROOT::Math::Similarity2(lh, rh);
0206 s3 = edm::hrRealTime() - s3;
0207
0208 Matrix1 res4;
0209 s4 = edm::hrRealTime();
0210 similarity(res4, lh, rh);
0211 s4 = edm::hrRealTime() - s4;
0212
0213 if (print) {
0214 if (!isSym(rh))
0215 std::cout << " rh is not sym" << std::endl;
0216 if (!isSym(res1))
0217 std::cout << " res1 is not sym" << std::endl;
0218 if (!isSym(res2))
0219 std::cout << " res2 is not sym" << std::endl;
0220 if (!isSym(res3))
0221 std::cout << " res3 is not sym" << std::endl;
0222 if (!isSym(res4))
0223 std::cout << " res4 is not sym" << std::endl;
0224
0225 std::cout << D1 << "x" << D2 << std::endl;
0226 std::cout << "eps sim " << eps(res1, res2) << std::endl;
0227 std::cout << "eps std " << eps(res1, res3) << std::endl;
0228 std::cout << "eps loop " << eps(res1, res4) << std::endl;
0229 }
0230
0231 ok &= isSym(rh) && isSym(res1) && isSym(res2) && isSym(res3) && isSym(res4);
0232 }
0233
0234 template <typename T, IndexType D1, IndexType D2>
0235 void loop(std::ostream& co) {
0236 ok = true;
0237
0238 int N = 100000;
0239 edm::HRTimeType t1 = 0;
0240 edm::HRTimeType t2 = 0;
0241 edm::HRTimeType t3 = 0;
0242 edm::HRTimeType t4 = 0;
0243 edm::HRTimeType s1 = 0, s2 = 0, s3 = 0, s4 = 0;
0244 for (int i = 0; i != N; ++i) {
0245 go<T, D1, D2>(s1, s2, s3, s4, false);
0246 t1 += s1;
0247 t2 += s2;
0248 t3 += s3;
0249 t4 += s4;
0250 }
0251
0252 std::cout << D1 << "x" << D2 << std::endl;
0253 std::cout << "root sim " << t1 / N << std::endl;
0254 std::cout << "sym sim " << t2 / N << std::endl;
0255 std::cout << "std sim " << t3 / N << std::endl;
0256 std::cout << "loop sim " << t4 / N << std::endl;
0257
0258 co << "| " << t1 / N << "| " << t2 / N << "| " << t3 / N << "| " << t4 / N << "|";
0259
0260 if (ok)
0261 std::cout << " OK " << std::endl;
0262 }
0263
0264 #include <sstream>
0265 int main() {
0266 edm::HRTimeType s1 = 0, s2 = 0, s3 = 0, s4 = 0;
0267
0268 go<double, 3, 3>(s1, s2, s3, s4, true);
0269 go<double, 5, 5>(s1, s2, s3, s4, true);
0270 go<double, 5, 15>(s1, s2, s3, s4, true);
0271 go<double, 15, 15>(s1, s2, s3, s4, true);
0272 std::cout << std::endl;
0273
0274 std::ostringstream co;
0275 co << "| *3x3* |||| | *5x5* |||| | *5x15* |||| | *15x15* ||||\n";
0276 co << "| *root* | *sym* | *std* | *loop* |";
0277 co << "| *root* | *sym* | *std* | *loop* |";
0278 co << "| *root* | *sym* | *std* | *loop* |";
0279 co << "| *root* | *sym* | *std* | *loop* |\n";
0280 loop<double, 3, 3>(co);
0281 loop<double, 5, 5>(co);
0282 loop<double, 5, 15>(co);
0283 loop<double, 15, 15>(co);
0284 std::cout << co.str() << std::endl;
0285
0286 return 0;
0287 }