chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:05 +08:00
commit 4f3b7da785
7394 changed files with 2005594 additions and 0 deletions
@@ -0,0 +1,873 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
// @author AbdelRauf
#include <array/ShapeDescriptor.h>
#include <helpers/ShapeBuilders.h>
#include <helpers/shape.h>
#include <helpers/ModularHasher.h>
#include "helpers/ShapeUtils.h"
namespace sd {
//////////////////////////////////////////////////////////////////////////
// equal to operator
bool ShapeDescriptor::operator==(const ShapeDescriptor& other) const {
// First check scalar values to fail fast
if (_rank != other._rank ||
_dataType != other._dataType ||
_order != other._order ||
_extraProperties != other._extraProperties ||
_offset != other._offset) {
return false;
}
// Handle null pointers
if (_shape_strides == nullptr && other._shape_strides == nullptr) {
return true;
}
if (_shape_strides == nullptr || other._shape_strides == nullptr) {
return false;
}
// Compare shape and strides
const int total_length = (_rank < 1 ? 1 : _rank) * 2;
return memcmp(_shape_strides, other._shape_strides, total_length * sizeof(LongType)) == 0;
}
//////////////////////////////////////////////////////////////////////////
// less than operator
bool ShapeDescriptor::operator<(const ShapeDescriptor &other) const {
return std::tie(_extraProperties, _rank, _dataType, _order, _shape_strides) <
std::tie(other._extraProperties, other._rank, other._dataType, other._order, other._shape_strides);
}
LongType *ShapeDescriptor::toShapeInfo() const {
// for empty array use original
return ShapeBuilders::createShapeInfoFrom(const_cast<ShapeDescriptor *>(this));
}
ShapeDescriptor::~ShapeDescriptor() {
// no-op
if(_shape_strides != nullptr && this->ownsShapeStrides) {
delete[] _shape_strides;
_shape_strides = nullptr;
}
}
LongType ShapeDescriptor::offset() {
return _offset;
}
ShapeDescriptor::ShapeDescriptor(const DataType type, const char order, const LongType *shape, const LongType rank)
: _rank(rank), _order(order), _dataType(type) {
int rank2 = rank < 1 ? 1 : rank;
_shape_strides = new LongType[2 * rank2];
this->ownsShapeStrides = true;
if(order != 'c' && order != 'f') {
std::string errorMessage;
errorMessage += "Invalid ordering from shape buffer";
errorMessage += std::to_string(order);
delete[] _shape_strides;
THROW_EXCEPTION(errorMessage.c_str());
}
if(!DataTypeUtils::validDataType(_dataType)) {
delete[] _shape_strides;
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
auto _shape = _shape_strides;
for (int i = 0; i < rank2; i++) {
_shape[i] = shape[i];
}
_extraProperties = ArrayOptions::flagForDataType(type);
fillStrides();
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const DataType type, const char order, const LongType *shape,
const LongType *strides, const LongType rank, LongType extras = -1) {
if(shape == nullptr)
THROW_EXCEPTION("ShapeDescriptor constructor: Shape can not be null!");
_shape_strides = nullptr;
ownsShapeStrides = false;
if(type == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
ownsShapeStrides = true;
//note this used to operate directly on the vector buffer
//it now does manual copies with more checks.
//this is to handle the 0 length case.
if(rank < 1) {
_shape_strides = new LongType[2 * rank];
_dataType = type;
_order = order;
_rank = rank;
_extraProperties = extras;
} else {
_shape_strides = new LongType [2 * rank];
_dataType = type;
_order = order;
_rank = rank;
_extraProperties = extras;
auto _shape = _shape_strides;
auto _strides = _shape_strides + rank;
for (int e = 0; e < rank; e++) {
_shape[e] = shape[e];
if(rank > 1 && shape[e] == 0 && !ArrayOptions::hasPropertyBitSet(_extraProperties, ARRAY_EMPTY)) {
_extraProperties = ArrayOptions::setPropertyBitForFlagsValue(_extraProperties, ARRAY_EMPTY);
}
if(strides != nullptr)
_strides[e] = strides[e];
}
if(strides == nullptr)
fillStrides();
}
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
//////////////////////////////////////////////////////////////////////////
ShapeDescriptor::ShapeDescriptor(const DataType type, const char order, const std::vector<LongType> &shape)
: _order(order), _dataType(type) {
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
_rank = shape.size();
_extraProperties = ArrayOptions::defaultFlag();
_extraProperties = ArrayOptions::setDataTypeValue(_extraProperties, type);
int rank2 = shape.size() < 1 ? 1 : shape.size();
_shape_strides = new LongType [2 * rank2];
this->ownsShapeStrides = true;
if(_rank > 0) {
auto _shape = _shape_strides;
for (int i = 0; i < _rank; i++) {
_shape[i] = shape[i];
if(shape[i] == 0 && !ArrayOptions::hasPropertyBitSet(_extraProperties, ARRAY_EMPTY)) {
_extraProperties = ArrayOptions::setPropertyBitForFlagsValue(_extraProperties, ARRAY_EMPTY);
}
}
fillStrides();
}
_order = order;
if(_order != 'c' && _order != 'f') {
std::string errorMessage;
errorMessage += "Invalid ordering from shape buffer";
errorMessage += std::to_string(_order);
delete[] _shape_strides;
THROW_EXCEPTION(errorMessage.c_str());
}
if(!DataTypeUtils::validDataType(_dataType)) {
delete[] _shape_strides;
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
//////////////////////////////////////////////////////////////////////////
ShapeDescriptor::ShapeDescriptor(const DataType type, const char order, const std::vector<LongType> &shape,
const std::vector<LongType> &strides, const LongType ews)
: ShapeDescriptor(type, order, shape, strides) {
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const DataType type, const LongType length)
: _rank(1), _order('c'), _dataType(type), _extraProperties(0) {
_shape_strides = new LongType [2];
_shape_strides[0] = length;
_shape_strides[1] = 1; //{shape, stride}
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const LongType *shapeInfo, bool validateDataType, bool overrideStrides) {
if(shapeInfo == nullptr) {
THROW_EXCEPTION("ShapeDescriptor constructor: Shape info cannot be null!");
}
sd::LongType rankVal = shape::rank(shapeInfo);
if(rankVal < 0 || rankVal > SD_MAX_RANK) {
std::string errorMessage;
errorMessage += "Shape descriptor created with invalid rank: ";
errorMessage += std::to_string(rankVal);
errorMessage += ". Valid range is 0 to ";
errorMessage += std::to_string(SD_MAX_RANK);
THROW_EXCEPTION(errorMessage.c_str());
}
if(rankVal == 0) {
//detect when the shape buffer values are unset.
auto len = shape::shapeInfoLength(rankVal);
//min number of values in a shape info buffer
bool allZero = true;
for(int i = 0; i < len; i++) {
if(shapeInfo[i] != 0) {
allZero = false;
break;
}
}
if(allZero) {
THROW_EXCEPTION("Found shape buffer with all zero values. Values likely unset.");
}
}
_shape_strides = nullptr;
_order = shape::order(shapeInfo);
this->ownsShapeStrides = true;
if(_order != 'c' && _order != 'f') {
std::string errorMessage;
errorMessage += "Invalid ordering from shape buffer";
errorMessage += std::to_string(_order);
THROW_EXCEPTION(errorMessage.c_str());
}
_rank = static_cast<sd::LongType >(rankVal);
_extraProperties = shape::extra(shapeInfo);
_dataType = ArrayOptions::dataType(shapeInfo);
if(_rank > 0 && shape::isEmptyConst(shapeInfo)) {
_shape_strides = new LongType[2 * _rank];
auto _strides = _shape_strides + _rank;
auto shapePtr = shape::shapeOf(shapeInfo);
for (LongType e = 0; e < _rank; e++) {
_shape_strides[e] = shapePtr[e];
_strides[e] = 0;
}
}
else if (_rank > 0 && !shape::isEmptyConst(shapeInfo)) {
_shape_strides = new LongType[2 * rankVal];
auto _strides = _shape_strides + _rank;
auto shapePtr = shape::shapeOf(shapeInfo);
auto stridePtr = shape::stride(shapeInfo);
if(overrideStrides) {
LongType *stridesNew = shape::order(shapeInfo) == 'c' ? shape::calcStrides(shapePtr, rankVal) : shape::calcStridesFortran(shapePtr, rankVal);
for (LongType e = 0; e < _rank; e++) {
_shape_strides[e] = shapePtr[e];
_shape_strides[e + _rank] = stridesNew[e];
}
delete[] stridesNew;
} else {
for (LongType e = 0; e < _rank; e++) {
_shape_strides[e] = shapePtr[e];
_shape_strides[e + _rank] = stridePtr[e];
}
}
//validate construction of the shape descriptor. This is to prevent flag regressions when modifying
//_extraProperties.
//ensure that we only validate this for array size > 1
if(!ArrayOptions::hasPropertyBitSet(_extraProperties, ARRAY_EMPTY) && this->arrLength() > 1) {
for(int i = 0; i < _rank; i++) {
if(_strides[i] == 0 && shapePtr[i] != 1) {
std::string errorMessage;
errorMessage += "Shape descriptor:";
errorMessage += toString();
errorMessage += "Array set as not empty but stride is not 0. Index is ";
errorMessage += std::to_string(i);
errorMessage += " Stride is ";
errorMessage += std::to_string(_strides[i]);
//append the full _shape_strides data
errorMessage += " _shape_strides is ";
for(int j = 0; j < _rank * 2; j++) {
errorMessage += std::to_string(_shape_strides[j]);
if(j < _rank * 2 - 1) {
errorMessage += ", ";
}
}
THROW_EXCEPTION(errorMessage.c_str());
}
}
} else if(this->arrLength() > 1) {
for(int i = 0; i < _rank; i++) {
if(_strides[i] != 0) {
std::string errorMessage;
errorMessage += "Array set as not empty but stride is 0. Index is";
errorMessage += std::to_string(i);
THROW_EXCEPTION(errorMessage.c_str());
}
}
}
} else if(!shape::isEmptyConst(shapeInfo)) { // Handle scalar case
_shape_strides = new LongType [2]; // Since we're setting shape and stride
_shape_strides[0] = 0; // Shape for scalar
_shape_strides[1] = 1; // Stride for scalar
} else {
_shape_strides = new LongType[2];
_shape_strides[0] = 0;
_shape_strides[1] = 0;
}
_order = shape::order(shapeInfo);
_dataType = ArrayOptions::dataType(shapeInfo);
if(validateDataType && _dataType == UNKNOWN) {
std::string errorMessage;
errorMessage += "Shape descriptor created with invalid data type ";
errorMessage += DataTypeUtils::asString(_dataType);
errorMessage += " extra properties for data type was ";
errorMessage += DataTypeUtils::asString(ArrayOptions::dataTypeValue(_extraProperties));
errorMessage += " Underlying extra value was ";
errorMessage += std::to_string(_extraProperties);
THROW_EXCEPTION(errorMessage.c_str());
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const LongType *shapeInfo, const DataType dtypeOverride, const bool overrideStrides)
: ShapeDescriptor(shapeInfo, false, overrideStrides) {
if(dtypeOverride == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
_dataType = dtypeOverride;
_order = shape::order(shapeInfo);
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
//data type has already been set by another constructor. We need to update the _extraProperties
//to reflect the new data type. This is effectively a cast.
_extraProperties = ArrayOptions::propertyWithoutDataTypeValue(_extraProperties);
_extraProperties = ArrayOptions::setDataTypeValue(_extraProperties, dtypeOverride);
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const LongType *shapeInfo, const LongType *dtypeOverride)
: ShapeDescriptor(shapeInfo, ArrayOptions::dataType(dtypeOverride), false) {
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
ShapeDescriptor::ShapeDescriptor(const LongType *shapeInfo, const LongType *dtypeOverride,
const LongType *orderOverride)
: ShapeDescriptor(shapeInfo, ArrayOptions::dataType(dtypeOverride), false) {
_order = shape::order(orderOverride);
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
int ShapeDescriptor::rank() const { return _rank; }
LongType ShapeDescriptor::arrLength() const {
if(_shape_strides== nullptr) {
return 0;
}
// when _ews == 1 allocation length is also array length
LongType len = 1;
for (int i = 0; i < _rank; i++) len *= _shape_strides[i];
return len;
}
void ShapeDescriptor::print() const {
printf("ShapeDescriptor: [");
for (int i = 0; i < _rank; i++) {
printf("%lld", _shape_strides[i]);
if (i < _rank - 1) printf(", ");
}
printf("], [");
for (int i = _rank; i < 2 * _rank; i++) {
printf("%lld", _shape_strides[i]);
if (i < 2 * _rank - 1) printf(", ");
}
printf("], %c, %s, %lld\n", _order, DataTypeUtils::asString(_dataType).c_str(), _extraProperties);
}
LongType ShapeDescriptor::allocLength() const {
if (_paddedAllocSize > 0) return _paddedAllocSize;
auto _shape = _shape_strides;
auto _strides = _shape_strides + _rank;
int rank2 = _rank < 1 ? 1 : _rank;
LongType len = 1;
if (_rank > 1) {
// calculate using max stride
int ind = _order == 'c' ? 0 : rank2 - 1;
return _shape[ind] * _strides[ind];
}
for (int i = 0; i < rank2; i++) {
len += (_shape[i] - 1) * _strides[i];
}
return len;
}
void ShapeDescriptor::collectStoreStackTrace() {
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
this->storeStackTrace = backward::StackTrace();
#ifdef __cpp_exceptions
try {
this->storeStackTrace.load_here(32);
} catch (...) {
// Stack trace capture failed - storeStackTrace will remain empty (size() == 0)
}
#else
this->storeStackTrace.load_here(32);
#endif
#endif
}
LongType ShapeDescriptor::validate() const {
auto status = SHAPE_DESC_OK;
bool is_continous = true;
//exclude scalars on purpose here
if (_rank > 0 || _rank > SD_MAX_RANK) status |= SHAPE_DESC_INCORRECT_RANK;
auto _shape = _shape_strides;
auto _strides = _shape_strides + _rank;
if(_order != 'c' && _order != 'f') {
THROW_EXCEPTION("Invalid ordering from shape buffer");
}
bool hasZero = false;
for (int i = 0; i < _rank; i++) {
if (_shape[i] == 0) {
hasZero = true;
break;
}
}
//this check isn't correct for vectors
if (_rank > 0 && !shape::isVector(_shape_strides,2) && !hasZero) {
if (_order == 'c') {
for (int j = _rank - 2; j >= 0; j--) {
LongType currentStride = _strides[j];
LongType allowedStride = _strides[j + 1] * _shape[j + 1];
if (currentStride < allowedStride) {
status = status | SHAPE_DESC_INCORRECT_STRIDES;
break;
}
is_continous = is_continous & (currentStride == allowedStride);
}
} else {
for (int j = 1; j < _rank; j++) {
LongType currentStride = _strides[j];
LongType allowedStride = _strides[j - 1] * _shape[j - 1];
if (currentStride < allowedStride) {
status = status | SHAPE_DESC_INCORRECT_STRIDES;
break;
}
is_continous = is_continous & (currentStride == allowedStride);
}
}
int index = (_order == 'c') ? _rank - 1 : 0;
auto correctEws = is_continous ? _strides[index] : 0;
}
if(isEmpty()) {
for(int i = 0; i < _rank; i++) {
if(_strides[i] != 0) {
std::string errorMessage;
errorMessage += "Array set as empty but stride is not 0. Index is ";
errorMessage += std::to_string(i);
errorMessage += " Stride is ";
errorMessage += std::to_string(_strides[i]);
THROW_EXCEPTION(errorMessage.c_str());
break;
}
}
}
if(!DataTypeUtils::validDataType(_dataType)) {
THROW_EXCEPTION("Shape descriptor created with invalid data type");
}
return status;
}
char ShapeDescriptor::order() const { return _order; }
DataType ShapeDescriptor::dataType() const {
if(!DataTypeUtils::validDataType(_dataType)) {
std::string errorMessage;
errorMessage += "Shape descriptor created with invalid data type";
errorMessage += DataTypeUtils::asString(_dataType);
THROW_EXCEPTION(errorMessage.c_str());
}
return _dataType;
}
bool ShapeDescriptor::isEmpty() const { return (_extraProperties & ARRAY_EMPTY) == ARRAY_EMPTY; }
bool ShapeDescriptor::isScalar() const { return (!isEmpty() && rank() == 0) || (rank() == 1 && arrLength() == 1); }
sd::LongType * ShapeDescriptor::shape_strides() { return _shape_strides; }
const LongType *ShapeDescriptor::stridesPtr() const {
return _shape_strides == nullptr ? nullptr : _shape_strides + _rank;
}
ShapeDescriptor::ShapeDescriptor(const ShapeDescriptor &other) {
_rank = other._rank;
_extraProperties = other._extraProperties;
if(other._dataType == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
_dataType = other._dataType;
_order = other._order;
_shape_strides = other._shape_strides;
this->ownsShapeStrides = false;
_paddedAllocSize = other._paddedAllocSize;
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
}
//////////////////////////////////////////////////////////////////////////
ShapeDescriptor::ShapeDescriptor(const DataType type, const char order, const std::vector<LongType> &shape,
const std::vector<LongType> &strides)
: _order(order), _dataType(type) {
_rank = shape.size();
int rank2 = _rank < 1 ? 1 : _rank;
_shape_strides = new LongType [2 * rank2];
this->ownsShapeStrides = true;
#if defined(SD_GCC_FUNCTRACE)
// - backward-cpp's backtrace() is NOT safe during very early JVM initialization
#ifdef __cpp_exceptions
try {
this->st.load_here();
} catch (...) {
// Stack trace capture failed - st will remain empty (size() == 0)
}
#else
this->st.load_here();
#endif
#endif
auto _shape = _shape_strides;
auto _strides = _shape_strides + rank2;
if (!shape.empty() && strides.size() != shape.size() ) {
for (int i = 0; i < rank2; i++) {
_shape[i] = shape[i];
}
fillStrides();
} else {
for (int i = 0; i < rank2; i++) {
_shape[i] = shape[i];
_strides[i] = strides[i];
}
}
}
ShapeDescriptor * ShapeDescriptor::emptyDescriptor(const DataType type) {
ShapeDescriptor *descriptor = new ShapeDescriptor();
if(type == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
descriptor->_dataType = type;
descriptor->_extraProperties = ARRAY_EMPTY | ArrayOptions::flagForDataType(type);
descriptor->_rank = 0;
descriptor->_order = 'c';
descriptor->ownsShapeStrides = true;
descriptor->_shape_strides = new LongType [1];
descriptor->_shape_strides[0] = 0;
return descriptor;
}
ShapeDescriptor * ShapeDescriptor::scalarDescriptor(const DataType type) {
ShapeDescriptor *descriptor = new ShapeDescriptor();
if(type == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
descriptor->_dataType = type;
descriptor->_extraProperties = ArrayOptions::flagForDataType(type);
descriptor->_rank = 0;
descriptor->_order = 'c';
descriptor->ownsShapeStrides = true;
descriptor->_shape_strides = new LongType [2];
descriptor->_shape_strides[0] = 0;
descriptor->_shape_strides[1] = 1;
descriptor->_offset = 0;
return descriptor;
}
ShapeDescriptor * ShapeDescriptor::vectorDescriptor(const LongType length, const DataType type) {
ShapeDescriptor *descriptor = new ShapeDescriptor();
if(type == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
descriptor->_dataType = type;
descriptor->_shape_strides = new LongType [2];
descriptor->_shape_strides[0] = length;
descriptor->_shape_strides[1] = 0;
descriptor->ownsShapeStrides = true;
descriptor->_offset = 0;
if (length > 0) {
descriptor->_shape_strides[1] = 1;
descriptor->_extraProperties = ArrayOptions::flagForDataType(type);
}
else {
descriptor->_shape_strides[1] = 0;
descriptor->_extraProperties = ARRAY_EMPTY;
descriptor->_extraProperties = ArrayOptions::setDataTypeValue(descriptor->_extraProperties, type);
}
descriptor->_order = 'c';
descriptor->_rank = 1;
return descriptor;
}
ShapeDescriptor * ShapeDescriptor::paddedBufferDescriptor(const DataType type, const char order,
const std::vector<LongType> &shape,
const std::vector<LongType> &paddings) {
ShapeDescriptor *descriptor = new ShapeDescriptor();
if(type == UNKNOWN)
THROW_EXCEPTION("Shape descriptor created with invalid data type");
descriptor->_dataType = type;
descriptor->_order = order;
descriptor->_rank = shape.size();
descriptor->_extraProperties = ArrayOptions::flagForDataType(type);
descriptor->ownsShapeStrides = true;
if (descriptor->_rank < 1) {
return descriptor;
}
int rank2 = descriptor->_rank < 1 ? 1 : descriptor->_rank;
descriptor->_shape_strides = new LongType [2 * rank2];
auto _shape = descriptor->_shape_strides;
auto _strides = descriptor->_shape_strides + rank2;
for (size_t i = 0; i < shape.size(); i++) {
_shape[i] = shape[i];
}
// calculate strides with paddings
int min_rank = static_cast<size_t>(descriptor->_rank) > paddings.size() ? paddings.size() : rank2;
bool is_continous = true;
if (order == 'c') {
_strides[rank2 - 1] = 1L;
for (int j = descriptor->_rank - 2; j >= 0; j--) {
LongType pad = (j + 1 < min_rank) ? paddings[j + 1] : 0;
_strides[j] = _strides[j + 1] * (_shape[j + 1] + pad);
descriptor->_extraProperties = descriptor->_extraProperties | (_shape[j + 1] == 0);
if (pad != 0) is_continous = false;
}
if (!is_continous && descriptor->_rank > 0) {
LongType size_pad = paddings.size() > 0 ? paddings[0] : 0;
// alloc size should be supplied manually as we dont have place to store it
descriptor->_paddedAllocSize = _strides[0] * (_shape[0] + size_pad);
}
} else {
_strides[0] = 1L;
for (int j = 1; j < rank2; j++) {
LongType pad = (j - 1 < min_rank) ? paddings[j - 1] : 0;
_strides[j] = _strides[j - 1] * (_shape[j - 1] + pad);
descriptor->_extraProperties = descriptor->_extraProperties | (_shape[j - 1] == 0);
if (pad != 0) is_continous = false;
}
if (!is_continous && descriptor->_rank > 0) {
LongType size_pad = paddings.size() >= static_cast<size_t>(descriptor->_rank) ? paddings[descriptor->_rank - 1] : 0;
// alloc size should be supplied manually as we dont have place to store it
descriptor->_paddedAllocSize = _strides[descriptor->_rank - 1] * (_shape[descriptor->_rank - 1] + size_pad);
}
}
if (!is_continous) descriptor->_extraProperties |= ARRAY_HAS_PADDED_BUFFER;
return descriptor;
}
} // namespace sd
namespace std {
size_t hash<sd::ShapeDescriptor>::operator()(sd::ShapeDescriptor k) const {
// Check cache first
if (k._hash_computed) {
return k._cached_hash;
}
// Check cache first
if (k._hash_computed) {
return k._cached_hash;
}
using namespace sd::helpers::detail;
// Combine order and dataType into initial hash
uint64_t hash = ModularHasher::combine_hashes({
static_cast<uint64_t>(k.order()),
static_cast<uint64_t>(k.dataType()) << 8
});
// Hash the shape and strides array
sd::LongType* shape_strides = k.shape_strides();
const int stop = k.rank() * 2;
if (shape_strides != nullptr) {
hash = DataChunkHasher<sd::LongType>::hash_data(
shape_strides,
stop,
hash
);
}
// Cache the computed hash
k._cached_hash = hash;
k._hash_computed = true;
return hash;
}
} // namespace std