GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/PTensor_impl.h Lines: 270 297 90.9 %
Date: 2026-03-27 22:08:32 Branches: 98 126 77.8 %

Line Branch Exec Source
1
/***************************************
2
	Auteur : Pierre Aubert
3
	Mail : pierre.aubert@lapp.in2p3.fr
4
	Licence : CeCILL-C
5
****************************************/
6
7
#ifndef __PTENSOR_H_IMPL__
8
#define __PTENSOR_H_IMPL__
9
10
#include "block_copy.h"
11
#include "PTensor.h"
12
13
///Default constructeur of PTensor
14
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
15
 * 	@param tabShape : shape of the table to be allocated
16
 * 	@param nbDim : number of dimensions of the PTensor
17
*/
18
template<typename T>
19
1494
PTensor<T>::PTensor(AllocMode::AllocMode allocMode, const size_t * tabShape, size_t nbDim){
20
1494
	initialisationPTensor(allocMode, tabShape, nbDim);
21
1494
}
22
23
///Default constructeur of PTensor
24
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
25
 * 	@param nbElement : number of elemnts to be allocated
26
*/
27
template<typename T>
28
416
PTensor<T>::PTensor(AllocMode::AllocMode allocMode, size_t nbElement){
29
	size_t tabShape[1];
30
416
	tabShape[0] = nbElement;
31
416
	initialisationPTensor(allocMode, tabShape, 1lu);
32
416
}
33
34
///Default constructeur of PTensor
35
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
36
 * 	@param nbRow : number of rows to be allocated
37
 * 	@param nbCol : number of columns to be allocated
38
*/
39
template<typename T>
40
810
PTensor<T>::PTensor(AllocMode::AllocMode allocMode, size_t nbRow, size_t nbCol){
41
	size_t tabShape[2];
42
810
	tabShape[0] = nbRow;
43
810
	tabShape[1] = nbCol;
44
810
	initialisationPTensor(allocMode, tabShape, 2lu);
45
810
}
46
47
///Default constructeur of PTensor
48
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
49
 * 	@param nbSlice : number of slices to be allocated
50
 * 	@param nbRow : number of rows to be allocated
51
 * 	@param nbCol : number of columns to be allocated
52
*/
53
template<typename T>
54
792
PTensor<T>::PTensor(AllocMode::AllocMode allocMode, size_t nbSlice, size_t nbRow, size_t nbCol){
55
	size_t tabShape[3];
56
792
	tabShape[0] = nbSlice;
57
792
	tabShape[1] = nbRow;
58
792
	tabShape[2] = nbCol;
59
60
792
	initialisationPTensor(allocMode, tabShape, 3lu);
61
792
}
62
63
///Copy constructor of PTensor
64
/**	@param other : class to copy
65
*/
66
template<typename T>
67
PTensor<T>::PTensor(const PTensor<T> & other){
68
	initialisationPTensor(AllocMode::NONE, NULL, 0lu);
69
	copyPTensor(other);
70
}
71
72
///Destructor of PTensor
73
template<typename T>
74
3696
PTensor<T>::~PTensor(){
75
3696
	freeTabData();
76

3696
	if(p_shape != NULL){delete [] p_shape;}
77

3696
	if(p_reservedShape != NULL){delete [] p_reservedShape;}
78
}
79
80
///Definition of equal operator of PTensor
81
/**	@param other : class to copy
82
 * 	@return copied class
83
*/
84
template<typename T>
85
PTensor<T> & PTensor<T>::operator = (const PTensor<T> & other){
86
	copyPTensor(other);
87
	return *this;
88
}
89
90
///Reserve allocated memory to the PTensor, without resizing it
91
/**	@param tabDim : table of the size of each dimensions
92
 * 	@param nbDim : number of dimensions
93
 * 	@return true if the resize/reserve has been done, false otherwise
94
*/
95
template<typename T>
96
3446
bool PTensor<T>::reserve(const size_t * tabDim, size_t nbDim){
97
3446
	if(tensor_isSameShape(p_reservedShape, p_reservedNbDimension, tabDim, nbDim)){return false;}
98
3446
	tensor_copyShape(p_reservedShape, p_reservedNbDimension, tabDim, nbDim);
99
3446
	freeTabData();
100
3446
	p_tabData = template_alloc<T>(p_padding, p_isAligned, p_allocMode, tabDim, nbDim);
101
3446
	p_isOwnData = true;
102
3446
	return true;
103
}
104
105
///Resize the PTensor
106
/**	@param tabDim : table of the size of each dimensions
107
 * 	@param nbDim : number of dimensions
108
 * 	@return true if the resize/reserve has been done, false otherwise
109
*/
110
template<typename T>
111
4942
bool PTensor<T>::resize(const size_t * tabDim, size_t nbDim){
112

4942
	if(tabDim == NULL || nbDim == 0lu){return false;}
113
3448
	if(tensor_isSameShape(p_shape, p_nbDimension, tabDim, nbDim)){return false;}
114
3446
	tensor_copyShape(p_shape, p_nbDimension, tabDim, nbDim);
115
3446
	bool b(reserve(tabDim, nbDim));
116

3446
	if(tabDim != NULL && nbDim != 0lu){
117
3446
		p_fullSize = tensor_getFullSize(p_shape, p_nbDimension);
118
3446
		p_nbCol = (p_shape[p_nbDimension - 1lu]);
119
3446
		p_fullNbRow = (p_fullSize/p_nbCol);
120
3446
		p_fullPaddedSize = p_fullNbRow*(p_nbCol + p_padding);
121
	}
122
3446
	return b;
123
}
124
125
///Reserve allocated memory to the PTensor, without resizing it
126
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
127
 * 	@param tabDim : table of the size of each dimensions
