1 /* 2 * Copyright 2016 CodiLime 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 #pragma once 18 19 #include "data/bindata.h" 20 #include "models.h" 21 22 namespace veles { 23 namespace data { 24 25 /** Represents data repacking format. */ 26 class Repacker : public RepackerModel { 27 public: 28 explicit Repacker(Endian endian = Endian::LITTLE, uint64_t from_width = 8, 29 uint64_t to_width = 8, uint64_t high_pad = 0, 30 uint64_t low_pad = 0) RepackerModel(endian,from_width,to_width,high_pad,low_pad)31 : RepackerModel(endian, from_width, to_width, high_pad, low_pad) {} 32 using RepackerModel::RepackerModel; 33 34 /** Element width, including padding. */ paddedWidth()35 unsigned paddedWidth() const { return to_width + high_pad + low_pad; } 36 37 /** Returns repacking unit for given format, ie. lowest common multiple 38 of source and padded destination widths in bits. */ 39 unsigned repackUnit() const; 40 41 /** Returns the number of source elements that would be read to perform 42 the given repacking. This is equal to 43 ceil(paddedWidth() * num_elements / from_width). */ 44 size_t repackSize(size_t num_elements) const; 45 46 /** Returns the number of destination elements that can be retrieved 47 from the given source with the given repacking. This is equal to 48 floor(from_width * src_size / paddedWidth()). */ 49 size_t repackableSize(size_t src_size) const; 50 51 /** Repacks binary data to a different element width. Repacking conceptually 52 works as follows: 53 54 1. All source elements starting from the given index, are glued 55 together to form a big string of bits. If LITTLE endian is selected, 56 lower-indexed elements are less significant in the resulting 57 string, otherwise they are more significant. 58 2. Starting from LSB (for LITTLE endian) or MSB (for BIG 59 endian) of the resulting string, num_elements * (format.width + 60 format.lowPad + format.highPad) bits are extracted and cut into 61 num_elements pieces (again ordered according to the selected 62 endian). 63 3. From each of the num_element pieces, high highPad and low lowPad bits 64 are cut off, and the rest is returned as the result. 65 66 Of course, the actual repacking operation only reads as many source 67 elements as are actually necessary to determine the output. This number 68 can be determined by the repackSize() function. It is an error if fewer 69 elements than that are available in the source. */ 70 BinData repack(const BinData& src, size_t start, size_t num_elements) const; 71 }; 72 73 } // namespace data 74 } // namespace veles 75