Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ca-npy.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
42#ifndef CA_NPY_H
43#define CA_NPY_H
44
45#include <bit>
46#include <concepts>
47#include <cstdint>
48#include <filesystem>
49#include <fstream>
50#include <ostream>
51#include <sstream>
52#include <string>
53#include <type_traits>
54#include <utility>
55
56#include <ah-errors.H>
57
58#include <ca-frame-stream.H>
59#include <tpl_ca_concepts.H>
60
61namespace Aleph {
62namespace CA {
63
64namespace ca_npy_detail {
65
66template <typename T>
67[[nodiscard]] inline std::string dtype_descr()
68{
69 using U = std::remove_cv_t<T>;
70 static_assert(std::is_arithmetic_v<U>, "write_npy requires an arithmetic cell state");
71
72 if constexpr (std::is_same_v<U, bool>)
73 return "|b1";
74 else if constexpr (std::is_floating_point_v<U>)
75 return (std::endian::native == std::endian::little ? "<f" : ">f") + std::to_string(sizeof(U));
76 else if constexpr (std::is_signed_v<U>)
77 return (sizeof(U) == 1 ? "|i" : (std::endian::native == std::endian::little ? "<i" : ">i"))
78 + std::to_string(sizeof(U));
79 else
80 return (sizeof(U) == 1 ? "|u" : (std::endian::native == std::endian::little ? "<u" : ">u"))
81 + std::to_string(sizeof(U));
82}
83
84template <typename T>
85inline void write_scalar(std::ostream &out, const T &value)
86{
87 using U = std::remove_cv_t<T>;
88 if constexpr (std::is_same_v<U, bool>)
89 {
90 const std::uint8_t byte = value ? 1u : 0u;
91 out.write(reinterpret_cast<const char *>(&byte), 1);
92 }
93 else
94 {
95 out.write(reinterpret_cast<const char *>(&value), static_cast<std::streamsize>(sizeof(U)));
96 }
97}
98
99template <std::size_t Dim, typename Lattice>
100inline void write_payload_rec(std::ostream &out,
101 const Lattice &frame,
102 typename Lattice::coord_type &coord)
103{
104 if constexpr (Dim == Lattice::rank)
105 {
106 write_scalar(out, frame.at(coord));
107 }
108 else
109 {
110 for (ca_size_t i = 0; i < frame.size(Dim); ++i)
111 {
112 coord[Dim] = static_cast<ca_index_t>(i);
113 write_payload_rec<Dim + 1>(out, frame, coord);
114 }
115 }
116}
117
118template <typename Lattice>
119[[nodiscard]] inline std::string shape_tuple(const Lattice &frame)
120{
121 std::ostringstream out;
122 out << '(';
123 for (std::size_t d = 0; d < Lattice::rank; ++d)
124 {
125 if (d != 0)
126 out << ", ";
127 out << frame.size(d);
128 }
129 if constexpr (Lattice::rank == 1)
130 out << ',';
131 out << ')';
132 return out.str();
133}
134
135} // namespace ca_npy_detail
136
150template <typename Lattice>
151inline void write_npy(std::ostream &out, const Lattice &frame)
152{
153 static_assert(LatticeLike<Lattice>, "write_npy requires a LatticeLike frame");
154 using state_t = typename Lattice::state_type;
155 static_assert(std::is_arithmetic_v<state_t>, "write_npy requires arithmetic cell states");
156
157 std::string header = "{'descr': '" + ca_npy_detail::dtype_descr<state_t>()
158 + "', 'fortran_order': False, 'shape': " + ca_npy_detail::shape_tuple(frame)
159 + ", }";
160 constexpr std::size_t prelude = 10;
161 const std::size_t rem = (prelude + header.size() + 1) % 16;
162 const std::size_t padding = rem == 0 ? 0 : 16 - rem;
163 header.append(padding, ' ');
164 header.push_back('\n');
165
166 ah_domain_error_if(header.size() > 65535u) << "write_npy: NPY v1.0 header too large";
167
168 static constexpr unsigned char magic[] = {0x93, 'N', 'U', 'M', 'P', 'Y'};
169 out.write(reinterpret_cast<const char *>(magic), 6);
170 out.put(static_cast<char>(1));
171 out.put(static_cast<char>(0));
172 const std::uint16_t len = static_cast<std::uint16_t>(header.size());
173 out.put(static_cast<char>(len & 0xffu));
174 out.put(static_cast<char>((len >> 8) & 0xffu));
175 out.write(header.data(), static_cast<std::streamsize>(header.size()));
176
177 typename Lattice::coord_type coord{};
178 ca_npy_detail::write_payload_rec<0>(out, frame, coord);
179 ah_runtime_error_if(not out) << "write_npy: output stream failed";
180}
181
184{
185 std::filesystem::path pattern_;
186 std::size_t zero_pad_ = 6;
187
188public:
193 explicit Npy_Frame_Sink(std::filesystem::path path_pattern, const std::size_t zero_pad = 6)
194 : pattern_(std::move(path_pattern)), zero_pad_(zero_pad)
195 {}
196
202 template <typename Lattice>
203 void accept(const std::size_t step, const Lattice &frame)
204 {
205 const std::filesystem::path path = format_step_path(pattern_, step, zero_pad_);
206 if (const auto parent = path.parent_path(); not parent.empty())
207 std::filesystem::create_directories(parent);
208 std::ofstream out(path, std::ios::binary);
209 ah_runtime_error_if(not out) << "Npy_Frame_Sink::accept: cannot open '" << path.string() << "'";
210 write_npy(out, frame);
211 }
212
214 void flush() {}
215};
216
217} // namespace CA
218} // namespace Aleph
219
220#endif // CA_NPY_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:271
size_t size_t int32_t value
Definition ca-c-api.h:116
size_t size_t int32_t * out
Definition ca-c-api.h:120
Directory-backed frame sinks for CA trajectories.
Lattice that adds boundary-aware access on top of a storage.
typename Storage::state_type state_type
typename Storage::coord_type coord_type
static constexpr std::size_t rank
ca_size_t size() const noexcept
state_type at(const coord_type &c) const
Strict access: throws if c is out of range.
Path-pattern sink that writes one .npy file per frame.
Definition ca-npy.H:184
std::filesystem::path pattern_
Definition ca-npy.H:185
Npy_Frame_Sink(std::filesystem::path path_pattern, const std::size_t zero_pad=6)
Build an NPY frame sink.
Definition ca-npy.H:193
std::size_t zero_pad_
Definition ca-npy.H:186
void accept(const std::size_t step, const Lattice &frame)
Write one NPY frame.
Definition ca-npy.H:203
void flush()
NPY frames are written eagerly; this is a no-op.
Definition ca-npy.H:214
Storage + topology that carries the cell values.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
std::string dtype_descr()
Definition ca-npy.H:67
void write_scalar(std::ostream &out, const T &value)
Definition ca-npy.H:85
void write_payload_rec(std::ostream &out, const Lattice &frame, typename Lattice::coord_type &coord)
Definition ca-npy.H:100
std::string shape_tuple(const Lattice &frame)
Definition ca-npy.H:119
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
Definition ca-traits.H:60
std::filesystem::path format_step_path(const std::filesystem::path &pattern, const std::size_t step, const std::size_t zero_pad=6)
Format a step-indexed file path.
std::size_t ca_size_t
Unsigned size component used for extents and counts.
Definition ca-traits.H:63
void write_npy(std::ostream &out, const Lattice &frame)
Write a lattice frame as a NumPy .npy array.
Definition ca-npy.H:151
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
STL namespace.
C++20 concepts for the Cellular Automata module.