128
 * 	@param nbDim : number of dimensions
129
 * 	@return true if the resize/reserve has been done, false otherwise
130
*/
131
template<typename T>
132
bool PTensor<T>::reserve(AllocMode::AllocMode allocMode, const size_t * tabDim, size_t nbDim){
133
	setAllocMode(allocMode);
134
	return reserve(tabDim, nbDim);
135
}
136
137
///Resize the PTensor
138
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
139
 * 	@param tabDim : table of the size of each dimensions
140
 * 	@param nbDim : number of dimensions
141
 * 	@return true if the resize/reserve has been done, false otherwise
142
*/
143
template<typename T>
144
102
bool PTensor<T>::resize(AllocMode::AllocMode allocMode, const size_t * tabDim, size_t nbDim){
145
102
	setAllocMode(allocMode);
146
102
	return resize(tabDim, nbDim);
147
}
148
149
///Resize the PTensor
150
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
151
 * 	@param nbValue : number of values
152
 * 	@return true if the resize/reserve has been done, false otherwise
153
*/
154
template<typename T>
155
bool PTensor<T>::resize(AllocMode::AllocMode allocMode, size_t nbValue){
156
	size_t dims[1];
157
	dims[0] = nbValue;
158
	return resize(allocMode, dims, 1lu);
159
}
160
161
///Resize the PTensor
162
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
163
 * 	@param nbRow : number of rows
164
 * 	@param nbCol : number of columns
165
 * 	@return true if the resize/reserve has been done, false otherwise
166
*/
167
template<typename T>
168
102
bool PTensor<T>::resize(AllocMode::AllocMode allocMode, size_t nbRow, size_t nbCol){
169
	size_t dims[2];
170
102
	dims[0] = nbRow;
171
102
	dims[1] = nbCol;
172
102
	return resize(allocMode, dims, 2lu);
173
}
174
175
///Resize the PTensor
176
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
177
 * 	@param nbSlice : number of slices (number of matrices or size nbRow, nbCol)
178
 * 	@param nbRow : number of rows
179
 * 	@param nbCol : number of columns
180
 * 	@return true if the resize/reserve has been done, false otherwise
