Beatmup
chunk_collection.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2020, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "chunk_collection.h"
20 #include <stdexcept>
21 #include <algorithm>
22 
23 using namespace Beatmup;
24 
25 namespace Internal {
26 
27  /**
28  Copies data from multidimensional strided tensor to a continuous memory space.
29  Makes use of densely packed dimensions for a faster copy.
30  */
31  class Copy {
32  private:
33  const pybind11::buffer_info& info;
34  int firstStridedDim; //!< first non-dense dimension
35  size_t packetSize; //!< largest continuous packet size
36  uint8_t* outPtr; //!< output pointer
37  size_t limit; //!< number of bytes remaining to copy
38 
39 
40  /**
41  \internal
42  Searches for first strided (non-dense) dimension.
43  */
44  size_t discover(int dim = 0) {
45  size_t entrySize;
46  if (dim + 1 < info.ndim) {
47  entrySize = discover(dim + 1);
48  if (entrySize == 0)
49  return 0;
50  }
51  else
52  entrySize = info.itemsize;
53 
54  // check if densely packed
55  if (info.strides[dim] == entrySize) {
56  if (dim == 0) {
57  // all dimensions are densely packed
58  firstStridedDim = -1;
59  packetSize = info.size * info.itemsize;
60  return 0;
61  }
62  else
63  // just return dimension size
64  return entrySize * info.shape[dim];
65  }
66 
67  // not densely packed, so copy by pieces
68  firstStridedDim = dim;
69  packetSize = entrySize;
70  return 0;
71  }
72 
73 
74  /**
75  \internal
76  Recursively copies strided data to output.
77  */
78  void copy(const uint8_t* inPtr, int dim = 0) {
79  if (dim > firstStridedDim) {
80  // densely packed dimensions follow
81  size_t size = std::min(limit, packetSize);
82  memcpy(outPtr, inPtr, size);
83  outPtr += size;
84  limit -= size;
85  }
86  else
87  for (size_t i = 0; i < info.shape[dim]; ++i)
88  copy(inPtr + i * info.strides[dim], dim + 1);
89  }
90 
91  public:
92  Copy(const pybind11::buffer_info& info, void* outputBuffer, size_t limit):
93  info(info), outPtr(static_cast<uint8_t*>(outputBuffer)), limit(limit)
94  {
95  discover();
96  copy(static_cast<const uint8_t*>(info.ptr));
97  }
98 
99  inline size_t remaining() const { return limit; }
100  };
101 
102 }
103 
105  auto it = data.find(id);
106  if (it == data.cend())
107  return 0;
108  auto info = it->second.request();
109  return info.size * info.itemsize;
110 }
111 
112 
113 chunksize_t Python::WritableChunkCollection::fetch(const std::string& id, void* data, const chunksize_t limit) {
114  auto it = this->data.find(id);
115  if (it == this->data.end())
116  return 0;
117  Internal::Copy copy(it->second.request(), data, limit);
118  return limit - copy.remaining();
119 }
120 
121 
122 void Python::WritableChunkCollection::save(const std::string& filename, bool append) {
124  for (auto it : data) {
125  Chunk chunk(*this, it.first);
126  writer(it.first, chunk(), chunk.size());
127  }
128 }
Writes chunks to a file.
Definition: chunkfile.h:191
Simply a piece of binary data of a specific size.
Definition: chunkfile.h:210
size_t size() const
Definition: chunkfile.h:257
std::map< std::string, pybind11::buffer > data
chunksize_t chunkSize(const std::string &id) const
Retrieves size of a specific chunk.
chunksize_t fetch(const std::string &id, void *data, const chunksize_t limit)
Reads a chunk.
void save(const std::string &filename, bool append=false)
Saves the collection to a file.
Copies data from multidimensional strided tensor to a continuous memory space.
uint8_t * outPtr
output pointer
int firstStridedDim
first non-dense dimension
Copy(const pybind11::buffer_info &info, void *outputBuffer, size_t limit)
size_t packetSize
largest continuous packet size
const pybind11::buffer_info & info
size_t remaining() const
void copy(const uint8_t *inPtr, int dim=0)
size_t discover(int dim=0)
size_t limit
number of bytes remaining to copy
uint32_t chunksize_t
Definition: chunkfile.h:29
Beatmup internal declarations.
Definition: basic_types.h:78
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
Beatmup::AbstractBitmap * copy
JNIEnv jlong jstring filename
JNIEnv jlong jstring jboolean append
jlong jobject size