grid.h
6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#ifndef STIM_GRID_H
#define STIM_GRID_H
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <cstdarg>
#include <stim/math/vector.h>
namespace stim{
/**This object describes a generic D-dimensional grid containing data of type T.
Functions are provided for saving and loading binary data.
**/
template<typename T, unsigned int D = 1, typename F = float>
class grid{
protected:
size_t R[D]; //elements in each dimension
F S[D]; //spacing between element samples
T* ptr; //pointer to the data (on the GPU or CPU)
///Initializes a grid by allocating the necessary memory and setting all values to zero
void init(){
ptr = NULL; //initialize the data pointer to NULL
memset(R, 0, sizeof(size_t) * D); //set the resolution to zero
for(size_t d = 0; d < D; d++) S[d] = (F)1.0; //initialize the spacing to unity
}
void alloc(){
if(ptr != NULL) free(ptr); //if memory has already been allocated, free it
size_t N = samples(); //calculate the total number of values
ptr = (T*)calloc(sizeof(T), N); //allocate memory to store the grid
}
public:
///Default constructor doesn't do anything
grid(){
init();
}
///Constructor used to specify the grid size as a vector
/// @param _R is a vector describing the grid resolution
grid( stim::vec<size_t> _R){
for (size_t d = 0; d < D; d++)
R[d] = _R[d];
init();
}
///Return the total number of values in the binary file
size_t samples(){
size_t s = 1;
for(size_t d = 0; d < D; d++)
s *= R[d];
return s;
}
///Return the number of bytes in the binary file
size_t bytes(){
return samples() * sizeof(T);
}
void
setDim(stim::vec<float> s){
for(size_t d = 0; d < D; d++)
S[d] = s[d];
}
///Constructor used to specify the grid size as a set of parameters
/// @param X0... is a list of values describing the grid size along each dimension
/*grid( size_t X0, ...){
R[0] = X0; //set the grid size of the first dimension
va_list ap; //get a variable list
va_start(ap, X0); //start the variable list at the first element
for(size_t d = 1; d<D; d++) //for each additional element
R[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t
va_end(ap);
init(); //initialize the grid
}*/
///Set the spacing between grid sample points
/// @param X0... is a list of values describing the grid sample spacing
/*void spacing(F X0, ...) {
S[0] = X0; //set the grid size of the first dimension
va_list ap; //get a variable list
va_start(ap, X0); //start the variable list at the first element
for (size_t d = 1; d<D; d++) //for each additional element
S[d] = va_arg(ap, F); //read the value from the variable list as a size_t
va_end(ap);
}*/
/// Set the spacing between grid sample points for the specified dimension
void spacing(size_t d, F sp){
if(d < D) S[d] = sp;
else{
std::cout<<"error in stim::grid::spacing() - insufficient dimensions"<<std::endl;
exit(1);
}
}
/// Return the spacing for a given dimension
F spacing(size_t d){
if(d < D) return S[d];
else{
std::cout<<"error in stim::grid::spacing() - insufficient dimensions"<<std::endl;
exit(1);
}
}
/// Get the sample spacing for the given dimension
F get_spacing(size_t d) {
return S[d];
}
/// Get the size of the grid along the specified dimension
F size(size_t d){
return (F)R[d] * S[d];
}
/// Return the number of samples
size_t samples(size_t d){
return R[d];
}
///Writes the binary data to disk
/// @param filename is the name of the binary file to be written
void write(std::string filename){
std::fstream file;
file.open(filename.c_str(), std::ios::out | std::ios::binary); //open the file as binary for reading
file.write((char *)ptr, samples() * sizeof(T)); //write file to disk
}
///Loads a binary file from disk
/// @param filename is the name of the file containing the binary data
/// @param S is the size of the binary file along each dimension
/// @param header is the size of the header in bytes
void read(std::string filename, stim::vec<size_t> X, unsigned long header = 0){
for(size_t d = 0; d < D; d++)
R[d] = X[d]; //set the sample resolution
init(); //allocate space for the data
std::fstream file;
file.open(filename.c_str(), std::ios::in | std::ios::binary); //open the file as binary for writing
file.seekg(header, std::ios::beg); //seek past the header
file.read((char *)ptr, samples() * sizeof(T)); //read the data
}
///Gets a single value from the grid given a set of coordinates
/// @param x0... is a list of coordinates specifying the desired value
/*T get(unsigned long x0, ...){
va_list ap; //create a variable list
unsigned long F = 1; //initialize the dimension size to 1
unsigned long idx = x0;
va_start(ap, x0); //start a variable list
for(unsigned int d = 1; d<D; d++){ //for each dimension
F *= R[d-1]; //get the size of the first dimension
idx += va_arg(ap, unsigned int) * F; //increment the index
}
va_end(ap);
return ptr[idx]; //access the appropriate element and return the value
}*/
///Sets a value in the grid
/// @param value is the grid point value
/// @x0... is the coordinate of the value to be set
/*void set(T value, unsigned long x0, ...){
va_list ap; //create a variable list
unsigned long F = 1; //initialize the dimension counter to 1
unsigned long idx = x0; //initialize the index to the first variable
va_start(ap, x0); //start the variable list
for(unsigned int d = 1; d<D; d++){ //for each dimension
F *= R[d - 1];
idx += va_arg(ap, unsigned int) * F; //update the index
}
va_end(ap);
ptr[idx] = value; //set the value at the indexed location
}*/
///Outputs grid data as a string
std::string str(){
std::stringstream result;
result<<"stim::grid structure of size [";
for(unsigned int d = 0; d<D; d++){
if(d!=0) result<<", ";
result<<R[d];
}
result<<"]"<<std::endl;
//calculate the number of values to output
unsigned long nV = std::min((unsigned long long)R[0], (unsigned long long)10);
for(unsigned long v = 0; v<nV; v++){
result<<ptr[v];
if(v != nV-1) result<<", ";
}
return result.str();
}
};
}
#endif