diff options
Diffstat (limited to 'compiler/angkor/src/ADT')
37 files changed, 2145 insertions, 0 deletions
diff --git a/compiler/angkor/src/ADT/feature/Accessor.cpp b/compiler/angkor/src/ADT/feature/Accessor.cpp new file mode 100644 index 000000000..03ff9a31e --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Accessor.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Accessor.h" + +// DO NOT REMOVE THIS FILE +// +// This file is introduced to check the self-completeness of 'Accessor.h' diff --git a/compiler/angkor/src/ADT/feature/Buffer.test.cpp b/compiler/angkor/src/ADT/feature/Buffer.test.cpp new file mode 100644 index 000000000..1e4430251 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Buffer.test.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Buffer.h" +#include "nncc/core/ADT/feature/CHWLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::feature::Shape; +using nncc::core::ADT::feature::CHWLayout; +using nncc::core::ADT::feature::Buffer; + +using nncc::core::ADT::feature::make_buffer; + +TEST(ADT_FEATURE_BUFFER, ctor) +{ + const Shape shape{4, 6, 3}; + auto buffer = make_buffer<int, CHWLayout>(shape); + + ASSERT_EQ(buffer.shape().depth(), shape.depth()); + ASSERT_EQ(buffer.shape().height(), shape.height()); + ASSERT_EQ(buffer.shape().width(), shape.width()); +} + +TEST(ADT_FEATURE_BUFFER, access) +{ + const Shape shape{4, 6, 3}; + auto buffer = make_buffer<int, CHWLayout>(shape); + + ASSERT_EQ(buffer.at(3, 5, 2), 0); + buffer.at(3, 5, 2) = 4; + + // Casting is introduced to use 'const T &at(...) const' method + ASSERT_EQ(static_cast<const Buffer<int> &>(buffer).at(3, 5, 2), 4); +} diff --git a/compiler/angkor/src/ADT/feature/CHWLayout.cpp b/compiler/angkor/src/ADT/feature/CHWLayout.cpp new file mode 100644 index 000000000..31415a1bd --- /dev/null +++ b/compiler/angkor/src/ADT/feature/CHWLayout.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/CHWLayout.h" + +using nncc::core::ADT::feature::Shape; + +static uint32_t CHW_offset(const Shape &shape, uint32_t ch, uint32_t row, uint32_t col) +{ + return (ch * shape.height() + row) * shape.width() + col; +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace feature +{ + +CHWLayout::CHWLayout() : Layout{CHW_offset} +{ + // DO NOTHING +} + +} // namespace feature +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/feature/CHWLayout.test.cpp b/compiler/angkor/src/ADT/feature/CHWLayout.test.cpp new file mode 100644 index 000000000..5610df8f3 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/CHWLayout.test.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/CHWLayout.h" + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT::feature; + +TEST(ADT_FEATURE_CHW_LAYOUT, col_increase) +{ + const Shape shape{4, 3, 6}; + const CHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 2, 1) + 1, l.offset(shape, 1, 2, 2)); +} + +TEST(ADT_FEATURE_CHW_LAYOUT, row_increase) +{ + const Shape shape{4, 3, 6}; + const CHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1) + 6, l.offset(shape, 1, 2, 1)); +} + +TEST(ADT_FEATURE_CHW_LAYOUT, ch_increase) +{ + const Shape shape{4, 3, 6}; + const CHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1) + 6 * 3, l.offset(shape, 2, 1, 1)); +} diff --git a/compiler/angkor/src/ADT/feature/HWCLayout.cpp b/compiler/angkor/src/ADT/feature/HWCLayout.cpp new file mode 100644 index 000000000..016535625 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/HWCLayout.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/HWCLayout.h" + +using nncc::core::ADT::feature::Shape; + +static uint32_t HWC_offset(const Shape &shape, uint32_t ch, uint32_t row, uint32_t col) +{ + return (row * shape.width() + col) * shape.depth() + ch; +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace feature +{ + +HWCLayout::HWCLayout() : Layout{HWC_offset} +{ + // DO NOTHING +} + +} // namespace feature +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/feature/HWCLayout.test.cpp b/compiler/angkor/src/ADT/feature/HWCLayout.test.cpp new file mode 100644 index 000000000..d1f359753 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/HWCLayout.test.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/HWCLayout.h" + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT::feature; + +TEST(ADT_FEATURE_HWC_LAYOUT, C_increase) +{ + const uint32_t C = 4; + const uint32_t H = 3; + const uint32_t W = 6; + + const Shape shape{C, H, W}; + const HWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1) + 1, l.offset(shape, 2, 1, 1)); +} + +TEST(ADT_FEATURE_HWC_LAYOUT, W_increase) +{ + const uint32_t C = 4; + const uint32_t H = 3; + const uint32_t W = 6; + + const Shape shape{C, H, W}; + const HWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 2, 1) + C, l.offset(shape, 1, 2, 2)); +} + +TEST(ADT_FEATURE_HWC_LAYOUT, H_increase) +{ + const uint32_t C = 4; + const uint32_t H = 3; + const uint32_t W = 6; + + const Shape shape{C, H, W}; + const HWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1) + W * C, l.offset(shape, 1, 2, 1)); +} diff --git a/compiler/angkor/src/ADT/feature/Layout.cpp b/compiler/angkor/src/ADT/feature/Layout.cpp new file mode 100644 index 000000000..49ab7cbf9 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Layout.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Layout.h" + +#include <cassert> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace feature +{ + +Layout::Layout(const Func &func) : _func{func} { assert(_func != nullptr); } + +} // namespace feature +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/feature/Layout.test.cpp b/compiler/angkor/src/ADT/feature/Layout.test.cpp new file mode 100644 index 000000000..023594e16 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Layout.test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Layout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::feature::Shape; +using nncc::core::ADT::feature::Layout; + +static uint32_t offset_0(const Shape &, uint32_t, uint32_t, uint32_t) { return 0; } +static uint32_t offset_1(const Shape &, uint32_t, uint32_t, uint32_t) { return 1; } + +TEST(ADT_FEATURE_LAYOUT, ctor) +{ + Layout l{offset_0}; + + ASSERT_EQ(l.offset(Shape{4, 3, 6}, 1, 1, 1), 0); +} + +TEST(ADT_FEATURE_LAYOUT, copy) +{ + Layout orig{offset_0}; + Layout copy{offset_1}; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6}, 1, 1, 1), 1); + + copy = orig; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6}, 1, 1, 1), 0); +} + +TEST(ADT_FEATURE_LAYOUT, move) +{ + Layout orig{offset_0}; + Layout move{offset_1}; + + ASSERT_EQ(move.offset(Shape{4, 3, 6}, 1, 1, 1), 1); + + move = std::move(orig); + + ASSERT_EQ(move.offset(Shape{4, 3, 6}, 1, 1, 1), 0); +} diff --git a/compiler/angkor/src/ADT/feature/Overlay.test.cpp b/compiler/angkor/src/ADT/feature/Overlay.test.cpp new file mode 100644 index 000000000..c8e2943f8 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Overlay.test.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Overlay.h" +#include "nncc/core/ADT/feature/CHWLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::feature::Shape; +using nncc::core::ADT::feature::CHWLayout; +using nncc::core::ADT::feature::Overlay; + +using nncc::core::ADT::feature::make_overlay; + +TEST(ADT_FEATURE_OVERLAY, ctor) +{ + const Shape shape{4, 6, 3}; + + int data[4 * 6 * 3] = { + 0, + }; + auto overlay = make_overlay<int, CHWLayout>(shape, data); + + ASSERT_EQ(overlay.shape().depth(), shape.depth()); + ASSERT_EQ(overlay.shape().height(), shape.height()); + ASSERT_EQ(overlay.shape().width(), shape.width()); +} + +TEST(ADT_FEATURE_OVERLAY, read) +{ + const Shape shape{4, 6, 3}; + + int data[4 * 6 * 3] = { + 0, + }; + const auto overlay = make_overlay<int, CHWLayout>(shape, data); + + CHWLayout layout{}; + + ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 0); + data[layout.offset(shape, 3, 5, 2)] = 2; + ASSERT_EQ(overlay.at(3, 5, 2), 2); +} + +TEST(ADT_FEATURE_OVERLAY, access) +{ + const Shape shape{4, 6, 3}; + + int data[4 * 6 * 3] = { + 0, + }; + auto overlay = make_overlay<int, CHWLayout>(shape, data); + + CHWLayout layout{}; + + ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 0); + overlay.at(3, 5, 2) = 4; + ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 4); +} diff --git a/compiler/angkor/src/ADT/feature/Reader.cpp b/compiler/angkor/src/ADT/feature/Reader.cpp new file mode 100644 index 000000000..5f1c0d22b --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Reader.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/feature/Reader.h" + +// DO NOT REMOVE THIS FILE +// +// This file is introduced to check the self-completeness of 'Reader.h' diff --git a/compiler/angkor/src/ADT/feature/Shape.test.cpp b/compiler/angkor/src/ADT/feature/Shape.test.cpp new file mode 100644 index 000000000..9216182f0 --- /dev/null +++ b/compiler/angkor/src/ADT/feature/Shape.test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include <nncc/core/ADT/feature/Shape.h> + +#include <gtest/gtest.h> + +TEST(ADT_FEATURE_SHAPE, ctor) +{ + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + nncc::core::ADT::feature::Shape shape{C, H, W}; + + ASSERT_EQ(shape.depth(), C); + ASSERT_EQ(shape.height(), H); + ASSERT_EQ(shape.width(), W); +} + +TEST(ADT_FEATURE_SHAPE, num_elements) +{ + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + using nncc::core::ADT::feature::Shape; + using nncc::core::ADT::feature::num_elements; + + ASSERT_EQ(num_elements(Shape{C, H, W}), C * H * W); +} + +TEST(ADT_FEATURE_SHAPE, operator_eq) +{ + using nncc::core::ADT::feature::Shape; + + // NOTE We use ASSERT_TRUE/ASSERT_FALSE instead of ASSERT_EQ/ASSERT_NE as it is impossible to + // introduce negative tests with ASSERT_NE (it uses operator!= instead of operator==). + ASSERT_TRUE(Shape(1, 1, 1) == Shape(1, 1, 1)); + ASSERT_FALSE(Shape(1, 1, 1) == Shape(2, 1, 1)); + ASSERT_FALSE(Shape(1, 1, 1) == Shape(1, 2, 1)); + ASSERT_FALSE(Shape(1, 1, 1) == Shape(1, 1, 2)); +} diff --git a/compiler/angkor/src/ADT/kernel/Buffer.test.cpp b/compiler/angkor/src/ADT/kernel/Buffer.test.cpp new file mode 100644 index 000000000..da344593e --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Buffer.test.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Buffer.h" +#include "nncc/core/ADT/kernel/NCHWLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::kernel::Shape; +using nncc::core::ADT::kernel::NCHWLayout; +using nncc::core::ADT::kernel::Buffer; + +using nncc::core::ADT::kernel::make_buffer; + +TEST(ADT_KERNEL_BUFFER, ctor) +{ + const Shape shape{2, 4, 6, 3}; + auto buffer = make_buffer<int, NCHWLayout>(shape); + + ASSERT_EQ(buffer.shape().count(), shape.count()); + ASSERT_EQ(buffer.shape().depth(), shape.depth()); + ASSERT_EQ(buffer.shape().height(), shape.height()); + ASSERT_EQ(buffer.shape().width(), shape.width()); +} + +TEST(ADT_KERNEL_BUFFER, access) +{ + const Shape shape{2, 4, 6, 3}; + auto buffer = make_buffer<int, NCHWLayout>(shape); + + ASSERT_EQ(buffer.at(1, 3, 5, 2), 0); + buffer.at(1, 3, 5, 2) = 4; + + // Casting is introduced to use 'const T &at(...) const' method + ASSERT_EQ(static_cast<const Buffer<int> &>(buffer).at(1, 3, 5, 2), 4); +} diff --git a/compiler/angkor/src/ADT/kernel/IndexEnumerator.cpp b/compiler/angkor/src/ADT/kernel/IndexEnumerator.cpp new file mode 100644 index 000000000..0b1db090d --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/IndexEnumerator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/IndexEnumerator.h" + +#include <cassert> +#include <algorithm> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace kernel +{ + +IndexEnumerator::IndexEnumerator(const Shape &shape) : _cursor(0) +{ + _max[0] = shape.width(); + _max[1] = shape.height(); + _max[2] = shape.depth(); + _max[3] = shape.count(); + + std::fill(_cur, _cur + 4, 0); + + // NOTE Null dimension should NOT exist + assert(std::find(_max, _max + 4, 0) == (_max + 4)); +} + +bool IndexEnumerator::valid(void) const { return _cursor < 4; } + +uint32_t IndexEnumerator::count(void) const { return _cur[3]; } +uint32_t IndexEnumerator::depth(void) const { return _cur[2]; } +uint32_t IndexEnumerator::height(void) const { return _cur[1]; } +uint32_t IndexEnumerator::width(void) const { return _cur[0]; } + +void IndexEnumerator::advance(void) +{ + while (_cursor < 4) + { + if (_cur[_cursor] + 1 < _max[_cursor]) + { + break; + } + + ++_cursor; + } + + if (_cursor == 4) + { + return; + } + + // Increment index + _cur[_cursor] += 1; + + // Reset indices for lower dimensions + for (uint32_t head = 0; head < _cursor; ++head) + { + _cur[head] = 0; + } + + // Reset cursor + _cursor = 0; +} + +} // namespace kernel +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/kernel/IndexEnumerator.test.cpp b/compiler/angkor/src/ADT/kernel/IndexEnumerator.test.cpp new file mode 100644 index 000000000..21ba19209 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/IndexEnumerator.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/IndexEnumerator.h" + +#include <vector> +#include <algorithm> + +#include <gtest/gtest.h> + +using nncc::core::ADT::kernel::Shape; +using nncc::core::ADT::kernel::IndexEnumerator; + +TEST(ADT_KERNEL_INDEX_ENUMERATOR, iterate_full_range) +{ + const uint32_t N = 2; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + const Shape shape{N, C, H, W}; + + std::vector<uint32_t> count; + count.resize(N * C * H * W, 0); + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + const uint32_t offset = ((e.count() * C + e.depth()) * H + e.height()) * W + e.width(); + count.at(offset) += 1; + } + + ASSERT_TRUE(std::all_of(count.begin(), count.end(), [](uint32_t n) { return n == 1; })); +} diff --git a/compiler/angkor/src/ADT/kernel/Layout.cpp b/compiler/angkor/src/ADT/kernel/Layout.cpp new file mode 100644 index 000000000..acadd2448 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Layout.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Layout.h" + +#include <cassert> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace kernel +{ + +Layout::Layout(const Func &func) : _func{func} +{ + // DO NOTHING +} + +} // namespace kernel +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/kernel/Layout.test.cpp b/compiler/angkor/src/ADT/kernel/Layout.test.cpp new file mode 100644 index 000000000..94885cd4e --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Layout.test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Layout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::kernel::Shape; +using nncc::core::ADT::kernel::Layout; + +static uint32_t offset_0(const Shape &, uint32_t, uint32_t, uint32_t, uint32_t) { return 0; } +static uint32_t offset_1(const Shape &, uint32_t, uint32_t, uint32_t, uint32_t) { return 1; } + +TEST(ADT_KERNEL_LAYOUT, ctor) +{ + Layout l{offset_0}; + + ASSERT_EQ(l.offset(Shape{4, 3, 6, 5}, 1, 1, 1, 1), 0); +} + +TEST(ADT_KERNEL_LAYOUT, copy) +{ + Layout orig{offset_0}; + Layout copy{offset_1}; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6, 5}, 1, 1, 1, 1), 1); + + copy = orig; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6, 5}, 1, 1, 1, 1), 0); +} + +TEST(ADT_KERNEL_LAYOUT, move) +{ + Layout orig{offset_0}; + Layout move{offset_1}; + + ASSERT_EQ(move.offset(Shape{4, 3, 6, 5}, 1, 1, 1, 1), 1); + + move = std::move(orig); + + ASSERT_EQ(move.offset(Shape{4, 3, 6, 5}, 1, 1, 1, 1), 0); +} diff --git a/compiler/angkor/src/ADT/kernel/NCHWLayout.cpp b/compiler/angkor/src/ADT/kernel/NCHWLayout.cpp new file mode 100644 index 000000000..be7551182 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/NCHWLayout.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/NCHWLayout.h" + +using nncc::core::ADT::kernel::Shape; + +static uint32_t NCHW_offset(const Shape &shape, uint32_t n, uint32_t ch, uint32_t row, uint32_t col) +{ + return (((n * shape.depth() + ch) * shape.height() + row) * shape.width() + col); +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace kernel +{ + +NCHWLayout::NCHWLayout() : Layout{NCHW_offset} +{ + // DO NOTHING +} + +} // namespace kernel +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/kernel/NCHWLayout.test.cpp b/compiler/angkor/src/ADT/kernel/NCHWLayout.test.cpp new file mode 100644 index 000000000..ba03b7b04 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/NCHWLayout.test.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/NCHWLayout.h" + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT::kernel; + +TEST(ADT_KERNEL_KERNEL_NCHW_LAYOUT, col_increment) +{ + const Shape shape{4, 3, 6, 5}; + const NCHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + 1, l.offset(shape, 1, 1, 1, 2)); +} + +TEST(ADT_KERNEL_KERNEL_NCHW_LAYOUT, row_increment) +{ + const Shape shape{4, 3, 6, 5}; + const NCHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + 5, l.offset(shape, 1, 1, 2, 1)); +} + +TEST(ADT_KERNEL_KERNEL_NCHW_LAYOUT, ch_increment) +{ + const Shape shape{4, 3, 6, 5}; + const NCHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + 6 * 5, l.offset(shape, 1, 2, 1, 1)); +} + +TEST(ADT_KERNEL_KERNEL_NCHW_LAYOUT, n_increment) +{ + const Shape shape{4, 3, 6, 5}; + const NCHWLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + 3 * 6 * 5, l.offset(shape, 2, 1, 1, 1)); +} diff --git a/compiler/angkor/src/ADT/kernel/NHWCLayout.cpp b/compiler/angkor/src/ADT/kernel/NHWCLayout.cpp new file mode 100644 index 000000000..8e0524425 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/NHWCLayout.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/NHWCLayout.h" + +using nncc::core::ADT::kernel::Shape; + +static uint32_t NHWC_offset(const Shape &shape, uint32_t n, uint32_t ch, uint32_t row, uint32_t col) +{ + return ((n * shape.height() + row) * shape.width() + col) * shape.depth() + ch; +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace kernel +{ + +NHWCLayout::NHWCLayout() : Layout{NHWC_offset} +{ + // DO NOTHING +} + +} // namespace kernel +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/kernel/NHWCLayout.test.cpp b/compiler/angkor/src/ADT/kernel/NHWCLayout.test.cpp new file mode 100644 index 000000000..2c5df7d89 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/NHWCLayout.test.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/NHWCLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::kernel::Shape; +using nncc::core::ADT::kernel::NHWCLayout; + +TEST(ADT_KERNEL_KERNEL_NHWC_LAYOUT, ch_increment) +{ + const uint32_t N = 4; + const uint32_t C = 3; + const uint32_t H = 6; + const uint32_t W = 5; + + const Shape shape{N, C, H, W}; + const NHWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + 1, l.offset(shape, 1, 2, 1, 1)); +} + +TEST(ADT_KERNEL_KERNEL_NHWC_LAYOUT, col_increment) +{ + const uint32_t N = 4; + const uint32_t C = 3; + const uint32_t H = 6; + const uint32_t W = 5; + + const Shape shape{N, C, H, W}; + const NHWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + C, l.offset(shape, 1, 1, 1, 2)); +} + +TEST(ADT_KERNEL_KERNEL_NHWC_LAYOUT, row_increment) +{ + const uint32_t N = 4; + const uint32_t C = 3; + const uint32_t H = 6; + const uint32_t W = 5; + + const Shape shape{N, C, H, W}; + const NHWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + C * W, l.offset(shape, 1, 1, 2, 1)); +} + +TEST(ADT_KERNEL_KERNEL_NHWC_LAYOUT, n_increment) +{ + const uint32_t N = 4; + const uint32_t C = 3; + const uint32_t H = 6; + const uint32_t W = 5; + + const Shape shape{N, C, H, W}; + const NHWCLayout l; + + ASSERT_EQ(l.offset(shape, 1, 1, 1, 1) + H * W * C, l.offset(shape, 2, 1, 1, 1)); +} diff --git a/compiler/angkor/src/ADT/kernel/Overlay.test.cpp b/compiler/angkor/src/ADT/kernel/Overlay.test.cpp new file mode 100644 index 000000000..e80ebbc30 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Overlay.test.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Overlay.h" +#include "nncc/core/ADT/kernel/NCHWLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::kernel::Shape; +using nncc::core::ADT::kernel::NCHWLayout; +using nncc::core::ADT::kernel::Overlay; + +using nncc::core::ADT::kernel::make_overlay; + +TEST(ADT_KERNEL_OVERLAY, ctor) +{ + const Shape shape{2, 4, 6, 3}; + + int data[2 * 4 * 6 * 3] = { + 0, + }; + auto overlay = make_overlay<int, NCHWLayout>(shape, data); + + ASSERT_EQ(overlay.shape().count(), shape.count()); + ASSERT_EQ(overlay.shape().depth(), shape.depth()); + ASSERT_EQ(overlay.shape().height(), shape.height()); + ASSERT_EQ(overlay.shape().width(), shape.width()); +} + +TEST(ADT_KERNEL_OVERLAY, read) +{ + const Shape shape{2, 4, 6, 3}; + + int data[2 * 4 * 6 * 3] = { + 0, + }; + const auto overlay = make_overlay<int, NCHWLayout>(shape, data); + + NCHWLayout layout{}; + + ASSERT_EQ(data[layout.offset(shape, 1, 3, 5, 2)], 0); + data[layout.offset(shape, 1, 3, 5, 2)] = 2; + ASSERT_EQ(overlay.at(1, 3, 5, 2), 2); +} + +TEST(ADT_KERNEL_OVERLAY, access) +{ + const Shape shape{2, 4, 6, 3}; + + int data[2 * 4 * 6 * 3] = { + 0, + }; + auto overlay = make_overlay<int, NCHWLayout>(shape, data); + + NCHWLayout layout{}; + + ASSERT_EQ(data[layout.offset(shape, 1, 3, 5, 2)], 0); + overlay.at(1, 3, 5, 2) = 4; + ASSERT_EQ(data[layout.offset(shape, 1, 3, 5, 2)], 4); +} diff --git a/compiler/angkor/src/ADT/kernel/Reader.cpp b/compiler/angkor/src/ADT/kernel/Reader.cpp new file mode 100644 index 000000000..9e34167c8 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Reader.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Reader.h" + +// DO NOT REMOVE THIS FILE +// This file is introduced to test the self-completeness of 'Reader.h' diff --git a/compiler/angkor/src/ADT/kernel/Shape.cpp b/compiler/angkor/src/ADT/kernel/Shape.cpp new file mode 100644 index 000000000..8ad1edb67 --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Shape.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/kernel/Shape.h" + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace kernel +{ + +bool operator==(const Shape &l, const Shape &r) +{ + return (l.count() == r.count()) && (l.depth() == r.depth()) && (l.height() == r.height()) && + (l.width() == r.width()); +} + +} // namespace kernel +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/kernel/Shape.test.cpp b/compiler/angkor/src/ADT/kernel/Shape.test.cpp new file mode 100644 index 000000000..da608fb7f --- /dev/null +++ b/compiler/angkor/src/ADT/kernel/Shape.test.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include <nncc/core/ADT/kernel/Shape.h> + +#include <gtest/gtest.h> + +TEST(ADT_KERNEL_SHAPE, ctor) +{ + const uint32_t N = 1; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + nncc::core::ADT::kernel::Shape shape{N, C, H, W}; + + ASSERT_EQ(shape.count(), N); + ASSERT_EQ(shape.depth(), C); + ASSERT_EQ(shape.height(), H); + ASSERT_EQ(shape.width(), W); +} + +TEST(ADT_KERNEL_SHAPE, num_elements) +{ + const uint32_t N = 1; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + using nncc::core::ADT::kernel::Shape; + using nncc::core::ADT::kernel::num_elements; + + ASSERT_EQ(num_elements(Shape{N, C, H, W}), N * C * H * W); +} + +TEST(ADT_KERNEL_SHAPE, operator_eq) +{ + using nncc::core::ADT::kernel::Shape; + + EXPECT_TRUE(Shape(1, 1, 1, 1) == Shape(1, 1, 1, 1)); + EXPECT_FALSE(Shape(1, 1, 1, 1) == Shape(1, 1, 1, 2)); + EXPECT_FALSE(Shape(1, 1, 1, 1) == Shape(1, 1, 2, 1)); + EXPECT_FALSE(Shape(1, 1, 1, 1) == Shape(1, 2, 1, 1)); + EXPECT_FALSE(Shape(1, 1, 1, 1) == Shape(2, 1, 1, 1)); +} diff --git a/compiler/angkor/src/ADT/tensor/Buffer.test.cpp b/compiler/angkor/src/ADT/tensor/Buffer.test.cpp new file mode 100644 index 000000000..c2b6a9983 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Buffer.test.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Buffer.h" +#include "nncc/core/ADT/tensor/LexicalLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; +using nncc::core::ADT::tensor::LexicalLayout; +using nncc::core::ADT::tensor::Buffer; + +using nncc::core::ADT::tensor::make_buffer; + +TEST(ADT_TENSOR_BUFFER, ctor) +{ + const Shape shape{2, 3}; + auto buffer = make_buffer<int, LexicalLayout>(shape); + + ASSERT_EQ(buffer.shape(), shape); +} + +TEST(ADT_TENSOR_BUFFER, access) +{ + const Shape shape{2, 3}; + auto buffer = make_buffer<int, LexicalLayout>(shape); + + const Index index{1, 2}; + + ASSERT_EQ(buffer.at(index), 0); + buffer.at(index) = 4; + + // Casting is introduced to use 'const T &at(...) const' method + ASSERT_EQ(static_cast<const Buffer<int> &>(buffer).at(index), 4); +} diff --git a/compiler/angkor/src/ADT/tensor/Index.cpp b/compiler/angkor/src/ADT/tensor/Index.cpp new file mode 100644 index 000000000..61f0a7106 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Index.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Index.h" + +#include <stdexcept> +#include <algorithm> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace tensor +{ + +Index::Index(std::initializer_list<uint32_t> &&l) : _indices{l} +{ + // DO NOTHING +} + +uint32_t Index::rank(void) const { return _indices.size(); } +Index &Index::resize(uint32_t size) +{ + _indices.resize(size); + return *this; +} + +Index &Index::fill(uint32_t index) +{ + std::fill(_indices.begin(), _indices.end(), index); + return (*this); +} + +uint32_t &Index::at(uint32_t axis) { return _indices.at(axis); } +uint32_t Index::at(uint32_t axis) const { return _indices.at(axis); } + +Index operator+(const Index &lhs, const Index &rhs) +{ + if (lhs.rank() != rhs.rank()) + throw std::runtime_error("Two tensors should have same rank"); + + Index ret; + ret.resize(lhs.rank()); + for (uint32_t axis = 0; axis < lhs.rank(); axis++) + { + ret.at(axis) = lhs.at(axis) + rhs.at(axis); + } + return ret; +} + +bool operator==(const Index &lhs, const Index &rhs) +{ + if (lhs.rank() != rhs.rank()) + return false; + for (uint32_t axis = 0; axis < lhs.rank(); axis++) + { + if (lhs.at(axis) != rhs.at(axis)) + return false; + } + return true; +} + +} // namespace tensor +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/tensor/Index.test.cpp b/compiler/angkor/src/ADT/tensor/Index.test.cpp new file mode 100644 index 000000000..230602816 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Index.test.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Index.h" + +#include <gtest/gtest.h> + +TEST(ADT_TENSOR_INDEX, ctor) +{ + nncc::core::ADT::tensor::Index index; + + ASSERT_EQ(index.rank(), 0); +} + +TEST(ADT_TENSOR_INDEX, ctor_initializer_list) +{ + const nncc::core::ADT::tensor::Index index{1, 3, 5, 7}; + + ASSERT_EQ(index.rank(), 4); + + ASSERT_EQ(index.at(0), 1); + ASSERT_EQ(index.at(1), 3); + ASSERT_EQ(index.at(2), 5); + ASSERT_EQ(index.at(3), 7); +} + +TEST(ADT_TENSOR_INDEX, operator_add) +{ + nncc::core::ADT::tensor::Index index1{1, 2, 3, 4}; + nncc::core::ADT::tensor::Index index2{5, 6, 7, 8}; + nncc::core::ADT::tensor::Index result{index1 + index2}; + + ASSERT_EQ(result.at(0), 6); + ASSERT_EQ(result.at(1), 8); + ASSERT_EQ(result.at(2), 10); + ASSERT_EQ(result.at(3), 12); +} + +TEST(ADT_TENSOR_INDEX, operator_eqaul) +{ + nncc::core::ADT::tensor::Index index1{1, 2, 3, 4}; + nncc::core::ADT::tensor::Index index2{1, 2, 3, 4}; + nncc::core::ADT::tensor::Index index3{5, 6, 7, 8}; + nncc::core::ADT::tensor::Index index4{1, 2}; + + ASSERT_TRUE(index1 == index2); + ASSERT_FALSE(index1 == index3); + ASSERT_FALSE(index1 == index4); +} + +TEST(ADT_TENSOR_INDEX, operator_add_different_size) +{ + nncc::core::ADT::tensor::Index index1{1, 2, 3, 4}; + nncc::core::ADT::tensor::Index index2{5, 6}; + + EXPECT_THROW(index1 + index2, std::runtime_error); +} + +TEST(ADT_TENSOR_INDEX, resize) +{ + nncc::core::ADT::tensor::Index index; + + index.resize(4); + + ASSERT_EQ(index.rank(), 4); +} + +TEST(ADT_TENSOR_INDEX, at) +{ + nncc::core::ADT::tensor::Index index; + + index.resize(4); + + uint32_t indices[4] = {3, 5, 2, 7}; + + for (uint32_t axis = 0; axis < 4; ++axis) + { + index.at(axis) = indices[axis]; + ASSERT_EQ(index.at(axis), indices[axis]); + } +} + +TEST(ADT_TENSOR_INDEX, copy) +{ + const nncc::core::ADT::tensor::Index original{3, 5, 2, 7}; + const nncc::core::ADT::tensor::Index copied{original}; + + ASSERT_EQ(original.rank(), copied.rank()); + + for (uint32_t axis = 0; axis < 4; ++axis) + { + ASSERT_EQ(original.at(axis), copied.at(axis)); + } +} + +TEST(ADT_TENSOR_INDEX, fill) +{ + nncc::core::ADT::tensor::Index index{1, 6}; + + index.fill(3); + + ASSERT_EQ(index.rank(), 2); + + ASSERT_EQ(index.at(0), 3); + ASSERT_EQ(index.at(1), 3); +} diff --git a/compiler/angkor/src/ADT/tensor/IndexEnumerator.cpp b/compiler/angkor/src/ADT/tensor/IndexEnumerator.cpp new file mode 100644 index 000000000..623313a2e --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/IndexEnumerator.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/IndexEnumerator.h" + +#include <cassert> + +using nncc::core::ADT::tensor::Shape; + +inline uint32_t axis_of(const Shape &shape, uint32_t cursor) +{ + const uint32_t rank = shape.rank(); + assert(cursor < rank); + return rank - cursor - 1; +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace tensor +{ + +IndexEnumerator::IndexEnumerator(const Shape &shape) : _shape{shape}, _cursor(0) +{ + const uint32_t rank = _shape.rank(); + + // Initialize _index + _index.resize(rank); + for (uint32_t axis = 0; axis < rank; ++axis) + { + _index.at(axis) = 0; + } + + // Initialize _cursor + for (_cursor = 0; _cursor < rank; ++_cursor) + { + const auto axis = axis_of(_shape, _cursor); + + if (_index.at(axis) < _shape.dim(axis)) + { + break; + } + } +} + +void IndexEnumerator::advance(void) +{ + const uint32_t rank = _shape.rank(); + + // Find axis to be updated + while (_cursor < rank) + { + const auto axis = axis_of(_shape, _cursor); + + if ((_index.at(axis)) + 1 < _shape.dim(axis)) + { + break; + } + + ++_cursor; + } + + if (_cursor == rank) + { + return; + } + + // Update index + _index.at(axis_of(_shape, _cursor)) += 1; + + for (uint32_t pos = 0; pos < _cursor; ++pos) + { + const auto axis = axis_of(_shape, pos); + _index.at(axis) = 0; + } + + // Reset cursor + _cursor = 0; +} + +} // namespace tensor +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/tensor/IndexEnumerator.test.cpp b/compiler/angkor/src/ADT/tensor/IndexEnumerator.test.cpp new file mode 100644 index 000000000..204a8aa21 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/IndexEnumerator.test.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/IndexEnumerator.h" + +#include <vector> +#include <algorithm> + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; +using nncc::core::ADT::tensor::IndexEnumerator; + +TEST(ADT_TENSOR_INDEX_ENUMERATOR, iterate_full_range) +{ + const uint32_t H = 3; + const uint32_t W = 4; + + const Shape shape{H, W}; + + std::vector<uint32_t> count; + + count.resize(H * W, 0); + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + const auto &ind = e.current(); + + ASSERT_EQ(ind.rank(), 2); + count.at(ind.at(0) * W + ind.at(1)) += 1; + } + + ASSERT_TRUE(std::all_of(count.begin(), count.end(), [](uint32_t n) { return n == 1; })); +} diff --git a/compiler/angkor/src/ADT/tensor/Layout.cpp b/compiler/angkor/src/ADT/tensor/Layout.cpp new file mode 100644 index 000000000..7faf7507d --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Layout.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Layout.h" + +#include <cassert> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace tensor +{ + +Layout::Layout(const Func &func) : _func{func} { assert(_func != nullptr); } + +} // namespace tensor +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/tensor/Layout.test.cpp b/compiler/angkor/src/ADT/tensor/Layout.test.cpp new file mode 100644 index 000000000..145adfecc --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Layout.test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Layout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; + +static uint32_t offset_0(const Shape &, const Index &) { return 0; } +static uint32_t offset_1(const Shape &, const Index &) { return 1; } + +TEST(ADT_TENSOR_LAYOUT, ctor) +{ + nncc::core::ADT::tensor::Layout l{offset_0}; + + ASSERT_EQ(l.offset(Shape{4, 3, 6}, Index{1, 1, 1}), 0); +} + +TEST(ADT_TENSOR_LAYOUT, copy) +{ + nncc::core::ADT::tensor::Layout orig{offset_0}; + nncc::core::ADT::tensor::Layout copy{offset_1}; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6}, Index{1, 1, 1}), 1); + + copy = orig; + + ASSERT_EQ(copy.offset(Shape{4, 3, 6}, Index{1, 1, 1}), 0); +} + +TEST(ADT_TENSOR_LAYOUT, move) +{ + nncc::core::ADT::tensor::Layout orig{offset_0}; + nncc::core::ADT::tensor::Layout move{offset_1}; + + ASSERT_EQ(move.offset(Shape{4, 3, 6}, Index{1, 1, 1}), 1); + + move = std::move(orig); + + ASSERT_EQ(move.offset(Shape{4, 3, 6}, Index{1, 1, 1}), 0); +} diff --git a/compiler/angkor/src/ADT/tensor/LexicalLayout.cpp b/compiler/angkor/src/ADT/tensor/LexicalLayout.cpp new file mode 100644 index 000000000..671c60cec --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/LexicalLayout.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/LexicalLayout.h" + +#include <cassert> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; + +// NOTE This forward declaration is introduced to minimize code diff +static uint32_t lexical_offset(const Shape &shape, const Index &index) +{ + assert(shape.rank() > 0); + assert(shape.rank() == index.rank()); + + const uint32_t rank = shape.rank(); + + uint32_t res = index.at(0); + + for (uint32_t axis = 1; axis < rank; ++axis) + { + res *= shape.dim(axis); + res += index.at(axis); + } + + return res; +} + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace tensor +{ + +LexicalLayout::LexicalLayout() : Layout(lexical_offset) +{ + // DO NOTHING +} + +} // namespace tensor +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/tensor/LexicalLayout.test.cpp b/compiler/angkor/src/ADT/tensor/LexicalLayout.test.cpp new file mode 100644 index 000000000..8f9b7296f --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/LexicalLayout.test.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/LexicalLayout.h" + +#include <type_traits> + +#include <gtest/gtest.h> + +TEST(ADT_TENSOR_LEXICAL_LAYOUT, last) +{ + const nncc::core::ADT::tensor::Shape shape{4, 3, 6}; + const nncc::core::ADT::tensor::Index curr{1, 1, 1}; + const nncc::core::ADT::tensor::Index next{1, 1, 2}; + + const nncc::core::ADT::tensor::LexicalLayout l; + + ASSERT_EQ(l.offset(shape, curr) + 1, l.offset(shape, next)); +} + +TEST(ADT_TENSOR_LEXICAL_LAYOUT, lexical_middle) +{ + const nncc::core::ADT::tensor::Shape shape{4, 3, 6}; + const nncc::core::ADT::tensor::Index curr{1, 1, 1}; + const nncc::core::ADT::tensor::Index next{1, 2, 1}; + + const nncc::core::ADT::tensor::LexicalLayout l; + + ASSERT_EQ(l.offset(shape, curr) + 6, l.offset(shape, next)); +} + +TEST(ADT_TENSOR_LEXICAL_LAYOUT, lexical_first) +{ + const nncc::core::ADT::tensor::Shape shape{4, 3, 6}; + const nncc::core::ADT::tensor::Index curr{1, 1, 1}; + const nncc::core::ADT::tensor::Index next{2, 1, 1}; + + const nncc::core::ADT::tensor::LexicalLayout l; + + ASSERT_EQ(l.offset(shape, curr) + 6 * 3, l.offset(shape, next)); +} diff --git a/compiler/angkor/src/ADT/tensor/Overlay.test.cpp b/compiler/angkor/src/ADT/tensor/Overlay.test.cpp new file mode 100644 index 000000000..aacb5a9a1 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Overlay.test.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Overlay.h" +#include "nncc/core/ADT/tensor/LexicalLayout.h" + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; +using nncc::core::ADT::tensor::LexicalLayout; +using nncc::core::ADT::tensor::Overlay; + +using nncc::core::ADT::tensor::make_overlay; + +TEST(ADT_TENSOR_OVERLAY, ctor) +{ + const Shape shape{2, 3}; + + int data[2 * 3] = { + 0, + }; + auto view = make_overlay<int, LexicalLayout>(shape, data); + + ASSERT_EQ(view.shape(), shape); +} + +TEST(ADT_TENSOR_OVERLAY, read) +{ + const Shape shape{2, 3}; + + int data[2 * 3] = { + 0, + }; + const auto view = make_overlay<int, LexicalLayout>(shape, data); + + LexicalLayout layout{}; + + const Index index{1, 2}; + + ASSERT_EQ(data[layout.offset(shape, index)], 0); + data[layout.offset(shape, index)] = 2; + ASSERT_EQ(view.at(index), 2); +} + +TEST(ADT_TENSOR_OVERLAY, access) +{ + const Shape shape{2, 3}; + + int data[2 * 3] = { + 0, + }; + auto view = make_overlay<int, LexicalLayout>(shape, data); + + LexicalLayout layout{}; + + const Index index{1, 2}; + + ASSERT_EQ(data[layout.offset(shape, index)], 0); + view.at(index) = 4; + ASSERT_EQ(data[layout.offset(shape, index)], 4); +} diff --git a/compiler/angkor/src/ADT/tensor/Reader.cpp b/compiler/angkor/src/ADT/tensor/Reader.cpp new file mode 100644 index 000000000..d79e66dac --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Reader.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Reader.h" + +// DO NOT REMOVE THIS FILE +// +// This file is introduced to check the self-completeness of 'Reader.h' diff --git a/compiler/angkor/src/ADT/tensor/Shape.cpp b/compiler/angkor/src/ADT/tensor/Shape.cpp new file mode 100644 index 000000000..fb39ba192 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Shape.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Shape.h" + +#include <algorithm> + +namespace nncc +{ +namespace core +{ +namespace ADT +{ +namespace tensor +{ + +Shape::Shape(std::initializer_list<uint32_t> &&l) : _dims{l} +{ + // DO NOTHING +} + +uint32_t Shape::rank(void) const { return _dims.size(); } +Shape &Shape::resize(uint32_t size) +{ + _dims.resize(size); + return *this; +} + +uint32_t &Shape::dim(uint32_t axis) { return _dims.at(axis); } +uint32_t Shape::dim(uint32_t axis) const { return _dims.at(axis); } + +Shape &Shape::squeeze(void) +{ + _dims.erase(std::remove(_dims.begin(), _dims.end(), 1), _dims.end()); + return *this; +} + +uint64_t num_elements(const Shape &shape) +{ + uint64_t res = 1; + + for (uint32_t axis = 0; axis < shape.rank(); ++axis) + { + res *= shape.dim(axis); + } + + return res; +} + +Shape squeeze(const Shape &shape) +{ + Shape res{shape}; + res.squeeze(); + return res; +} + +bool operator==(const Shape &lhs, const Shape &rhs) +{ + if (lhs.rank() != rhs.rank()) + { + return false; + } + + for (uint32_t axis = 0; axis < lhs.rank(); ++axis) + { + if (lhs.dim(axis) != rhs.dim(axis)) + { + return false; + } + } + + return true; +} + +} // namespace tensor +} // namespace ADT +} // namespace core +} // namespace nncc diff --git a/compiler/angkor/src/ADT/tensor/Shape.test.cpp b/compiler/angkor/src/ADT/tensor/Shape.test.cpp new file mode 100644 index 000000000..711ae3d40 --- /dev/null +++ b/compiler/angkor/src/ADT/tensor/Shape.test.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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. + */ + +#include "nncc/core/ADT/tensor/Shape.h" + +#include <gtest/gtest.h> + +TEST(ADT_TENSOR_SHAPE, ctor) +{ + nncc::core::ADT::tensor::Shape shape; + + ASSERT_EQ(shape.rank(), 0); +} + +TEST(ADT_TENSOR_SHAPE, ctor_initializer_list) +{ + nncc::core::ADT::tensor::Shape shape{1, 3, 5, 7}; + + ASSERT_EQ(shape.rank(), 4); + + ASSERT_EQ(shape.dim(0), 1); + ASSERT_EQ(shape.dim(1), 3); + ASSERT_EQ(shape.dim(2), 5); + ASSERT_EQ(shape.dim(3), 7); +} + +TEST(ADT_TENSOR_SHAPE, resize) +{ + nncc::core::ADT::tensor::Shape shape; + + shape.resize(4); + + ASSERT_EQ(shape.rank(), 4); +} + +TEST(ADT_TENSOR_SHAPE, dim) +{ + nncc::core::ADT::tensor::Shape shape; + + shape.resize(4); + + uint32_t dims[4] = {3, 5, 2, 7}; + + for (uint32_t axis = 0; axis < 4; ++axis) + { + shape.dim(axis) = dims[axis]; + ASSERT_EQ(shape.dim(axis), dims[axis]); + } +} + +TEST(ADT_TENSOR_SHAPE, copy) +{ + const nncc::core::ADT::tensor::Shape original{3, 5, 2, 7}; + const nncc::core::ADT::tensor::Shape copied{original}; + + ASSERT_EQ(original.rank(), copied.rank()); + + for (uint32_t axis = 0; axis < 4; ++axis) + { + ASSERT_EQ(original.dim(axis), copied.dim(axis)); + } +} + +TEST(ADT_TENSOR_SHAPE, num_elements_rank_0) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::num_elements; + + Shape rank_0_shape; + + ASSERT_EQ(num_elements(rank_0_shape), 1); +} + +TEST(ADT_TENSOR_SHAPE, num_elements_zero) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::num_elements; + + ASSERT_EQ(num_elements(Shape{0, 0, 0, 0}), 0); +} + +TEST(ADT_TENSOR_SHAPE, num_elements_nonzero) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::num_elements; + + ASSERT_EQ(num_elements(Shape{2, 3}), 6); +} + +TEST(ADT_TENSOR_SHAPE, num_elements_nulldim) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::num_elements; + + ASSERT_EQ(num_elements(Shape{2, 0, 3}), 0); +} + +TEST(ADT_TENSOR_SHAPE, squeeze_neg) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::squeeze; + + auto squeezed = squeeze(Shape{3, 5, 2}); + + ASSERT_EQ(squeezed.rank(), 3); + ASSERT_EQ(squeezed.dim(0), 3); + ASSERT_EQ(squeezed.dim(1), 5); + ASSERT_EQ(squeezed.dim(2), 2); +} + +TEST(ADT_TENSOR_SHAPE, squeeze_neg_0) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::squeeze; + + auto squeezed = squeeze(Shape{3, 0, 2}); + + ASSERT_EQ(squeezed.rank(), 3); + ASSERT_EQ(squeezed.dim(0), 3); + ASSERT_EQ(squeezed.dim(1), 0); + ASSERT_EQ(squeezed.dim(2), 2); +} + +TEST(ADT_TENSOR_SHAPE, squeeze_pos) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::squeeze; + + auto squeezed = squeeze(Shape{3, 1, 2}); + + ASSERT_EQ(squeezed.rank(), 2); + ASSERT_EQ(squeezed.dim(0), 3); + ASSERT_EQ(squeezed.dim(1), 2); +} + +TEST(ADT_TENSOR_SHAPE, squeeze_nested) +{ + using nncc::core::ADT::tensor::Shape; + using nncc::core::ADT::tensor::squeeze; + + Shape shape{3, 1, 2}; + + shape.squeeze().squeeze(); + + ASSERT_EQ(shape.rank(), 2); + ASSERT_EQ(shape.dim(0), 3); + ASSERT_EQ(shape.dim(1), 2); +} + +TEST(ADT_TENSOR_SHAPE, eq_negative_on_unmatched_rank) +{ + const nncc::core::ADT::tensor::Shape left{1, 1, 1}; + const nncc::core::ADT::tensor::Shape right{1, 1, 1, 1}; + + ASSERT_FALSE(left == right); +} + +TEST(ADT_TENSOR_SHAPE, eq_negative_on_unmatched_dim) +{ + const nncc::core::ADT::tensor::Shape left{2, 3}; + const nncc::core::ADT::tensor::Shape right{2, 4}; + + ASSERT_FALSE(left == right); +} + +TEST(ADT_TENSOR_SHAPE, eq_positive) +{ + const nncc::core::ADT::tensor::Shape left{2, 3}; + const nncc::core::ADT::tensor::Shape right{2, 3}; + + ASSERT_TRUE(left == right); +} |