Files
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

111 lines
3.6 KiB
C++

/* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
==============================================================================*/
#ifndef TENSORFLOW_LITE_EXPERIMENTAL_SHLO_SHAPE_H_
#define TENSORFLOW_LITE_EXPERIMENTAL_SHLO_SHAPE_H_
#include <cstddef>
#include <cstdint>
#include "absl/container/inlined_vector.h"
#include "absl/types/span.h"
namespace shlo_ref {
// The SHLO Spec states that dimensions are non-negative. We diverge from the
// spec here to use negative values to represent dynamic dimensions.
using DimensionSize = int64_t;
using Axis = size_t;
inline constexpr DimensionSize kDynamicDimension = -1;
inline constexpr Axis kMaxNumDimensions = 6;
using Strides = absl::InlinedVector<DimensionSize, kMaxNumDimensions>;
class Shape {
public:
Shape() = default;
explicit Shape(absl::Span<const DimensionSize> dims);
absl::Span<const DimensionSize> Dimensions() const;
absl::Span<DimensionSize> MutableDimensions();
// range(rank(x))
absl::InlinedVector<Axis, kMaxNumDimensions> Axes() const;
// shape(x)[axis]
DimensionSize Dim(Axis axis) const;
// list(map(lambda axis: dim(x, axis), filter(lambda axis: axis < rank(x),
// axes)))
absl::InlinedVector<DimensionSize, kMaxNumDimensions> Dims(
absl::Span<const Axis> axes) const;
// size(shape(x))
size_t Rank() const;
// reduce(lambda x, y: x * y, shape(x))
// Note: in the SHLO spec, this is called size. We've diverged for readability
// and possible confusion with C++ container's usage of size().
// Precondition: shape(x) is static (does not contain kDynamicDimension).
DimensionSize NumElements() const;
// The following members are provided for compatibility with the standard
// library.
using value_type = DimensionSize;
const value_type& operator[](Axis dim) const { return dims_[dim]; }
value_type& operator[](Axis dim) { return dims_[dim]; }
auto cbegin() const { return dims_.begin(); }
auto begin() const { return dims_.begin(); }
auto begin() { return dims_.begin(); }
auto cend() const { return dims_.end(); }
auto end() const { return dims_.end(); }
auto end() { return dims_.end(); }
bool empty() const { return dims_.empty(); }
size_t size() const { return dims_.size(); }
const value_type* data() const { return dims_.data(); }
value_type* data() { return dims_.data(); }
private:
absl::InlinedVector<DimensionSize, kMaxNumDimensions> dims_;
};
bool operator==(const Shape& lhs, const Shape& rhs);
bool operator!=(const Shape& lhs, const Shape& rhs);
Strides ComputeStrides(const Shape& shape);
// Precondition: shape is static (does not contain kDynamicDimension).
template <class T>
Strides ComputeStrides(absl::Span<const T> shape) {
absl::InlinedVector<DimensionSize, kMaxNumDimensions> strides(shape.size());
if (!shape.empty()) {
strides[shape.size() - 1] = 1;
if (shape.size() > 1) {
for (size_t i = shape.size() - 1; i != 0; --i) {
strides[i - 1] = shape[i] * strides[i];
}
}
}
return strides;
}
} // namespace shlo_ref
#endif // TENSORFLOW_LITE_EXPERIMENTAL_SHLO_SHAPE_H_