* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include "NumberUtil.h"
#include "CurveContainer.h"
namespace Dic::Module::Memory {
CurveView CurveContainer::ComputeCurve(double xMin, double xMax, const std::string &input) {
std::unique_lock<std::mutex> lock(mutex);
CurveView res;
if (key != input || legends.empty()) {
return res;
}
if (!legends.empty() && flatData.size() >= legends.size() && NumberUtil::IsDoubleEqual(xMin, xMax) &&
NumberUtil::IsDoubleEqual(xMin, 0)) {
xMin = flatData[0];
xMax = flatData[flatData.size() - legends.size()];
}
res.title = title;
res.legends = legends;
const uint16_t numBuckets = 1000;
size_t n = flatData.size() / legends.size();
if (n == 0) {
return res;
}
std::vector<size_t> indices;
indices.reserve(n);
for (size_t i = 0; i < n; i++) {
double x = flatData[i * legends.size()];
if (x >= xMin && x <= xMax) {
indices.push_back(i);
}
}
size_t m = indices.size();
if (m == 0) {
return res;
}
if (m <= numBuckets) {
GetAllPoint(res, indices);
return res;
}
uint64_t bucketSize = static_cast<uint64_t>(ceil(static_cast<double>(m) / numBuckets));
for (int b = 0; b < numBuckets; b++) {
std::vector<int> indexRes = ComputeDataIndex(indices, m, bucketSize, b);
AddCompeteData(res, indexRes);
}
return res;
}
void CurveContainer::PutCurve(const std::string &inputKey, CurveView &curve) {
std::unique_lock<std::mutex> lock(mutex);
key = inputKey;
title = curve.title;
legends = curve.legends;
flatData = curve.tempData;
}
bool CurveContainer::Exist(const std::string &inputKey) {
std::unique_lock<std::mutex> lock(mutex);
return inputKey == key;
}
void CurveContainer::Clear() {
std::unique_lock<std::mutex> lock(mutex);
key.clear();
title.clear();
legends.clear();
flatData.clear();
}
std::vector<int> CurveContainer::ComputeDataIndex(
const std::vector<size_t> &indices, size_t m, uint64_t bucketSize, int b) {
uint64_t start = static_cast<size_t>(b) * bucketSize;
uint64_t tempM = m;
uint64_t end = std::min(tempM, start + bucketSize);
std::vector<int> indexRes;
for (size_t col = 1; col <= legends.size() - 1; col++) {
double minVal = std::numeric_limits<double>::infinity();
double maxVal = -std::numeric_limits<double>::infinity();
int minIdx = -1;
int maxIdx = -1;
for (size_t k = start; k < end; k++) {
size_t i = indices[k];
double val = flatData[i * legends.size() + col];
if (std::isnan(val)) {
continue;
}
if (val < minVal) {
minVal = val;
minIdx = static_cast<int>(i);
}
if (val > maxVal) {
maxVal = val;
maxIdx = static_cast<int>(i);
}
}
if (minIdx > maxIdx) {
std::swap(minIdx, maxIdx);
}
if (minIdx >= 0 && std::find(indexRes.begin(), indexRes.end(), minIdx) == indexRes.end()) {
indexRes.emplace_back(minIdx);
}
if (maxIdx >= 0 && std::find(indexRes.begin(), indexRes.end(), maxIdx) == indexRes.end()) {
indexRes.emplace_back(maxIdx);
}
}
return indexRes;
}
void CurveContainer::AddCompeteData(CurveView &res, std::vector<int> &indexRes) {
for (const auto &item : indexRes) {
res.dataLines.emplace_back();
res.dataLines.reserve(legends.size());
uint64_t startIndex = legends.size() * item;
for (size_t i = 0; i < legends.size(); ++i) {
if (std::isnan(flatData[startIndex + i])) {
res.dataLines.back().emplace_back("NULL");
continue;
}
res.dataLines.back().emplace_back(DoubleToString(flatData[startIndex + i]));
}
}
}
void CurveContainer::GetAllPoint(CurveView &res, std::vector<size_t> &indices) {
for (size_t idx : indices) {
res.dataLines.emplace_back();
res.dataLines.reserve(legends.size());
uint64_t start = legends.size() * idx;
for (size_t i = 0; i < legends.size(); ++i) {
if (std::isnan(flatData[start + i])) {
res.dataLines.back().emplace_back("NULL");
continue;
}
res.dataLines.back().emplace_back(DoubleToString(flatData[start + i]));
}
}
}
}