181
*/
182
template<typename T>
183
bool PTensor<T>::resize(AllocMode::AllocMode allocMode, size_t nbSlice, size_t nbRow, size_t nbCol){
184
	size_t dims[3];
185
	dims[0] = nbSlice;
186
	dims[1] = nbRow;
187
	dims[2] = nbCol;
188
	return resize(allocMode, dims, 3lu);
189
}
190
191
///Load a binary table of value
192
/**	@param fileName : name of the file to be loaded
193
 * 	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
194
 * 	@return true on success, false otherwise
195
*/
196
template<typename T>
197
bool PTensor<T>::fromFile(const std::string & fileName, AllocMode::AllocMode allocMode){
198
	if(fileName == ""){return false;}
199
	FILE* fp = fopen(fileName.c_str(), "r");
200
	if(fp == NULL){
201
		std::cerr << " PTensor<T>::fromFile : can't load file '" << fileName << "'" << std::endl;
202
		return false;
203
	}
204
	fseek(fp, 0l, SEEK_END);
205
	size_t fileSize(ftell(fp));
206
	fseek(fp, 0l, SEEK_SET);
207
	size_t nbElement = fileSize/sizeof(T);
208
	resize(allocMode, nbElement);
209
	if(fread(p_tabData, sizeof(T), nbElement, fp) != nbElement){
210
		std::cerr << " PTensor<T>::fromFile : can't get "<<nbElement<<" unsigned short in file '" << fileName << "'" << std::endl;
211
		fclose(fp);
212
		freeTabData();
213
		return false;
214
	}
215
	fclose(fp);
216
	return true;
217
}
218
219
///Copy only the pointers of the data and shape
220
/**	@param tabData : pointer to the data
221
 * 	@param tabDim : table of dimension
222
 * 	@param nbDim : number of dimension
223
 * 	@param isAligned : true if the data pointer is aligned
224
 * 	@param padding : padding of the table of data
225
*/
226
template<typename T>
227
74
void PTensor<T>::copyPointer(T * tabData, size_t * tabDim, size_t nbDim, bool isAligned, size_t padding){
228
74
	p_isOwnData = false;
229
74
	p_tabData = tabData;
230
231
74
	tensor_copyShape(p_shape, p_nbDimension, tabDim, nbDim);
232
74
	tensor_copyShape(p_reservedShape, p_reservedNbDimension, tabDim, nbDim);
233
234
74
	p_isAligned = isAligned;
235
74
	p_padding = padding;
236
237
74
	p_fullSize = tensor_getFullSize(tabDim, nbDim);
238
74
	p_nbCol = tabDim[nbDim - 1lu];
239
74
	p_fullNbRow = p_fullSize/p_nbCol;
240
241
74
	p_fullPaddedSize = p_fullNbRow*(p_nbCol + p_padding);
242
74
	p_allocMode = tensor_getAllocMode(isAligned, padding);
243
74
}
244
245
///Change the allocation mode
246
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
247
*/
248
template<typename T>
249
102
void PTensor<T>::setAllocMode(AllocMode::AllocMode allocMode){
250
102
	p_allocMode = allocMode;
251
102
}
252
253
///Fill the PTensor with a value
254
/**	@param value : value to fill
255
*/
256
template<typename T>
257
69
void PTensor<T>::fill(T value){
258
69
	if(p_tabData == NULL){return;}	//If there is nothing to fill, we quit
259
57501
	for(size_t i(0lu); i < p_fullPaddedSize; ++i){
260
57432
		p_tabData[i] = value;
261
	}
262
}
263
264
///Fill the PTensor with a table
265
/**	@param tabValue : table of values to be used
266
 * 	@param nbValue : number of value to be used
267
*/
268
template<typename T>
269
void PTensor<T>::setData(const T * tabValue, size_t nbValue){
270
	if(tabValue == NULL || nbValue == 0lu){return;}
271
	if(p_nbDimension != 1lu){throw std::runtime_error("PTensor<T>::setData : expect single dimension tensor");}
272
	if(p_fullSize != nbValue){throw std::runtime_error("PTensor<T>::setData : wrong number of elements");}
273
	for(size_t i(0lu); i < nbValue; ++i){
274
		p_tabData[i] = tabValue[i];
275
	}
276
}
277
278
///Fill the PTensor with a matrix
279
/**	@param tabValue : table of values to be used
280
 * 	@param nbRow : number of rows to be used
281
 * 	@param nbCol : number of columns to be used
282
*/
283
template<typename T>
284
void PTensor<T>::setData(const T * tabValue, size_t nbRow, size_t nbCol){
285
	if(tabValue == NULL || nbRow == 0lu || nbCol == 0lu){return;}
286
	if(p_nbDimension != 1lu){throw std::runtime_error("PTensor<T>::setData : expect two dimension tensor");}
287
	if(p_fullNbRow != nbRow){throw std::runtime_error("PTensor<T>::setData : wrong number of rows");}
288
	if(p_nbCol != nbCol){throw std::runtime_error("PTensor<T>::setData : wrong number of columns");}
289
	size_t rowSize(p_nbCol + p_padding);
290
	for(size_t i(0lu); i < nbRow; ++i){
291
		for(size_t j(0lu); j < nbCol; ++j){
292
			p_tabData[i*rowSize + j] = tabValue[i*nbCol + j];
293
		}
294
	}
295
}
296
297
///Set the value of an element of the tensor
298
/**	@param index : index of the element to be set
299
 * 	@param value : value to be set
300
*/
301
template<typename T>
302
15029596
void PTensor<T>::setValue(size_t index, T value){
303
15029596
	p_tabData[index] = value;
304
15029596
}
305
306
///Set the value of an element of the tensor
307
/**	@param indexRow : row index of the element to be set
308
 * 	@param indexCol : column index of the element to be set
309
 * 	@param value : value to be set
310
*/
311
template<typename T>
312
14993164
void PTensor<T>::setValue(size_t indexRow, size_t indexCol, T value){
313
14993164
	setValue(indexRow*(p_nbCol + p_padding) + indexCol, value);
314
14993164
}
315
316
///Set the padding value of the PTensor
317
/**	@param value : padding value of the PTensor
318
*/
319
template<typename T>
320
2
void PTensor<T>::setPaddingValue(T value){
321

2
	if(p_padding == 0lu || p_tabData == NULL){return;}	//If there is not padding or no data, we quit
322
2
	size_t rowSize(p_nbCol + p_padding);
323
10
	for(size_t i(0lu); i < p_fullNbRow; ++i){
324
48
		for(size_t j(0lu); j < p_nbCol; ++j){
325
160
			for(size_t k(0lu); k < p_padding; ++k){
326
120
				p_tabData[i*rowSize + j + k] = value;
327
			}
328
		}
329
	}
330
}
331
332
///Get the value of the padding
333
/**	@return padding value
334
*/
335
template<typename T>
336
T PTensor<T>::getPaddingValue() const{
337
	if(p_padding == 0lu || p_tabData == NULL){return (T)0;}
338
	return p_tabData[p_fullPaddedSize - 1lu];
339
}
340
341
///Set the size of the neighbours vector
342
/**	@param nbNeighbour : number of elements in the neighbours vector (scalar: 1, vectorial: n)
343
*/
344
template<typename T>
345
152
void PTensor<T>::setNbVecNeighbour(size_t nbNeighbour){
346
152
	p_nbNeighbour = nbNeighbour;
347
152
}
348
349
///Get the size of the neighbours vector
350
/**	@return number of elements in the neighbours vector (scalar: 1, vectorial: n)
351
*/
352
template<typename T>
353
size_t PTensor<T>::getNbVecNeighbour() const{
354
	return p_nbNeighbour;
355
}
356
357
///Convert the given tensor (with scalar neighbours), in vectorial neighbours
358
/**	@param tensorScal : input tensor (with scalar neighbours) to be converted
359
*/
360
template<typename T>
361
2
void PTensor<T>::fromScalToVecNeigbhour(const PTensor<T> & tensorScal){
362
2
	fromScalToVecNeigbhour(tensorScal, p_nbNeighbour);
363
2
}
364
365
///Convert the given tensor (with scalar neighbours), in vectorial neighbours
366
/**	@param tensorScal : input tensor (with scalar neighbours) to be converted
367
 * 	@param vectorSize : number of elements in the neighbours vector (scalar: 1, vectorial: n)
368
 * 	The allocation mode of the current Tensor is not changed and used as it was set
369
*/
370
template<typename T>
371
2
void PTensor<T>::fromScalToVecNeigbhour(const PTensor<T> & tensorScal, size_t vectorSize){
372
2
	p_nbNeighbour = vectorSize;
373
374
2
	size_t nbRow(tensorScal.getFullNbRow()), nbCol(tensorScal.getNbCol());
375
376
2
	size_t vecNbCol(nbCol*vectorSize);	//Vectorial number of columns
377
	//+2 is for the first and last rows where we dupplicate some values to increase the potential vectorisation of the computation
378
2
	size_t basicVecNbRow((nbRow/vectorSize) + (nbRow % vectorSize != 0lu));
379
2
	size_t vecNbRow(basicVecNbRow + 2lu);
380
381
2
	resize(p_allocMode, vecNbRow, vecNbCol);	//Let's allocate the new tensor with vectorial neighbours
382
383
2
	p_nbScalRow = nbRow;
384
	//Now, reshuffle data to vecotial mode
385
22
	for(size_t i(0lu); i < nbRow; ++i){
386
20
		size_t rowShift(i % basicVecNbRow);
387
20
		size_t vecRowIdx(rowShift + 1lu);
388
20
		size_t colShift(i / basicVecNbRow);
389
204
		for(size_t j(0lu); j < nbCol; ++j){
390
184
			size_t vecColIdx(j*vectorSize + colShift);
391
184
			setValue(vecRowIdx, vecColIdx, tensorScal.getValue(i, j));
392
		}
393
	}
394
	//Now let's deal with the dupplicated rows
395
2
	size_t nbDupplicate(vectorSize - 1lu), lastRow(vecNbRow - 1lu);
396
7
	for(size_t i(0lu); i < nbDupplicate; ++i){
397
5
		size_t duppliRowDownIdx((i + 1lu)*basicVecNbRow);
398
5
		size_t duppliRowUpIdx(duppliRowDownIdx - 1lu);
399
400
		//It is not a bug, the column shift down is given by the up row index
401
5
		size_t colShiftDown(duppliRowUpIdx / basicVecNbRow);
402
403
51
		for(size_t j(0lu); j < nbCol; ++j){
404
46
			size_t vecColDownIdx(j*vectorSize + colShiftDown);
405
46
			size_t vecColUpIdx(vecColDownIdx + 1lu);
406
407
			//Up row
408
46
			setValue(0lu, vecColUpIdx, tensorScal.getValue(duppliRowUpIdx, j));
409
			//Down row
410
46
			setValue(lastRow, vecColDownIdx, tensorScal.getValue(duppliRowDownIdx, j));
411
		}
412
	}
413
	//Then, let's put zeros at the rigth places to update padding values and avoid wrong computation
414
19
	for(size_t i(0lu); i < nbCol; ++i){
415
17
		setValue(0lu, i*vectorSize, 0.0f);			//First row padding
416
17
		setValue(lastRow, (i + 1lu)*vectorSize - 1lu, 0.0f);	//Last row padding
417
	}
418
	//Finally, the facultative padding (depending on the number of rows of the input scalar tensor)
419
2
	size_t nbFacultativePaddingRow((vectorSize - (nbRow % vectorSize)) % vectorSize);
420
2
	if(nbFacultativePaddingRow != 0lu){
421
2
		for(size_t i(0lu); i < nbFacultativePaddingRow; ++i){
422
1
			size_t paddingRowIdx(vecNbRow - i - 2lu);
423
6
			for(size_t j(0lu); j < nbCol; ++j){
424
5
				setValue(paddingRowIdx, (j + 1lu)*vectorSize - 1lu, 0.0f);	//Last row padding
425
			}
426
		}
427
	}
428
2
}
429
430
///Convert the given tensor (with vectorial neighbours), in scalar neighbours
431
/**	@param tensorVec : input tensor (with vectorial neighbours) to be converted
432
 * 	The allocation mode of the current Tensor is not changed and used as it was set
433
*/
434
template<typename T>
435
2
void PTensor<T>::fromVecToScalNeigbhour(const PTensor<T> & tensorVec){
436
2
	p_nbNeighbour = 1lu;
437
438
2
	size_t vectorSize(tensorVec.p_nbNeighbour);
439
2
	size_t vecNbRow(tensorVec.getFullNbRow()), nbVecCol(tensorVec.getNbCol());
440
2
	size_t nbCol(nbVecCol/vectorSize);		//Scalar number of columns
441
2
	size_t nbRow(tensorVec.p_nbScalRow);		//Scalart number of rows
442
2
	if(resize(p_allocMode, nbRow, nbCol)){		//Let's allocate the new tensor with scalar neighbours
443
		fill(0.0);				//If the resize has been done, we initialse the unused values
444
	}
445
446
2
	size_t basicVecNbRow((nbRow/vectorSize) + (nbRow % vectorSize != 0lu));
447
2
	p_nbScalRow = nbRow;
448
	//Now, reshuffle data back to scalar mode
449
22
	for(size_t i(0lu); i < nbRow; ++i){
450
20
		size_t rowShift(i % basicVecNbRow);
451
20
		size_t vecRowIdx(rowShift + 1lu);
452
20
		size_t colShift(i / basicVecNbRow);
453
204
		for(size_t j(0lu); j < nbCol; ++j){
454
184
			size_t vecColIdx(j*vectorSize + colShift);
455
184
			setValue(i, j, tensorVec.getValue(vecRowIdx, vecColIdx));
456
		}
457
	}
458
	//Now let's deal with the dupplicated rows
459
2
	size_t nbDupplicate(vectorSize - 1lu), lastCol(vecNbRow - 1lu);
460
7
	for(size_t i(0lu); i < nbDupplicate; ++i){
461
5
		size_t duppliRowDownIdx((i + 1lu)*basicVecNbRow);
462
5
		size_t duppliRowUpIdx(duppliRowDownIdx - 1lu);
463
464
		//It is not a bug, the column shift down is given by the up row index
465
5
		size_t colShiftDown(duppliRowUpIdx / basicVecNbRow);
466
467
51
		for(size_t j(0lu); j < nbCol; ++j){
468
46
			size_t vecColDownIdx(j*vectorSize + colShiftDown);
469
46
			size_t vecColUpIdx(vecColDownIdx + 1lu);
470
471
			//Up row
472
46
			setValue(duppliRowUpIdx, j, tensorVec.getValue(0lu, vecColUpIdx));
473
			//Down row
474
46
			setValue(duppliRowDownIdx, j, tensorVec.getValue(lastCol, vecColDownIdx));
475
		}
476
	}
477
2
}
478
479
///Update the value of the dupplicated vectorial neighbours with an average
480
template<typename T>
481
void PTensor<T>::updateDupplicateVecNeighbour(){
482
	size_t nbRow(getFullNbRow());
483
	if(nbRow < 4lu){return;}
484
	size_t lastRowIdx(nbRow - 1lu);
485
	size_t prevLastRowIdx(lastRowIdx - 1lu);
486
	size_t nbCompute(p_nbCol/p_nbNeighbour);
487
	size_t nbComputeVec(p_nbNeighbour - 1lu);
488
	for(size_t i(0lu); i < nbCompute; ++i){
489
		for(size_t j(0lu); j < nbComputeVec; ++j){
490
			setValue(0lu, i*p_nbNeighbour + 1lu + j, getValue(prevLastRowIdx, i*p_nbNeighbour + j));
491
			setValue(lastRowIdx, i*p_nbNeighbour + j, getValue(1lu, i*p_nbNeighbour + 1lu + j));
492
		}
493
	}
494
}
495
496
///Split the current PTensor in blocks of size blockSizeRow x blockSizeCol, never bigger, and can have a neighborRing (or border) around it
497
/**	@param[out] vecBlock : vector of PBlock
498
 * 	@param blockSizeRow : maximum size of the created block in rows (taking account the neighborRing)
499
 * 	@param blockSizeCol : maximum size of the created block in columns (taking account the neighborRing)
500
 * 	@param neighborRing : number of border ring to be added around the created blocks
501
*/
502
template<typename T>
503
8
void PTensor<T>::splitBlock(std::vector<PBlock<T> > & vecBlock, size_t blockSizeRow, size_t blockSizeCol, size_t neighborRing) const{
504
8
	size_t nbInBlockRow(0lu), sizeLastInBlockRow(0lu), nbInBlockCol(0lu), sizeLastInBlockCol(0lu), nbTotalBlock(0lu);
505
8
	updateBlockSize(nbTotalBlock, nbInBlockRow, nbInBlockCol,
506
			sizeLastInBlockRow, sizeLastInBlockCol,
507
			vecBlock, blockSizeRow, blockSizeCol, neighborRing);
508
8
	size_t nbCol(getNbCol());
509
8
	size_t blockIndex(0lu);
510
26
	for(size_t i(0lu); i < nbInBlockRow; ++i){		//Loop over block rows
511
78
		for(size_t j(0lu); j < nbInBlockCol; ++j){		//Loop over block columns
512
60
			copyTensorToBlock(vecBlock[blockIndex], nbCol, blockSizeRow, blockSizeCol,
513
					blockSizeRow, blockSizeCol, i, j, neighborRing);
514
60
			++blockIndex;
515
		}
516
18
		if(sizeLastInBlockCol != 0lu){	//There is a small block at the end of the row
517
5
			copyTensorToBlock(vecBlock[blockIndex], nbCol, blockSizeRow, sizeLastInBlockCol,
518
					blockSizeRow, blockSizeCol, i, nbInBlockCol, neighborRing);
519
5
			++blockIndex;
520
		}
521
	}
522
8
	if(sizeLastInBlockRow != 0lu){	//There is a small blocks row as last row
523
6
		for(size_t j(0lu); j < nbInBlockCol; ++j){		//Loop over block columns
524
4
			copyTensorToBlock(vecBlock[blockIndex], nbCol, sizeLastInBlockRow, blockSizeCol,
525
					blockSizeRow, blockSizeCol, nbInBlockRow, j, neighborRing);
526
4
			++blockIndex;
527
		}
528
2
		if(sizeLastInBlockCol != 0lu){	//There is a small block at the end of the row
529
2
			copyTensorToBlock(vecBlock[blockIndex], nbCol, sizeLastInBlockRow, sizeLastInBlockCol,
530
					blockSizeRow, blockSizeCol, nbInBlockRow, nbInBlockCol, neighborRing);
531
2
			++blockIndex;
532
		}
533
	}
534
8
}
535
536
///Merge the block values into the current PTensor
537
/**	@param vecBlock : vector of blocks to be merged
538
 * 	@param neighborRing : number of border ring to be added around blocks
539
*/
540
template<typename T>
541
8
void PTensor<T>::mergeBlock(const std::vector<PBlock<T> > & vecBlock, size_t neighborRing){
542
79
	for(typename std::vector<PBlock<T> >::const_iterator it(vecBlock.begin()); it != vecBlock.end(); ++it){
543
355
		block_copy_blockToTensor(p_tabData, getNbCol(), getPadding(),
544
284
				it->getData(), it->getFullNbRow(), it->getNbCol(), it->getPadding(),
545
				it->getLocationRow(), it->getLocationCol(), neighborRing, p_nbNeighbour);
546
	}
547
8
}
548
549
///Split the current PTensor in blocks of size blockSizeRow x blockSizeCol, never bigger, and can have a neighborRing (or border) around it (no data copy, just a link with pointer)
550
/**	@param[out] vecBlock : vector of PBlock
551
 * 	@param blockSizeRow : maximum size of the created block in rows (taking account the neighborRing)
552
 * 	@param blockSizeCol : maximum size of the created block in columns (taking account the neighborRing)
553
 * 	@param neighborRing : number of border ring to be added around the created blocks
554
*/
555
template<typename T>
556
8
void PTensor<T>::splitBlockLink(std::vector<PBlock<T> > & vecBlock, size_t blockSizeRow, size_t blockSizeCol, size_t neighborRing) const{
557
8
	size_t nbInBlockRow(0lu), sizeLastInBlockRow(0lu), nbInBlockCol(0lu), sizeLastInBlockCol(0lu), nbTotalBlock(0lu);
558
8
	updateBlockSize(nbTotalBlock, nbInBlockRow, nbInBlockCol,
559
			sizeLastInBlockRow, sizeLastInBlockCol,
560
			vecBlock, blockSizeRow, blockSizeCol, neighborRing);
561
8
	size_t nbCol(getNbCol());
562
8
	size_t blockIndex(0lu);
563
26
	for(size_t i(0lu); i < nbInBlockRow; ++i){		//Loop over block rows
564
78
		for(size_t j(0lu); j < nbInBlockCol; ++j){		//Loop over block columns
565
60
			linkTensorToBlock(vecBlock[blockIndex], nbCol, blockSizeRow, blockSizeCol,
566
					blockSizeRow, blockSizeCol, i, j, neighborRing);
567
60
			++blockIndex;
568
		}
569
18
		if(sizeLastInBlockCol != 0lu){	//There is a small block at the end of the row
570
5
			linkTensorToBlock(vecBlock[blockIndex], nbCol, blockSizeRow, sizeLastInBlockCol,
571
					blockSizeRow, blockSizeCol, i, nbInBlockCol, neighborRing);
572
5
			++blockIndex;
573
		}
574
	}
575
8
	if(sizeLastInBlockRow != 0lu){	//There is a small blocks row as last row
576
6
		for(size_t j(0lu); j < nbInBlockCol; ++j){		//Loop over block columns
577
4
			linkTensorToBlock(vecBlock[blockIndex], nbCol, sizeLastInBlockRow, blockSizeCol,
578
					blockSizeRow, blockSizeCol, nbInBlockRow, j, neighborRing);
579
4
			++blockIndex;
580
		}
581
2
		if(sizeLastInBlockCol != 0lu){	//There is a small block at the end of the row
582
2
			linkTensorToBlock(vecBlock[blockIndex], nbCol, sizeLastInBlockRow, sizeLastInBlockCol,
583
					blockSizeRow, blockSizeCol, nbInBlockRow, nbInBlockCol, neighborRing);
584
2
			++blockIndex;
585
		}
586
	}
587
8
}
588
589
///Get the number of dimensions of the PTensor
590
/**	@return number of dimensions of the PTensor
591
*/
592
template<typename T>
593
65878
size_t PTensor<T>::getNbDim() const{return p_nbDimension;}
594
595
///Get the full size of the PTensor
596
/**	@return full size of the PTensor
597
*/
598
template<typename T>
599
size_t PTensor<T>::getFullSize() const{return p_fullSize;}
600
601
///Get the padding of the PTensor
602
/**	@return padding of the PTensor
603
*/
604
template<typename T>
605
2913
size_t PTensor<T>::getPadding() const{return p_padding;}
606
607
///Say if the data of the PTensor is aligned
608
/**	@return true if the data of the PTensor is aligned, false otherwise
609
*/
610
template<typename T>
611
3
bool PTensor<T>::isAligned() const{return p_isAligned;}
612
613
///Get the number of columns of the tensor
614
/**	@return number of columns of the tensor
615
*/
616
template<typename T>
617
10289000
size_t PTensor<T>::getNbCol() const{return p_nbCol;}
618
619
///Get the full number of rows of the tensor (all dimension merged but without the last one)
620
/**	@return full number of rows of the tensor (all dimension merged but without the last one)
621
*/
622
template<typename T>
623
249812
size_t PTensor<T>::getFullNbRow() const{return p_fullNbRow;}
624
625
///Get the allocation mode of the PTensor
626
/**	@return allocation mode of the PTensor
627
*/
628
template<typename T>
629
2672
AllocMode::AllocMode PTensor<T>::getAllocMode() const{return p_allocMode;}
630
631
///Get the shape of the PTensor
632
/**	@return shape of the PTensor
633
*/
634
template<typename T>
635
2691
const size_t * PTensor<T>::getShape() const{return p_shape;}
636
637
///Get the data of the PTensor
638
/**	@return data of the PTensor
639
*/
640
template<typename T>
641
71
const T * PTensor<T>::getData() const{return p_tabData;}
642
643
///Get the data of the PTensor
644
/**	@return data of the PTensor
645
*/
646
template<typename T>
647
110
T * PTensor<T>::getData(){return p_tabData;}
648
649
///Get the value at index
650
/**	@param index ; index of the value to get
651
 * 	@return value at index
652
*/
653
template<typename T>
654
19964464
const T & PTensor<T>::getValue(size_t index) const{
655
19964464
	return p_tabData[index];
656
}
657
658
///Get the value at index
659
/**	@param index ; index of the value to get
660
 * 	@return value at index
661
*/
662
template<typename T>
663
113861
T & PTensor<T>::getValue(size_t index){
664
113861
	return p_tabData[index];
665
}
666
667
///Get the value at index
668
/**	@param indexRow : row index of the value to get
669
 * 	@param indexCol : column index of the value to get
670
 * 	@return value at index
671
*/
672
template<typename T>
673
19964464
const T & PTensor<T>::getValue(size_t indexRow, size_t indexCol) const{
674
19964464
	return getValue(indexRow*(p_nbCol + p_padding) + indexCol);
675
}
676
677
///Get the value at index
678
/**	@param indexRow : row index of the value to get
679
 * 	@param indexCol : column index of the value to get
680
 * 	@return value at index
681
*/
682
template<typename T>
683
113861
T & PTensor<T>::getValue(size_t indexRow, size_t indexCol){
684
113861
	return getValue(indexRow*(p_nbCol + p_padding) + indexCol);
685
}
686
687
///Copy function of PTensor
688
/**	@param other : class to copy
689
*/
690
template<typename T>
691
void PTensor<T>::copyPTensor(const PTensor<T> & other){
692
	p_isAligned = other.p_isAligned;
693
	p_allocMode = other.p_allocMode;
694
	p_nbNeighbour = other.p_nbNeighbour;
695
	p_nbScalRow = other.p_nbScalRow;
696
	p_isOwnData = other.p_isOwnData;
697
	if(p_isOwnData){
698
		reserve(other.p_reservedShape, other.p_reservedNbDimension);
699
		resize(other.p_shape, other.p_nbDimension);
700
		for(size_t i(0lu); i < p_fullSize; ++i){
701
			p_tabData[i] = other.p_tabData[i];
702
		}
703
	}else{
704
		p_reservedShape = other.p_reservedShape;
705
		p_reservedNbDimension = other.p_reservedNbDimension;
706
		p_shape = other.p_shape;
707
		p_nbDimension = other.p_nbDimension;
708
709
		p_fullSize = other.p_fullSize;
710
		p_tabData = other.p_tabData;
711
712
		p_padding = other.p_padding;
713
		p_fullPaddedSize = other.p_fullPaddedSize;
714
		p_nbCol = other.p_nbCol;
715
		p_fullNbRow = other.p_fullNbRow;
716
	}
717
}
718
719
///Initialisation function of the class PTensor
720
/**	@param allocMode : allocation mode (AllocMode::NONE, AllocMode::ALIGNED, AllocMode::PADDING)
721
 * 	@param tabShape : shape of the table to be allocated
722
 * 	@param nbDim : number of dimensions of the PTensor
723
*/
724
template<typename T>
725
3520
void PTensor<T>::initialisationPTensor(AllocMode::AllocMode allocMode, const size_t * tabShape, size_t nbDim){
726
3520
	p_tabData = NULL;
727
3520
	p_shape = NULL;
728
3520
	p_nbDimension = 0lu;
729
3520
	p_reservedShape = NULL;
730
3520
	p_reservedNbDimension = 0lu;
731
3520
	p_padding = 0lu;
732
3520
	p_isAligned = false;
733
3520
	p_allocMode = allocMode;
734
3520
	p_nbNeighbour = 1lu;
735
3520
	p_nbScalRow = 0lu;
736
3520
	p_fullSize = 0lu;
737
3520
	p_fullPaddedSize = 0lu;
738
3520
	p_nbCol = 0lu;
739
3520
	p_fullNbRow = 0lu;
740
3520
	resize(tabShape, nbDim);
741
3520
}
742
743
///Free the table of data
744
template<typename T>
745
6922
void PTensor<T>::freeTabData(){
746

6922
	if(p_tabData == NULL || !p_isOwnData){return;}
747
3424
	if(p_isAligned){freeAlignedVector(p_tabData);}
748
1205
	else{delete [] p_tabData;}
749
3424
	p_tabData = NULL;
750
}
751
752
///Copy tensor data into a block
753
/**	@param[out] block : block to be set
754
 * 	@param tensorNbCol : number of columns of the tensor
755
 * 	@param blockSizeRow : current block size rows
756
 * 	@param blockSizeCol : current block size columns
757
 * 	@param fullBlockSizeRow : full number of block rows
758
 * 	@param fullBlockSizeCol : full number of block columns
759
 * 	@param i : row index of the current block
760
 * 	@param j : columns index of the current block
761
 * 	@param neighborRing : number of border ring of padding around a block
762
*/
763
template<typename T>
764
71
void PTensor<T>::copyTensorToBlock(PBlock<T> & block, size_t tensorNbCol, size_t blockSizeRow, size_t blockSizeCol,
765
					size_t fullBlockSizeRow, size_t fullBlockSizeCol, size_t i, size_t j, size_t neighborRing) const
