#include <cstring>
#include <cmath>
#include <algorithm>
#include "../../XGlobal.h"


class VectorBuffer{
    private:
        DTYPE values[32 / sizeof(DTYPE)] = {0};
    public:
        static int size() {
            return 32 / sizeof(DTYPE);
        }
        VectorBuffer() {}
        VectorBuffer(DTYPE val) {
            for (int i = 0; i != size(); i++) {
              values[i] = val;
            }
        }
        static VectorBuffer loadu(const DTYPE* ptr, bool isExp = false, DTYPE power = (DTYPE)1.0F, DTYPE* bias = NULL) {
            int count = 32 / sizeof(DTYPE);
            VectorBuffer vec;
            if(isExp){
                if(bias == NULL){
                    if(power == (DTYPE)1.0){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(*(ptr + i));
                        }
                    } else if(power == (DTYPE)2.0){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp((*(ptr + i)) * (*(ptr + i)));
                        }
                    } else if(power == (DTYPE)0.5){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(std::sqrt(*(ptr + i)));
                        }
                    } else{
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(std::pow(*(ptr + i), power));
                        }
                    }
                }//is bias == NULL
                else{
                    if(power == (DTYPE)1.0){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(*(ptr + i) - bias[i]);
                        }
                    } else if(power == (DTYPE)2.0){
                        for (int i = 0; i != count; i++) {
                          DTYPE value = *(ptr + i) - bias[i];
                          vec.values[i] = (DTYPE)std::exp(value * value);
                        }
                    } else if(power == (DTYPE)0.5){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(std::sqrt(*(ptr + i) - bias[i]));
                        }
                    } else{
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::exp(std::pow(*(ptr + i) - bias[i], power));
                        }
                    }
                }
            }//isExp
            else{
                if(bias == NULL){
                    if(power == (DTYPE)1.0){
                        std::memcpy(vec.values, ptr, count * sizeof(DTYPE));
                    } else if(power == (DTYPE)2.0){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (*(ptr + i)) * (*(ptr + i));
                        }
                    } else if(power == (DTYPE)0.5){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::sqrt(*(ptr + i));
                        }
                    } else{
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::pow(*(ptr + i), power);
                        }
                    }
                }// if bias == NULL
                else{
                    if(power == (DTYPE)1.0){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = *(ptr + i) - bias[i];
                        }
                    } else if(power == (DTYPE)2.0){
                        for (int i = 0; i != count; i++) {
                        DTYPE value = *(ptr + i) - bias[i];
                          vec.values[i] = value * value;
                        }
                    } else if(power == (DTYPE)0.5){
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::sqrt(*(ptr + i) - bias[i]);
                        }
                    } else{
                        for (int i = 0; i != count; i++) {
                          vec.values[i] = (DTYPE)std::pow(*(ptr + i) - bias[i], power);
                        }
                    }
                }
            }
            return vec;
        }
        const DTYPE& operator[](int idx) const {
            return values[idx];
        }
        inline VectorBuffer operator+(const VectorBuffer &a) {
            for (int i = 0; i != a.size(); i++) {
                this->values[i] = a[i] + this->values[i];
            }
            return *this;
        }
        inline VectorBuffer max(const VectorBuffer &a) {
            for (int i = 0; i != a.size(); i++) {
                this->values[i] = std::max(a[i], this->values[i]);
            }
            return *this;
        }
};