// // NumericCoder.hpp // Clock Signal // // Created by Thomas Harte on 17/01/2023. // Copyright © 2023 Thomas Harte. All rights reserved. // #ifndef NumericCoder_hpp #define NumericCoder_hpp namespace Numeric { /// Stores and retrieves an arbitrary number of fields into an int with arbitrary modulos. /// /// E.g. NumericEncoder<8, 3, 14> establishes an encoder and decoder for three fields, /// the first is modulo 8, the second is modulo 3, the third is modulo 14. /// /// NumericEncoder<8, 3, 14>::encode<2>(v, 9) will mutate v so that the third field /// (i.e. field 2) has value 9. template class NumericCoder { public: /// Modifies @c target to hold @c value at @c index. template static void encode(int &target, int value) { static_assert(index < sizeof...(Sizes), "Index must be within range"); NumericEncoder::template encode(target, value); } /// @returns The value from @c source at @c index. template static int decode(int source) { static_assert(index < sizeof...(Sizes), "Index must be within range"); return NumericDecoder::template decode(source); } private: template struct NumericEncoder { template static void encode(int &target, int value) { if constexpr (i == index) { const int suffix = target % divider; target /= divider; target -= target % size; target += value % size; target *= divider; target += suffix; } else { NumericEncoder::template encode(target, value); } } }; template struct NumericDecoder { template static int decode(int source) { if constexpr (i == index) { return (source / divider) % size; } else { return NumericDecoder::template decode(source); } } }; }; } #endif /* NumericCoder_hpp */