766
{
767
71
	block.resize(p_allocMode, blockSizeRow, blockSizeCol);	//Let's resize the block
768
71
	block.setNbVecNeighbour(p_nbNeighbour);
769
71
	size_t currentBlockIdxRow(i*(fullBlockSizeRow - 2lu*neighborRing));		//Let's determine its location in the main PTensor
770
71
	size_t currentBlockIdxCol(j*(fullBlockSizeCol - 2lu*neighborRing*p_nbNeighbour));
771
71
	block.setLocation(currentBlockIdxRow, currentBlockIdxCol);
772
773
71
	block_copy_tensorToBlock(block.getData(), blockSizeRow, blockSizeCol, block.getPadding(),
774
				currentBlockIdxRow, currentBlockIdxCol,
775
71
				p_tabData, tensorNbCol, p_padding);
776
71
}
777
778
///Link tensor data into a block
779
/**	@param[out] block : block to be set
780
 * 	@param tensorNbCol : number of columns of the tensor
781
 * 	@param blockSizeRow : current block size rows
782
 * 	@param blockSizeCol : current block size columns
783
 * 	@param fullBlockSizeRow : full number of block rows
784
 * 	@param fullBlockSizeCol : full number of block columns
785
 * 	@param i : row index of the current block
786
 * 	@param j : columns index of the current block
787
 * 	@param neighborRing : number of border ring of padding around a block
788
*/
789
template<typename T>
790
71
void PTensor<T>::linkTensorToBlock(PBlock<T> & block, size_t tensorNbCol, size_t blockSizeRow, size_t blockSizeCol,
791
					size_t fullBlockSizeRow, size_t fullBlockSizeCol, size_t i, size_t j, size_t neighborRing) const
