#include #include #include #include #include #include #include #include #include #include #include template std::tuple minmax_t(const span& 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 highest) highest = item; } //fmt::print("MMX {}, {}\n", lowest, highest); return {lowest, highest}; } template inline std::tuple minmax_t(const span& array) { return minmax_t(array, [](T _val) { return true; }); } namespace work { /// Shuffle or unshuffle in place template 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()); 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 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()); auto [long_l, long_h] = minmax_t(map.as_span().reinterpret()); D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h); rng::xoroshiro128plus xorng(std::bit_cast(long_l), std::bit_cast(long_h)); rng::unshuffle(xorng, map.as_span().reinterpret()); } else { auto [long_l, long_h] = minmax_t(map.as_span().reinterpret()); D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h); rng::xoroshiro128plus xorng(std::bit_cast(long_l), std::bit_cast(long_h)); rng::shuffle(xorng, map.as_span().reinterpret()); auto [float_l, float_h] = minmax_t(map.as_span().reinterpret(), [](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()); auto [byte_l, byte_h] = minmax_t(map.as_span().reinterpret()); 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 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(args.data.op_shuffle_ip.file); case A::OP_SHUFFLE_OP: return work::xshuffle_op(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(args.data.op_unshuffle_ip.file); case A::OP_UNSHUFFLE_OP: return work::xshuffle_op(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; }