File indexing completed on 2025-01-18 09:12:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <cmath>
0012 #include <exception>
0013 #include <functional>
0014 #include <sstream>
0015 #include <vector>
0016
0017 #include "TDictionary.h"
0018 #include "TTreeReaderValue.h"
0019
0020
0021 template <typename T>
0022 using HomogeneousPair = std::pair<T, T>;
0023
0024
0025
0026
0027
0028 class AnyVector {
0029 public:
0030
0031
0032
0033 template <typename T, typename... Args>
0034 static std::pair<AnyVector, std::vector<T>*> create(Args&&... args) {
0035 std::vector<T>* vector = new std::vector<T>(std::forward<Args>(args)...);
0036 std::function<void()> deleter = [vector] { delete vector; };
0037 return {AnyVector{static_cast<void*>(vector), std::move(deleter)}, vector};
0038 }
0039
0040
0041 AnyVector() = default;
0042
0043
0044 AnyVector(AnyVector&& other)
0045 : m_vector{other.m_vector}, m_deleter{std::move(other.m_deleter)} {
0046 other.m_vector = nullptr;
0047 }
0048
0049
0050 AnyVector& operator=(AnyVector&& other) {
0051 if (&other != this) {
0052 m_vector = other.m_vector;
0053 m_deleter = std::move(other.m_deleter);
0054 other.m_vector = nullptr;
0055 }
0056 return *this;
0057 }
0058
0059
0060 AnyVector(const AnyVector&) = delete;
0061 AnyVector& operator=(const AnyVector&) = delete;
0062
0063
0064 ~AnyVector() {
0065 if (m_vector != nullptr) {
0066 m_deleter();
0067 }
0068 }
0069
0070 private:
0071
0072 AnyVector(void* vector, std::function<void()>&& deleter)
0073 : m_vector{vector}, m_deleter{std::move(deleter)} {}
0074
0075 void* m_vector{nullptr};
0076 std::function<void()> m_deleter;
0077 };
0078
0079
0080
0081
0082 enum class Ordering { SMALLER, EQUAL, GREATER };
0083
0084
0085
0086 template <typename T>
0087 Ordering compare(const T& x, const T& y) {
0088 if (x < y) {
0089 return Ordering::SMALLER;
0090 } else if (x == y) {
0091 return Ordering::EQUAL;
0092 } else {
0093 return Ordering::GREATER;
0094 }
0095 }
0096
0097
0098 template <typename T>
0099 Ordering compareFloat(const T& x, const T& y) {
0100 if (std::isless(x, y)) {
0101 return Ordering::SMALLER;
0102 } else if (std::isgreater(x, y)) {
0103 return Ordering::GREATER;
0104 } else {
0105 return Ordering::EQUAL;
0106 }
0107 }
0108
0109 template <>
0110 Ordering compare(const float& x, const float& y) {
0111 return compareFloat(x, y);
0112 }
0113
0114 template <>
0115 Ordering compare(const double& x, const double& y) {
0116 return compareFloat(x, y);
0117 }
0118
0119
0120
0121 template <typename U>
0122 Ordering compare(const std::vector<U>& v1, const std::vector<U>& v2) {
0123
0124 if (v1.size() < v2.size()) {
0125 return Ordering::SMALLER;
0126 } else if (v1.size() > v2.size()) {
0127 return Ordering::GREATER;
0128 }
0129
0130 else {
0131
0132 for (std::size_t i = 0; i < v1.size(); ++i) {
0133 if (v1[i] < v2[i]) {
0134 return Ordering::SMALLER;
0135 } else if (v1[i] > v2[i]) {
0136 return Ordering::GREATER;
0137 }
0138 }
0139
0140
0141 return Ordering::EQUAL;
0142 }
0143 }
0144
0145
0146
0147
0148
0149
0150 using IndexComparator = std::function<Ordering(std::size_t, std::size_t)>;
0151 using IndexSwapper = std::function<void(std::size_t, std::size_t)>;
0152
0153
0154
0155 void selectionSort(const std::size_t firstIndex, const std::size_t lastIndex,
0156 const IndexComparator& compare, const IndexSwapper& swap) {
0157 for (std::size_t targetIndex = firstIndex; targetIndex < lastIndex;
0158 ++targetIndex) {
0159 std::size_t minIndex = targetIndex;
0160 for (std::size_t readIndex = targetIndex + 1; readIndex <= lastIndex;
0161 ++readIndex) {
0162 if (compare(readIndex, minIndex) == Ordering::SMALLER) {
0163 minIndex = readIndex;
0164 }
0165 }
0166 if (minIndex != targetIndex) {
0167 swap(minIndex, targetIndex);
0168 }
0169 }
0170 }
0171
0172
0173 void quickSort(const std::size_t firstIndex, const std::size_t lastIndex,
0174 const IndexComparator& compare, const IndexSwapper& swap) {
0175
0176
0177 static const std::size_t NON_RECURSIVE_THRESHOLD = 25;
0178 if (lastIndex - firstIndex < NON_RECURSIVE_THRESHOLD) {
0179 selectionSort(firstIndex, lastIndex, compare, swap);
0180 return;
0181 }
0182
0183
0184
0185
0186 std::size_t pivotIndex = firstIndex + (lastIndex - firstIndex) / 2;
0187
0188
0189 std::size_t splitIndex = 0;
0190 {
0191
0192 std::size_t i = firstIndex - 1;
0193 std::size_t j = lastIndex + 1;
0194 while (true) {
0195
0196
0197 do {
0198 i = i + 1;
0199 } while (compare(i, pivotIndex) == Ordering::SMALLER);
0200
0201
0202
0203 do {
0204 j = j - 1;
0205 } while (compare(j, pivotIndex) == Ordering::GREATER);
0206
0207
0208
0209 if (i < j) {
0210
0211 swap(i, j);
0212
0213
0214
0215 if (i == pivotIndex) {
0216 pivotIndex = j;
0217 } else if (j == pivotIndex) {
0218 pivotIndex = i;
0219 }
0220 } else {
0221
0222 splitIndex = j;
0223 break;
0224 }
0225 }
0226 }
0227
0228
0229
0230
0231 if (splitIndex - firstIndex <= lastIndex - splitIndex - 1) {
0232 quickSort(firstIndex, splitIndex, compare, swap);
0233 quickSort(splitIndex + 1, lastIndex, compare, swap);
0234 } else {
0235 quickSort(splitIndex + 1, lastIndex, compare, swap);
0236 quickSort(firstIndex, splitIndex, compare, swap);
0237 }
0238 }
0239
0240
0241
0242
0243
0244
0245
0246 struct BranchComparisonHarness {
0247
0248 std::string branchName;
0249
0250
0251 HomogeneousPair<AnyVector> eventData;
0252
0253
0254
0255
0256 void loadCurrentEvent() { (*m_eventLoaderPtr)(); }
0257
0258
0259
0260
0261 HomogeneousPair<std::pair<IndexComparator, IndexSwapper>> sortHarness;
0262
0263
0264
0265
0266
0267 using TreeComparator = std::function<bool()>;
0268 TreeComparator eventDataEqual;
0269
0270
0271
0272 std::function<void()> dumpEventData;
0273
0274
0275 struct TreeMetadata {
0276 TTreeReader& tree1Reader;
0277 TTreeReader& tree2Reader;
0278 const std::size_t entryCount;
0279 };
0280
0281
0282 class UnsupportedBranchType : public std::exception {};
0283
0284
0285
0286 static BranchComparisonHarness create(TreeMetadata& treeMetadata,
0287 const std::string& branchName,
0288 const EDataType dataType,
0289 const std::string& className) {
0290 switch (dataType) {
0291 case kChar_t:
0292 return BranchComparisonHarness::create<char>(treeMetadata, branchName);
0293 case kUChar_t:
0294 return BranchComparisonHarness::create<unsigned char>(treeMetadata,
0295 branchName);
0296 case kShort_t:
0297 return BranchComparisonHarness::create<short>(treeMetadata, branchName);
0298 case kUShort_t:
0299 return BranchComparisonHarness::create<unsigned short>(treeMetadata,
0300 branchName);
0301 case kInt_t:
0302 return BranchComparisonHarness::create<int>(treeMetadata, branchName);
0303 case kUInt_t:
0304 return BranchComparisonHarness::create<unsigned int>(treeMetadata,
0305 branchName);
0306 case kLong_t:
0307 return BranchComparisonHarness::create<long>(treeMetadata, branchName);
0308 case kULong_t:
0309 return BranchComparisonHarness::create<unsigned long>(treeMetadata,
0310 branchName);
0311 case kULong64_t:
0312 return BranchComparisonHarness::create<unsigned long long>(treeMetadata,
0313 branchName);
0314
0315 case kFloat_t:
0316 return BranchComparisonHarness::create<float>(treeMetadata, branchName);
0317 case kDouble_t:
0318 return BranchComparisonHarness::create<double>(treeMetadata,
0319 branchName);
0320 case kBool_t:
0321 return BranchComparisonHarness::create<bool>(treeMetadata, branchName);
0322 case kOther_t:
0323 if (className.substr(0, 6) == "vector") {
0324 std::string elementType = className.substr(7, className.size() - 8);
0325 return BranchComparisonHarness::createVector(treeMetadata, branchName,
0326 std::move(elementType));
0327 } else {
0328 throw UnsupportedBranchType();
0329 }
0330 default:
0331 throw UnsupportedBranchType();
0332 }
0333 }
0334
0335 private:
0336
0337
0338 template <typename T>
0339 static BranchComparisonHarness create(TreeMetadata& treeMetadata,
0340 const std::string& branchName) {
0341
0342 BranchComparisonHarness result;
0343
0344
0345 result.branchName = branchName;
0346
0347
0348 auto tree1DataStorage = AnyVector::create<T>();
0349 auto tree2DataStorage = AnyVector::create<T>();
0350 result.eventData = std::make_pair(std::move(tree1DataStorage.first),
0351 std::move(tree2DataStorage.first));
0352 std::vector<T>& tree1Data = *tree1DataStorage.second;
0353 std::vector<T>& tree2Data = *tree2DataStorage.second;
0354
0355
0356 tree1Data.reserve(treeMetadata.entryCount);
0357 tree2Data.reserve(treeMetadata.entryCount);
0358
0359
0360 result.m_eventLoaderPtr.reset(
0361 new EventLoaderT<T>{treeMetadata.tree1Reader, treeMetadata.tree2Reader,
0362 branchName, tree1Data, tree2Data});
0363
0364
0365 result.sortHarness = std::make_pair(
0366 std::make_pair(
0367 [&tree1Data](std::size_t i, std::size_t j) -> Ordering {
0368 return compare(tree1Data[i], tree1Data[j]);
0369 },
0370 [&tree1Data](std::size_t i, std::size_t j) {
0371 std::swap(tree1Data[i], tree1Data[j]);
0372 }),
0373 std::make_pair(
0374 [&tree2Data](std::size_t i, std::size_t j) -> Ordering {
0375 return compare(tree2Data[i], tree2Data[j]);
0376 },
0377 [&tree2Data](std::size_t i, std::size_t j) {
0378 std::swap(tree2Data[i], tree2Data[j]);
0379 }));
0380
0381
0382 result.eventDataEqual = [&tree1Data, &tree2Data]() -> bool {
0383 for (std::size_t i = 0; i < tree1Data.size(); ++i) {
0384 if (compare(tree1Data[i], tree2Data[i]) != Ordering::EQUAL) {
0385 return false;
0386 }
0387 }
0388 return true;
0389 };
0390
0391
0392 result.dumpEventData = [&tree1Data, &tree2Data] {
0393 std::cout << "File 1 \tFile 2" << std::endl;
0394 for (std::size_t i = 0; i < tree1Data.size(); ++i) {
0395 std::cout << toString(tree1Data[i]) << " \t"
0396 << toString(tree2Data[i]) << std::endl;
0397 }
0398 };
0399
0400
0401 return std::move(result);
0402 }
0403
0404
0405
0406
0407
0408 class IEventLoader {
0409 public:
0410 virtual ~IEventLoader() = default;
0411 virtual void operator()() = 0;
0412 };
0413
0414 template <typename T>
0415 class EventLoaderT : public IEventLoader {
0416 public:
0417 EventLoaderT(TTreeReader& tree1Reader, TTreeReader& tree2Reader,
0418 const std::string& branchName, std::vector<T>& tree1Data,
0419 std::vector<T>& tree2Data)
0420 : branch1Reader{tree1Reader, branchName.c_str()},
0421 branch2Reader{tree2Reader, branchName.c_str()},
0422 branch1Data(tree1Data),
0423 branch2Data(tree2Data) {}
0424
0425 void operator()() override {
0426 branch1Data.push_back(*branch1Reader);
0427 branch2Data.push_back(*branch2Reader);
0428 }
0429
0430 private:
0431 TTreeReaderValue<T> branch1Reader, branch2Reader;
0432 std::vector<T>& branch1Data;
0433 std::vector<T>& branch2Data;
0434 };
0435
0436 std::unique_ptr<IEventLoader> m_eventLoaderPtr;
0437
0438
0439
0440 static BranchComparisonHarness createVector(TreeMetadata& treeMetadata,
0441 const std::string& branchName,
0442 const std::string elemType) {
0443
0444 #define CREATE_VECTOR__HANDLE_TYPE(type_name) \
0445 if (elemType == #type_name) { \
0446 return BranchComparisonHarness::create<std::vector<type_name>>( \
0447 treeMetadata, branchName); \
0448 }
0449
0450
0451 CREATE_VECTOR__HANDLE_TYPE(bool)
0452
0453
0454 else CREATE_VECTOR__HANDLE_TYPE(float) else CREATE_VECTOR__HANDLE_TYPE(
0455 double)
0456
0457
0458 #define CREATE_VECTOR__HANDLE_INTEGER_TYPE(integer_type_name) \
0459 CREATE_VECTOR__HANDLE_TYPE(integer_type_name) \
0460 else CREATE_VECTOR__HANDLE_TYPE(unsigned integer_type_name)
0461
0462
0463 else CREATE_VECTOR__HANDLE_INTEGER_TYPE(char) else CREATE_VECTOR__HANDLE_INTEGER_TYPE(short) else CREATE_VECTOR__HANDLE_INTEGER_TYPE(
0464 int) else CREATE_VECTOR__HANDLE_INTEGER_TYPE(long) else CREATE_VECTOR__HANDLE_INTEGER_TYPE(long long)
0465
0466
0467 else throw UnsupportedBranchType();
0468 }
0469
0470
0471
0472 template <typename T>
0473 static std::string toString(const T& data) {
0474 std::ostringstream oss;
0475 oss << data;
0476 return oss.str();
0477 }
0478
0479 template <typename U>
0480 static std::string toString(const std::vector<U>& vector) {
0481 std::ostringstream oss{"{ "};
0482 for (const auto& data : vector) {
0483 oss << data << " \t";
0484 }
0485 oss << " }";
0486 return oss.str();
0487 }
0488 };