9#include <memory_resource>
10#include <nk/value/value.hpp>
26 enum class Kind { Flat, Matrix };
31 bool matrix()
const {
return kind == Kind::Matrix; }
37 double s = sz.toScalar();
39 return SizeSpec{SizeSpec::Kind::Flat, SIZE_MAX, 0, 0};
40 if (s < 0 || !std::isfinite(s))
41 throw Error(std::string(fn) +
": size must be Inf or a non-negative integer");
42 return SizeSpec{SizeSpec::Kind::Flat,
static_cast<size_t>(s), 0, 0};
44 if (sz.numel() == 2) {
47 if (r < 0 || !std::isfinite(r) || std::isinf(r))
48 throw Error(std::string(fn) +
": rows in [m n] must be finite non-negative");
49 size_t rows =
static_cast<size_t>(r);
56 if (c < 0 || !std::isfinite(c))
57 throw Error(std::string(fn)
58 +
": cols in [m n] must be finite non-negative or Inf");
59 cols =
static_cast<size_t>(c);
62 return SizeSpec{SizeSpec::Kind::Matrix, limit, rows, cols};
64 throw Error(std::string(fn) +
": size must be scalar, Inf, or a 2-element vector");
67inline Value shapeFreadOutput(
const double *values,
size_t n,
68 SizeSpec sz, std::pmr::memory_resource *mr)
72 return Value::matrix(0, 0, ValueType::DOUBLE, mr);
73 Value M = Value::matrix(n, 1, ValueType::DOUBLE, mr);
74 std::memcpy(M.doubleDataMut(), values, n *
sizeof(
double));
77 size_t cols_out = (sz.cols == SIZE_MAX)
78 ? (sz.rows == 0 ? 0 : (n + sz.rows - 1) / sz.rows)
80 if (sz.rows == 0 || cols_out == 0)
81 return Value::matrix(sz.rows, cols_out, ValueType::DOUBLE, mr);
82 Value M = Value::matrix(sz.rows, cols_out, ValueType::DOUBLE, mr);
83 std::memcpy(M.doubleDataMut(), values, n *
sizeof(
double));
89inline std::optional<std::pair<int, size_t>> parsePrecision(
const std::string &raw)
92 auto arrow = p.find(
"=>");
93 if (arrow != std::string::npos) p = p.substr(0, arrow);
94 while (!p.empty() && std::isspace(
static_cast<unsigned char>(p.front()))) p.erase(0, 1);
95 while (!p.empty() && std::isspace(
static_cast<unsigned char>(p.back()))) p.pop_back();
97 if (p ==
"uint8" || p ==
"uchar" || p ==
"char")
return std::make_pair(0,
size_t{1});
98 if (p ==
"int8" || p ==
"schar")
return std::make_pair(1,
size_t{1});
99 if (p ==
"uint16")
return std::make_pair(0,
size_t{2});
100 if (p ==
"int16")
return std::make_pair(1,
size_t{2});
101 if (p ==
"uint32")
return std::make_pair(0,
size_t{4});
102 if (p ==
"int32")
return std::make_pair(1,
size_t{4});
103 if (p ==
"uint64")
return std::make_pair(0,
size_t{8});
104 if (p ==
"int64")
return std::make_pair(1,
size_t{8});
105 if (p ==
"single" || p ==
"float32" || p ==
"real*4")
return std::make_pair(2,
size_t{4});
106 if (p ==
"double" || p ==
"float64" || p ==
"real*8")
return std::make_pair(2,
size_t{8});
112inline bool parseEndian(
const std::string &raw,
const char *fn)
115 lo.reserve(raw.size());
116 for (
char c : raw) lo +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
117 if (lo ==
"b" || lo ==
"ieee-be" || lo ==
"ieee-be.l64")
return true;
118 if (lo ==
"l" || lo ==
"ieee-le" || lo ==
"ieee-le.l64"
119 || lo ==
"n" || lo ==
"native")
121 throw Error(std::string(fn) +
": unsupported machine format '" + raw +
"'");
124inline void byteSwap(
char *p,
size_t n)
126 for (
size_t i = 0, j = n - 1; i < j; ++i, --j) std::swap(p[i], p[j]);
Core MATLAB-compatible multidimensional array and scalar value type.