//
// Created by matrixai on 4/2/24.
//

#include "Utils.h"


namespace ai_matrix
{
    Utils *Utils::ins = nullptr;
    Utils::GarbageCollector Utils::gc;
    std::mutex Utils::mx;

    Utils *Utils::getins()
    {
        //双层锁，确保线程安全
        if (ins == nullptr)
        {
            std::lock_guard<std::mutex> guard(mx); //防止异常发生不能解锁
            if (ins == nullptr)
            {
                ins = new Utils();
            }
        }
        return ins;
    }

    float Utils::getMean(const std::vector<float> &data)
    {
        int size = data.size();

        if (size == 0)
        {
            return 0;
        }

        float sum = 0;
        for (int i = 0; i < size; i++)
        {
            sum += data[i];
        }
        return sum / size;
    }

    float Utils::getMax(const std::vector<float> &data)
    {
        int size = data.size();

        if (size == 0)
        {
            return 0;
        }

        float max = 0;
        for (int i = 0; i < size; i++)
        {
            if (i == 0)
            {
                max = data[i];
            }
            else if (data[i] > max)
            {
                max = data[i];
            }
        }
        return max;
    }

    float Utils::getMin(const std::vector<float> &data)
    {
        int size = data.size();

        if (size == 0)
        {
            return 0;
        }

        float min = 0;
        for (int i = 0; i < size; i++)
        {
            if (i == 0)
            {
                min = data[i];
            }
            else if (data[i] < min)
            {
                min = data[i];
            }
        }
        return min;
    }

    float Utils::getMedian(const std::vector<float> &data)
    {
        if (data.size() < 2)
        {
            return 0;
        }

        std::vector<float> data_tmp;

        int n = data.size();
        for (int i = 0; i < n; i++)
        {
            data_tmp.push_back(data[i]);
        }

        std::sort(data_tmp.begin(), data_tmp.end(), std::less<float>());

        if (n % 2 == 0)
        {
            return (data_tmp[n / 2] + data_tmp[n / 2 - 1]) / 2;
        }
        else
        {
            return data_tmp[(n - 1) / 2];
        }
    }

    bool Utils::contains_vec(const std::vector<std::string> &vec, std::string x) {
        return count(vec.begin(), vec.end(), x) > 0;
    }

}