792
{
793
71
	size_t currentBlockIdxRow(i*(fullBlockSizeRow - 2lu*neighborRing));		//Let's determine its location in the main PTensor
794
71
	size_t currentBlockIdxCol(j*(fullBlockSizeCol - 2lu*neighborRing*p_nbNeighbour));
795
796
71
	size_t tensorColSize(tensorNbCol + p_padding);
797
71
	T * ptrData = p_tabData + currentBlockIdxRow*tensorColSize + currentBlockIdxCol;
798
799
71
	size_t tabDim[] = {blockSizeRow, blockSizeCol};
800
71
	size_t blockPadding(tensorColSize - blockSizeCol);
801
71
	block.copyPointer(ptrData, tabDim, 2lu, p_isAligned, blockPadding);
802
71
	block.setLocation(currentBlockIdxRow, currentBlockIdxCol);
803
71
	block.setNbVecNeighbour(p_nbNeighbour);
804
71
	block.p_padding = getNbCol() - blockSizeCol;
805
71
}
806
807
///Compute an update size of given parameters by respect to the block creation
808
/**	@param[out] nbTotalBlock : total number of blocks
809
 * 	@param[out] nbInBlockRow : number of inside block on rows
810
 * 	@param[out] nbInBlockCol : number of inside block on columns
811
 * 	@param[out] sizeLastInBlockRow : size of the last block on the row
812
 * 	@param[out] sizeLastInBlockCol : size of the last block on the row
813
 * 	@param[out] vecBlock : vector of PBlock
814
 * 	@param blockSizeRow : maximum size of the created block in rows (taking account the neighborRing)
815
 * 	@param[out] blockSizeCol : maximum size of the created block in columns (taking account the neighborRing) (can be adjusted)
816
 * 	@param neighborRing : number of border ring to be added around the created blocks
817
*/
818
template<typename T>
819
16
void PTensor<T>::updateBlockSize(size_t & nbTotalBlock, size_t & nbInBlockRow, size_t & nbInBlockCol,
820
				size_t & sizeLastInBlockRow, size_t & sizeLastInBlockCol,
821
				std::vector<PBlock<T> > & vecBlock, size_t blockSizeRow, size_t & blockSizeCol, size_t neighborRing) const
