You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shuffle3/src/work.cpp

135 lines
4.5 KiB

#include <tuple>
#include <functional>
#include <bit>
#include <cfloat>
#include <shuffle3.h>
#include <panic.h>
#include <map.h>
#include <reinterpret.h>
#include <shuffle.hpp>
#include <work.h>
#include <debug.h>
template<typename T, typename Fn>
std::tuple<T, T> minmax_t(const span<T>& array, Fn keep)
{
T highest;
T lowest;
bool init=false;
D_dprintf("minmax_t: %p (%lu)", array.as_ptr(), array.size());
for(std::size_t i=0;i<array.size();i++)
{
if(!keep(array[i])) continue;
auto item = array[i];
if(!init) {
init = true;
lowest = highest = item;
}
else if(item < lowest) lowest = item;
else if(item > highest) highest = item;
}
//fmt::print("MMX {}, {}\n", lowest, highest);
return {lowest, highest};
}
template<typename T>
inline std::tuple<T, T> minmax_t(const span<T>& array)
{
return minmax_t(array, [](T _val) { return true; });
}
namespace work
{
/// Shuffle or unshuffle in place
template<bool unshuffle>
int xshuffle_ip(const char* file)
{
mm::mmap map(file);
map.access(mm::Access::Random, true);
if constexpr(unshuffle)
{
auto [byte_l, byte_h] = minmax_t(map.as_span().reinterpret<std::int8_t>());
D_dprintf("MMX res (s8): %d -- %d", byte_l, byte_h);
rng::drng drng((std::int32_t) ((0xfffa << 16) | (byte_l<<7) | byte_h ));
rng::unshuffle(drng, map.as_span());
auto [float_l, float_h] = minmax_t(map.as_span().reinterpret<float>(), [](float f) -> bool { return !( (f!=f) || f < -FLT_MAX || f > FLT_MAX); });
D_dprintf("MMX res (f32): %f -- %f", float_l, float_h);
rng::frng frng(float_l, float_h);
rng::unshuffle(frng, map.as_span().reinterpret<float>());
auto [long_l, long_h] = minmax_t(map.as_span().reinterpret<std::int64_t>());
D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h);
rng::xoroshiro128plus xorng(std::bit_cast<std::uint64_t>(long_l), std::bit_cast<std::uint64_t>(long_h));
rng::unshuffle(xorng, map.as_span().reinterpret<std::int64_t>());
} else {
auto [long_l, long_h] = minmax_t(map.as_span().reinterpret<std::int64_t>());
D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h);
rng::xoroshiro128plus xorng(std::bit_cast<std::uint64_t>(long_l), std::bit_cast<std::uint64_t>(long_h));
rng::shuffle(xorng, map.as_span().reinterpret<std::int64_t>());
auto [float_l, float_h] = minmax_t(map.as_span().reinterpret<float>(), [](float f) -> bool { return !( (f!=f) || f < -FLT_MAX || f > FLT_MAX); });
D_dprintf("MMX res (f32): %f -- %f", float_l, float_h);
rng::frng frng(float_l, float_h);
rng::shuffle(frng, map.as_span().reinterpret<float>());
auto [byte_l, byte_h] = minmax_t(map.as_span().reinterpret<std::int8_t>());
D_dprintf("MMX res (s8): %d -- %d", byte_l, byte_h);
rng::drng drng((std::int32_t) ((0xfffa << 16) | (byte_l<<7) | byte_h ));
rng::shuffle(drng, map.as_span());
}
return 0;
}
/// Shuffle or unshuffle out of place
template<bool unshuffle>
int xshuffle_op(const char* ifile, const char* ofile, bool is_buffered)
{
//TODO: Use libcow's `cow_create_fd()`/`Cow::Cow(fd, size)` to try to map `ifile`
// Then, clone it, and use the `Fake` to do the shuffling on, and write the data to `ofile`.
// If `ifile` cannot be mapped, create a shim `Cow(size(ifile))`, `sendfile()/copy_file_range()/splice()` `ifile` into the shim memory fd, and use that (do *not* clone it to a Fake,)
// Then, perform the shuffling on the original `Cow`, and `sendfile()/copy_file_range()/splice()` the `ifile` file memory descriptor used for the `Cow` into `ofile`, and then destroy the `Cow`, **make sure to `msync()` the Cow'd range before the copy**.
mm::vmap imap; //{ifile};
if constexpr(unshuffle)
{
} else {
}
panic("Unimplemented");
return 0;
}
}
int help()
{
//Print help then exit
return 1;
}
extern "C" int do_work(const work_args_t args)
{
using A = decltype(args.op);
switch (args.op) {
case A::OP_SHUFFLE_IP: return work::xshuffle_ip<false >(args.data.op_shuffle_ip.file);
case A::OP_SHUFFLE_OP: return work::xshuffle_op<false >(args.data.op_shuffle_op.ifile,
args.data.op_shuffle_op.ofile,
args.data.op_shuffle_op.buffered == WORK_BO_BUFFERED);
case A::OP_UNSHUFFLE_IP: return work::xshuffle_ip<true >(args.data.op_unshuffle_ip.file);
case A::OP_UNSHUFFLE_OP: return work::xshuffle_op<true>(args.data.op_unshuffle_op.ifile,
args.data.op_unshuffle_op.ofile,
args.data.op_unshuffle_op.buffered == WORK_BO_BUFFERED);
case A::OP_HELP: return help();
default: panic("Unknown op %d", (int)args.op);
}
return 0;
}