Sync public subset from Flux (private)

This commit is contained in:
Gitea CI
2025-10-06 20:14:13 +00:00
parent 272e77c536
commit b2d00af0e1
390 changed files with 152131 additions and 0 deletions

249
include/utils/matrix.h Normal file
View File

@@ -0,0 +1,249 @@
#ifndef _matrix_n_
#define _matrix_n_
#include "./utils/vector.h"
#include "./utils/random.h"
#ifdef _OPENMP
#include <omp.h>
#endif
#include <initializer_list>
#include <iomanip>
namespace utils{
//#######################################
//# MATRIX TYPE #
//# Backed by utils::Vector<T> #
//#######################################
template <typename T>
class Matrix{
public:
Matrix() : rows_(0), cols_(0), data_() {} // Default constructor
// Constructor to initialize matrix with rows × cols and a fill value
Matrix(uint64_t rows, uint64_t cols, const T& value = T())
: rows_(rows), cols_(cols), data_(rows * cols, value) {}
// Construct from list-of-lists:
// utils::Mf A{{1,2,3}, {4,5,6}};
Matrix(std::initializer_list<std::initializer_list<T>> init) {
rows_ = static_cast<uint64_t>(init.size());
if (rows_ > 0) {
cols_ = static_cast<uint64_t>(init.begin()->size());
} else {
cols_ = 0;
}
// Validate all rows have the same length
for (const auto& row : init) {
if (row.size() != cols_) {
throw std::runtime_error("Matrix(list of lists): ragged rows");
}
}
data_.resize(rows_ * cols_);
uint64_t r = 0;
for (uint64_t i = 0; i < init.size(); ++i, ++r){
const std::initializer_list<T>& row = *(init.begin() + i);
uint64_t c = 0;
for (uint64_t j = 0; j < row.size(); ++j, ++c){
const T& val = *(row.begin() + j);
data_[r * cols_ + c] = val;
}
}
}
// Assign from list-of-lists after default construction:
// utils::Md M; M = {{1,2},{3,4}};
Matrix& operator=(std::initializer_list<std::initializer_list<T>> init) {
// Set sizes
rows_ = static_cast<uint64_t>(init.size());
if (rows_ > 0) {
cols_ = static_cast<uint64_t>((init.begin())->size());
} else {
cols_ = 0;
}
// Validate: all rows must have same length
for (uint64_t i = 0; i < rows_; ++i) {
const std::initializer_list<T>& row = *(init.begin() + i);
if (row.size() != cols_) {
throw std::runtime_error("Matrix(list of lists): ragged rows");
}
}
// Allocate storage
data_.resize(rows_ * cols_);
// Copy data row by row
for (uint64_t i = 0; i < rows_; ++i) {
const std::initializer_list<T>& row = *(init.begin() + i);
for (uint64_t j = 0; j < cols_; ++j) {
const T& val = *(row.begin() + j);
data_[i * cols_ + j] = val;
}
}
return *this;
}
//# MATRIX: basic properties #
uint64_t rows() const noexcept {return rows_;}
uint64_t cols() const noexcept {return cols_;}
//# MATRIX: element access (fast; unchecked) #
T& operator()(uint64_t i, uint64_t j) { return data_[i * cols_ + j]; }
const T& operator()(uint64_t i, uint64_t j) const { return data_[i * cols_ + j]; }
//# MATRIX: data access #
T* data() noexcept { return data_.data(); }
const T* data() const noexcept { return data_.data(); }
void resize(uint64_t rows, uint64_t cols, const T& value = T(0)){
rows_ = rows;
cols_ = cols;
data_.resize(rows_*cols_, value);
}
void random(uint64_t rows, uint64_t cols, const T& lower, const T& higher){
rows_ = rows;
cols_ = cols;
data_.resize(rows_*cols_, 0);
// Copy data row by row
for (uint64_t i = 0; i < rows_; ++i) {
for (uint64_t j = 0; j < cols_; ++j) {
data_[i * cols_ + j] = utils::random(lower, higher);
}
}
}
//# MATRIX: row helpers (copy out) #
// Read whole row as an owning Vector<T>
// utils::Vf v = M.get_row(2);
Vector<T> get_row(const uint64_t row) const {
if (row >= rows_) {
throw std::out_of_range("Matrix::get_row -> row index");
}
utils::Vector<T> result(cols_, T{});
for (uint64_t i = 0; i < cols_; ++i){
result[i] = data_[row * cols_ + i];
}
return result;
}
//# MATRIX: row helpers (copy in) #
// Assign a whole Vector<T> to a row
// M.set_row(2) = v;
void set_row(const uint64_t row, const Vector<T>& vector){
if (row >= rows_) {
throw std::out_of_range("Matrix::set_row -> row index");
}
if (vector.size() != cols_){
throw std::runtime_error("Matrix::set_row -> size mismatch");
}
for (uint64_t i = 0; i < cols_; ++i){
data_[row * cols_ + i] = vector[i];
}
}
//# MATRIX: col helpers (copy out) #
// Read whole col as an owning Vector<T>
// utils::Vf v = M.get_col(2);
Vector<T> get_col(const uint64_t col) const {
if (col >= cols_) {
throw std::out_of_range("Matrix::get_col -> col index");
}
utils::Vector<T> result(rows_, T{});
for (uint64_t i = 0; i < rows_; ++i){
result[i] = data_[i * cols_ + col];
}
return result;
}
//# MATRIX: col helpers (copy in) #
// Assign a whole Vector<T> to a col
// M.set_col(2) = v;
void set_col(const uint64_t col, const Vector<T>& vector){
if (col >= cols_) {
throw std::out_of_range("Matrix::set_col -> col index");
}
if (vector.size() != rows_){
throw std::runtime_error("Matrix::set_col -> size mismatch");
}
for (uint64_t i = 0; i < rows_; ++i){
data_[i * cols_ + col] = vector[i];
}
}
void swap_rows(uint64_t a, uint64_t b){
if (a >= rows_ || b >= rows_) {
throw std::out_of_range("Matrix::swap_rows -> row index");
}
if (a == b){
return;
}
for (uint64_t i = 0; i < cols_; ++i){
T tmp = data_[a * cols_ + i];
data_[a * cols_ + i] = data_[b * cols_ + i];
data_[b * cols_ + i] = tmp;
}
}
void swap_cols(uint64_t a, uint64_t b){
if (a >= cols_ || b >= cols_) {
throw std::out_of_range("Matrix::swap_cols -> col index");
}
if (a == b){
return;
}
for (uint64_t i = 0; i < rows_; ++i){
T tmp = data_[i * cols_ + a];
data_[i * cols_ + a] = data_[i * cols_ + b];
data_[i * cols_ + b] = tmp;
}
}
inline friend std::ostream& operator<<(std::ostream& out, const Matrix& M) {
out << "[";
for (uint64_t i = 0; i < M.rows_; ++i) {
out << "[";
for (uint64_t j = 0; j < M.cols_; ++j) {
out << std::setw(4) << std::setprecision(3) << std::fixed << M(i, j);
if (j + 1 < M.cols_) out << ", ";
}
out << "]";
if (i + 1 < M.rows_) out << ",\n ";
}
out << "]";
return out;
}
void print() const {
std::cout << *this << std::endl;
}
private:
uint64_t rows_, cols_;
std::vector<T> data_;
};
typedef Matrix<int64_t> Mi;
typedef Matrix<float> Mf;
typedef Matrix<double> Md;
}
#endif // _matrix_n_