<commit_before>#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <memory>
#include <streambuf>
#include <string>
#include <vector>

#include "shared.hpp"

#ifdef __APPLE__
#include <Accelerate/Accelerate.h>
#else
#include <cblas.h>
#endif

#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
#include <cublas_v2.h>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include "cumatrix.hpp"
#endif

class Matrix;
typedef std::shared_ptr<Matrix> SMatrix;
SMatrix operator*(const SMatrix &m1, const SMatrix &m2);

SMatrix eye(int rows, int cols);

inline int _matrix_index_for(int cols, int row, int col) {
  return row * cols + col;
}

inline int _matrix_index_for_position(int rows, int cols, int position) {
  return _matrix_index_for(cols, (position - 1) % rows, (position - 1) / rows);
}

struct Cholesky {
  SMatrix matrix;
  bool error = false;
};

#if ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
void checkClError(cl_int res) {
  if (res != CL_SUCCESS) {
    cl_int errs[] = {CL_INVALID_COMMAND_QUEUE, CL_INVALID_CONTEXT, CL_INVALID_MEM_OBJECT, CL_INVALID_VALUE, CL_INVALID_EVENT_WAIT_LIST, CL_MEM_OBJECT_ALLOCATION_FAILURE, CL_OUT_OF_HOST_MEMORY};
    std::string strs[] = {"CL_INVALID_COMMAND_QUEUE", "CL_INVALID_CONTEXT", "CL_INVALID_MEM_OBJECT", "CL_INVALID_VALUE", "CL_INVALID_EVENT_WAIT_LIST", "CL_MEM_OBJECT_ALLOCATION_FAILURE", "CL_OUT_OF_HOST_MEMORY"};
    for (auto i = 0; i < 7; ++i) {
      if (res == errs[i]) {
        puts(strs[i].c_str());
        break;
      }
    }
    assert(res == CL_SUCCESS);
  }
}
#endif

#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
void checkCuError(cudaError_t res) {
  if (res != cudaSuccess) {
    printf("CUDA err: %s\n", cudaGetErrorString(res));
    assert(res == cudaSuccess);
  }
}
#endif

class Matrix {
private:
  bool accelerated = false;
#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
  double *accelerate_data = nullptr;
  void inherit(double *accelerate_data) {
    if (this->accelerate_data != nullptr) {
      std::cout << "You cannot inherit twice." << std::endl;
      throw "You cannot inherit twice.";
    }
    this->accelerated = true;
    this->accelerate_data = accelerate_data;
  }
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
  cl_mem accelerate_data = nullptr;
  void inherit(cl_mem accelerate_data) {
    if (this->accelerate_data != nullptr) {
      std::cout << "You cannot inherit twice." << std::endl;
      throw "You cannot inherit twice.";
    }
    this->accelerated = true;
    this->accelerate_data = accelerate_data;
  }
#endif

public:
  int rows, cols;
  double *data;

  friend SMatrix operator+(const SMatrix &A, const SMatrix &B);
  friend SMatrix operator-(const SMatrix &A, const SMatrix &B);

  Matrix(int rows, int cols, bool init) {
    assert(rows >= 0 && cols >= 0);
    this->rows = rows;
    this->cols = cols;
    if (rows == 0 || cols == 0)
      data = nullptr;
    else {
      data = new double[rows * cols];
      if (init) {
        for (auto i = 0; i < rows * cols; ++i) {
          data[i] = 0;
        }
      }
    }
  }

  Matrix(int rows, int cols, double value) {
    assert(rows >= 0 && cols >= 0);
    this->rows = rows;
    this->cols = cols;
    if (rows == 0 || cols == 0)
      data = nullptr;
    else {
      data = new double[rows * cols];
      for (auto i = 0; i < rows * cols; ++i) {
        data[i] = value;
      }
    }
  }

  Matrix(int rows, int cols) : Matrix(rows, cols, true) {}

