blob: f6b63f4a8ee782075d7e2144e65f078da0bffee1 [file] [log] [blame]
#include "THAtomic.h"
#include "THStorage.h"
#include "generic/THStorage.c"
#include "THGenerateAllTypes.h"
#include "generic/THStorage.c"
#include "THGenerateHalfType.h"
#include "generic/THStorageCopy.c"
#include "THGenerateAllTypes.h"
#include "generic/THStorageCopy.c"
#include "THGenerateHalfType.h"
THDescBuff THLongStorage_sizeDesc(const THLongStorage *size) {
return _THSizeDesc(size->data, size->size);
}
THLongStorage *THLongStorage_newInferSize(THLongStorage *size, ptrdiff_t nElement)
{
ptrdiff_t total_size = (size->size > 0 ? 1 : 0);
ptrdiff_t dim_infer = -1;
ptrdiff_t i;
for (i = 0; i < size->size; i++) {
if (size->data[i] == -1) {
THArgCheck(dim_infer == -1, 1, "only one dimension can be inferred");
dim_infer = i;
} else {
total_size *= size->data[i];
}
}
if (dim_infer != -1) {
THDescBuff buf = THLongStorage_sizeDesc(size);
THArgCheck(total_size > 0 && nElement % total_size == 0, 2,
"size '%s' is invalid for input of with %td elements", buf.str, nElement);
} else {
THDescBuff buf = THLongStorage_sizeDesc(size);
THArgCheck(nElement == total_size, 2,
"size '%s' is invalid for input of with %td elements", buf.str, nElement);
}
THLongStorage* copy = THLongStorage_newWithSize(size->size);
THLongStorage_copy(copy, size);
if (dim_infer != -1) {
copy->data[dim_infer] = nElement / total_size;
}
return copy;
}
int THLongStorage_inferSize2(THLongStorage *output, long *sizesA, long dimsA, long *sizesB, long dimsB,
char *error_buffer, int buffer_len) {
THArgCheck(sizesA != NULL, 1, "sizesA must not be null");
THArgCheck(sizesB != NULL, 2, "sizesB must not be null");
THArgCheck(dimsA, 1, "Can't expand empty tensor a");
THArgCheck(dimsB, 1, "Can't expand empty tensor b");
ptrdiff_t ndim = dimsA > dimsB ? dimsA : dimsB;
long *expandedSizes = THAlloc(sizeof(long)*ndim);
for (long i = ndim - 1; i >= 0; --i) {
long offset = ndim - 1 - i;
long dimA = dimsA - 1 - offset;
long dimB = dimsB - 1 - offset;
long sizeA = (dimA >= 0) ? sizesA[dimA] : 1;
long sizeB = (dimB >= 0) ? sizesB[dimB] : 1;
if (sizeA == sizeB || sizeA == 1 || sizeB == 1) {
expandedSizes[i] = THMax(sizeA, sizeB);
} else {
THFree(expandedSizes);
snprintf(error_buffer, buffer_len, "The size of tensor a (%ld) must match the size of tensor b (%ld) at "
"non-singleton dimension %ld.", sizeA, sizeB, i);
return -1;
}
}
THLongStorage_resize(output, ndim);
memcpy(THLongStorage_data(output), expandedSizes, sizeof(long)*ndim);
THFree(expandedSizes);
return 0;
}
int THLongStorage_inferSizeN(THLongStorage *output, int n, long **sizes, long *dims,
char *error_buffer, int buffer_len) {
THArgCheck(n > 0, 2, "n must be greater than 0");
THArgCheck(sizes != NULL, 1, "sizes must not be null");
THArgCheck(dims != NULL, 1, "dims must not be null");
ptrdiff_t ndim = 0;
for (int j = 0; j < n; ++j) {
THArgCheck(sizes[ j ] != NULL, 1, "size %d must not be null", j);
THArgCheck(dims[ j ], 1, "Can't expand empty tensor %d", j);
ndim = dims[ j ] > ndim ? dims[ j ] : ndim;
}
long *expandedSizes = THAlloc(sizeof(long)*ndim);
for (long i = ndim - 1; i >= 0; --i) {
expandedSizes[ i ] = 1;
long offset = ndim - 1 - i;
for (int j = 0; j < n; ++j) {
long dim = dims[ j ] - 1 - offset;
long size = (dim >= 0) ? sizes[ j ][ dim ] : 1;
if (size == expandedSizes[ i ] || size == 1 || expandedSizes[ i ] == 1) {
expandedSizes[ i ] = THMax(expandedSizes[ i ], size);
} else {
THFree(expandedSizes);
snprintf(error_buffer, buffer_len, "The size of tensor %i (%ld) must match the expanded size"
"of tensor (%ld) at non-singleton dimension %ld.", j, size, expandedSizes[ i ], i);
return -1;
}
}
}
THLongStorage_resize(output, ndim);
memcpy(THLongStorage_data(output), expandedSizes, sizeof(long)*ndim);
THFree(expandedSizes);
return 0;
}
int THLongStorage_inferExpandGeometry(long *tensorSizes, long *tensorStrides, long tensorDim,
THLongStorage *sizes, long **expandedSizes, long **expandedStrides,
char *error_buffer, int buffer_len) {
ptrdiff_t ndim = THLongStorage_size(sizes);
long *expandedSizesCalc = THAlloc(sizeof(long)*ndim);
long *expandedStridesCalc = THAlloc(sizeof(long)*ndim);
// create a new geometry for the tensors
for (long i = ndim - 1; i >= 0; --i) {
long offset = ndim - 1 - i;
long dim = tensorDim - 1 - offset;
long size = (dim >= 0) ? tensorSizes[dim] : 1;
long stride = (dim >= 0) ?
tensorStrides[dim] : expandedSizesCalc[i + 1] * expandedStridesCalc[i+1];
long targetSize = THLongStorage_data(sizes)[i];
if (size != targetSize) {
if (size == 1) {
size = targetSize;
stride = 0;
} else {
THFree(expandedSizesCalc);
THFree(expandedStridesCalc);
snprintf(error_buffer, buffer_len, "The expanded size of the tensor (%ld) must match the existing size (%ld) at "
"non-singleton dimension %ld.", targetSize, size, i);
return -1;
}
}
expandedSizesCalc[i] = size;
expandedStridesCalc[i] = stride;
}
*expandedSizes = expandedSizesCalc;
*expandedStrides = expandedStridesCalc;
return 0;
}