822
{
823
	//Modify blockSizeCol if it is not a multiple of the p_nbNeighbour
824
16
	if(blockSizeCol % p_nbNeighbour != 0lu){
825
		size_t nbVecBlock(blockSizeCol/p_nbNeighbour);
826
		blockSizeCol = nbVecBlock*p_nbNeighbour;
827
	}
828
16
	size_t nbRow(getFullNbRow()), nbCol(getNbCol());
829
830
16
	nbInBlockRow = 0lu;
831
16
	sizeLastInBlockRow = 0lu;
832
16
	splitBlockSize(nbInBlockRow, sizeLastInBlockRow, blockSizeRow, nbRow, neighborRing, 1lu);
833
16
	nbInBlockCol = 0lu;
834
16
	sizeLastInBlockCol = 0lu;
835
16
	splitBlockSize(nbInBlockCol, sizeLastInBlockCol, blockSizeCol, nbCol, neighborRing, p_nbNeighbour);
836
837
16
	nbTotalBlock = (nbInBlockRow + (sizeLastInBlockRow != 0lu))*(nbInBlockCol + (sizeLastInBlockCol != 0lu));
838
16
	if(vecBlock.size() != nbTotalBlock){
839
16
		vecBlock.resize(nbTotalBlock);		//Let's resize the vector of blocks
840
	}
841
16
}
842
843
///@brief How to write a class in a file
844
template<typename Stream, typename T>
845
struct DataStream<Stream, DataStreamMode::WRITE, PTensor<T> >{
846
	///Get the size of a class PTensor T
847
	/**	@param[out] ds : stream to write the class PTensor T
848
	 * 	@param data : data to be saved
849
	 * 	@return true on success, false otherwise
850
	*/
851
2310
	static bool data_stream(Stream & ds, PTensor<T> & data){
852
2310
		return data.writeStream(ds);
853
	}
854
};
855
856
///@brief How to read a class in a file
857
template<typename Stream, typename T>
858
struct DataStream<Stream, DataStreamMode::READ, PTensor<T> >{
859
	///Get the size of a class PTensor T
860
	/**	@param[out] ds : stream to load the class PTensor T
861
	 * 	@param data : data to be saved
862
	 * 	@return true on success, false otherwise
863
	*/
864
660
	static bool data_stream(Stream & ds, PTensor<T> & data){
865
660
		return data.readStream(ds);
866
	}
867
};
868
869
870
871
872
873
#endif
874
875
876