  template <typename T, std::size_t rowC, std::size_t colC>
  Matrix(T (&arr)[rowC][colC]) : Matrix(rowC, colC) {
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        data[_matrix_index_for(cols, r, c)] = arr[r][c];
      }
    }
  }

  Matrix(const Matrix &matrix) : Matrix(matrix.rows, matrix.cols, false) {
    for (int i = 0; i < rows * cols; ++i) {
      data[i] = matrix.data[i];
    }
  }

  ~Matrix() {
    delete[] data;
#if ACCELERATE_MODE == ACCELERATE_MODE_NONE
    return;
#else
    if (accelerate_data == nullptr) {
      return;
    }
#endif
#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
    checkCuError(cudaFree(accelerate_data));
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
    clReleaseMemObject(accelerate_data);
#else
    assert(false);
#endif
  }

  bool shouldAccelerate(bool linear) {
    if (accelerated) {
      return true;
    }

    const int _1M = 1000000;

#if ACCELERATE_MODE == ACCELERATE_MODE_NONE
    return false;
#elif ACCELERATE_MODE == ACCELERATE_MODE_CUDA
    const int MS_PER_1M_CPU_MULT = 367;
    const int MS_PER_10M_ELEMS = 16;
    return linear ? true : rows * cols >= 204800 && rows * cols <= 6553600;
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL<commit_msg>sync before free<commit_after>#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <memory>
#include <streambuf>
#include <string>
#include <vector>

#include "shared.hpp"

#ifdef __APPLE__
#include <Accelerate/Accelerate.h>
#else
#include <cblas.h>
#endif

#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
#include <cublas_v2.h>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include "cumatrix.hpp"
#endif

class Matrix;
typedef std::shared_ptr<Matrix> SMatrix;
SMatrix operator*(const SMatrix &m1, const SMatrix &m2);

SMatrix eye(int rows, int cols);

inline int _matrix_index_for(int cols, int row, int col) {
  return row * cols + col;
}

inline int _matrix_index_for_position(int rows, int cols, int position) {
  return _matrix_index_for(cols, (position - 1) % rows, (position - 1) / rows);
}

struct Cholesky {
  SMatrix matrix;
  bool error = false;
};

#if ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
void checkClError(cl_int res) {
  if (res != CL_SUCCESS) {
    cl_int errs[] = {CL_INVALID_COMMAND_QUEUE, CL_INVALID_CONTEXT, CL_INVALID_MEM_OBJECT, CL_INVALID_VALUE, CL_INVALID_EVENT_WAIT_LIST, CL_MEM_OBJECT_ALLOCATION_FAILURE, CL_OUT_OF_HOST_MEMORY};
    std::string strs[] = {"CL_INVALID_COMMAND_QUEUE", "CL_INVALID_CONTEXT", "CL_INVALID_MEM_OBJECT", "CL_INVALID_VALUE", "CL_INVALID_EVENT_WAIT_LIST", "CL_MEM_OBJECT_ALLOCATION_FAILURE", "CL_OUT_OF_HOST_MEMORY"};
    for (auto i = 0; i < 7; ++i) {
      if (res == errs[i]) {
        puts(strs[i].c_str());
        break;
      }
    }
    assert(res == CL_SUCCESS);
  }
}
#endif

#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
void checkCuError(cudaError_t res) {
  if (res != cudaSuccess) {
    printf("CUDA err: %s\n", cudaGetErrorString(res));
    assert(res == cudaSuccess);
  }
}
#endif

class Matrix {
private:
  bool accelerated = false;
#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
  double *accelerate_data = nullptr;
  void inherit(double *accelerate_data) {
    if (this->accelerate_data != nullptr) {
      std::cout << "You cannot inherit twice." << std::endl;
      throw "You cannot inherit twice.";
    }
    this->accelerated = true;
    this->accelerate_data = accelerate_data;
  }
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
  cl_mem accelerate_data = nullptr;
  void inherit(cl_mem accelerate_data) {
    if (this->accelerate_data != nullptr) {
      std::cout << "You cannot inherit twice." << std::endl;
      throw "You cannot inherit twice.";
    }
    this->accelerated = true;
    this->accelerate_data = accelerate_data;
  }
#endif

public:
  int rows, cols;
  double *data;

  friend SMatrix operator+(const SMatrix &A, const SMatrix &B);
  friend SMatrix operator-(const SMatrix &A, const SMatrix &B);

  Matrix(int rows, int cols, bool init) {
    assert(rows >= 0 && cols >= 0);
    this->rows = rows;
    this->cols = cols;
    if (rows == 0 || cols == 0)
      data = nullptr;
    else {
      data = new double[rows * cols];
      if (init) {
        for (auto i = 0; i < rows * cols; ++i) {
          data[i] = 0;
        }
      }
    }
  }

  Matrix(int rows, int cols, double value) {
    assert(rows >= 0 && cols >= 0);
    this->rows = rows;
    this->cols = cols;
    if (rows == 0 || cols == 0)
      data = nullptr;
    else {
      data = new double[rows * cols];
      for (auto i = 0; i < rows * cols; ++i) {
        data[i] = value;
      }
    }
  }

  Matrix(int rows, int cols) : Matrix(rows, cols, true) {}

  template <typename T, std::size_t rowC, std::size_t colC>
  Matrix(T (&arr)[rowC][colC]) : Matrix(rowC, colC) {
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        data[_matrix_index_for(cols, r, c)] = arr[r][c];
      }
    }
  }

  Matrix(const Matrix &matrix) : Matrix(matrix.rows, matrix.cols, false) {
    for (int i = 0; i < rows * cols; ++i) {
      data[i] = matrix.data[i];
    }
  }

  ~Matrix() {
    delete[] data;
#if ACCELERATE_MODE == ACCELERATE_MODE_NONE
    return;
#else
    if (accelerate_data == nullptr) {
      return;
    }
#endif
#if ACCELERATE_MODE == ACCELERATE_MODE_CUDA
    cudaDeviceSynchronize();
    checkCuError(cudaFree(accelerate_data));
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
    clReleaseMemObject(accelerate_data);
#else
    assert(false);
#endif
  }

  bool shouldAccelerate(bool linear) {
    if (accelerated) {
      return true;
    }

    const int _1M = 1000000;

#if ACCELERATE_MODE == ACCELERATE_MODE_NONE
    return false;
#elif ACCELERATE_MODE == ACCELERATE_MODE_CUDA
    const int MS_PER_1M_CPU_MULT = 367;
    const int MS_PER_10M_ELEMS = 16;
    return linear ? true : rows * cols >= 204800 && rows * cols <= 6553600;
#elif ACCELERATE_MODE == ACCELERATE_MODE_OPENCL
{'fraction_non_alphanumeric': 0.1324358171571697, 'fraction_numerical': 0.010436234606553955, 'mean_word_length': 3.5417061611374407, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '294777', 'n_tokens_mistral': 3744, 'n_tokens_neox': 3557, 'n_words': 870}