7#include <kernel/geometry/voxel_map.hpp>
19 typedef std::int64_t
i64;
21 typedef std::uint64_t
u64;
33 _out_of_bounds_value(true),
39 _create_stage(
other._create_stage),
40 _bbox_min(
other._bbox_min),
41 _bbox_max(
other._bbox_max),
42 _num_points(
other._num_points),
43 _stride_line(
other._stride_line),
44 _stride_plane(
other._stride_plane),
45 _num_lines(
other._num_lines),
46 _num_planes(
other._num_planes),
47 _voxel_map(std::forward<std::vector<char>>(
other._voxel_map)),
48 _out_of_bounds_value(
other._out_of_bounds_value),
49 _coverage(
other._coverage)
61 _bbox_max =
other._bbox_max;
81 XASSERTM(x_min < x_max,
"invalid X dimensions for voxel map bounding box");
82 XASSERTM(y_min < y_max,
"invalid Y dimensions for voxel map bounding box");
88 XASSERTM(
_bbox_min[0u] + 1 < _bbox_max[0u],
"bounding box is too small in X dimension");
89 XASSERTM(
_bbox_min[1u] + 1 < _bbox_max[1u],
"bounding box is too small in Y dimension");
94 XASSERTM(x_min < x_max,
"invalid X dimensions for voxel map bounding box");
95 XASSERTM(y_min < y_max,
"invalid Y dimensions for voxel map bounding box");
96 XASSERTM(z_min < z_max,
"invalid Z dimensions for voxel map bounding box");
103 XASSERTM(
_bbox_min[0u] + 1 < _bbox_max[0u],
"bounding box is too small in X dimension");
104 XASSERTM(
_bbox_min[1u] + 1 < _bbox_max[1u],
"bounding box is too small in Y dimension");
105 XASSERTM(
_bbox_min[2u] + 1 < _bbox_max[2u],
"bounding box is too small in Z dimension");
129 XASSERTM(max_res > 1E-12,
"invalid resolution for voxel map");
138#ifdef FEAT_HAVE_FPARSER
142 XABORTM(
"FEAT is not build and lined against FPARSER third-party library!");
151#ifdef FEAT_HAVE_FPARSER
155 XABORTM(
"FEAT is not build and lined against FPARSER third-party library!");
164 XASSERTM(
_bbox_min[2u] < _bbox_max[2u],
"CGAL OFF voxel map creation is only available in 3D");
165 std::stringstream sstr;
172 XASSERTM(
_bbox_min[2u] < _bbox_max[2u],
"CGAL OFF voxel map creation is only available in 3D");
178 XABORTM(
"FEAT is not build and linked against CGAL third-party library!");
188 std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary);
189 if(!ofs.is_open() || !ofs.good())
192 return write(ofs, compress_block_size, compress_level);
197 std::size_t written = 0u;
201 memset(&header, 0,
sizeof(header));
203 header.header_size =
sizeof(header);
205 header.max_x = _bbox_max[0];
209 header.max_y = _bbox_max[1];
213 header.max_z = _bbox_max[2];
223 if(compress_block_size > 0u)
225 XASSERTM(compress_block_size < 1024u,
"maximum compression block size is 1024 MB");
228 header.planes_per_block = (compress_block_size*1024ull*1024ull) /
_stride_plane;
229 XASSERTM(header.planes_per_block > 0ull,
"compression block size is to small to hold a single plane!");
231 header.num_blocks = (
_num_planes + header.planes_per_block - 1u) / header.planes_per_block;
232 XASSERTM(header.num_blocks > 0ull,
"invalid number of compression blocks!");
237 os.write(
reinterpret_cast<char*
>(&header),
sizeof(header));
238 written +=
sizeof(header);
241 if(header.num_blocks == 0ull)
244 os.write(
reinterpret_cast<const char*
>(
_voxel_map.data()), std::streamsize(header.stride_volume));
245 return WriteResult(written + header.stride_volume);
250 XASSERTM(header.planes_per_block *
_stride_plane < 1073741824ull,
"voxel map plane compression block size is too big");
253 std::vector<std::vector<char>> compress_buffers(header.num_blocks);
256 std::vector<u64> compress_blocks(header.num_blocks, 0u);
265 FEAT_PRAGMA_OMP(parallel
for schedule(dynamic,1) reduction(+:failures))
266 for(
u64 iblock = 0; iblock < header.num_blocks; ++iblock)
269 u64 first_plane = iblock * header.planes_per_block;
273 u64 buffer_size =
u64(::compressBound(uLong(block_bytes)));
276 compress_buffers[iblock].resize(buffer_size);
279 uLongf dest_size = uLongf(buffer_size);
282 int rtn = ::compress2(
reinterpret_cast<Bytef*
>(compress_buffers[iblock].data()), &dest_size,
293 compress_blocks[iblock] =
u64(dest_size);
297 XASSERTM(failures == 0,
"ZLIB failed to compress at least one plane block!");
300 os.write(
reinterpret_cast<const char*
>(compress_blocks.data()), std::streamsize(compress_blocks.size() *
sizeof(
u64)));
301 written += compress_blocks.size() *
sizeof(
u64);
304 u64 compress_size = 0u;
305 for(std::size_t i(0); i < compress_buffers.size(); ++i)
307 os.write(
reinterpret_cast<const char*
>(compress_buffers[i].data()), std::streamsize(compress_blocks[i]));
308 written += compress_blocks[i];
309 compress_size += compress_blocks[i];
313 return WriteResult(written, compress_block_size,
u64(compress_level), compress_buffers.size(), compress_size);
316 (void)compress_block_size;
317 (void)compress_level;
326 return read(stream, filename);
333 memset(&header, 0,
sizeof(header));
336 if(!is.read(
reinterpret_cast<char*
>(&header),
sizeof(header)).good())
339 u64 bytes_read =
sizeof(header);
350 if((header.num_x > 0u) && (header.max_x <= header.min_x))
352 if((header.num_y > 0u) && (header.max_y <= header.min_y))
354 if((header.num_z > 0u) && (header.max_z <= header.min_z))
356 if((header.num_x == 0u) && (header.max_x != header.min_x))
358 if((header.num_y == 0u) && (header.max_y != header.min_y))
360 if((header.num_z == 0u) && (header.max_z != header.min_z))
362 if(header.stride_line*8u < header.num_x)
364 if((header.stride_line & 0xF) != 0)
366 if(header.stride_plane < header.num_y * header.stride_line)
368 if((header.stride_plane & 0xF) != 0)
370 if(header.stride_volume < header.num_z * header.stride_plane)
372 if((header.stride_volume & 0xF) != 0)
377 _bbox_max[0u] = header.max_x;
379 _bbox_max[1u] = header.max_y;
381 _bbox_max[2u] = header.max_z;
395 if(header.num_blocks == 0u)
398 if(!is.read(
_voxel_map.data(), std::streamsize(header.stride_volume)).good())
399 throw VoxelMapFileError(filename,
"Failed to read uncompressed voxel map buffer");
400 bytes_read +=
u64(is.gcount());
408 std::vector<u64> blocks(header.num_blocks);
409 if(!is.read(
reinterpret_cast<char*
>(blocks.data()), std::streamsize(header.num_blocks *
sizeof(
u64))).good())
410 throw VoxelMapFileError(filename,
"Failed to read voxel map compression blocks");
411 bytes_read +=
u64(is.gcount());
414 std::vector<std::size_t> buffer_offset(header.num_blocks + 1u);
415 buffer_offset[0u] = 0u;
416 for(std::size_t i(0); i < blocks.size(); ++i)
417 buffer_offset[i+1u] = buffer_offset[i] + blocks[i];
420 std::vector<char> compression_buffer(buffer_offset.back());
421 if(!is.read(compression_buffer.data(), std::streamsize(compression_buffer.size())).good())
423 bytes_read +=
u64(is.gcount());
429 FEAT_PRAGMA_OMP(parallel
for schedule(dynamic,1) reduction(+:failures))
430 for(
u64 iblock = 0; iblock < header.num_blocks; ++iblock)
432 u64 first_plane = iblock * header.planes_per_block;
434 u64 compress_size = blocks[iblock];
437 uLongf dest_size = uLongf(block_bytes);
439 reinterpret_cast<const Bytef*
>(&compression_buffer[buffer_offset[iblock]]), uLong(compress_size));
449 XASSERTM(failures == 0,
"ZLIB failed to decompress at least one plane block!");
450 return ReadResult(bytes_read, header.num_blocks, compression_buffer.size());
452 XABORTM(
"Cannot read compressed voxel map file, because FEAT was compiled without the ZLIB third-party library");
463 std::ofstream ofs(filename, std::ios_base::binary);
471 std::ofstream ofs(filename, std::ios_base::binary);
483 XASSERTM(depth <= 20000,
"render width is too big for BMP export!");
484 for(
i64 iplane(0); iplane <
i64(depth); ++iplane)
487 std::ofstream ofs(filename, std::ios_base::binary);
497 std::ofstream ofs(filename, std::ios_base::binary);
524 FEAT_PRAGMA_OMP(parallel
for reduction(+:count))
525 for(
u64 i = 0u; i < n; ++i)
527 for(
int k = 0; k < 8; ++k)
636 return (this->
_voxel_map[(xidx >> 3)] >> (xidx & 0x7)) & 0x1;
643 if((xidx|yidx) == ~
u64(0))
653 if((xidx|yidx|zidx) == ~
u64(0))
661 for(
u64 xidx(box_min[0]); xidx <= box_max[0]; ++xidx)
663 if((this->
_voxel_map[(xidx >> 3)] >> (xidx & 0x7)) & 0x1)
671 for(
u64 yidx(box_min[1]); yidx <= box_max[1]; ++yidx)
673 for(
u64 xidx(box_min[0]); xidx <= box_max[0]; ++xidx)
684 for(
u64 zidx(box_min[2]); zidx <= box_max[2]; ++zidx)
686 for(
u64 yidx(box_min[1]); yidx <= box_max[1]; ++yidx)
689 for(
u64 xidx(box_min[0]); xidx <= box_max[0]; ++xidx)
773 Real v0 = v01 + (v00 - v01) * s0;
774 Real v1 = v10 + (v11 - v10) * s1;
778 if(xidx1 == xidx0 + 1)
779 return Real(0.5) * (v0 + v1);
820 Real result =
Real(0.5) * (s0*v0 + s1*v1);
823 if(xidx1 == xidx0 + 2)
836 for(
i64 i = xidx0+2; i < xidx1-1; ++i)
840 return result / (
Real(xidx1 - xidx0 - 2) + s0 + s1);
866 Real v0 = v01 + (v00 - v01) * s0;
867 Real v1 = v10 + (v11 - v10) * s1;
871 if(yidx1 == yidx0 + 1)
872 return Real(0.5) * (v0 + v1);
877 Real result =
Real(0.5) * (s0*v0 + s1*v1);
880 if(yidx1 == yidx0 + 2)
883 result +=
Real(0.5) * (s0 + s1) *
_sample_box_1d(px0, px1, xidx0, xidx1, yidx0+1, zidx);
893 for(
i64 i = yidx0+2; i < yidx1-1; ++i)
897 return result / (
Real(yidx1 - yidx0 - 2) + s0 +s1);
900 Real VoxelMap::_sample_box_3d(
i64 px0,
i64 px1,
i64 py0,
i64 py1,
i64 pz0,
i64 pz1,
i64 xidx0,
i64 xidx1,
i64 yidx0,
i64 yidx1,
i64 zidx0,
i64 zidx1)
const
923 Real v0 = v01 + (v00 - v01) * s0;
924 Real v1 = v10 + (v11 - v10) * s1;
928 if(zidx1 == zidx0 + 1)
929 return Real(0.5) * (v0 + v1);
934 Real result =
Real(0.5) * (s0*v0 + s1*v1);
937 if(zidx1 == zidx0 + 2)
940 result +=
Real(0.5) * (s0 + s1) *
_sample_box_2d(px0, px1, py0, py1, xidx0, xidx1, yidx0, yidx1, zidx0+1);
945 result +=
Real(0.5) * (s0 +
Real(1)) *
_sample_box_2d(px0, px1, py0, py1, xidx0, xidx1, yidx0, yidx1, zidx0+1);
946 result +=
Real(0.5) * (s1 +
Real(1)) *
_sample_box_2d(px0, px1, py0, py1, xidx0, xidx1, yidx0, yidx1, zidx1-1);
950 for(
i64 i = zidx0+2; i < zidx1-1; ++i)
951 result +=
_sample_box_2d(px0, px1, py0, py1, xidx0, xidx1, yidx0, yidx1, i);
954 return result / (
Real(zidx1 - zidx0 - 2) + s0 +s1);
969 return _sample_box_2d(box_min[0], box_max[0], box_min[1], box_max[1],
982 return _sample_box_3d(box_min[0], box_max[0], box_min[1], box_max[1], box_min[2], box_max[2],
987 return _sample_box_2d(box_min[0], box_max[0], box_min[1], box_max[1],
1000 const u64 n =
u64(mask.size());
1002 for(u64 i(0); i < n; ++i)
1004 _voxel_map[off + (i >> 3)] |=
char(mask[i] != 0) << (i & 0x7);
1016 typedef std::uint16_t u16;
1017 typedef std::uint32_t u32;
1024 u32 stride = ((width + 31u) & ~31u) >> 3;
1029 os.write((
char*)&magic, 2u);
1031 u32 filesize = 62u + height * stride;
1032 os.write((
char*)&filesize, 4u);
1035 os.write((
char*)&zeros, 4u);
1037 u32 offbits = 54u + 2u*4u;
1038 os.write((
char*)&offbits, 4u);
1043 os.write((
char*)&bisize, 4u);
1045 os.write((
char*)&width, 4u);
1046 os.write((
char*)&height, 4u);
1049 os.write((
char*)&planes, 2u);
1052 os.write((
char*)&bitcount, 2u);
1054 os.write((
char*)&zeros, 4u);
1056 u32 size_image = height * stride;
1057 os.write((
char*)&size_image, 4u);
1059 u32 px_per_m = 3780;
1060 os.write((
char*)&px_per_m, 4u);
1061 os.write((
char*)&px_per_m, 4u);
1064 os.write((
char*)&clr_used, 4u);
1066 os.write((
char*)&zeros, 4u);
1069 u32 clr_black = 0u, clr_white = ~u32(0);
1070 os.write((
char*)&clr_black, 4u);
1071 os.write((
char*)&clr_white, 4u);
1073 std::vector<char> linebuffer(stride);
1074 char* oline = linebuffer.data();
1077 for(u32 i(0); i < height; ++i)
1080 for(u32 j(0); j < stride; ++j)
1081 for(
int k(0); k < 8; ++k)
1082 (oline[j] <<= 1) |= ((iline[j] >> k) & 1);
1083 os.write(oline, stride);
1091 XASSERTM(width <= 20000,
"render width is too big for BMP export!");
1092 XASSERTM(height <= 20000,
"render width is too big for BMP export!");
1093 XASSERTM(box_min_z < box_max_z,
"invalid depth for voxel map render!");
1095 XASSERTM(box_max_z <= _bbox_max[2],
"invalid depth for voxel map render!");
1097 typedef std::uint8_t u8;
1098 typedef std::uint16_t u16;
1099 typedef std::uint32_t u32;
1102 u32 width2 = u32(width);
1103 u32 height2 = u32(height);
1106 u32 stride = ((width2*8 + 31u) & ~31u) >> 3;
1111 os.write((
char*)&magic, 2u);
1113 u32 filesize = 54u + height2 * stride + 256u*4u;
1114 os.write((
char*)&filesize, 4u);
1117 os.write((
char*)&zeros, 4u);
1119 u32 offbits = 54u + 256u*4u;
1120 os.write((
char*)&offbits, 4u);
1125 os.write((
char*)&bisize, 4u);
1127 os.write((
char*)&width2, 4u);
1128 os.write((
char*)&height2, 4u);
1131 os.write((
char*)&planes, 2u);
1134 os.write((
char*)&bitcount, 2u);
1136 os.write((
char*)&zeros, 4u);
1138 u32 size_image = height2 * stride;
1139 os.write((
char*)&size_image, 4u);
1141 u32 px_per_m = 3780;
1142 os.write((
char*)&px_per_m, 4u);
1143 os.write((
char*)&px_per_m, 4u);
1145 u32 clr_used = 256u;
1146 os.write((
char*)&clr_used, 4u);
1148 os.write((
char*)&zeros, 4u);
1151 std::vector<u32> colors(256);
1152 for(u32 i = 0u; i < 256u; ++i)
1154 colors[i] = i | (i << 8) | (i << 16);
1156 os.write((
char*)colors.data(), 256u*4u);
1158 std::vector<u8> linebuffer(stride);
1159 u8* oline = linebuffer.data();
1162 std::array<i64, 3u> box_min, box_max;
1163 box_min[2u] = box_min_z;
1164 box_max[2u] = box_max_z;
1167 for(
Index i(0); i < height; ++i)
1171 for(
Index j(0); j < width; ++j)
1176 oline[j] = (w <= 0.0 ? 0 : (w >= 255.0 ? 255 : u8(w)));
1178 os.write((
char*)oline, stride);
#define ASSERT(expr)
Debug-Assertion macro definition.
#define XABORTM(msg)
Abortion macro definition with custom message.
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
static void read_common(std::stringstream &stream, const String &filename, const Dist::Comm &comm, int root_rank=0)
Reads a common text file for all ranks.
File-Not-Created exception.
Wrapper for the CGAL Library.
Voxel masker implementation for CGAL wrapper.
helper class for read function result
helper class for write function result
Error class for VoxelMap related file errors.
i64 _map_coord_idx_lower(i64 xyz, std::size_t sdim) const
Maps a unit coordinate to a X-/Y-/Z-index of the lower voxel in the voxel map.
bool _check_point_nearest(const std::array< i64, 1 > &p) const
Checks the nearest voxel map entry for a given 1D point.
static constexpr u64 header_size
size of voxel map header in bytes
Real _sample_box_1d(i64 px0, i64 px1, i64 xidx0, i64 xidx1, i64 yidx=i64(0), i64 zidx=i64(0)) const
Helper function for _sample_box: samples a 1D edge in X line.
Real _calc_sample_rate(i64 xyz, i64 idx, std::size_t sdim) const
Helper function for _sample_voxel_map_Xd: compute the sample rate in a given dimension.
std::vector< char > _voxel_map
the actual voxel map; its size may be larger than necessary due to padding
void export_to_bmp(const String &filename_prefix) const
Exports the voxel map to a sequence of monochrome BMP image files.
bool _check_point(i64 xidx, i64 yidx, i64 zidx) const
Helper function for _sample_point: checks a single voxel point value.
WriteResult write(const String &filename, const u64 compress_block_size=128u, const int compress_level=9) const
Writes the voxel map into a file that can later be read in.
void render_to_bmp(const String &filename_prefix, Index width, Index height, Index depth) const
Renders the voxel map to a sequence of gray-scale BMP image files.
void _export_plane_to_bmp(std::ostream &os, u64 plane) const
Exports a single plane of the voxel map to a monochrome BMP image file.
i64 _map_coord_idx_upper(i64 xyz, std::size_t sdim) const
Maps a unit coordinate to a X-/Y-/Z-index of the upper voxel in the voxel map.
Real _sample_point_1d_y(i64 py, i64 xidx, i64 yidx, i64 zidx=i64(0)) const
Helper function for _sample_point: samples a 1D edge in Y-parallel line.
Real _sample_box_2d(i64 px0, i64 px1, i64 py0, i64 py1, i64 xidx0, i64 xidx1, i64 yidx0, i64 yidx1, i64 zidx=i64(0)) const
Helper function for _sample_box: samples a 2D rectangle in XY plane.
std::array< u64, 3u > _num_points
number of points in each dimension
Real _sample_box_3d(i64 px0, i64 px1, i64 py0, i64 py1, i64 pz0, i64 pz1, i64 xidx0, i64 xidx1, i64 yidx0, i64 yidx1, i64 zidx0, i64 zidx1) const
Helper function for _sample_box: samples a 3D cuboid in XYZ volume.
void _compress_voxel_map_line(const std::vector< int > &mask, const u64 line)
Compresses a voxel map line into the voxel map.
u64 _compute_domain_coverage() const
Computes the domain coverage of the voxel map.
void export_plane_to_bmp(const String &filename, Real z_coord) const
Exports a single plane of the voxel map to a monochrome BMP image file.
void _compute_voxel_map(const Dist::Comm &comm, VoxelMasker< CoordType, dim_ > &masker, bool gather_to_all)
Computes the voxel map for the domain.
static constexpr u64 magic_number
voxel map magic number
bool check_point(u64 ix, u64 iy=0u, u64 iz=0u) const
Returns the value of a specific voxel point in the voxel map.
Real get_bounding_box_volume() const
Returns the volume of the 1D/2D/3D voxel map bounding box.
u64 _num_planes
number of planes; 2D = 1; 3D = num_points[3]
std::uint64_t u64
unsigned 64-bit integer type
Real _sample_point_1d_z(i64 pz, i64 xidx, i64 yidx, i64 zidx) const
Helper function for _sample_point: samples a 1D edge in Z-parallel line.
Index get_num_voxels() const
Returns the total number of voxels in the voxel map.
void set_resolution(Real max_res)
Sets the resolution for the voxel map, i.e. the maximum voxel size in each dimension.
u64 _stride_line
stride of a single voxel line in X dimension
void compute_map_from_formula_3d(const Dist::Comm &comm, const String &formula, bool gather_to_all=true)
Creates the voxel map based on a 3D formula by utilizing MPI parallelization.
void set_num_points(Index num_x, Index num_y, Index num_z=0u)
Sets the number of points of the voxel map in each dimension.
virtual ~VoxelMap()
virtual destructor
void render_plane_to_bmp(const String &filename, Index width, Index height, Real z_min, Real z_max) const
Renders a plane range of voxel map to a single gray-scale BMP image file.
std::int64_t i64
signed 64-bit integer type
Real _sample_point_1d_x(i64 px, i64 xidx, i64 yidx=i64(0), i64 zidx=i64(0)) const
Helper function for _sample_point: samples a 1D edge in X-parallel line.
void compute_map_from_off_3d(const Dist::Comm &comm, const String &filename, bool invert, bool gather_to_all=true)
Creates the voxel map based on a 3D OFF model handled by CGAL by utilizing MPI parallelization.
u64 _stride_plane
stride of a single plane in XY dimensions
u64 _coverage
the coverage of the domain, relative to unit size
void set_bounding_box_2d(Real x_min, Real x_max, Real y_min, Real y_max)
Sets the bounding box for a 2D voxel map.
Real _sample_point_2d(i64 px, i64 py, i64 xidx, i64 yidx, i64 zidx=i64(0)) const
Helper function for _sample_point: samples a 2D square in XY-parallel plane.
static constexpr i64 unit_size
size of a real unit (meter) in our internal units (nanometers)
bool _out_of_bounds_value
the out-of-bounds-value for the voxel map
ReadResult read(const Dist::Comm &comm, const String &filename)
Reads a voxel map from a file.
std::array< i64, 3u > _bbox_min
bounding box dimensions of domain
bool _check_box(const std::array< u64, 1 > &box_min, const std::array< u64, 1 > &box_max) const
Checks whether a 1D box contains at least one active voxel.
void compute_map_from_formula_2d(const Dist::Comm &comm, const String &formula, bool gather_to_all=true)
Creates the voxel map based on a 2D formula by utilizing MPI parallelization.
Real _sample_point(const std::array< i64, 1 > &p) const
Samples the voxel map for a given 1D point by multi-linear interpolation.
int _create_stage
current creation stage
u64 _map_coord_idx_nearest(i64 xyz, std::size_t sdim) const
Maps a unit coordinate to a X-/Y-/Z-index of the closest voxel in the voxel map.
VoxelMap()
standard constructor
Real _sample_point_3d(i64 px, i64 py, i64 pz, i64 xidx, i64 yidx, i64 zidx) const
Helper function for _sample_point: samples a 3D cube in XYZ volume.
void set_bounding_box_3d(Real x_min, Real x_max, Real y_min, Real y_max, Real z_min, Real z_max)
Sets the bounding box for a 3D voxel map.
void _render_plane_to_bmp(std::ostream &os, Index width, Index height, i64 box_min_z, i64 box_max_z) const
Renders a plane range of voxel map to a single gray-scale BMP image file.
static u64 calc_line_stride(u64 num_x)
ensure that we're not compiling on some freak architecture...
Real _sample_box(const std::array< i64, 1 > &box_min, const std::array< i64, 1 > &box_max) const
Samples a 1D box of the voxel map.
u64 _num_lines
number of lines; 2D = num_points[2]; 3D: = num_points[2] * num_points[3]
String class implementation.
String pad_front(size_type len, char c=' ') const
Pads the front of the string up to a desired length.
std::uint64_t u64
unsigned 64-bit integer type
@ other
generic/other permutation strategy
std::int64_t i64
signed 64-bit integer type
T_ abs(T_ x)
Returns the absolute value.
T_ sqr(T_ x)
Returns the square of a value.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ cub(T_ x)
Returns the cube of a value.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
double Real
Real data type.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.