set(NGRAPH_LIBRARIES ngraph PARENT_SCOPE)
endfunction()
+file(REMOVE "${CMAKE_BINARY_DIR}/openvino_targets_developer.cmake")
+
+unset(OpenVINODeveloperPackageTargets CACHE)
+
+function(openvino_developer_export_targets)
+ set(OpenVINODeveloperPackageTargets "${OpenVINODeveloperPackageTargets};${ARGV}")
+
+ # to allow exporting of aliased targets with the original names
+ foreach(target_name ${OpenVINODeveloperPackageTargets})
+ if(TARGET "${target_name}")
+ get_target_property(original_name ${target_name} ALIASED_TARGET)
+ if(TARGET "${original_name}")
+ message(STATUS "The name ${target_name} is an ALIAS for ${original_name}. "
+ "It will be exported to the InferenceEngineDeveloperPackage with the original name.")
+ list(REMOVE_ITEM OpenVINODeveloperPackageTargets ${target_name})
+ list(APPEND OpenVINODeveloperPackageTargets ${original_name})
+ endif()
+ endif()
+ endforeach()
+
+ list(REMOVE_DUPLICATES OpenVINODeveloperPackageTargets)
+ set(OpenVINODeveloperPackageTargets "${OpenVINODeveloperPackageTargets}" CACHE INTERNAL
+ "Paths to extra Inference Engine plugins" FORCE)
+endfunction()
+
+
add_subdirectory(openvino)
build_ngraph()
#include "details/ie_exception.hpp"
#include "ngraph/opsets/opset1.hpp"
-#include "ngraph/runtime/reference/relu.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/layer_test_utils.hpp"
#include "details/ie_exception.hpp"
#include "ngraph/opsets/opset1.hpp"
-#include "ngraph/runtime/reference/relu.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/layer_test_utils.hpp"
add_definitions(-DIN_NGRAPH_LIBRARY)
-file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
+file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp)
file(GLOB_RECURSE PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
set(NGRAPH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/ngraph CACHE INTERNAL "")
+add_subdirectory(reference)
+
# Create named folders for the sources within the .vcproj
# Empty name lists them directly under the .vcproj
C_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON)
-target_link_libraries(ngraph PRIVATE openvino::itt)
+target_link_libraries(ngraph PRIVATE openvino::itt ngraph::reference)
find_package(Graphviz QUIET)
if (GRAPHVIZ_FOUND)
target_include_directories(ngraph PRIVATE ${NGRAPH_INCLUDE_DIR}
${NGRAPH_INCLUDE_DIR}/builder
${NGRAPH_INCLUDE_DIR}/op
- ${NGRAPH_INCLUDE_DIR}/op/fused
${NGRAPH_INCLUDE_DIR}/op/util
${NGRAPH_INCLUDE_DIR}/pass
${NGRAPH_INCLUDE_DIR}/pattern
${NGRAPH_INCLUDE_DIR}/pattern/op
${NGRAPH_INCLUDE_DIR}/runtime
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
)
#Add an alias so that library can be used inside the build tree, e.g. when testing
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/coordinate.hpp"
-#include "ngraph/coordinate_diff.hpp"
-#include "ngraph/shape.hpp"
-#include "ngraph/strides.hpp"
-
-namespace ngraph
-{
- /// \brief A useful class that allows to iterate over the tensor coordinates.
- /// For example, for tensor with dimensions {2, 3} this iterator
- /// produces the following coordinates:
- /// {0,0}, {0,1}, {0,2},
- /// {1,0}, {1,1}, {2,2}
- class NGRAPH_API CoordinateIterator
- {
- public:
- /// \brief Coordinates iterator constructor
- /// \param target_shape The target shape for coordinates iteration
- /// \param is_end The flag indicates that the coordinate iterator is the last.
- CoordinateIterator(const Shape& target_shape, bool is_end = false);
-
- /// \brief The postfix operation increment the iterator by one.
- void operator++();
-
- /// \brief The prefix operation increment the iterator by one.
- CoordinateIterator operator++(int);
-
- /// \brief Increments iterator n times.
- /// \param n number of elements it should be advanced
- void operator+=(size_t n);
-
- /// \brief Iterator dereferencing operator returns reference to current pointed coordinate.
- const Coordinate& operator*() const noexcept;
-
- /// \brief Checks for iterator inequality.
- /// \param it second iterator to compare
- bool operator!=(const CoordinateIterator& it) const noexcept;
-
- /// \brief Checks for iterator equality.
- /// \param it second iterator to compare
- bool operator==(const CoordinateIterator& it) const noexcept;
-
- /// \brief Increments iterator using specified axis of the shape n times.
- /// \param axis index used for iteration
- size_t advance(size_t axis) noexcept;
-
- /// \brief Useful function to build the last iterator.
- /// Returns a singleton that points to the last iterator.
- static const CoordinateIterator& end();
-
- private:
- const Shape& m_target_shape;
- Coordinate m_coordinate;
- bool m_oob;
- };
-
- /// \brief Class which allows to calculate item index with given coordinates in tensor
- /// and helps to iterate over all coordinates.
- /// Tensor items should be placed in memory in row-major order.
- class NGRAPH_API CoordinateTransformBasic
- {
- public:
- using Iterator = CoordinateIterator;
-
- CoordinateTransformBasic(const Shape& source_shape);
-
- /// \brief The tensor element index calculation by given coordinate.
- /// \param c tensor element coordinate
- size_t index(const Coordinate& c) const noexcept;
-
- /// \brief Returns an iterator to the first coordinate of the tensor.
- CoordinateIterator begin() const noexcept;
-
- /// \brief Returns an iterator to the coordinate following the last element of the tensor.
- const CoordinateIterator& end() const noexcept;
-
- protected:
- Shape m_source_shape;
- };
-
- /// \brief Class which allows to calculate item index with given coordinates in tensor
- /// and helps to iterate over the subset of coordinates.
- /// Tensor items should be placed in memory in row-major order.
- class NGRAPH_API CoordinateTransform : protected CoordinateTransformBasic
- {
- public:
- using Iterator = CoordinateIterator;
-
- CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order,
- const CoordinateDiff& target_padding_below,
- const CoordinateDiff& target_padding_above,
- const Strides& source_dilation_strides);
-
- CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order,
- const CoordinateDiff& target_padding_below,
- const CoordinateDiff& target_padding_above);
-
- CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order);
-
- CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides);
-
- CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner);
-
- CoordinateTransform(const Shape& source_shape);
-
- /// \brief The tensor element index calculation by given coordinate.
- /// \param c tensor element coordinate
- size_t index(const Coordinate& c) const;
-
- /// \brief Checks that coordinate belongs to given coordinates subset.
- /// \param c tensor element coordinate
- bool has_source_coordinate(const Coordinate& c) const;
-
- /// \brief Convert a target-space coordinate to a source-space coordinate.
- /// \param c tensor element coordinate
- Coordinate to_source_coordinate(const Coordinate& c) const;
-
- const Shape& get_source_shape() const noexcept;
- const Shape& get_target_shape() const noexcept;
- const Coordinate& get_source_start_corner() const noexcept;
- const Coordinate& get_source_end_corner() const noexcept;
- const Strides& get_source_strides() const noexcept;
- const AxisVector& get_source_axis_order() const noexcept;
- const Strides& get_target_dilation_strides() const noexcept;
-
- /// \brief Returns an iterator to the first coordinate of the tensor.
- CoordinateIterator begin() const noexcept;
-
- /// \brief Returns an iterator to the coordinate following the last element of the tensor.
- const CoordinateIterator& end() const noexcept;
-
- private:
- Coordinate m_source_start_corner;
- Coordinate m_source_end_corner;
- Strides m_source_strides;
- AxisVector m_source_axis_order;
- CoordinateDiff m_target_padding_below;
- CoordinateDiff m_target_padding_above;
- Strides m_target_dilation_strides;
-
- Shape m_target_shape;
- size_t m_n_axes;
- };
-}
#include "ngraph/builder/autobroadcast.hpp"
#include "ngraph/builder/reduce_ops.hpp"
#include "ngraph/builder/reshape.hpp"
-#include "ngraph/coordinate_transform.hpp"
#include "ngraph/descriptor/input.hpp"
#include "ngraph/descriptor/output.hpp"
#include "ngraph/descriptor/tensor.hpp"
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <utility>
-
-#include "ngraph/runtime/reference/broadcast.hpp"
-#include "ngraph/shape_util.hpp"
-#include "ngraph/util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace opt_kernel
- {
- template <typename T>
- void broadcast_2d(
- const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
- {
- size_t index[2];
- size_t& in_index = index[out_axis];
- auto out_strides = row_major_strides(out_shape);
- for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
- {
- for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
- {
- // clang-format off
- out[index[0] * out_strides[0] +
- index[1]] =
- in[in_index];
- // clang-format on
- }
- }
- }
-
- // #define PARALLEL
- template <typename T>
- void broadcast_3d(
- const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
- {
- size_t index[3];
- size_t& in_index = index[out_axis];
- auto out_strides = row_major_strides(out_shape);
- for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
- {
- for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
- {
- for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
- {
- // clang-format off
- out[index[0] * out_strides[0] +
- index[1] * out_strides[1] +
- index[2]] =
- in[in_index];
- // clang-format on
- }
- }
- }
- }
-
- template <typename T>
- void broadcast_4d(
- const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
- {
- size_t index[4];
- size_t& in_index = index[out_axis];
- auto out_strides = row_major_strides(out_shape);
- for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
- {
- for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
- {
- for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
- {
- for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
- {
- // clang-format off
- out[index[0] * out_strides[0] +
- index[1] * out_strides[1] +
- index[2] * out_strides[2] +
- index[3]] =
- in[in_index];
- // clang-format on
- }
- }
- }
- }
- }
-
- template <typename T>
- void broadcast_5d(
- const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
- {
- size_t index[5];
- size_t& in_index = index[out_axis];
- auto out_strides = row_major_strides(out_shape);
- for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
- {
- for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
- {
- for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
- {
- for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
- {
- for (index[4] = 0; index[4] < out_shape[4]; ++index[4])
- {
- // clang-format off
- out[index[0] * out_strides[0] +
- index[1] * out_strides[1] +
- index[2] * out_strides[2] +
- index[3] * out_strides[3] +
- index[4]] =
- in[in_index];
- // clang-format on
- }
- }
- }
- }
- }
- }
-
- template <typename T>
- void broadcast_6d(
- const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
- {
- size_t index[6];
- size_t& in_index = index[out_axis];
- auto out_strides = row_major_strides(out_shape);
- for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
- {
- for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
- {
- for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
- {
- for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
- {
- for (index[4] = 0; index[4] < out_shape[4]; ++index[4])
- {
- for (index[5] = 0; index[5] < out_shape[5]; ++index[5])
- {
- // clang-format off
- out[index[0] * out_strides[0] +
- index[1] * out_strides[1] +
- index[2] * out_strides[2] +
- index[3] * out_strides[3] +
- index[4] * out_strides[4] +
- index[5]] =
- in[in_index];
- // clang-format on
- }
- }
- }
- }
- }
- }
- }
-
- template <typename T>
- void broadcast(const T* in,
- T* out,
- const Shape& in_shape,
- const Shape& out_shape,
- const AxisSet& broadcast_axes)
- {
- if (is_scalar(in_shape))
- {
- for (size_t i = 0; i < shape_size(out_shape); ++i)
- {
- out[i] = in[0];
- }
- }
- else if (in_shape.size() == 1)
- {
- size_t output_axis = 0;
- for (size_t i = 0; i < out_shape.size(); i++)
- {
- if (broadcast_axes.count(i) == 0)
- {
- output_axis = i;
- break;
- }
- }
- switch (out_shape.size())
- {
- case 2: broadcast_2d<T>(in, out, in_shape, out_shape, output_axis); break;
- case 3: broadcast_3d<T>(in, out, in_shape, out_shape, output_axis); break;
- case 4: broadcast_4d<T>(in, out, in_shape, out_shape, output_axis); break;
- case 5: broadcast_5d<T>(in, out, in_shape, out_shape, output_axis); break;
- case 6: broadcast_6d<T>(in, out, in_shape, out_shape, output_axis); break;
- default:
- runtime::reference::broadcast<T>(
- in, out, in_shape, out_shape, broadcast_axes);
- break;
- }
- }
- else
- {
- runtime::reference::broadcast<T>(in, out, in_shape, out_shape, broadcast_axes);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/runtime/reference/reshape.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace opt_kernel
- {
- void reshape(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void abs(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- // TODO: generic "abs" doesn't work here for some reason.
- out[i] = (arg[i] < T(0) ? T(-arg[i]) : arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void acos(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::acos(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void acosh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::acosh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void add(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] + arg1[i];
- }
- }
-
- template <typename T>
- void add(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x + y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void logical_and(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = static_cast<T>(arg0[i] && arg1[i]);
- }
- }
-
- template <typename T>
- void logical_and(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return static_cast<T>(x && y);
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- static inline void any(const char* arg,
- char* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- CoordinateTransform output_transform(reduce(in_shape, reduction_axes, keep_dims));
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 0;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
- out[output_transform.index(output_coord)] =
- out[output_transform.index(output_coord)] ||
- arg[input_transform.index(input_coord)];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void asin(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::asin(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void asinh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::asinh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void atan(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::atan(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename X, typename Y, typename Z>
- void atan2(const X* py, const Y* px, Z* pout, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- *pout++ = static_cast<Z>(std::atan2(*py++, *px++));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void atanh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::atanh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include <utility>
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- namespace internal
- {
- inline void
- row_major_strides(const Shape& shape, size_t* strides, size_t size) noexcept
- {
- size_t* st = strides + size - 1;
- size_t s = 1;
- for (auto d = shape.rbegin(); d != shape.rend(); d++)
- {
- *st-- = s;
- s *= *d;
- }
- std::fill(strides, st + 1, s);
- }
-
- template <typename C, typename T>
- inline T value_with_padding_or(const C& arr,
- size_t padding,
- size_t idx,
- T&& default_value)
- {
- return idx < padding ? std::forward<T>(default_value) : arr[idx - padding];
- }
-
- template <int A0, int A1, typename T, typename U, typename Functor>
- inline void numpy_autobroadcast_binop(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& shape0,
- const Shape& shape1,
- const size_t* strides0,
- const size_t* strides1,
- const size_t padding0,
- const size_t padding1,
- const Shape& output_shape,
- const size_t axis,
- const size_t stride,
- Functor elementwise_functor)
- {
- for (CoordinateIterator it(output_shape), ite = CoordinateIterator::end();;)
- {
- for (size_t i = 0; i < stride; ++i)
- *out++ = elementwise_functor(arg0[i * A0], arg1[i * A1]);
-
- arg0 += A0 ? stride : 1;
- arg1 += A1 ? stride : 1;
-
- auto p = it.advance(axis);
-
- if (it == ite)
- break;
-
- if (value_with_padding_or(shape0, padding0, p, 1) == 1)
- arg0 -= strides0[p];
-
- if (value_with_padding_or(shape1, padding1, p, 1) == 1)
- arg1 -= strides1[p];
- }
- }
-
- inline size_t calculate_fixed_axis(size_t axis, const size_t* strides)
- {
- while (axis > 0 && strides[axis - 1] == 1)
- --axis;
- return axis;
- }
- }
-
- /// \brief Helper function to implement autobroadcasting elementwise binop references.
- ///
- /// \tparam T Element type of the input tensors.
- /// \tparam U Element type of the output tensor.
- /// \tparam Functor Type of the functor for the elementwise operation. Must support
- /// operator()(T,T), and operator()(T,T) must return a value of type
- /// U.
- ///
- /// \param arg0 Pointer to the buffer for left operand input tensor.
- /// \param arg1 Pointer to the buffer for right operand input tensor.
- /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
- /// the caller, and must be large enough to hold a tensor of the correct
- /// shape.
- /// \param broadcast_spec Specification of the auto-broadcasting scheme.
- /// \param elementwise_functor Functor implementing the elementwise operation to be
- /// applied across the input tensors. Must accept two
- /// arguments of type T, and return a value of type U.
- template <typename T, typename U, typename Functor>
- void autobroadcast_binop(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec,
- Functor elementwise_functor)
- {
- switch (broadcast_spec.m_type)
- {
- case op::AutoBroadcastType::NONE:
- for (size_t i = 0; i < shape_size(arg0_shape); i++)
- {
- out[i] = elementwise_functor(arg0[i], arg1[i]);
- }
- break;
- case op::AutoBroadcastType::NUMPY:
- // We'll be using CoordinateTransform to handle the broadcasting. The general
- // procedure is as follows:
- //
- // (1) Left pad the shorter of the two shapes with ones.
- // (2) Squeeze (remove ones from) both shapes, and record the squeezed axis
- // indices.
- // (3) Using CoordinateTransform, broadcast both args to the final output
- // shape. The "broadcasted axes" will be those that were squeezed in step
- // 2.
- //
- // Example:
- //
- // Input shape->Padded shape->Squeezed Shape/Squeezed Axes
- // ----------- ------------ ----------------------------
- // a: [ 3, 2, 1] [ 3, 2, 1] [ 3, 2 ] {2}
- // b: [ 1, 6] [ 1, 1, 6] [ 6] {0,1}
- // | | |
- // v v v
- // Output shape
- // ------------
- // [ 3, 2, 6]
- {
- using namespace internal;
-
- size_t const shape_rank =
- std::max(arg0_shape.size(), arg1_shape.size()) + 1;
-
- // TODO: Use compiler-specific alloca() or variable-length array
- std::vector<size_t> tmp(shape_rank * 2);
-
- size_t* strides0 = tmp.data();
- size_t* strides1 = tmp.data() + shape_rank;
-
- row_major_strides(arg0_shape, strides0, shape_rank);
- row_major_strides(arg1_shape, strides1, shape_rank);
-
- size_t const padding0 = shape_rank - arg0_shape.size();
- size_t const padding1 = shape_rank - arg1_shape.size();
-
- Shape output_shape(shape_rank, 0);
-
- size_t axis = 0;
-
- for (size_t i = 0; i < shape_rank; i++)
- {
- auto const dim0 = value_with_padding_or(arg0_shape, padding0, i, 1);
- auto const dim1 = value_with_padding_or(arg1_shape, padding1, i, 1);
-
- output_shape[i] = std::max(dim0, dim1);
-
- if (dim0 != dim1)
- axis = std::max(axis, i);
- }
-#if 0
- // Universal function without optimisations
- CoordinateTransformBasic arg0_transform(arg0_shape);
- CoordinateTransformBasic arg1_transform(arg1_shape);
- U *dst = out;
-
- for(CoordinateIterator it(output_shape),
- ite = CoordinateIterator::end();
- it != ite;
- ++it)
- {
- const Coordinate& output_coord = *it;
- size_t const idx0 = arg0_transform.index(output_coord);
- size_t const idx1 = arg1_transform.index(output_coord);
- *dst++ = elementwise_functor(arg0[idx0], arg1[idx1]);
- }
-#else
-
- if (axis == 0)
- {
- for (size_t i = 0, end = strides0[0]; i < end; ++i)
- out[i] = elementwise_functor(arg0[i], arg1[i]);
- }
- else if (strides0[axis] == 1 &&
- value_with_padding_or(arg0_shape, padding0, axis, 1) == 1)
- {
- axis = calculate_fixed_axis(axis, strides0);
-
- numpy_autobroadcast_binop<0, 1>(arg0,
- arg1,
- out,
- arg0_shape,
- arg1_shape,
- strides0,
- strides1,
- padding0,
- padding1,
- output_shape,
- axis,
- strides1[axis],
- elementwise_functor);
- }
- else if (strides1[axis] == 1 &&
- value_with_padding_or(arg1_shape, padding1, axis, 1) == 1)
- {
- axis = calculate_fixed_axis(axis, strides1);
-
- numpy_autobroadcast_binop<1, 0>(arg0,
- arg1,
- out,
- arg0_shape,
- arg1_shape,
- strides0,
- strides1,
- padding0,
- padding1,
- output_shape,
- axis,
- strides0[axis],
- elementwise_functor);
- }
- else
- numpy_autobroadcast_binop<1, 1>(arg0,
- arg1,
- out,
- arg0_shape,
- arg1_shape,
- strides0,
- strides1,
- padding0,
- padding1,
- output_shape,
- axis,
- strides0[axis],
- elementwise_functor);
-#endif
- }
- break;
- case op::AutoBroadcastType::PDPD:
- // We'll be using CoordinateTransform to handle the broadcasting. No need to
- // process arg0 and output shape will be the same as arg0. We need to process
- // arg1 and the general procedure is as follows:
- //
- // (1) Trim trailing ones from arg1 shape.
- // (2) Left and right pad arg1 to match arg0 shape. Axis is the index start
- // to align between arg0 and arg1.
- // (3) Squeeze (remove ones from) arg1 shape, and record the squeezed axis
- // indices.
- // (3) Using CoordinateTransform, broadcast arg1 to the final output
- // shape. The "broadcasted axes" will be those that were squeezed in step
- // 23.
- //
- // Example:
- //
- // Input shape-> Padded shape-> Squeezed Shape/Squeezed Axes
- // ----------- ------------ ----------------------------
- // a: [ 3, 4, 5, 6] [ 3, 4, 5, 6] [ 3, 4, 5, 6]
- // b: [ 4, 5, ] [ 1, 4, 5, 1] [ 4, 5 ] {0,3}
- // | | |
- // v v v
- // Output shape
- // ------------
- // [ 3, 4, 5, 6]
- {
- int64_t axis = broadcast_spec.m_axis;
- if (axis == -1)
- {
- axis = arg0_shape.size() - arg1_shape.size();
- }
-
- Shape arg1_padded_shape = arg1_shape;
- // Trim trailing ones
- while (arg1_padded_shape.size() > 0 && arg1_padded_shape.back() == 1)
- {
- arg1_padded_shape.pop_back();
- }
-
- for (int64_t i = 0; i < axis; ++i)
- {
- arg1_padded_shape.insert(arg1_padded_shape.begin(), 1);
- }
-
- while (arg1_padded_shape.size() < arg0_shape.size())
- {
- arg1_padded_shape.insert(arg1_padded_shape.end(), 1);
- }
-
- Shape arg1_squeezed_shape;
- AxisSet arg1_squeezed_axes;
-
- for (size_t i = 0; i < arg0_shape.size(); i++)
- {
- if (arg1_padded_shape[i] == 1)
- {
- arg1_squeezed_axes.insert(i);
- }
- else
- {
- arg1_squeezed_shape.push_back(arg1_padded_shape[i]);
- }
- }
-
- CoordinateTransform arg0_transform(arg0_shape);
- CoordinateTransform arg1_transform(arg1_squeezed_shape);
- CoordinateTransform output_transform(arg0_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- Coordinate arg1_coord = reduce(output_coord, arg1_squeezed_axes, false);
- out[output_transform.index(output_coord)] =
- elementwise_functor(arg0[arg0_transform.index(output_coord)],
- arg1[arg1_transform.index(arg1_coord)]);
- }
- }
- }
- }
-
- /// \brief Helper function to implement autobroadcasting elementwise ternaryop
- /// references.
- ///
- /// \tparam U Element type of the selector tensor.
- /// \tparam T Element type of the input tensors.
- /// \tparam Functor Type of the functor for the elementwise operation. Must support
- /// operator()(U,T,T), and operator()(U,T,T) must return a value of type
- /// T.
- ///
- /// \param arg0 Pointer to the buffer for selector tensor.
- /// \param arg1 Pointer to the buffer for left operand input tensor.
- /// \param arg2 Pointer to the buffer for right operand input tensor.
- /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
- /// the caller, and must be large enough to hold a tensor of the correct
- /// shape.
- /// \param broadcast_spec Specification of the auto-broadcasting scheme.
- /// \param elementwise_functor Functor implementing the elementwise operation to be
- /// applied across the input tensors. Must accept an argument
- /// of
- /// type U and two of type T, and return a value of type T.
- template <typename T, typename U, typename Functor>
- void autobroadcast_select(const U* arg0,
- const T* arg1,
- const T* arg2,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const Shape& arg2_shape,
- const op::AutoBroadcastSpec& broadcast_spec,
- Functor elementwise_functor)
- {
- switch (broadcast_spec.m_type)
- {
- case op::AutoBroadcastType::NONE:
- for (size_t i = 0; i < shape_size(arg0_shape); i++)
- {
- out[i] = elementwise_functor(arg0[i], arg1[i], arg2[i]);
- }
- break;
- case op::AutoBroadcastType::NUMPY:
- // Uses same approach as autobroadcast_binop.
- {
- Shape arg0_padded_shape = arg0_shape;
- Shape arg1_padded_shape = arg1_shape;
- Shape arg2_padded_shape = arg2_shape;
-
- while (arg1_padded_shape.size() < arg2_padded_shape.size())
- {
- arg1_padded_shape.insert(arg1_padded_shape.begin(), 1);
- }
-
- while (arg2_padded_shape.size() < arg1_padded_shape.size())
- {
- arg2_padded_shape.insert(arg2_padded_shape.begin(), 1);
- }
-
- while (arg0_padded_shape.size() < arg1_padded_shape.size())
- {
- arg0_padded_shape.insert(arg0_padded_shape.begin(), 1);
- }
-
- Shape arg0_squeezed_shape;
- Shape arg1_squeezed_shape;
- Shape arg2_squeezed_shape;
- AxisSet arg0_squeezed_axes;
- AxisSet arg1_squeezed_axes;
- AxisSet arg2_squeezed_axes;
- Shape output_shape;
-
- for (size_t i = 0; i < arg1_padded_shape.size(); i++)
- {
- if (arg1_padded_shape[i] == 1)
- {
- arg1_squeezed_axes.insert(i);
- }
- else
- {
- arg1_squeezed_shape.push_back(arg1_padded_shape[i]);
- }
-
- if (arg2_padded_shape[i] == 1)
- {
- arg2_squeezed_axes.insert(i);
- }
- else
- {
- arg2_squeezed_shape.push_back(arg2_padded_shape[i]);
- }
-
- if (arg0_padded_shape[i] == 1)
- {
- arg0_squeezed_axes.insert(i);
- }
- else
- {
- arg0_squeezed_shape.push_back(arg0_padded_shape[i]);
- }
-
- output_shape.push_back(arg1_padded_shape[i] == 1
- ? arg2_padded_shape[i]
- : arg1_padded_shape[i]);
- }
-
- CoordinateTransform arg0_transform(arg0_squeezed_shape);
- CoordinateTransform arg1_transform(arg1_squeezed_shape);
- CoordinateTransform arg2_transform(arg2_squeezed_shape);
- CoordinateTransform output_transform(output_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
- Coordinate arg1_coord = reduce(output_coord, arg1_squeezed_axes, false);
- Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
- out[output_transform.index(output_coord)] =
- elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
- arg1[arg1_transform.index(arg1_coord)],
- arg2[arg2_transform.index(arg2_coord)]);
- }
- }
- break;
- case op::AutoBroadcastType::PDPD:
- {
- // arg0 and arg2 are broadcast to arg1 shape
- int64_t axis = broadcast_spec.m_axis;
- if (axis == -1)
- {
- axis = arg1_shape.size() - arg2_shape.size();
- }
-
- Shape arg0_padded_shape = arg0_shape;
- Shape arg2_padded_shape = arg2_shape;
- // Trim trailing ones
- while (arg0_padded_shape.size() > 0 && arg0_padded_shape.back() == 1)
- {
- arg0_padded_shape.pop_back();
- }
-
- for (int64_t i = 0; i < axis; ++i)
- {
- arg0_padded_shape.insert(arg0_padded_shape.begin(), 1);
- }
-
- while (arg0_padded_shape.size() < arg1_shape.size())
- {
- arg0_padded_shape.insert(arg0_padded_shape.end(), 1);
- }
-
- while (arg2_padded_shape.size() > 0 && arg2_padded_shape.back() == 1)
- {
- arg2_padded_shape.pop_back();
- }
-
- for (int64_t i = 0; i < axis; ++i)
- {
- arg2_padded_shape.insert(arg2_padded_shape.begin(), 1);
- }
-
- while (arg2_padded_shape.size() < arg1_shape.size())
- {
- arg2_padded_shape.insert(arg2_padded_shape.end(), 1);
- }
-
- Shape arg0_squeezed_shape;
- AxisSet arg0_squeezed_axes;
- Shape arg2_squeezed_shape;
- AxisSet arg2_squeezed_axes;
-
- for (size_t i = 0; i < arg1_shape.size(); i++)
- {
- if (arg0_padded_shape[i] == 1)
- {
- arg0_squeezed_axes.insert(i);
- }
- else
- {
- arg0_squeezed_shape.push_back(arg0_padded_shape[i]);
- }
- if (arg2_padded_shape[i] == 1)
- {
- arg2_squeezed_axes.insert(i);
- }
- else
- {
- arg2_squeezed_shape.push_back(arg2_padded_shape[i]);
- }
- }
-
- CoordinateTransform arg0_transform(arg0_squeezed_shape);
- CoordinateTransform arg1_transform(arg1_shape);
- CoordinateTransform arg2_transform(arg2_squeezed_shape);
- CoordinateTransform output_transform(arg1_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
- Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
- out[output_transform.index(output_coord)] =
- elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
- arg1[arg1_transform.index(output_coord)],
- arg2[arg2_transform.index(arg2_coord)]);
- }
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cfenv>
-#include <cmath>
-#include <numeric>
-#include <stdexcept>
-#include <vector>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void avg_pool_backprop(const T* delta,
- T* out,
- const Shape& delta_shape,
- const Shape& out_shape,
- const Shape& window_shape,
- const Strides& window_movement_strides,
- const Shape& padding_below,
- const Shape& padding_above,
- bool include_padding_in_avg_computation)
- {
- CoordinateTransform out_transform(out_shape);
-
- for (const Coordinate& out_coord : out_transform)
- {
- out[out_transform.index(out_coord)] = 0;
- }
-
- CoordinateTransform delta_transform(delta_shape);
-
- for (const Coordinate& delta_coord : delta_transform)
- {
- size_t img_index = delta_coord[0];
- size_t channel = delta_coord[1];
-
- size_t n_image_dimensions = out_shape.size() - 2;
- Coordinate source_window_transform_start(2 + n_image_dimensions);
- Coordinate source_window_transform_end(2 + n_image_dimensions);
- Strides source_window_transform_source_strides(2 + n_image_dimensions, 1);
- AxisVector source_window_transform_source_axis_order(2 + n_image_dimensions);
- CoordinateDiff source_window_transform_padding_below(2 + n_image_dimensions);
- CoordinateDiff source_window_transform_padding_above(2 + n_image_dimensions);
-
- source_window_transform_start[0] = img_index;
- source_window_transform_end[0] = img_index + 1;
- source_window_transform_start[1] = channel;
- source_window_transform_end[1] = channel + 1;
- source_window_transform_padding_below[0] = 0;
- source_window_transform_padding_below[1] = 0;
- source_window_transform_padding_above[0] = 0;
- source_window_transform_padding_above[1] = 0;
-
- for (size_t i = 2; i < n_image_dimensions + 2; i++)
- {
- size_t window_shape_this_dim = window_shape[i - 2];
- size_t movement_stride = window_movement_strides[i - 2];
-
- source_window_transform_start[i] = movement_stride * delta_coord[i];
- source_window_transform_end[i] =
- source_window_transform_start[i] + window_shape_this_dim;
- source_window_transform_padding_below[i] = padding_below[i - 2];
- source_window_transform_padding_above[i] = padding_above[i - 2];
- }
- std::iota(begin(source_window_transform_source_axis_order),
- end(source_window_transform_source_axis_order),
- 0);
-
- CoordinateTransform source_window_transform(
- out_shape,
- source_window_transform_start,
- source_window_transform_end,
- source_window_transform_source_strides,
- source_window_transform_source_axis_order,
- source_window_transform_padding_below,
- source_window_transform_padding_above);
-
- size_t num_elements_in_window = 0;
-
- for (const Coordinate& source_window_coord : source_window_transform)
- {
- if (source_window_transform.has_source_coordinate(source_window_coord) ||
- include_padding_in_avg_computation)
- {
- num_elements_in_window++;
- }
- }
-
- for (const Coordinate& source_window_coord : source_window_transform)
- {
- if (source_window_transform.has_source_coordinate(source_window_coord))
- {
- size_t out_index = source_window_transform.index(source_window_coord);
- out[out_index] +=
- delta[delta_transform.index(delta_coord)] / num_elements_in_window;
- }
- }
- }
- }
-
- template <typename T>
- void avg_pool(const T* arg,
- T* out,
- const Shape& arg_shape,
- const Shape& out_shape,
- const Shape& window_shape,
- const Strides& window_movement_strides,
- const Shape& padding_below,
- const Shape& padding_above,
- bool include_padding_in_avg_computation)
- {
- auto old_mode = std::fegetround();
- std::fesetround(FE_TONEAREST);
- // At the outermost level we will walk over every output coordinate O.
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& out_coord : output_transform)
- {
- // Our output coordinate O will have the form:
- //
- // (N,chan,i_1,...,i_n)
-
- size_t batch_index = out_coord[0];
- size_t channel = out_coord[1];
-
- // For the input data we need to iterate the coordinate:
- //
- // I:
- //
- // over the range (noninclusive on the right):
- //
- // (N,chan,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
- //
- // (N+1,chan+1,s_1*i_1 + window_shape_1,...,s_n*i_n + window_shape_n)
- //
- // with unit stride.
- //
- // We iterate this over the *padded* data, so below we will need to check for
- // coordinates that fall in the padding area.
-
- size_t n_spatial_dimensions = arg_shape.size() - 2;
-
- Coordinate input_batch_transform_start(2 + n_spatial_dimensions);
- Coordinate input_batch_transform_end(2 + n_spatial_dimensions);
- Strides input_batch_transform_source_strides(2 + n_spatial_dimensions, 1);
- AxisVector input_batch_transform_source_axis_order(2 + n_spatial_dimensions);
- CoordinateDiff input_batch_transform_padding_below(2 + n_spatial_dimensions);
- CoordinateDiff input_batch_transform_padding_above(2 + n_spatial_dimensions);
-
- input_batch_transform_start[0] = batch_index;
- input_batch_transform_end[0] = batch_index + 1;
- input_batch_transform_start[1] = channel;
- input_batch_transform_end[1] = channel + 1;
- input_batch_transform_padding_below[0] = 0;
- input_batch_transform_padding_below[1] = 0;
- input_batch_transform_padding_above[0] = 0;
- input_batch_transform_padding_above[1] = 0;
-
- for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
- {
- size_t window_shape_this_dim = window_shape[i - 2];
- size_t movement_stride = window_movement_strides[i - 2];
-
- input_batch_transform_start[i] = movement_stride * out_coord[i];
- input_batch_transform_end[i] =
- input_batch_transform_start[i] + window_shape_this_dim;
- input_batch_transform_padding_below[i] = padding_below[i - 2];
- input_batch_transform_padding_above[i] = padding_above[i - 2];
- }
-
- for (size_t i = 0; i < arg_shape.size(); i++)
- {
- input_batch_transform_source_axis_order[i] = i;
- }
-
- CoordinateTransform input_batch_transform(
- arg_shape,
- input_batch_transform_start,
- input_batch_transform_end,
- input_batch_transform_source_strides,
- input_batch_transform_source_axis_order,
- input_batch_transform_padding_below,
- input_batch_transform_padding_above);
-
- // As we go, we compute the sum value:
- //
- // output[O] := output[O] + arg[I]
- //
- // and the number of elements:
- //
- // n_elements := n_elements + 1
-
- T result = 0;
- size_t n_elements = 0;
-
- for (const Coordinate& input_batch_coord : input_batch_transform)
- {
- bool in_bounds =
- input_batch_transform.has_source_coordinate(input_batch_coord);
-
- if (in_bounds || include_padding_in_avg_computation)
- {
- T v =
- in_bounds ? arg[input_batch_transform.index(input_batch_coord)] : 0;
- result += v;
- n_elements++;
- }
- }
-
- if (n_elements == 0)
- {
- throw std::runtime_error("AvgPool elements == 0, must be non-zero");
- }
-
- if (std::is_same<T, int8_t>::value || std::is_same<T, uint8_t>::value)
- {
- out[output_transform.index(out_coord)] =
- static_cast<T>(std::nearbyint(static_cast<float>(result) / n_elements));
- }
- else
- {
- out[output_transform.index(out_coord)] = result / n_elements;
- }
- std::fesetround(old_mode);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <vector>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/add.hpp"
-#include "ngraph/runtime/reference/broadcast.hpp"
-#include "ngraph/runtime/reference/divide.hpp"
-#include "ngraph/runtime/reference/multiply.hpp"
-#include "ngraph/runtime/reference/sum.hpp"
-#include "ngraph/shape.hpp"
-#include "ngraph/util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void batch_norm_inference(float eps,
- const T* gamma,
- const T* beta,
- const T* input,
- const T* mean,
- const T* variance,
- T* normed_input,
- const Shape& input_shape)
- {
- auto eps_casted = static_cast<T>(eps);
- CoordinateTransform input_transform(input_shape);
-
- for (Coordinate input_coord : input_transform)
- {
- auto channel_num = input_coord[1];
- auto channel_gamma = gamma[channel_num];
- auto channel_beta = beta[channel_num];
- auto channel_mean = mean[channel_num];
- auto channel_var = variance[channel_num];
-
- auto input_index = input_transform.index(input_coord);
- auto normalized =
- (input[input_index] - channel_mean) / (std::sqrt(channel_var + eps_casted));
- normed_input[input_index] = normalized * channel_gamma + channel_beta;
- }
- }
-
- template <typename T>
- void batch_norm_training(float eps,
- const T* gamma,
- const T* beta,
- const T* input,
- T* normed_input,
- T* mean,
- T* variance,
- const Shape& input_shape)
- {
- auto eps_casted = static_cast<T>(eps);
- auto channels = input_shape[1];
-
- // We use these objects to iterate over the indices in a channel.
- // The start and end points for the channel axis are modified in the loop.
- Coordinate start_corner;
- Coordinate end_corner;
- for (size_t i = 0; i < input_shape.size(); i++)
- {
- start_corner.push_back(0);
- end_corner.push_back(input_shape[i]);
- }
-
- for (size_t c = 0; c < channels; c++)
- {
- T channel_sum = 0;
-
- start_corner[1] = c;
- end_corner[1] = c + 1;
-
- // Compute the mean
- CoordinateTransform input_transform(input_shape, start_corner, end_corner);
- for (Coordinate input_coord : input_transform)
- {
- channel_sum += input[input_transform.index(input_coord)];
- }
- T channel_mean = channel_sum / (shape_size(input_shape) / channels);
- mean[c] = channel_mean;
-
- T channel_diff_square_sum = 0;
- for (Coordinate input_coord : input_transform)
- {
- auto centered = input[input_transform.index(input_coord)] - channel_mean;
- channel_diff_square_sum += centered * centered;
- }
- T channel_var = channel_diff_square_sum / (shape_size(input_shape) / channels);
- variance[c] = channel_var;
-
- auto channel_gamma = gamma[c];
- auto channel_beta = beta[c];
- T scale = channel_gamma / std::sqrt(channel_var + eps_casted);
-
- // Compute the normalized output
- for (Coordinate input_coord : input_transform)
- {
- auto input_index = input_transform.index(input_coord);
- normed_input[input_index] =
- (input[input_index] - channel_mean) * scale + channel_beta;
- }
- }
- }
-
- template <typename T>
- void batch_norm_backprop(float eps,
- const T* gamma,
- const T* /* beta */,
- const T* input,
- const T* mean,
- const T* variance,
- const T* delta_normed,
- T* delta_input,
- T* delta_gamma,
- T* delta_beta,
- const Shape& input_shape)
- {
- size_t channel_axis = 1;
- auto num_channels = input_shape[channel_axis];
- Shape moment_shape = Shape{num_channels};
- auto input_num_elements = shape_size(input_shape);
- auto elements_per_channel = input_num_elements / num_channels;
-
- Coordinate start_corner;
- Coordinate end_corner;
- for (size_t i = 0; i < input_shape.size(); i++)
- {
- start_corner.push_back(0);
- end_corner.push_back(input_shape[i]);
- }
- // The forward computation in gory detail
- // input[., C, ...]
- // gamma[C]
- // beta[C]
- // mu[c:C] = sum(input[., c, ...])/elements_per_channel
- // var[c:C] = sum(input[., c, ...]^2 - mu[c])/elements_per_channel
- // inv_sqrt[c:C] = 1/sqrt(var[c]+epsilon)
- // gammad[c:C] = gamma[c]*inv_sqrt[c]
- // normed[., c:C, ...] = (input[., c, ...]-mu)*gammad[c]+beta[c]
-
- for (uint64_t c = 0; c < num_channels; ++c)
- {
- start_corner[channel_axis] = c;
- end_corner[channel_axis] = c + 1;
-
- CoordinateTransform input_transform(input_shape, start_corner, end_corner);
- T delta_beta_sum = 0;
- T var = variance[c];
- T mu = mean[c];
- T var_eps = var + static_cast<T>(eps);
- T sqrt_var_eps = std::sqrt(var_eps);
- T inv_sqrt_var_eps = 1 / sqrt_var_eps;
- T gammad = gamma[c] * inv_sqrt_var_eps;
- T delta_gammad = 0;
- T delta_mu = 0;
- for (Coordinate input_coord : input_transform)
- {
- auto idx = input_transform.index(input_coord);
- auto delta_idx = delta_normed[idx];
- auto input_idx = input[idx];
- delta_beta_sum += delta_idx;
- delta_gammad += (input_idx - mu) * delta_idx;
- T delta_centered = gammad * delta_idx;
- delta_input[idx] = delta_centered;
- delta_mu -= delta_centered;
- }
- delta_beta[c] = delta_beta_sum;
- delta_gamma[c] = delta_gammad * inv_sqrt_var_eps;
- T delta_inv_sqrt = gamma[c] * delta_gammad;
- // y = x^(-1/2)
- // dy = -(1/2)x^(-3/2) = -y/(2x) dx
- T delta_var = -delta_inv_sqrt * inv_sqrt_var_eps / (2 * var_eps);
- T delta_two_var_sum = 2 * delta_var / elements_per_channel;
- T delta_mu_over_n = delta_mu / elements_per_channel;
- for (Coordinate input_coord : input_transform)
- {
- // v = 1/N sum(x_i - mu)^2
- // dv = 2/N sum[(x_i - mu)dx_i] - 2/N sum[(x_i - mu) dmu]
- // = 2/N sum[(x_i - mu)dx_i] - 2/N (Nmu-Nmu) dmu
- // = 2/N sum[(x_i - mu)dx_i]
- auto idx = input_transform.index(input_coord);
- // These two values mostly cancel out so add them first
- auto val = delta_input[idx] + delta_mu_over_n;
- delta_input[idx] = val + (input[idx] - mu) * delta_two_var_sum;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void broadcast(const T* arg,
- T* out,
- const Shape& in_shape,
- const Shape& out_shape,
- const AxisSet& broadcast_axes)
- {
- // Remove all broadcast axes from in_shape
- Shape adjusted_in_shape;
- for (auto length : in_shape)
- {
- if (length != 1)
- {
- adjusted_in_shape.push_back(length);
- }
- }
- // Remove 1s from out_shape
- AxisSet adjusted_axes(broadcast_axes);
- for (uint64_t axis = 0; axis < out_shape.size(); ++axis)
- {
- auto length = out_shape.at(axis);
- if (length == 1)
- {
- adjusted_axes.insert(axis);
- }
- }
- CoordinateTransform input_transform(adjusted_in_shape);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- Coordinate input_coord = reduce(output_coord, adjusted_axes, false);
- out[output_transform.index(output_coord)] =
- arg[input_transform.index(input_coord)];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void ceiling(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::ceil(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void clamp(const T* arg, T* out, T min, T max, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- if (arg[i] < min)
- {
- out[i] = min;
- }
- else if (arg[i] > max)
- {
- out[i] = max;
- }
- else
- {
- out[i] = arg[i];
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void concat(const std::vector<const T*>& args,
- T* out,
- const std::vector<Shape>& in_shapes,
- const Shape& out_shape,
- int64_t concatenation_axis)
- {
- // We will copy the inputs to the output one at a time. As we go, we will move out
- // along the concatenation axis, starting at 0.
- size_t concatenation_pos = 0;
- for (size_t i = 0; i < args.size(); i++)
- {
- // CoordinateTransform gets confused when the last input has a zero-size dim, so
- // we will just skip for zero-element tensors.
- if (shape_size(in_shapes[i]) == 0)
- {
- continue;
- }
-
- // The start coordinate for the copy is (0,...,0) except at the concatenation
- // axis.
- Coordinate out_start_coord(out_shape.size(), 0);
- out_start_coord[concatenation_axis] = concatenation_pos;
-
- // The end coordinate for the copy is the same as the output shape except at the
- // concatenation axis.
- Coordinate out_end_coord = out_shape;
- out_end_coord[concatenation_axis] =
- concatenation_pos + in_shapes[i][concatenation_axis];
-
- CoordinateTransform input_transform(in_shapes[i]);
- CoordinateTransform output_chunk_transform(
- out_shape, out_start_coord, out_end_coord);
-
- NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
- shape_size(output_chunk_transform.get_target_shape()));
-
- CoordinateTransform::Iterator output_chunk_it = output_chunk_transform.begin();
-
- for (const Coordinate& input_coord : input_transform)
- {
- size_t input_index = input_transform.index(input_coord);
- size_t output_chunk_index = output_chunk_transform.index(*output_chunk_it);
- ++output_chunk_it;
-
- out[output_chunk_index] = args[i][input_index];
- }
-
- concatenation_pos += in_shapes[i][concatenation_axis];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void constant(const T* arg0, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename TI, typename TO>
- void convert(const TI* arg, TO* out, size_t count)
- {
- for (size_t i = 0; i < count; ++i)
- {
- out[i] = static_cast<TO>(arg[i]);
- }
- }
-
- template <typename T>
- void convert_to_bool(const T* arg, char* out, size_t count)
- {
- for (size_t i = 0; i < count; ++i)
- {
- out[i] = static_cast<char>(static_cast<bool>(arg[i]));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cfenv>
-#include <cmath>
-#include <functional>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/reverse.hpp"
-#include "ngraph/util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- struct widen
- {
- using type = T;
- };
-
- template <>
- struct widen<float>
- {
- using type = double;
- };
-
- template <>
- struct widen<double>
- {
- using type = long double;
- };
-
- // in: NC_I...
- // filter: C_OC_I...
- // out: NC_O...
- template <typename INPUT,
- typename FILTER,
- typename OUTPUT,
- typename ACCUMULATION = typename widen<OUTPUT>::type>
- void general_convolution(const INPUT* in,
- const FILTER* filter,
- OUTPUT* out,
- const Shape& in_shape,
- const Shape& filter_shape,
- const Shape& out_shape,
- const Strides& stride,
- const Strides& filter_dilation,
- const CoordinateDiff& in_pad_below,
- const CoordinateDiff& in_pad_above,
- const Strides& in_dilation,
- size_t in_batch_axis,
- size_t in_channel_axis,
- size_t filter_out_channel_axis,
- size_t filter_in_channel_axis,
- size_t out_batch_axis,
- size_t out_channel_axis,
- const float* input_scale = nullptr,
- const INPUT* input_zero_point = nullptr,
- const float* filter_scale = nullptr,
- const FILTER* filter_zero_point = nullptr,
- const float* output_scale = nullptr,
- const OUTPUT* output_zero_point = nullptr)
- {
- bool is_quantized = false;
- if (input_scale && input_zero_point && filter_scale && filter_zero_point &&
- output_scale && output_zero_point)
- {
- is_quantized = true;
- }
-
- auto old_mode = std::fegetround();
- std::fesetround(FE_TONEAREST);
- // Comments throughout assume without loss of generality that:
- //
- // * batch axes for both in and out are 0
- // * in channel axes for both in and filter are 1
- // * out channel axes for filter is 0
- // * out channel axis for out is 1
-
- // At the outermost level we will walk over every out coordinate O.
- CoordinateTransform out_transform(out_shape);
-
- for (const Coordinate& out_coord : out_transform)
- {
- // Our out coordinate O will have the form:
- //
- // (N,chan_out,i_1,...,i_n)
-
- size_t batch_index = out_coord[out_batch_axis];
- size_t out_channel = out_coord[out_channel_axis];
-
- // For the in we need to iterate the coordinate:
- //
- // I:
- //
- // over the range (noninclusive on the right):
- //
- // (N,0,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
- //
- // (N+1,
- // chans_in_count,
- // s_1*i_1+ l_1*filter_dims_1,
- /// ...,
- /// s_n*i_n +l_n*filter_dims_n)
- //
- // with strides:
- //
- // (1,l_1,...,l_n).
- //
- // Note that we are iterating within the *padded* and *dilated* in batch, so
- // further down we must check the current coordinate is in the pad or dilation
- // gap.
-
- size_t n_spatial_dimensions = in_shape.size() - 2;
- size_t n_in_channels = in_shape[in_channel_axis];
-
- Coordinate in_transform_start(2 + n_spatial_dimensions);
- Coordinate in_transform_end(2 + n_spatial_dimensions);
- Strides in_transform_movement_strides(2 + n_spatial_dimensions, 1);
- CoordinateDiff in_transform_pad_below(2 + n_spatial_dimensions, 0);
- CoordinateDiff in_transform_pad_above(2 + n_spatial_dimensions, 0);
- Strides in_transform_dilation_strides(2 + n_spatial_dimensions, 1);
-
- in_transform_start[in_batch_axis] = batch_index;
- in_transform_end[in_batch_axis] = batch_index + 1;
- in_transform_start[in_channel_axis] = 0;
- in_transform_end[in_channel_axis] = 1;
-
- for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
- {
- size_t filter_dilation_stride = filter_dilation[i - 2];
- size_t filter_movement_stride = stride[i - 2];
- std::ptrdiff_t below_pad = in_pad_below[i - 2];
- std::ptrdiff_t above_pad = in_pad_above[i - 2];
- size_t in_dilation_stride = in_dilation[i - 2];
-
- in_transform_start[i] = filter_movement_stride * out_coord[i];
- in_transform_end[i] = in_transform_start[i] +
- (filter_shape[i] - 1) * filter_dilation_stride + 1;
- in_transform_movement_strides[i] = filter_dilation_stride;
- in_transform_pad_below[i] = below_pad;
- in_transform_pad_above[i] = above_pad;
- in_transform_dilation_strides[i] = in_dilation_stride;
- }
-
- AxisVector in_transform_axis_order(2 + n_spatial_dimensions);
- for (size_t i = 0; i < in_transform_axis_order.size(); i++)
- {
- in_transform_axis_order[i] = i;
- }
- CoordinateTransform in_transform(in_shape,
- in_transform_start,
- in_transform_end,
- in_transform_movement_strides,
- in_transform_axis_order,
- in_transform_pad_below,
- in_transform_pad_above,
- in_transform_dilation_strides);
-
- // Simultaneously with iterating I, for the filter we need to iterate the
- // coordinate:
- //
- // F
- //
- // over the range (noninclusive on the right):
- //
- // (chan_out,0,0,...,0) ->
- // (chan_out+1,
- // chans_in_count,
- // filter_dims_1,
- // ...,
- // filter_dims_n)
- //
- // with unit stride.
-
- Shape filter_transform_start(2 + n_spatial_dimensions);
- Shape filter_transform_end(2 + n_spatial_dimensions);
-
- filter_transform_start[filter_out_channel_axis] = out_channel;
- filter_transform_end[filter_out_channel_axis] = out_channel + 1;
- filter_transform_start[filter_in_channel_axis] = 0;
- filter_transform_end[filter_in_channel_axis] = 1;
-
- for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
- {
- filter_transform_start[i] = 0;
- filter_transform_end[i] = filter_shape[i];
- }
-
- CoordinateTransform filter_transform(
- filter_shape, filter_transform_start, filter_transform_end);
-
- // As we go, we sum up:
- //
- // out[O] += in[I] * filter[F].
-
- ACCUMULATION result = 0;
-
- CoordinateTransform::Iterator in_it = in_transform.begin();
- CoordinateTransform::Iterator filter_it = filter_transform.begin();
- CoordinateTransform::Iterator in_it_end = in_transform.end();
- CoordinateTransform::Iterator filter_it_end = filter_transform.end();
-
- size_t in_channel_stride = row_major_strides(in_shape).at(in_channel_axis);
- size_t filter_in_channel_stride =
- row_major_strides(filter_shape).at(filter_in_channel_axis);
-
- while (in_it != in_it_end && filter_it != filter_it_end)
- {
- const Coordinate& in_coord = *in_it;
- if (in_transform.has_source_coordinate(in_coord))
- {
- size_t in_idx = in_transform.index(in_coord);
- const Coordinate& filter_coord = *filter_it;
- size_t filter_idx = filter_transform.index(filter_coord);
- for (size_t in_channel = 0; in_channel < n_in_channels; ++in_channel)
- {
- ACCUMULATION in_v = static_cast<ACCUMULATION>(in[in_idx]);
- ACCUMULATION f_v = static_cast<ACCUMULATION>(filter[filter_idx]);
- if (is_quantized)
- {
- in_v = in_v - static_cast<ACCUMULATION>(*input_zero_point);
- f_v = f_v - static_cast<ACCUMULATION>(*filter_zero_point);
- }
- result += in_v * f_v;
- in_idx += in_channel_stride;
- filter_idx += filter_in_channel_stride;
- }
- }
- ++in_it;
- ++filter_it;
- }
- if (is_quantized)
- {
- float scale = *input_scale * *filter_scale / *output_scale;
- out[out_transform.index(out_coord)] =
- static_cast<OUTPUT>(std::round(static_cast<float>(result) * scale)) +
- *output_zero_point;
- }
- else
- {
- out[out_transform.index(out_coord)] = result;
- }
- }
- std::fesetround(old_mode);
- }
-
- template <typename INPUT,
- typename FILTER,
- typename OUTPUT,
- typename ACCUMULATION = typename widen<OUTPUT>::type>
- void convolution(const INPUT* in,
- const FILTER* filter,
- OUTPUT* out,
- const Shape& in_shape,
- const Shape& filter_shape,
- const Shape& out_shape,
- const Strides& stride,
- const Strides& filter_dilation,
- const CoordinateDiff& in_pad_below,
- const CoordinateDiff& in_pad_above,
- const Strides& in_dilation,
- const float* input_scale = nullptr,
- const INPUT* input_zero_point = nullptr,
- const float* filter_scale = nullptr,
- const FILTER* filter_zero_point = nullptr,
- const float* output_scale = nullptr,
- const OUTPUT* output_zero_point = nullptr)
-
- {
- general_convolution<INPUT, FILTER, OUTPUT, ACCUMULATION>(in,
- filter,
- out,
- in_shape,
- filter_shape,
- out_shape,
- stride,
- filter_dilation,
- in_pad_below,
- in_pad_above,
- in_dilation,
- 0,
- 1,
- 0,
- 1,
- 0,
- 1,
- input_scale,
- input_zero_point,
- filter_scale,
- filter_zero_point,
- output_scale,
- output_zero_point);
- }
-
- template <typename INPUT,
- typename OUTPUT,
- typename FILTER,
- typename ACCUMULATION = typename widen<FILTER>::type>
- void convolution_backprop_filter(const INPUT* in,
- const OUTPUT* delta_out,
- FILTER* delta_filter,
- const Shape& in_shape,
- const Shape& out_shape,
- const Shape& filter_shape,
- const Strides& filter_dilation,
- const Strides& stride,
- const CoordinateDiff& in_pad_below,
- const CoordinateDiff& backprop_in_pad_above,
- const Strides& in_dilation)
- {
- general_convolution<INPUT, OUTPUT, FILTER, ACCUMULATION>(in,
- delta_out,
- delta_filter,
- in_shape,
- out_shape,
- filter_shape,
- filter_dilation,
- stride,
- in_pad_below,
- backprop_in_pad_above,
- in_dilation,
- 1,
- 0,
- 1,
- 0,
- 1,
- 0);
- }
-
- template <typename OUTPUT,
- typename FILTER,
- typename INPUT,
- typename ACCUMULATION = typename widen<INPUT>::type>
- void convolution_backprop_in(const OUTPUT* delta_out,
- const FILTER* filter,
- INPUT* delta_in,
- const Shape& out_shape,
- const Shape& filter_shape,
- const Shape& in_shape,
- const Strides& in_dilation,
- const Strides& filter_dilation,
- const CoordinateDiff& backward_delta_out_pad_below,
- const CoordinateDiff& backward_delta_out_pad_above,
- const Strides& stride)
- {
- // Note that we only reverse the spatial dimensions here (loop
- // starts at 2)
- std::vector<INPUT> reversed(shape_size(filter_shape));
- AxisSet reverse_axes;
- for (size_t i = 2; i < filter_shape.size(); ++i)
- {
- reverse_axes.insert(i);
- }
- reverse(reinterpret_cast<const char*>(filter),
- reinterpret_cast<char*>(&reversed[0]),
- filter_shape,
- filter_shape,
- reverse_axes,
- sizeof(FILTER));
-
- general_convolution<OUTPUT, FILTER, INPUT, ACCUMULATION>(
- delta_out,
- &reversed[0],
- delta_in,
- out_shape,
- filter_shape,
- in_shape,
- in_dilation,
- filter_dilation,
- backward_delta_out_pad_below,
- backward_delta_out_pad_above,
- stride,
- 0,
- 1,
- 1,
- 0,
- 0,
- 1);
- }
- } // namespace reference
- } // namespace runtime
-} // namespace ngraph
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void copy(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void cos(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::cos(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void cosh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::cosh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/type/bfloat16.hpp"
-#include "ngraph/type/float16.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename P>
- void cumsum(const T* arg,
- const P* axis_tensor,
- T* out,
- const Shape& tensor_shape,
- const bool exclusive,
- const bool reverse)
- {
- CoordinateTransform temp_transform(tensor_shape);
- for (const Coordinate& output_coord : temp_transform)
- {
- out[temp_transform.index(output_coord)] = 0;
- }
-
- P axis = axis_tensor[0];
- P rank = tensor_shape.size();
-
- if (axis < -rank || axis > rank)
- {
- throw ngraph_error("axis must be in the range [-rank, rank]");
- }
- axis = axis < 0 ? rank + axis : axis;
-
- auto get_key = [&, axis](const Coordinate& coord) -> Coordinate {
- Coordinate result(coord.size(), 0);
- result[axis] = coord[axis];
-
- for (size_t i = 0; i < coord.size(); i++)
- {
- result[i] = coord[i] - result[i];
- }
- return result;
- };
-
- auto update_output_buffer =
- [&](size_t input_index,
- size_t output_index,
- T& prev,
- std::vector<std::pair<size_t, T>>& tensor_vec) -> void {
-
- tensor_vec[input_index].second = prev + tensor_vec[input_index].second;
- out[tensor_vec[output_index].first] = tensor_vec[input_index].second;
-
- // update prev to hold the last result value to compute ruuning sum for
- // subsequent iter
- prev = out[tensor_vec[output_index].first];
- };
-
- auto cum_sum =
- [&, exclusive, reverse](std::vector<std::pair<size_t, T>>& tensor_vec) {
- if (!reverse)
- {
- T prev = 0;
- for (size_t i = 0; i < tensor_vec.size(); i++)
- {
- if (exclusive && i == 0)
- {
- out[tensor_vec[i].first] = prev;
- continue;
- }
- // we will compute running sum of j-1 elements if exlusive=1 or else
- // for j elements if exclusive = 0
- size_t arg_index = exclusive == 1 ? i - 1 : i;
- update_output_buffer(arg_index, i, prev, tensor_vec);
- }
- }
- else // reverse == true
- {
- T prev = 0;
- for (size_t i = tensor_vec.size(); i-- > 0;)
- {
- if (exclusive && i == tensor_vec.size() - 1)
- {
- out[tensor_vec[i].first] = prev;
- continue;
- }
- // we will compute running sum of j-1 elements if exlusive=1 or else
- // for j elements if exclusive = 0
- size_t arg_index = exclusive == 1 ? i + 1 : i;
- update_output_buffer(arg_index, i, prev, tensor_vec);
- }
- }
- };
-
- // Map to collect tensor elements belonging to the same axis
- std::map<Coordinate, std::vector<std::pair<size_t, T>>> map_cooord_to_val;
- CoordinateTransform input_transform(tensor_shape);
- for (const Coordinate& input_coord : input_transform)
- {
- // points to the current element in the input tensor
- T current = arg[input_transform.index(input_coord)];
- auto key = get_key(input_coord);
- auto index = input_transform.index(input_coord);
- if (map_cooord_to_val.find(key) != map_cooord_to_val.end())
- {
- map_cooord_to_val[key].push_back(std::make_pair(index, current));
- }
- else
- {
- map_cooord_to_val.insert({key, std::vector<std::pair<size_t, T>>()});
- map_cooord_to_val[key].push_back(std::make_pair(index, current));
- }
- }
- // iterate the map and perform cumulative sum over the give axis
- for (auto& it : map_cooord_to_val)
- {
- cum_sum(it.second);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/axis_set.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename QUANT, typename REAL>
- void dequantize(const QUANT* input,
- const REAL* scale,
- const QUANT* zero_point,
- REAL* output,
- const Shape& input_shape,
- const Shape& scale_zero_point_shape,
- const AxisSet& axes)
- {
- CoordinateTransform input_transform(input_shape);
- CoordinateTransform scale_zero_point_transform(scale_zero_point_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate scale_zero_point_coord = project(input_coord, axes);
-
- output[input_transform.index(input_coord)] =
- static_cast<REAL>((
- input[input_transform.index(input_coord)] -
- zero_point[scale_zero_point_transform.index(scale_zero_point_coord)])) *
- scale[scale_zero_point_transform.index(scale_zero_point_coord)];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-#include <stdexcept>
-#include <type_traits>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-#include "ngraph/type/bfloat16.hpp"
-#include "ngraph/type/float16.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // NOTE: Execution throws `std::domain_error` if either a non-integral value or an
- // out-of-bounds value is detected in the input tensor.
-
- // In English: return type is void and T must be an integral type.
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value>::type
- divide(const T* arg0, const T* arg1, T* out, size_t count, bool pythondiv)
- {
- if (pythondiv)
- {
- for (size_t i = 0; i < count; i++)
- {
- if (arg1[i] == 0)
- {
- throw std::domain_error("integer division by zero");
- }
- T quot = arg0[i] / arg1[i];
- T rem = arg0[i] % arg1[i];
- if ((rem != 0) && ((arg0[i] < 0) != (arg1[i] < 0)))
- {
- out[i] = quot - 1;
- }
- else
- {
- out[i] = quot;
- }
- }
- }
- else
- {
- for (size_t i = 0; i < count; i++)
- {
- if (arg1[i] == 0)
- {
- throw std::domain_error("integer division by zero");
- }
- out[i] = arg0[i] / arg1[i];
- }
- }
- }
-
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value>::type
- divide(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec,
- bool pythondiv)
- {
- auto functor = [pythondiv](T x, T y) -> T {
- if (pythondiv)
- {
- if (y == 0)
- {
- throw std::domain_error("integer division by zero");
- }
- T quot = x / y;
- T rem = x % y;
- if ((rem != 0) && ((x < 0) != (y < 0)))
- {
- return quot - 1;
- }
- else
- {
- return quot;
- }
- }
- else
- {
- if (y == 0)
- {
- throw std::domain_error("integer division by zero");
- }
- return x / y;
- }
- };
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, functor);
- }
-
- // In English: return type is void and T must be a standard floating point type, or
- // bfloat16, or float16.
- template <typename T>
- typename std::enable_if<std::is_floating_point<T>::value ||
- std::is_same<T, bfloat16>::value ||
- std::is_same<T, float16>::value>::type
- divide(const T* arg0, const T* arg1, T* out, size_t count, bool pythondiv)
- {
- (void)pythondiv;
- for (size_t i = 0; i < count; i++)
- {
- // TODO: Here we do not check for div by zero, so we'll get +-inf here
- // if arg1[i] == 0. Is that the right thing to do? Jury's still out.
- out[i] = arg0[i] / arg1[i];
- }
- }
-
- template <typename T>
- typename std::enable_if<std::is_floating_point<T>::value ||
- std::is_same<T, bfloat16>::value ||
- std::is_same<T, float16>::value>::type
- divide(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec,
- bool pythondiv)
- {
- (void)pythondiv;
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x / y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <utility>
-
-#include <cfenv>
-#include <functional>
-#include "convolution.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename INPUT0,
- typename INPUT1,
- typename OUTPUT,
- typename ACCUMULATION = typename widen<OUTPUT>::type>
- void dot(const INPUT0* arg0,
- const INPUT1* arg1,
- OUTPUT* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const Shape& out_shape,
- size_t reduction_axes_count,
- const float* input0_scale = nullptr,
- const INPUT0* input0_zero_point = nullptr,
- const float* input1_scale = nullptr,
- const INPUT1* input1_zero_point = nullptr,
- const float* output_scale = nullptr,
- const OUTPUT* output_zero_point = nullptr)
- {
- bool is_quantized = false;
- if (input0_scale && input0_zero_point && input1_scale && input1_zero_point &&
- output_scale && output_zero_point)
- {
- is_quantized = true;
- }
-
- auto old_mode = std::fegetround();
- std::fesetround(FE_TONEAREST);
- // Get the sizes of the dot axes. It's easiest to pull them from arg1 because
- // they're right up front.
- Shape dot_axis_sizes(reduction_axes_count);
- std::copy(arg1_shape.begin(),
- arg1_shape.begin() + reduction_axes_count,
- dot_axis_sizes.begin());
-
- CoordinateTransform arg0_transform(arg0_shape);
- CoordinateTransform arg1_transform(arg1_shape);
- CoordinateTransform output_transform(out_shape);
-
- // Create coordinate transforms for arg0 and arg1 that throw away the dotted axes.
- size_t arg0_projected_rank = arg0_shape.size() - reduction_axes_count;
- size_t arg1_projected_rank = arg1_shape.size() - reduction_axes_count;
-
- Shape arg0_projected_shape(arg0_projected_rank);
- std::copy(arg0_shape.begin(),
- arg0_shape.begin() + arg0_projected_rank,
- arg0_projected_shape.begin());
-
- Shape arg1_projected_shape(arg1_projected_rank);
- std::copy(arg1_shape.begin() + reduction_axes_count,
- arg1_shape.end(),
- arg1_projected_shape.begin());
-
- CoordinateTransform arg0_projected_transform(arg0_projected_shape);
- CoordinateTransform arg1_projected_transform(arg1_projected_shape);
-
- // Create a coordinate transform that allows us to iterate over all possible values
- // for the dotted axes.
- CoordinateTransform dot_axes_transform(dot_axis_sizes);
-
- for (const Coordinate& arg0_projected_coord : arg0_projected_transform)
- {
- for (const Coordinate& arg1_projected_coord : arg1_projected_transform)
- {
- // The output coordinate is just the concatenation of the projected
- // coordinates.
- Coordinate out_coord(arg0_projected_coord.size() +
- arg1_projected_coord.size());
-
- auto out_coord_it = std::copy(arg0_projected_coord.begin(),
- arg0_projected_coord.end(),
- out_coord.begin());
- std::copy(
- arg1_projected_coord.begin(), arg1_projected_coord.end(), out_coord_it);
-
- // Zero out to start the sum.
- ACCUMULATION sum = 0;
-
- size_t out_index = output_transform.index(out_coord);
-
- // Walk along the dotted axes.
- Coordinate arg0_coord(arg0_shape.size());
- Coordinate arg1_coord(arg1_shape.size());
- auto arg0_it = std::copy(arg0_projected_coord.begin(),
- arg0_projected_coord.end(),
- arg0_coord.begin());
- for (const Coordinate& dot_axis_positions : dot_axes_transform)
- {
- // In order to find the points to multiply together, we need to inject
- // our current positions along the dotted axes back into the projected
- // arg0 and arg1 coordinates.
- std::copy(
- dot_axis_positions.begin(), dot_axis_positions.end(), arg0_it);
-
- auto arg1_it = std::copy(dot_axis_positions.begin(),
- dot_axis_positions.end(),
- arg1_coord.begin());
- std::copy(
- arg1_projected_coord.begin(), arg1_projected_coord.end(), arg1_it);
-
- // Multiply and add to the sum.
- if (is_quantized)
- {
- sum = sum + ((static_cast<ACCUMULATION>(
- arg0[arg0_transform.index(arg0_coord)]) -
- static_cast<ACCUMULATION>(*input0_zero_point)) *
- (static_cast<ACCUMULATION>(
- arg1[arg1_transform.index(arg1_coord)]) -
- static_cast<ACCUMULATION>(*input1_zero_point)));
- }
- else
- {
- sum = sum + (static_cast<ACCUMULATION>(
- arg0[arg0_transform.index(arg0_coord)]) *
- static_cast<ACCUMULATION>(
- arg1[arg1_transform.index(arg1_coord)]));
- }
- }
-
- if (is_quantized)
- {
- float scale = *input0_scale * *input1_scale / *output_scale;
- // Write the sum back.
- out[out_index] =
- static_cast<OUTPUT>(std::round(static_cast<float>(sum) * scale)) +
- *output_zero_point;
- }
- else
- {
- out[out_index] = sum;
- }
- }
- std::fesetround(old_mode);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void elu(const T* arg, T* out, size_t count, double alpha)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i] < 0 ? alpha * (std::exp(arg[i]) - 1.0) : arg[i];
- }
- }
- }
- }
-}
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void embeddingBagOffsetsSum(const T* emb_table,
- const U* indices,
- const U* offsets,
- const U* default_index,
- const T* weights,
- T* out,
- const size_t indices_count,
- const Shape& outShape)
- {
- const size_t offsets_size = outShape[0];
- std::vector<U> default_indices;
- if (default_index)
- default_indices.push_back(default_index[0]);
-
- size_t embDepth = 1;
- for (size_t i = 1; i < outShape.size(); i++)
- {
- embDepth *= outShape[i];
- }
- memset(out, 0, shape_size(outShape) * sizeof(T));
-
- auto get_indices = [&](size_t emb_index,
- const U*& indices_ref,
- size_t& indices_num,
- size_t& weights_idx,
- bool& with_weights) {
- if (emb_index >= offsets_size)
- throw ngraph_error("Invalid embedding bag index.");
- if (offsets[emb_index] >= indices_count)
- throw ngraph_error(
- std::string(
- "Offset value exceeds indices size in the model.\noffset: ") +
- std::to_string(offsets[emb_index]) + "; indices size: " +
- std::to_string(indices_count));
-
- indices_ref = nullptr;
- indices_num = 0lu;
- with_weights = (weights != nullptr);
-
- if (emb_index == offsets_size - 1lu)
- indices_num = indices_count - offsets[emb_index];
- else
- indices_num = offsets[emb_index + 1lu] - offsets[emb_index];
-
- if (indices_num != 0lu)
- {
- indices_ref = indices + offsets[emb_index];
- }
- else
- {
- // Empty or default bag
- with_weights = false;
- if (default_indices.size() == 1lu)
- {
- indices_ref = default_indices.data();
- indices_num = 1lu;
- }
- return;
- }
-
- if (with_weights)
- weights_idx = offsets[emb_index];
- };
-
- size_t indices_size = 0lu;
- const U* indices_emb = nullptr;
- size_t weights_idx = 0lu;
- bool with_weights_b = (weights != nullptr);
- bool with_weights = with_weights_b;
-
- for (size_t obi = 0lu; obi < outShape.at(0); obi++)
- {
- size_t dst_index = obi * embDepth;
- get_indices(obi, indices_emb, indices_size, weights_idx, with_weights);
- if (indices_emb != nullptr)
- {
- with_weights = with_weights_b & with_weights;
- for (size_t in_idx = 0lu; in_idx < indices_size; in_idx++)
- {
- size_t src_index = indices_emb[in_idx] * embDepth;
-
- if (with_weights)
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] +=
- emb_table[src_index + i] * weights[weights_idx];
- }
- weights_idx++;
- }
- else
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] += emb_table[src_index + i];
- }
- }
- }
- }
- }
-
- } // embeddingBagOffsetsSum
-
- } // reference
- } // runtime
-} // ngraph
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void embeddingBagPackedSum(const T* emb_table,
- const U* indices,
- const T* weights,
- T* out,
- const Shape& indicesShape,
- const Shape& outShape)
- {
- const size_t indices_per_bag = indicesShape[1];
-
- size_t embDepth = 1lu;
- for (size_t i = 1; i < outShape.size(); i++)
- {
- embDepth *= outShape[i];
- }
- memset(out, 0, shape_size(outShape) * sizeof(T));
-
- bool with_weights = (weights != nullptr);
- size_t idx_idx = 0lu;
-
- for (size_t obi = 0lu; obi < outShape.at(0); obi++)
- {
- size_t dst_index = obi * embDepth;
- for (size_t in_idx = 0lu; in_idx < indices_per_bag; in_idx++, idx_idx++)
- {
- size_t src_index = indices[idx_idx] * embDepth;
-
- if (with_weights)
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] += emb_table[src_index + i] * weights[idx_idx];
- }
- }
- else
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] += emb_table[src_index + i];
- }
- }
- }
- }
-
- } // embeddingBagPackedSum
-
- } // reference
- } // runtime
-} // ngraph
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void embeddingSegmentsSum(const T* embTable,
- const U* indices,
- const U* segmentIds,
- const U* defaultIndex,
- const T* weights,
- T* out,
- const Shape& embTableShape,
- const Shape& indicesShape,
- const Shape& outShape)
- {
- const size_t indices_len = indicesShape[0];
- const size_t segments_num = outShape[0];
- const size_t inDimsSize = outShape.size();
- const size_t embDimsNum = outShape.size() - 1;
-
- size_t embDepth = 1lu;
- for (size_t i = 1; i < outShape.size(); i++)
- {
- embDepth *= outShape[i];
- }
- memset(out, 0, shape_size(outShape) * sizeof(T));
-
- bool with_weights = (weights != nullptr);
-
- for (size_t index = 0; index < indices_len; index++)
- {
- size_t obi = segmentIds[index];
- if (obi >= segments_num)
- throw ngraph_error("Segment index could not be more than segments number");
- size_t dst_index = obi * embDepth;
- size_t src_index = indices[index] * embDepth;
-
- if (with_weights)
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] += embTable[src_index + i] * weights[index];
- }
- }
- else
- {
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] += embTable[src_index + i];
- }
- }
- }
-
- if (defaultIndex != nullptr)
- {
- U defIndex = defaultIndex[0];
- if (defIndex < U(0) && defIndex >= embTableShape[0])
- throw ngraph_error(std::string("Invalid default index") +
- std::to_string(defIndex));
- for (size_t obi = 0; obi < segments_num; obi++)
- {
- bool found = false;
- for (size_t index = 0; index < indices_len; index++)
- {
- if (segmentIds[index] == obi)
- {
- found = true;
- break;
- }
- }
- if (found)
- continue;
- size_t src_index = defIndex * embDepth;
- size_t dst_index = obi * embDepth;
- for (size_t i = 0lu; i < embDepth; i++)
- {
- out[dst_index + i] = embTable[src_index + i];
- }
- }
- }
- } // embeddingSegmentsSum
-
- } // reference
- } // runtime
-} // ngraph
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
-#endif
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void equal(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] == arg1[i];
- }
- }
-
- template <typename T, typename U>
- void equal(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x == y;
- });
- }
- }
- }
-}
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void erf(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::erf(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/runtime/host_tensor.hpp"
-
-namespace ngraph
-{
- namespace eval
- {
- AxisSet extract_reduction_axes(const HostTensorPtr& axes, const char* op_name);
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void exp(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::exp(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void extractImagePatches(const op::ExtractImagePatches* extImgPatches,
- const T* input,
- T* out,
- const Shape& inShape,
- const Shape& outShape)
- {
- const size_t dimsSize = inShape.size();
- const size_t BATCH = 0, CHANNEL = 1, HIGHT = 0, WIDTH = 1;
-
- const int64_t KH = extImgPatches->get_sizes()[HIGHT];
- const int64_t KW = extImgPatches->get_sizes()[WIDTH];
- const int64_t SH = extImgPatches->get_strides()[HIGHT];
- const int64_t SW = extImgPatches->get_strides()[WIDTH];
- const int64_t RH = extImgPatches->get_rates()[HIGHT];
- const int64_t RW = extImgPatches->get_rates()[WIDTH];
- const auto auto_pad = extImgPatches->get_auto_pad();
-
- const int64_t IB = inShape[BATCH];
- const int64_t IC = inShape[CHANNEL];
- const int64_t IH = inShape[dimsSize - 2];
- const int64_t IW = inShape[dimsSize - 1];
-
- const int64_t OB = outShape[BATCH];
- const int64_t OC = outShape[CHANNEL];
- const int64_t OH = outShape[dimsSize - 2];
- const int64_t OW = outShape[dimsSize - 1];
-
- int64_t ihStart = 0;
- int64_t iwStart = 0;
-
- int64_t iwStep = KW + (RW - 1) * (KW - 1);
- int64_t ihStep = KH + (RH - 1) * (KH - 1);
-
- const int64_t OH_OW = OH * OW;
- const int64_t OC_OH_OW = OC * OH_OW;
- const int64_t OB_OC_OH_OW = OC_OH_OW * OB;
- const int64_t IH_IW = IH * IW;
- const int64_t IC_IH_IW = IC * IH_IW;
- const int64_t IB_IC_IH_IW = IC_IH_IW * IB;
- const int64_t KH_KW = KH * KW;
-
- int64_t PL = 0, PT = 0;
-
- if (auto_pad != op::PadType::VALID)
- {
- int64_t PW = (std::ceil(1.f * IW / SW) - 1) * SW + iwStep - IW;
- int64_t PH = (std::ceil(1.f * IH / SH) - 1) * SH + ihStep - IH;
-
- if ((PW > 0) && (PW < iwStep))
- {
- if (PW % 2 == 1)
- {
- if (auto_pad == op::PadType::SAME_LOWER)
- {
- PL = (PW + 1) / 2;
- }
- else if (auto_pad == op::PadType::SAME_UPPER)
- {
- PL = (PW - 1) / 2;
- }
- }
- else
- {
- PL = PW / 2;
- }
- }
- if ((PH > 0) && (PH < ihStep))
- {
- if (PH % 2 == 1)
- {
- if (auto_pad == op::PadType::SAME_LOWER)
- {
- PT = (PH + 1) / 2;
- }
- else if (auto_pad == op::PadType::SAME_UPPER)
- {
- PT = (PH - 1) / 2;
- }
- }
- else
- {
- PT = PH / 2;
- }
- }
- }
-
- for (int64_t ob = 0; ob < OB; ob++)
- {
- const int64_t ib_ICIHIW = ob * IC_IH_IW;
- const int64_t ob_OCOHOW = ob * OC_OH_OW;
- for (int64_t oh = 0; oh < OH; oh++)
- {
- const int64_t ob_OCOHOW_ohOW = ob_OCOHOW + oh * OW;
- int64_t ih0 = oh * SH - PT;
- for (int64_t ow = 0; ow < OW; ow++)
- {
- const int64_t ob_OCOHOW_ohOW_ow = ob_OCOHOW_ohOW + ow;
- int64_t iw0 = ow * SW - PL;
- int64_t oc = 0;
-
- for (int64_t kh = 0; kh < KH; kh++)
- {
- int64_t ihKH = ih0 + kh * RH;
- int64_t ib_ICIHIW_ihKH_IW = ib_ICIHIW + ihKH * IW;
- for (int64_t kw = 0; kw < KW; kw++)
- {
- for (int64_t ic = 0; ic < IC; ic++, oc++)
- {
- int64_t iwKW = iw0 + kw * RW;
- int64_t dst_idx = ob_OCOHOW_ohOW_ow + oc * OH_OW;
- if (dst_idx >= OB_OC_OH_OW)
- throw ngraph_error(
- "ExtractImagePatches. Destination index is out of "
- "bounds.");
- if (ihKH < 0 || ihKH >= IH || iwKW < 0 || iwKW >= IW)
- {
- out[dst_idx] = T(0);
- }
- else
- {
- int64_t src_idx = ib_ICIHIW_ihKH_IW + ic * IH_IW + iwKW;
- if (src_idx >= IB_IC_IH_IW)
- throw ngraph_error(
- "ExtractImagePatches. Source index is out of "
- "bounds.");
- out[dst_idx] = input[src_idx];
- }
- }
- }
- }
- }
- }
- }
- } // extractImagePatches
-
- } // reference
- } // runtime
-} // ngraph
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void floor(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::floor(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/gather_nd.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // Implement gather by calling gather_nd on sub-problems
- // # prepare constant shapes for tensors used for sub problems
- // indices'.shape = indices.shape[-1] + [1]
- // params'.shape = params.shape[axis:]
- // out'.shape = params'.shape
- // out'.shape[0] = indices.shape[-1]
- // # call sub-problems
- // foreach (params_index, out_index) in outer "axis" dimensions
- // # params_prime is shared by inner loop
- // params' = param[params_index] # rank(params') == rank(params) - axis
- // foreach indices_index in outer N-1 dimensions
- // indices' = indices[indices_index] # rank(indices') == 2
- // out_index = out_index + indices_index
- // out' = out[out_index] # rank(out') == rank(params')
- // gather_nd(params', indices'', out')
- template <typename T, typename U>
- void gather(const T* params,
- const U* indices,
- T* out,
- const Shape& params_shape,
- const Shape& indices_shape,
- const Shape& out_shape,
- size_t axis)
- {
- using namespace std;
- // prepare shape of params_prime (remove first "axis" dimensions)
- Shape params_prime_shape(params_shape);
- params_prime_shape.erase(params_prime_shape.begin(),
- params_prime_shape.begin() + axis);
- // prepare shape of indices_prime
- size_t indices_ndim = static_cast<size_t>(indices_shape.size());
- Shape indices_prime_shape;
- // prepare shape of out_prime (same as params_prime except for first dim)
- Shape out_prime_shape(params_prime_shape);
- if (indices_ndim > 0)
- {
- out_prime_shape[0] = indices_shape[indices_ndim - 1];
- indices_prime_shape.emplace_back(indices_shape[indices_ndim - 1]);
- }
- else
- {
- out_prime_shape[0] = 1;
- }
- indices_prime_shape.emplace_back(1);
-
- // Create a CoordinateTransform for "out" that visits the outer "axis" dimensions
- size_t out_ndim = static_cast<size_t>(out_shape.size());
- Coordinate out_outer_start_corner(out_ndim, 0);
- Coordinate out_outer_end_corner(out_shape);
- for (size_t i = axis; i < out_ndim; i++)
- {
- out_outer_end_corner[i] = 1;
- }
- Strides out_outer_strides(out_ndim, 1);
- AxisVector out_outer_axis_order(out_ndim);
- std::iota(out_outer_axis_order.begin(), out_outer_axis_order.end(), 0);
- CoordinateTransform out_outer_transform(out_shape,
- out_outer_start_corner,
- out_outer_end_corner,
- out_outer_strides,
- out_outer_axis_order);
-
- // Create a CoordinateTransform for "params" that visits the outer "axis" dimensions
- size_t params_ndim = static_cast<size_t>(params_shape.size());
- Coordinate params_outer_start_corner(params_ndim, 0);
- Coordinate params_outer_end_corner(params_shape);
- for (size_t i = axis; i < params_ndim; i++)
- {
- params_outer_end_corner[i] = 1;
- }
- Strides params_outer_strides(params_ndim, 1);
- AxisVector params_outer_axis_order(params_ndim);
- std::iota(params_outer_axis_order.begin(), params_outer_axis_order.end(), 0);
- CoordinateTransform params_outer_transform(params_shape,
- params_outer_start_corner,
- params_outer_end_corner,
- params_outer_strides,
- params_outer_axis_order);
-
- // Create a CoordinateTransform for "indices" that visits only the first element
- // along inner most axis
- Coordinate indices_outer_start_corner(indices_ndim, 0);
- Coordinate indices_outer_end_corner(indices_shape);
- if (indices_ndim > 0)
- {
- indices_outer_end_corner[indices_ndim - 1] = 1;
- }
- Strides indices_outer_strides(indices_ndim, 1);
- AxisVector indices_outer_axis_order(indices_ndim);
- std::iota(indices_outer_axis_order.begin(), indices_outer_axis_order.end(), 0);
- CoordinateTransform indices_outer_transform(indices_shape,
- indices_outer_start_corner,
- indices_outer_end_corner,
- indices_outer_strides,
- indices_outer_axis_order);
-
- // Create an inner CoordinateTransfrom for "out"
- size_t out_inner_ndim = out_ndim - axis;
- Shape out_inner_shape(out_shape);
- out_inner_shape.erase(out_inner_shape.begin(), out_inner_shape.begin() + axis);
- Coordinate out_inner_start_corner(out_inner_ndim, 0);
- Coordinate out_inner_end_corner(out_inner_shape);
- if (indices_ndim > 0)
- {
- out_inner_end_corner[indices_ndim - 1] = 1;
- }
- for (size_t i = indices_ndim; i < out_inner_ndim; i++)
- {
- out_inner_end_corner[i] = 1;
- }
- Strides out_inner_strides(out_inner_ndim, 1);
- AxisVector out_inner_axis_order(out_inner_ndim);
- std::iota(out_inner_axis_order.begin(), out_inner_axis_order.end(), 0);
- CoordinateTransform out_inner_transform(out_inner_shape,
- out_inner_start_corner,
- out_inner_end_corner,
- out_inner_strides,
- out_inner_axis_order);
-
- auto out_outer_coord_iter = out_outer_transform.begin();
- for (const Coordinate& params_outer_coord : params_outer_transform)
- {
- const T* params_prime =
- ¶ms[params_outer_transform.index(params_outer_coord)];
- T* out_outer = &out[out_outer_transform.index(*out_outer_coord_iter)];
-
- auto out_inner_coord_iter = out_inner_transform.begin();
- for (const Coordinate& indices_outer_coord : indices_outer_transform)
- {
- const U* indices_prime =
- &indices[indices_outer_transform.index(indices_outer_coord)];
- T* out_prime = &out_outer[out_inner_transform.index(*out_inner_coord_iter)];
- gather_nd<T, U>(params_prime,
- indices_prime,
- out_prime,
- params_prime_shape,
- indices_prime_shape,
- out_prime_shape);
- out_inner_coord_iter++;
- }
- out_outer_coord_iter++;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // foreach leaf_vector_index in indices.shape[:-1]
- // vector = indices[leaf_vector_index]
- // out[leaf_vector_index:] = params[vector]
- template <typename T, typename U>
- void gather_nd(const T* params,
- const U* indices,
- T* out,
- const Shape& params_shape,
- const Shape& indices_shape,
- const Shape& out_shape)
- {
- using namespace std;
- // Create a CoordinateTransform for "indices" that visits only the first element
- // along inner most axis
- size_t indices_ndim = static_cast<size_t>(indices_shape.size());
- Coordinate indices_outer_start_corner(indices_ndim, 0);
- Coordinate indices_outer_end_corner(indices_shape);
- size_t slice_rank = indices_shape[indices_ndim - 1];
- indices_outer_end_corner[indices_ndim - 1] = 1;
- Strides indices_strides(indices_ndim, 1);
- AxisVector indices_axis_order(indices_ndim);
- std::iota(indices_axis_order.begin(), indices_axis_order.end(), 0);
- CoordinateTransform indices_outer_transform(indices_shape,
- indices_outer_start_corner,
- indices_outer_end_corner,
- indices_strides,
- indices_axis_order);
-
- // Create a matching CoordinateTransform for "out" that visits the same outer
- // coordinates
- size_t out_ndim = static_cast<size_t>(out_shape.size());
- Coordinate out_start_corner(out_ndim, 0);
- Coordinate out_end_corner(out_shape);
- for (size_t i = indices_ndim - 1; i < out_ndim; i++)
- {
- out_end_corner[i] = 1;
- }
- Strides out_strides(out_ndim, 1);
- AxisVector out_axis_order(out_ndim);
- std::iota(out_axis_order.begin(), out_axis_order.end(), 0);
- CoordinateTransform out_transform(
- out_shape, out_start_corner, out_end_corner, out_strides, out_axis_order);
- size_t params_ndim = static_cast<size_t>(params_shape.size());
- Strides params_strides(params_ndim, 1);
- AxisVector params_axis_order(params_ndim);
- std::iota(params_axis_order.begin(), params_axis_order.end(), 0);
-
- // Gather slices from "params" and copy to "out"
- auto out_coord_iter = out_transform.begin();
- for (const Coordinate& indices_coord : indices_outer_transform)
- {
- Coordinate params_start_corner(params_ndim, 0);
- Coordinate params_end_corner(params_shape);
- auto indices_index = indices_outer_transform.index(indices_coord);
- for (size_t i = 0; i < slice_rank; i++)
- {
- U index = indices[indices_index];
- // take care of negative indices
- index = index >= 0 ? index : index + params_shape[i];
- params_start_corner[i] = index;
- params_end_corner[i] = index + 1;
- indices_index++;
- }
- CoordinateTransform params_transform(params_shape,
- params_start_corner,
- params_end_corner,
- params_strides,
- params_axis_order);
- auto out_index = out_transform.index(*out_coord_iter);
- for (const Coordinate& params_coord : params_transform)
- {
- out[out_index] = params[params_transform.index(params_coord)];
- out_index++;
- }
- out_coord_iter++;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void greater(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] > arg1[i];
- }
- }
-
- template <typename T, typename U>
- void greater(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x > y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void greater_eq(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] >= arg1[i];
- }
- }
-
- template <typename T, typename U>
- void greater_eq(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x >= y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void less(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] < arg1[i];
- }
- }
-
- template <typename T, typename U>
- void less(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x < y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void less_eq(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] <= arg1[i];
- }
- }
-
- template <typename T, typename U>
- void less_eq(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x <= y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void log(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::log(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/any.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- static inline void reduce_logical_and(const char* arg,
- char* out,
- const Shape& input_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- CoordinateTransform output_transform(
- reduce(input_shape, reduction_axes, keep_dims));
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 1;
- }
-
- CoordinateTransform input_transform(input_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
- out[output_transform.index(output_coord)] =
- out[output_transform.index(output_coord)] &&
- arg[input_transform.index(input_coord)];
- }
- }
-
- static inline void reduce_logical_or(const char* arg,
- char* out,
- const Shape& input_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- runtime::reference::any(arg, out, input_shape, reduction_axes, keep_dims);
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <algorithm>
-#include <cmath>
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sum_region_across_axes(const T* arg,
- size_t current_axis_index,
- const std::vector<size_t>& axes,
- Coordinate& sum_coord,
- T& square_sum,
- const std::vector<size_t>& begin_area,
- const std::vector<size_t>& end_area,
- const CoordinateTransform& input_transform)
- {
- // all nested axes were visited
- if (current_axis_index == axes.size())
- {
- square_sum += arg[input_transform.index(sum_coord)] *
- arg[input_transform.index(sum_coord)];
- return;
- }
- auto current_axis = axes[current_axis_index];
- for (auto current_axis_coord = begin_area[current_axis];
- current_axis_coord < end_area[current_axis];
- ++current_axis_coord)
- {
- sum_coord.at(current_axis) = current_axis_coord;
- sum_region_across_axes(arg,
- current_axis_index + 1,
- axes,
- sum_coord,
- square_sum,
- begin_area,
- end_area,
- input_transform);
- }
- }
-
- template <typename T>
- void lrn(const T* arg,
- const AxisSet& axes,
- T* out,
- const Shape& arg_shape,
- double dalpha,
- double dbeta,
- double dbias,
- size_t size)
- {
- T alpha = static_cast<T>(dalpha);
- T beta = static_cast<T>(dbeta);
- T bias = static_cast<T>(dbias);
-
- std::vector<size_t> begin_area(arg_shape.size());
- std::vector<size_t> end_area(arg_shape.size());
-
- CoordinateTransform input_transform(arg_shape);
- for (const Coordinate& in_coord : input_transform)
- {
- // area determined by in_coord local neighborhood
- for (const auto& axis_coord : axes)
- {
- begin_area[axis_coord] =
- std::max<int>(0, in_coord.at(axis_coord) - (size - 1) / 2);
- end_area[axis_coord] = std::min<int>(
- arg_shape.at(axis_coord), in_coord.at(axis_coord) + (size - 1) / 2 + 1);
- }
-
- T square_sum = 0;
- auto sum_coord = in_coord;
- auto axes_vec = std::vector<size_t>(axes.begin(), axes.end());
- sum_region_across_axes(arg,
- 0,
- axes_vec,
- sum_coord,
- square_sum,
- begin_area,
- end_area,
- input_transform);
-
- T x = arg[input_transform.index(in_coord)];
- out[input_transform.index(in_coord)] =
- x / (std::pow(bias + (alpha / size) * square_sum, beta));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <numeric>
-#include <utility>
-#include <vector>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/builder/autobroadcast.hpp"
-#include "ngraph/runtime/opt_kernel/reshape.hpp"
-#include "ngraph/runtime/reference/broadcast.hpp"
-#include "ngraph/runtime/reference/dot.hpp"
-#include "ngraph/shape_util.hpp"
-
-using namespace std;
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- /// \brief Reference kernel for matmul computation.
- ///
- /// \tparam T Type of input and output tensors.
- ///
- /// \param arg0 Pointer to the buffer for left operand input tensor.
- /// \param arg1 Pointer to the buffer for right operand input tensor.
- /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
- /// the caller, and must be large enough to hold a tensor of the correct
- /// shape.
- /// \param arg0_shape Shape of arg0.
- /// \param arg1_shape Shape of arg1.
- /// \param out_shape Shape of out.
- /// \param transpose_arg0 Flag to indicate if transpose on arg0.
- /// \param transpose_arg1 Flag to indicate if transpose on arg1.
- template <typename T>
- void matmul(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const Shape& out_shape,
- bool transpose_arg0,
- bool transpose_arg1)
- {
- // Steps to compute matmul:
- // 1) Check inputs and perform transpose on arg if applicable
- // 2) If ranks of both args are 2D and below (no batch dim),
- // perform dot and return result; otherwise, continue next
- // 3) Check if auto broadcast is needed on args or transposed args,
- // and perform broadcast if applicable
- // 4) Perform dot on the args or updated args and return result
-
- size_t arg0_rank = arg0_shape.size();
- size_t arg1_rank = arg1_shape.size();
- size_t out_rank = out_shape.size();
-
- // vector vars to hold pontential intermediate transpose,
- // broadcast result
- vector<T> arg0_transpose_vec;
- vector<T> arg1_transpose_vec;
- vector<T> arg0_broadcast_vec;
- vector<T> arg1_broadcast_vec;
-
- // pointers to updated inputs
- const T* arg0_update = arg0;
- const T* arg1_update = arg1;
-
- // vars for updated inputs shapes
- Shape wip_arg0_shape = arg0_shape;
- Shape wip_arg1_shape = arg1_shape;
-
- auto get_transpose_order = [](const Shape& input_shape) {
- size_t rank = input_shape.size();
- NGRAPH_CHECK(rank > 1, "Invalid input for transpose");
- vector<size_t> axes_order(rank);
- iota(axes_order.begin(), axes_order.end(), 0);
- swap(axes_order[rank - 1], axes_order[rank - 2]);
- return AxisVector{begin(axes_order), end(axes_order)};
- };
-
- auto get_broadcast_axes = [](const Shape& marker_shape, const Shape& target_shape) {
- NGRAPH_CHECK(marker_shape.size() == target_shape.size(),
- "Incompatible input shapes");
- AxisSet broadcast_axes;
- for (size_t i = 0; i < marker_shape.size(); i++)
- {
- if (marker_shape[i] == 1 && target_shape[i] != 1)
- {
- broadcast_axes.insert(i);
- }
- }
- return broadcast_axes;
- };
-
- // Perform transpose if requested
- if (transpose_arg0 && arg0_rank > 1)
- {
- arg0_transpose_vec.reserve(shape_size(arg0_shape));
- auto axis_vector = get_transpose_order(arg0_shape);
- swap(wip_arg0_shape[arg0_rank - 1], wip_arg0_shape[arg0_rank - 2]);
- opt_kernel::reshape(reinterpret_cast<const char*>(arg0),
- reinterpret_cast<char*>(arg0_transpose_vec.data()),
- arg0_shape,
- axis_vector,
- wip_arg0_shape,
- sizeof(T));
-
- arg0_update = arg0_transpose_vec.data();
- }
-
- if (transpose_arg1 && arg1_rank > 1)
- {
- arg1_transpose_vec.reserve(shape_size(arg1_shape));
- auto axis_vector = get_transpose_order(arg1_shape);
- swap(wip_arg1_shape[arg1_rank - 1], wip_arg1_shape[arg1_rank - 2]);
- opt_kernel::reshape(reinterpret_cast<const char*>(arg1),
- reinterpret_cast<char*>(arg1_transpose_vec.data()),
- arg1_shape,
- axis_vector,
- wip_arg1_shape,
- sizeof(T));
-
- arg1_update = arg1_transpose_vec.data();
- }
-
- // Inputs are 2D and below, perform dot directly
- if (arg0_rank <= 2 && arg1_rank <= 2)
- {
- return dot(arg0_update,
- arg1_update,
- out,
- wip_arg0_shape,
- wip_arg1_shape,
- out_shape,
- 1);
- }
-
- // Check and perform auto-broadcast if needed
- // If one of the arg is 2D or below, no need to
- // do broadcast on it, just use its value for
- // every batch of dot compuatation later
-
- if (arg0_rank > 2 && arg1_rank > 2)
- {
- const auto& broadcast_shapes = builder::get_numpy_broadcast_shapes(
- {Shape{begin(wip_arg0_shape), next(end(wip_arg0_shape), -2)},
- Shape{begin(wip_arg1_shape), next(end(wip_arg1_shape), -2)}});
-
- Shape arg0_br_target_shape = broadcast_shapes.first;
- Shape arg1_br_target_shape = broadcast_shapes.first;
- Shape arg0_br_marker_shape = broadcast_shapes.second.at(0);
- Shape arg1_br_marker_shape = broadcast_shapes.second.at(1);
-
- arg0_br_target_shape.insert(
- end(arg0_br_target_shape),
- next(begin(wip_arg0_shape), wip_arg0_shape.size() - 2),
- end(wip_arg0_shape));
- arg1_br_target_shape.insert(
- end(arg1_br_target_shape),
- next(begin(wip_arg1_shape), wip_arg1_shape.size() - 2),
- end(wip_arg1_shape));
-
- arg0_br_marker_shape.insert(
- end(arg0_br_marker_shape),
- next(begin(wip_arg0_shape), wip_arg0_shape.size() - 2),
- end(wip_arg0_shape));
- arg1_br_marker_shape.insert(
- end(arg1_br_marker_shape),
- next(begin(wip_arg1_shape), wip_arg1_shape.size() - 2),
- end(wip_arg1_shape));
-
- if (arg0_br_target_shape != wip_arg0_shape)
- {
- auto broadcast_axes =
- get_broadcast_axes(arg0_br_marker_shape, arg0_br_target_shape);
- if (!broadcast_axes.empty())
- {
- arg0_broadcast_vec.reserve(shape_size(arg0_br_target_shape));
- broadcast(arg0_update,
- arg0_broadcast_vec.data(),
- wip_arg0_shape,
- arg0_br_target_shape,
- broadcast_axes);
-
- arg0_update = arg0_broadcast_vec.data();
- wip_arg0_shape = arg0_br_target_shape;
- arg0_rank = wip_arg0_shape.size();
- }
- }
-
- if (arg1_br_target_shape != wip_arg1_shape)
- {
- auto broadcast_axes =
- get_broadcast_axes(arg1_br_marker_shape, arg1_br_target_shape);
- if (!broadcast_axes.empty())
- {
- arg1_broadcast_vec.reserve(shape_size(arg1_br_target_shape));
- broadcast(arg1_update,
- arg1_broadcast_vec.data(),
- wip_arg1_shape,
- arg1_br_target_shape,
- broadcast_axes);
-
- arg1_update = arg1_broadcast_vec.data();
- wip_arg1_shape = arg1_br_target_shape;
- arg1_rank = wip_arg1_shape.size();
- }
- }
- }
-
- // Perform batched dot
-
- size_t output_batch_size = 1;
-
- // Calculate number of batches
- if (out_rank < 3)
- {
- // Output is {batch_size, dot_result}, i.e.,
- // arg 0 shape {2}, arg1 shape {3, 2, 1}, output shape {3, 1}
- output_batch_size = out_shape[0];
- }
- else
- {
- for (size_t i = 0; i < (out_rank - 2); i++)
- {
- output_batch_size *= out_shape[i];
- }
- }
-
- Shape dot_arg0_shape = (arg0_rank > 2) ? Shape{wip_arg0_shape[arg0_rank - 2],
- wip_arg0_shape[arg0_rank - 1]}
- : wip_arg0_shape;
- Shape dot_arg1_shape = (arg1_rank > 2) ? Shape{wip_arg1_shape[arg1_rank - 2],
- wip_arg1_shape[arg1_rank - 1]}
- : wip_arg1_shape;
- Shape dot_output_shape =
- (out_rank > 2) ? Shape{out_shape[out_rank - 2], out_shape[out_rank - 1]}
- : Shape{out_shape[out_rank - 1]};
-
- const size_t arg0_offset = (arg0_rank > 2) ? shape_size(dot_arg0_shape) : 0;
- const size_t arg1_offset = (arg1_rank > 2) ? shape_size(dot_arg1_shape) : 0;
- const size_t output_offset = shape_size(dot_output_shape);
- for (size_t i = 0; i < output_batch_size; i++)
- {
- dot(arg0_update + i * arg0_offset,
- arg1_update + i * arg1_offset,
- out + i * output_offset,
- dot_arg0_shape,
- dot_arg1_shape,
- dot_output_shape,
- 1);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <limits>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void max(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- T minval = std::numeric_limits<T>::has_infinity
- ? T(-std::numeric_limits<T>::infinity())
- : std::numeric_limits<T>::min();
-
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = minval;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- T x = arg[input_transform.index(input_coord)];
- T max = out[output_transform.index(output_coord)];
- if (x > max)
- {
- out[output_transform.index(output_coord)] = x;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void max_pool_backprop(const T* arg_forward,
- const T* delta,
- T* out,
- const Shape& delta_shape,
- const Shape& out_shape, // same as arg_forward_shape
- const Shape& window_shape,
- const Strides& window_movement_strides,
- const Shape& padding_below,
- const Shape& padding_above)
- {
- CoordinateTransform out_transform(out_shape);
-
- for (const Coordinate& out_coord : out_transform)
- {
- out[out_transform.index(out_coord)] = 0;
- }
-
- CoordinateTransform delta_transform(delta_shape);
-
- for (const Coordinate& delta_coord : delta_transform)
- {
- size_t img_index = delta_coord[0];
- size_t channel = delta_coord[1];
-
- size_t n_image_dimensions = out_shape.size() - 2;
- Coordinate source_window_transform_start(2 + n_image_dimensions);
- Coordinate source_window_transform_end(2 + n_image_dimensions);
- Strides source_window_transform_source_strides(2 + n_image_dimensions, 1);
- AxisVector source_window_transform_source_axis_order(2 + n_image_dimensions);
- CoordinateDiff source_window_transform_padding_below(2 + n_image_dimensions);
- CoordinateDiff source_window_transform_padding_above(2 + n_image_dimensions);
-
- source_window_transform_start[0] = img_index;
- source_window_transform_end[0] = img_index + 1;
- source_window_transform_start[1] = channel;
- source_window_transform_end[1] = channel + 1;
- source_window_transform_padding_below[0] = 0;
- source_window_transform_padding_below[1] = 0;
- source_window_transform_padding_above[0] = 0;
- source_window_transform_padding_above[1] = 0;
-
- for (size_t i = 2; i < n_image_dimensions + 2; i++)
- {
- size_t window_shape_this_dim = window_shape[i - 2];
- size_t movement_stride = window_movement_strides[i - 2];
-
- source_window_transform_start[i] = movement_stride * delta_coord[i];
- source_window_transform_end[i] =
- source_window_transform_start[i] + window_shape_this_dim;
- source_window_transform_padding_below[i] = padding_below[i - 2];
- source_window_transform_padding_above[i] = padding_above[i - 2];
- }
- std::iota(begin(source_window_transform_source_axis_order),
- end(source_window_transform_source_axis_order),
- 0);
-
- CoordinateTransform source_window_transform(
- out_shape,
- source_window_transform_start,
- source_window_transform_end,
- source_window_transform_source_strides,
- source_window_transform_source_axis_order,
- source_window_transform_padding_below,
- source_window_transform_padding_above);
-
- Coordinate argmax_coord;
- bool argmax_coord_valid = false;
- T max_val = 0; // just initializing to keep compiler happy, this 0 is ignored
-
- for (const Coordinate& source_window_coord : source_window_transform)
- {
- if (source_window_transform.has_source_coordinate(source_window_coord))
- {
- T candidate =
- arg_forward[source_window_transform.index(source_window_coord)];
-
- if (!argmax_coord_valid || candidate > max_val)
- {
- max_val = candidate;
- argmax_coord = source_window_coord;
- argmax_coord_valid = true;
- }
- }
- }
-
- if (argmax_coord_valid)
- {
- out[source_window_transform.index(argmax_coord)] +=
- delta[delta_transform.index(delta_coord)];
- }
- }
- }
-
- template <typename T>
- void max_pool(const T* arg,
- T* out,
- const Shape& arg_shape,
- const Shape& out_shape,
- const Shape& window_shape,
- const Strides& window_movement_strides,
- const Shape& padding_below,
- const Shape& padding_above)
- {
- // At the outermost level we will walk over every output coordinate O.
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& out_coord : output_transform)
- {
- // Our output coordinate O will have the form:
- //
- // (N,chan,i_1,...,i_n)
-
- size_t batch_index = out_coord[0];
- size_t channel = out_coord[1];
-
- // For the input data we need to iterate the coordinate:
- //
- // I:
- //
- // over the range (noninclusive on the right):
- //
- // (N,chan,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
- //
- // (N+1,chan+1,s_1*i_1 + window_shape_1,...,s_n*i_n + window_shape_n)
- //
- // with unit stride.
- //
- // We iterate this over the *padded* data, so below we will need to check for
- // coordinates that fall in the padding area.
-
- size_t n_spatial_dimensions = arg_shape.size() - 2;
-
- Coordinate input_batch_transform_start(2 + n_spatial_dimensions);
- Coordinate input_batch_transform_end(2 + n_spatial_dimensions);
- Strides input_batch_transform_source_strides(2 + n_spatial_dimensions, 1);
- AxisVector input_batch_transform_source_axis_order(2 + n_spatial_dimensions);
- CoordinateDiff input_batch_transform_padding_below(2 + n_spatial_dimensions);
- CoordinateDiff input_batch_transform_padding_above(2 + n_spatial_dimensions);
-
- input_batch_transform_start[0] = batch_index;
- input_batch_transform_end[0] = batch_index + 1;
- input_batch_transform_start[1] = channel;
- input_batch_transform_end[1] = channel + 1;
- input_batch_transform_padding_below[0] = 0;
- input_batch_transform_padding_below[1] = 0;
- input_batch_transform_padding_above[0] = 0;
- input_batch_transform_padding_above[1] = 0;
-
- for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
- {
- size_t window_shape_this_dim = window_shape[i - 2];
- size_t movement_stride = window_movement_strides[i - 2];
-
- input_batch_transform_start[i] = movement_stride * out_coord[i];
- input_batch_transform_end[i] =
- input_batch_transform_start[i] + window_shape_this_dim;
- input_batch_transform_padding_below[i] = padding_below[i - 2];
- input_batch_transform_padding_above[i] = padding_above[i - 2];
- }
-
- for (size_t i = 0; i < arg_shape.size(); i++)
- {
- input_batch_transform_source_axis_order[i] = i;
- }
-
- CoordinateTransform input_batch_transform(
- arg_shape,
- input_batch_transform_start,
- input_batch_transform_end,
- input_batch_transform_source_strides,
- input_batch_transform_source_axis_order,
- input_batch_transform_padding_below,
- input_batch_transform_padding_above);
-
- // As we go, we compute the maximum value:
- //
- // output[O] = max(output[O],arg[I])
-
- T result = std::numeric_limits<T>::lowest();
-
- for (const Coordinate& input_batch_coord : input_batch_transform)
- {
- if (input_batch_transform.has_source_coordinate(input_batch_coord))
- {
- T x = arg[input_batch_transform.index(input_batch_coord)];
- result = x > result ? x : result;
- }
- }
-
- out[output_transform.index(out_coord)] = result;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void maximum(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] > arg1[i] ? arg0[i] : arg1[i];
- }
- }
-
- template <typename T>
- void maximum(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x > y ? x : y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <map>
-#include <vector>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/sum.hpp"
-#include "ngraph/shape_util.hpp"
-#include "ngraph/type/bfloat16.hpp"
-#include "ngraph/type/float16.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void mean(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
- std::vector<T> cs(shape_size(out_shape));
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 0;
- cs[output_transform.index(output_coord)] = 0;
- }
-
- CoordinateTransform input_transform(in_shape);
- std::map<size_t, int> index_to_count_map;
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- T x = arg[input_transform.index(input_coord)];
- T& z = out[output_transform.index(output_coord)];
- auto index = output_transform.index(output_coord);
- if (index_to_count_map.find(index) == index_to_count_map.end())
- {
- index_to_count_map[index] = 1;
- }
- else
- {
- index_to_count_map[index]++;
- }
-
- if (is_finite(x) && is_finite(z))
- {
- T& c = cs[output_transform.index(output_coord)];
- T t = z + (x - c);
- c = (t - z) - (x - c);
- z = t;
- }
- else
- {
- z = z + x;
- }
- }
-
- for (const Coordinate& output_coord : output_transform)
- {
- auto count = index_to_count_map[output_transform.index(output_coord)];
- out[output_transform.index(output_coord)] =
- out[output_transform.index(output_coord)] / count;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <limits>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-#ifdef _WIN32
-#undef min
-#endif
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void min(const T* arg, T* out, const Shape& in_shape, const AxisSet& reduction_axes)
- {
- T minval = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity()
- : std::numeric_limits<T>::max();
-
- auto out_shape = reduce(in_shape, reduction_axes, false);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = minval;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, false);
-
- T x = arg[input_transform.index(input_coord)];
- T min = out[output_transform.index(output_coord)];
- if (x < min)
- {
- out[output_transform.index(output_coord)] = x;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void minimum(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] < arg1[i] ? arg0[i] : arg1[i];
- }
- }
-
- template <typename T>
- void minimum(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x < y ? x : y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void mish(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i] * std::tanh(std::log((std::exp(arg[i]) + 1.0)));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void multiply(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] * arg1[i];
- }
- }
-
- template <typename T>
- void multiply(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x * y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void negate(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = -arg[i];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- /// \brief Return number of non-zero entries in the input argument.
- ///
- /// \param arg Input tensor
- /// \param arg_shape Input tensor shape
- /// Output number of non-zero entries in arg
- template <typename T>
- size_t non_zero_get_count(const T* arg, const Shape& arg_shape)
- {
- T zero = 0;
- size_t arg_rank = arg_shape.size();
- size_t arg_count = shape_size(arg_shape);
- size_t non_zero_count = 0;
-
- // Input arg is scalar
- if (arg_rank == 0)
- {
- if (*arg != zero)
- {
- non_zero_count = 1;
- }
- }
- else // Input is non scalar case
- {
- for (size_t i = 0; i < arg_count; i++)
- {
- if (arg[i] != zero)
- {
- non_zero_count++;
- }
- }
- }
-
- return non_zero_count;
- }
-
- /// \brief Return indices of non-zero entries in input argument.
- ///
- /// \param arg Input tensor
- /// \param arg_shape Input tensor shape
- /// \param out Output containing indices of non-zero entries in arg
- template <typename T, typename U>
- void non_zero(const T* arg, U* out, const Shape& arg_shape)
- {
- T zero = 0;
- size_t arg_rank = arg_shape.size();
- size_t arg_count = shape_size(arg_shape);
-
- size_t non_zero_count = non_zero_get_count(arg, arg_shape);
-
- // Input arg only contains 0s
- if (non_zero_count == 0)
- {
- return;
- }
-
- // Input arg is non-zero scalar
- if (arg_rank == 0)
- {
- out[0] = static_cast<U>(0);
- return;
- }
-
- // Dimensional size for the arg_shape. This is used to map one-dimentional
- // arg array indices to corresponding arg_rank-dimentional shape indices.
- // i.e., arg_shape {2, 3, 2} => elem_per_axis {6, 2, 1}.
- // Array index 4 in arg (arg[4]) correspond to 3-D index of [0][2][0]
- std::vector<size_t> elem_per_axis;
- elem_per_axis.reserve(arg_rank);
-
- size_t temp = arg_count;
- for (size_t i = 0; i < arg_rank; i++)
- {
- temp = temp / arg_shape[i];
- elem_per_axis.push_back(temp);
- }
-
- // Column index in out to record a non-zero entry
- size_t col_index = 0;
-
- // Array index in out to write non-zero index value
- size_t out_index = 0;
-
- // Find non-zero entries in arg and write the indices info in out.
- // For a non-zero entry, map its array index to corresponding indices
- // in arg_shape, then, write each of the arg_shape index value to
- // out array at the position that is determined by entry's dimension
- // distance and number of non-zero entries prior to it.
- // i,e., Given input with shape{2, 3, 2}, rank = 3
- // input [[[0, 2], [0, 0], [3, 4]],
- // [[5, 0], [6, 0], [7, 8]]]
- //
- // output shape {3, 7}, rank = 2
- // output [[0, 0, 0, 1, 1, 1, 1],
- // [0, 2, 2, 0, 1, 2, 2],
- // [1, 0, 1, 0, 0, 0, 1]]
- //
- // input[0][2][0] = 3 is arg[4]
- // output for this entry out[1] = 0, out[8] = 2, out[15] = 0
- for (size_t i = 0; i < arg_count; i++)
- {
- if (arg[i] != zero)
- {
- temp = i;
-
- for (size_t j = 0; j < arg_rank; j++)
- {
- out_index = j * non_zero_count + col_index;
- out[out_index] = static_cast<U>(temp / elem_per_axis[j]);
-
- temp = temp % elem_per_axis[j];
- }
-
- col_index++;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void logical_not(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = static_cast<T>(!(arg[i]));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
-#endif
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void not_equal(const T* arg0,
- const T* arg1,
- char* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] != arg1[i];
- }
- }
-
- template <typename T, typename U>
- void not_equal(const T* arg0,
- const T* arg1,
- U* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x != y;
- });
- }
- }
- }
-}
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename INDICES_TYPE, typename OUTPUT_TYPE>
- void one_hot(const INDICES_TYPE* arg,
- OUTPUT_TYPE* out,
- const Shape& in_shape,
- const Shape& out_shape,
- size_t one_hot_axis,
- const OUTPUT_TYPE on_value,
- const OUTPUT_TYPE off_value)
- {
- // Step 1: Set off_value to the output.
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = off_value;
- }
-
- // Step 2: Write off_value at needed positions, throwing exceptions when invalid
- // conditions are encountered.
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- INDICES_TYPE val = arg[input_transform.index(input_coord)];
-
- if (std::floor(val) < val || std::floor(val) > val)
- {
- continue;
- }
-
- size_t one_hot_pos = static_cast<size_t>(val);
-
- if (one_hot_pos >= out_shape[one_hot_axis])
- {
- continue;
- }
-
- Coordinate one_hot_coord = inject(input_coord, one_hot_axis, one_hot_pos);
-
- out[output_transform.index(one_hot_coord)] = on_value;
- }
- }
-
- template <typename T>
- void one_hot(const T* arg,
- T* out,
- const Shape& in_shape,
- const Shape& out_shape,
- size_t one_hot_axis)
- {
- const T on_value = 1;
- const T off_value = 0;
- one_hot<T, T>(arg, out, in_shape, out_shape, one_hot_axis, on_value, off_value);
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void logical_or(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = static_cast<T>(arg0[i] || arg1[i]);
- }
- }
-
- template <typename T>
- void logical_or(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return static_cast<T>(x || y);
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/pad.hpp" // for op::PadMode
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void pad(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& out_shape,
- const CoordinateDiff& padding_below,
- const CoordinateDiff& padding_above,
- op::PadMode pad_mode)
- {
- Coordinate input_start(arg0_shape.size(), 0); // start at (0,0,...,0)
- Coordinate input_end = out_shape; // end at (d'0,d'1,...,d'n), the outer corner of
- // the post-padding shape
-
- Strides input_strides(arg0_shape.size(), 1);
-
- AxisVector input_axis_order(arg0_shape.size());
- for (size_t i = 0; i < arg0_shape.size(); i++)
- {
- input_axis_order[i] = i;
- }
-
- CoordinateTransform input_transform(arg0_shape,
- input_start,
- input_end,
- input_strides,
- input_axis_order,
- padding_below,
- padding_above);
- CoordinateTransform output_transform(out_shape);
-
- CoordinateTransform::Iterator output_it = output_transform.begin();
-
- NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
- shape_size(output_transform.get_target_shape()));
-
- for (const Coordinate& in_coord : input_transform)
- {
- const Coordinate& out_coord = *output_it;
-
- T v(0);
-
- switch (pad_mode)
- {
- case op::PadMode::CONSTANT:
- // If the coordinate is out of bounds, substitute *arg1.
- v = input_transform.has_source_coordinate(in_coord)
- ? arg0[input_transform.index(in_coord)]
- : *arg1;
- break;
- case op::PadMode::EDGE:
- {
- Coordinate c = in_coord; // have to copy because in_coord is const
-
- // Truncate each out-of-bound dimension.
- for (size_t i = 0; i < c.size(); i++)
- {
- if (static_cast<ptrdiff_t>(c[i]) < padding_below[i])
- {
- c[i] = padding_below[i];
- }
-
- if (static_cast<ptrdiff_t>(c[i]) >=
- (padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i])))
- {
- c[i] = static_cast<size_t>(
- padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i]) - 1);
- }
- }
- v = arg0[input_transform.index(c)];
- break;
- }
- case op::PadMode::REFLECT:
- {
- // clang-format off
- // The algorithm here is a bit complicated because if the padding is
- // bigger than the tensor, we may reflect multiple times.
- //
- // Example:
- //
- // Input shape: [2]
- // Padding: 6 below, 6 above
- // Output shape: [14]
- //
- // Input: a b
- // Expected output: a b a b a b a b a b a b a b
- //
- // Computation for coordinate 13 of output:
- //
- // . . . . . . a b . . . . .[.] -> (oob above by 6 spaces, so reflection is at top-6)
- // .[.]. . . . a b . . . . . . -> (oob below by 5 spaces, so reflection is at bottom+5)
- // . . . . . . a b . . .[.]. . -> (oob above by 4 spaces, so reflection is at top-4)
- // . . .[.]. . a b . . . . . . -> (oob below by 3 spaces, so reflection is at bottom+3)
- // . . . . . . a b .[.]. . . . -> (oob above by 2 spaces, so reflection is at top-2)
- // . . . . .[.]a b . . . . . . -> (oob below by 1 space, so reflection is at bottom+1)
- // . . . . . . a[b]. . . . . . -> (no longer oob, so copy from here)
- //
- // Note that this algorithm works because REFLECT padding only makes sense
- // if each dim is >= 2.
- // clang-format on
- Coordinate c = in_coord; // have to copy because in_coord is const
-
- for (size_t i = 0; i < c.size(); i++)
- {
- ptrdiff_t new_dim = c[i];
- bool done_reflecting = false;
-
- while (!done_reflecting)
- {
- if (new_dim < padding_below[i])
- {
- ptrdiff_t distance_oob = padding_below[i] - new_dim;
- new_dim = padding_below[i] + distance_oob;
- }
- else if (new_dim >=
- padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i]))
- {
- ptrdiff_t distance_oob =
- new_dim - padding_below[i] -
- (static_cast<ptrdiff_t>(arg0_shape[i]) - 1);
- new_dim = padding_below[i] +
- static_cast<ptrdiff_t>(arg0_shape[i]) - distance_oob -
- 1;
- }
- else
- {
- done_reflecting = true;
- }
- }
-
- c[i] = static_cast<size_t>(new_dim);
- }
- v = arg0[input_transform.index(c)];
- break;
- }
- case op::PadMode::SYMMETRIC:
- {
- Coordinate c = in_coord; // have to copy because in_coord is const
- for (size_t i = 0; i < c.size(); i++)
- {
- ptrdiff_t pos = padding_below[i] - (c[i] + 1);
- if (pos >= 0)
- {
- c[i] = static_cast<size_t>(pos + padding_below[i]);
- }
- else
- {
- pos = -(pos + 1);
- ptrdiff_t src_dim = static_cast<ptrdiff_t>(arg0_shape[i]);
- if (pos < src_dim)
- {
- c[i] = static_cast<size_t>(pos + padding_below[i]);
- }
- else
- {
- c[i] = static_cast<size_t>(padding_below[i] + src_dim +
- padding_above[i] - pos);
- }
- }
- }
- v = arg0[input_transform.index(c)];
- break;
- }
- }
-
- out[output_transform.index(out_coord)] = v;
-
- ++output_it;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void power(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::pow(arg0[i], arg1[i]);
- }
- }
-
- template <typename T>
- void power(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return std::pow(x, y);
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-#include <op/util/attr_types.hpp>
-#include <shape.hpp>
-
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void prelu(const T* arg,
- const T* slope,
- T* out,
- const Shape& arg_shape,
- const Shape& slope_shape)
- {
- int cnt = 0;
- for (size_t i = 0; i < shape_size(arg_shape); ++i)
- {
- out[i] =
- arg[i] < T(0) ? T(arg[i] * slope[cnt++ % shape_size(slope_shape)]) : arg[i];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/prior_box.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- static inline float clip_great(float x, float threshold)
- {
- return x < threshold ? x : threshold;
- }
-
- static inline float clip_less(float x, float threshold)
- {
- return x > threshold ? x : threshold;
- }
-
- template <typename T>
- void prior_box(const T* data,
- const T* img,
- float* dst_data,
- const Shape& out_shape,
- const op::PriorBoxAttrs& attrs)
- {
- const int64_t W = data[1];
- const int64_t H = data[0];
- const int64_t IW = img[1];
- const int64_t IH = img[0];
-
- const int64_t OH = out_shape[1];
- const int64_t OW = 1;
-
- std::vector<float> aspect_ratios = {1.0f};
- for (const auto& aspect_ratio : attrs.aspect_ratio)
- {
- bool exist = false;
- for (const auto existed_value : aspect_ratios)
- exist |= std::fabs(aspect_ratio - existed_value) < 1e-6;
-
- if (!exist)
- {
- aspect_ratios.push_back(aspect_ratio);
- if (attrs.flip)
- {
- aspect_ratios.push_back(1.0f / aspect_ratio);
- }
- }
- }
-
- std::vector<float> variance = attrs.variance;
- NGRAPH_CHECK(variance.size() == 1 || variance.size() == 4 || variance.empty());
- if (variance.empty())
- variance.push_back(0.1f);
-
- int64_t num_priors = op::PriorBox::number_of_priors(attrs);
-
- float step = attrs.step;
- auto min_size = attrs.min_size;
- if (!attrs.scale_all_sizes)
- {
- // mxnet-like PriorBox
- if (step == -1)
- step = 1.f * IH / H;
- else
- step *= IH;
- for (auto& size : min_size)
- size *= IH;
- }
-
- int64_t idx = 0;
- float center_x, center_y, box_width, box_height, step_x, step_y;
- float IWI = 1.0f / static_cast<float>(IW);
- float IHI = 1.0f / static_cast<float>(IH);
-
- if (step == 0)
- {
- step_x = static_cast<float>(IW) / W;
- step_y = static_cast<float>(IH) / H;
- }
- else
- {
- step_x = step;
- step_y = step;
- }
-
- auto calculate_data = [&dst_data, &IWI, &IHI, &idx](
- float center_x, float center_y, float box_width, float box_height, bool clip) {
- if (clip)
- {
- // order: xmin, ymin, xmax, ymax
- dst_data[idx++] = clip_less((center_x - box_width) * IWI, 0);
- dst_data[idx++] = clip_less((center_y - box_height) * IHI, 0);
- dst_data[idx++] = clip_great((center_x + box_width) * IWI, 1);
- dst_data[idx++] = clip_great((center_y + box_height) * IHI, 1);
- }
- else
- {
- dst_data[idx++] = (center_x - box_width) * IWI;
- dst_data[idx++] = (center_y - box_height) * IHI;
- dst_data[idx++] = (center_x + box_width) * IWI;
- dst_data[idx++] = (center_y + box_height) * IHI;
- }
- };
-
- for (int64_t h = 0; h < H; ++h)
- {
- for (int64_t w = 0; w < W; ++w)
- {
- if (step == 0)
- {
- center_x = (w + 0.5f) * step_x;
- center_y = (h + 0.5f) * step_y;
- }
- else
- {
- center_x = (attrs.offset + w) * step;
- center_y = (attrs.offset + h) * step;
- }
-
- for (size_t s = 0; s < attrs.fixed_size.size(); ++s)
- {
- auto fixed_size_ = static_cast<size_t>(attrs.fixed_size[s]);
- box_width = box_height = fixed_size_ * 0.5f;
-
- if (!attrs.fixed_ratio.empty())
- {
- for (float ar : attrs.fixed_ratio)
- {
- auto density_ = static_cast<int64_t>(attrs.density[s]);
- auto shift =
- static_cast<int64_t>(attrs.fixed_size[s] / density_);
- ar = std::sqrt(ar);
- float box_width_ratio = attrs.fixed_size[s] * 0.5f * ar;
- float box_height_ratio = attrs.fixed_size[s] * 0.5f / ar;
- for (size_t r = 0; r < density_; ++r)
- {
- for (size_t c = 0; c < density_; ++c)
- {
- float center_x_temp = center_x - fixed_size_ / 2 +
- shift / 2.f + c * shift;
- float center_y_temp = center_y - fixed_size_ / 2 +
- shift / 2.f + r * shift;
- calculate_data(center_x_temp,
- center_y_temp,
- box_width_ratio,
- box_height_ratio,
- true);
- }
- }
- }
- }
- else
- {
- if (!attrs.density.empty())
- {
- auto density_ = static_cast<int64_t>(attrs.density[s]);
- auto shift =
- static_cast<int64_t>(attrs.fixed_size[s] / density_);
- for (int64_t r = 0; r < density_; ++r)
- {
- for (int64_t c = 0; c < density_; ++c)
- {
- float center_x_temp = center_x - fixed_size_ / 2 +
- shift / 2.f + c * shift;
- float center_y_temp = center_y - fixed_size_ / 2 +
- shift / 2.f + r * shift;
- calculate_data(center_x_temp,
- center_y_temp,
- box_width,
- box_height,
- true);
- }
- }
- }
- // Rest of priors
- for (float ar : aspect_ratios)
- {
- if (fabs(ar - 1.) < 1e-6)
- {
- continue;
- }
-
- auto density_ = static_cast<int64_t>(attrs.density[s]);
- auto shift =
- static_cast<int64_t>(attrs.fixed_size[s] / density_);
- ar = std::sqrt(ar);
- float box_width_ratio = attrs.fixed_size[s] * 0.5f * ar;
- float box_height_ratio = attrs.fixed_size[s] * 0.5f / ar;
- for (int64_t r = 0; r < density_; ++r)
- {
- for (int64_t c = 0; c < density_; ++c)
- {
- float center_x_temp = center_x - fixed_size_ / 2 +
- shift / 2.f + c * shift;
- float center_y_temp = center_y - fixed_size_ / 2 +
- shift / 2.f + r * shift;
- calculate_data(center_x_temp,
- center_y_temp,
- box_width_ratio,
- box_height_ratio,
- true);
- }
- }
- }
- }
- }
-
- for (size_t ms_idx = 0; ms_idx < min_size.size(); ms_idx++)
- {
- box_width = min_size[ms_idx] * 0.5f;
- box_height = min_size[ms_idx] * 0.5f;
- calculate_data(center_x, center_y, box_width, box_height, false);
-
- if (attrs.max_size.size() > ms_idx)
- {
- box_width = box_height =
- std::sqrt(min_size[ms_idx] * attrs.max_size[ms_idx]) * 0.5f;
- calculate_data(center_x, center_y, box_width, box_height, false);
- }
-
- if (attrs.scale_all_sizes ||
- (!attrs.scale_all_sizes && (ms_idx == min_size.size() - 1)))
- {
- size_t s_idx = attrs.scale_all_sizes ? ms_idx : 0;
- for (float ar : aspect_ratios)
- {
- if (std::fabs(ar - 1.0f) < 1e-6)
- {
- continue;
- }
-
- ar = std::sqrt(ar);
- box_width = min_size[s_idx] * 0.5f * ar;
- box_height = min_size[s_idx] * 0.5f / ar;
- calculate_data(
- center_x, center_y, box_width, box_height, false);
- }
- }
- }
- }
- }
-
- if (attrs.clip)
- {
- for (uint64_t i = 0; i < H * W * num_priors * 4; ++i)
- {
- dst_data[i] = (std::min)((std::max)(dst_data[i], 0.0f), 1.0f);
- }
- }
-
- uint64_t channel_size = OH * OW;
- if (variance.size() == 1)
- {
- for (uint64_t i = 0; i < channel_size; ++i)
- {
- dst_data[i + channel_size] = variance[0];
- }
- }
- else
- {
- for (uint64_t i = 0; i < H * W * num_priors; ++i)
- {
- for (size_t j = 0; j < 4; ++j)
- {
- dst_data[i * 4 + j + channel_size] = variance[j];
- }
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/prior_box_clustered.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void prior_box_clustered(const T* data,
- const T* img,
- float* dst_data,
- const Shape& out_shape,
- const op::PriorBoxClusteredAttrs& attrs)
- {
- size_t num_priors_ = attrs.widths.size();
-
- auto variances = attrs.variances;
- if (variances.empty())
- variances.push_back(0.1f);
-
- // Execute
- const int64_t layer_width = data[1];
- const int64_t layer_height = data[0];
-
- int64_t img_width = img[1];
- int64_t img_height = img[0];
-
- // TODO: Uncomment after PriorBoxClustered is aligned with the specification.
-
- // int img_width = img_w_ == 0 ? img[1] : img_w_;
- // int img_height = img_h_ == 0 ? img[0] : img_h_;
-
- // float step_w = attrs.step_widths == 0 ? step_ : attrs.step_widths;
- // float step_h = attrs.step_heights == 0 ? step_ :
- // attrs.step_heights;
-
- float step_w = attrs.step_widths;
- float step_h = attrs.step_heights;
-
- if (step_w == 0 && step_h == 0)
- {
- step_w = static_cast<float>(img_width) / layer_width;
- step_h = static_cast<float>(img_height) / layer_height;
- }
-
- size_t var_size = variances.size();
- for (int64_t h = 0; h < layer_height; ++h)
- {
- for (int64_t w = 0; w < layer_width; ++w)
- {
- float center_x = (w + attrs.offset) * step_w;
- float center_y = (h + attrs.offset) * step_h;
-
- for (size_t s = 0; s < num_priors_; ++s)
- {
- float box_width = attrs.widths[s];
- float box_height = attrs.heights[s];
-
- float xmin = (center_x - box_width / 2.0f) / img_width;
- float ymin = (center_y - box_height / 2.0f) / img_height;
- float xmax = (center_x + box_width / 2.0f) / img_width;
- float ymax = (center_y + box_height / 2.0f) / img_height;
-
- if (attrs.clip)
- {
- xmin = (std::min)((std::max)(xmin, 0.0f), 1.0f);
- ymin = (std::min)((std::max)(ymin, 0.0f), 1.0f);
- xmax = (std::min)((std::max)(xmax, 0.0f), 1.0f);
- ymax = (std::min)((std::max)(ymax, 0.0f), 1.0f);
- }
-
- auto get_idx = [&](uint64_t cnt) -> uint64_t {
- return h * layer_width * num_priors_ * cnt + w * num_priors_ * cnt +
- s * cnt;
- };
-
- uint64_t idx = get_idx(4);
- dst_data[idx + 0] = xmin;
- dst_data[idx + 1] = ymin;
- dst_data[idx + 2] = xmax;
- dst_data[idx + 3] = ymax;
-
- idx = get_idx(var_size);
- for (size_t j = 0; j < var_size; j++)
- dst_data[idx + j + out_shape[1]] = variances[j];
- }
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void product(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 1;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- size_t output_index = output_transform.index(output_coord);
-
- out[output_index] = out[output_index] * arg[input_transform.index(input_coord)];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/quantize.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename REAL, typename QUANT>
- void quantize(const REAL* input,
- const REAL* scale,
- const QUANT* zero_point,
- QUANT* output,
- const Shape& input_shape,
- const Shape& scale_zero_point_shape,
- const AxisSet& axes,
- op::Quantize::RoundMode round_mode)
- {
- CoordinateTransform input_transform(input_shape);
- CoordinateTransform scale_zero_point_transform(scale_zero_point_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate scale_zero_point_coord = project(input_coord, axes);
-
- // apply scale
- REAL qvalue = input[input_transform.index(input_coord)] /
- scale[scale_zero_point_transform.index(scale_zero_point_coord)];
-
- // round
- if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY)
- {
- REAL abs_qvalue = std::fabs(qvalue);
- REAL abs_qvalue_toward_inf =
- std::floor(abs_qvalue + static_cast<REAL>(0.5));
- qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
- : abs_qvalue_toward_inf;
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_ZERO)
- {
- auto abs_qvalue = std::fabs(qvalue);
- auto abs_qvalue_toward_zero =
- std::ceil(abs_qvalue - static_cast<REAL>(0.5));
- qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
- : abs_qvalue_toward_zero;
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_UPWARD)
- {
- qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_DOWNWARD)
- {
- qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN)
- {
- auto up_qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
- auto dn_qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
- auto rem = std::fmod(up_qvalue, 2.0);
- qvalue = (rem == 0.0) ? up_qvalue : dn_qvalue;
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_INFINITY)
- {
- auto abs_qvalue = std::fabs(qvalue);
- auto abs_qvalue_toward_inf = std::ceil(abs_qvalue);
- qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
- : abs_qvalue_toward_inf;
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_ZERO)
- {
- auto abs_qvalue = std::fabs(qvalue);
- auto abs_qvalue_toward_zero = std::floor(abs_qvalue);
- qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
- : abs_qvalue_toward_zero;
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_UP)
- {
- qvalue = std::ceil(qvalue);
- }
- else if (round_mode == op::Quantize::RoundMode::ROUND_DOWN)
- {
- qvalue = std::floor(qvalue);
- }
-
- // apply zero_point
- qvalue += zero_point[scale_zero_point_transform.index(scale_zero_point_coord)];
-
- // clamp
- qvalue = std::max<REAL>(qvalue,
- static_cast<REAL>(std::numeric_limits<QUANT>::min()));
- qvalue = std::min<REAL>(qvalue,
- static_cast<REAL>(std::numeric_limits<QUANT>::max()));
-
- // cast
- output[input_transform.index(input_coord)] = static_cast<QUANT>(qvalue);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <type_traits>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/type/bfloat16.hpp"
-#include "ngraph/type/float16.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // Return type is `void`, only enabled if `T` is a built-in FP
- // type, or nGraph's `bfloat16` or `float16` type.
- template <typename T>
- typename std::enable_if<std::is_floating_point<T>::value ||
- std::is_same<T, bfloat16>::value ||
- std::is_same<T, float16>::value>::type
- range(const T* start, const T* step, const Shape& out_shape, T* out)
- {
- for (size_t i = 0; i < shape_size(out_shape); i++)
- {
- out[i] = *start + (static_cast<T>(i) * (*step));
- }
- }
-
- // Return type is `void`, only enabled if `T` is `is_integral`.
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value>::type
- range(const T* start, const T* step, const Shape& out_shape, T* out)
- {
- T val = *start;
-
- for (size_t i = 0; i < shape_size(out_shape); i++)
- {
- out[i] = val;
- val += *step;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void reduce_l1(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 0;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- size_t output_index = output_transform.index(output_coord);
-
- out[output_index] =
- out[output_index] + abs(arg[input_transform.index(input_coord)]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void reduce_l2(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 0;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- size_t output_index = output_transform.index(output_coord);
-
- out[output_index] = out[output_index] +
- arg[input_transform.index(input_coord)] *
- arg[input_transform.index(input_coord)];
- }
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] =
- sqrt(out[output_transform.index(output_coord)]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void relu(const T* arg, T* out, size_t count)
- {
- T zero = 0;
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i] > zero ? arg[i] : zero;
- }
- }
- template <typename T>
- void relu_backprop(const T* arg, const T* delta_arg, T* out, size_t count)
- {
- T zero = 0;
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i] > zero ? delta_arg[i] : zero;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void replace_slice(const T* arg0, // replacement context
- const T* arg1, // replacement value
- T* out,
- const Shape& arg1_shape,
- const Coordinate& lower_bounds,
- const Coordinate& upper_bounds,
- const Strides& strides,
- const Shape& out_shape)
- {
- // Step 1: Copy the entire replacement context to the output.
- CoordinateTransform copy_transform(out_shape);
-
- for (Coordinate copy_coord : copy_transform)
- {
- out[copy_transform.index(copy_coord)] = arg0[copy_transform.index(copy_coord)];
- }
-
- // Step 2: Overwrite the slice for replacement.
- CoordinateTransform input_transform(arg1_shape);
- CoordinateTransform output_transform(
- out_shape, lower_bounds, upper_bounds, strides);
-
- NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
- shape_size(output_transform.get_target_shape()));
-
- CoordinateTransform::Iterator output_it = output_transform.begin();
-
- for (const Coordinate& input_coord : input_transform)
- {
- const Coordinate& output_coord = *output_it;
-
- out[output_transform.index(output_coord)] =
- arg1[input_transform.index(input_coord)];
-
- ++output_it;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/type/element_type.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- void reshape(const char* arg,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <algorithm>
-#include <cmath>
-#include <numeric>
-#include <vector>
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void result(const T* arg, T* out, size_t count)
- {
- memcpy(out, arg, sizeof(T) * count);
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- NGRAPH_API
- void reverse(const char* arg,
- char* out,
- const Shape& arg_shape,
- const Shape& out_shape,
- const AxisSet& reversed_axes,
- size_t elem_size);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void reverse_sequence(const T* arg,
- T* out,
- const Shape& arg_shape,
- size_t batch_axis,
- size_t sequence_axis,
- const U* sequence_lengths)
- {
- CoordinateTransform input_transform(arg_shape);
- for (const Coordinate& in_coord : input_transform)
- {
- size_t batch_index = in_coord[batch_axis];
- auto orig_seq_index = static_cast<size_t>(sequence_lengths[batch_index]);
-
- if (orig_seq_index > arg_shape.at(sequence_axis))
- {
- throw ngraph_error(
- "One of the elements of sequence lengths is greater than sequence axis "
- "dimension");
- }
-
- if (orig_seq_index == 0)
- {
- orig_seq_index = 1;
- }
-
- size_t sequence_index = in_coord[sequence_axis] < orig_seq_index
- ? orig_seq_index - in_coord[sequence_axis] - 1
- : in_coord[sequence_axis];
-
- // make a copy of in_coord and update sequence_index
- Coordinate out_coord = in_coord;
- out_coord[sequence_axis] = sequence_index;
- out[input_transform.index(out_coord)] = arg[input_transform.index(in_coord)];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- T round_to_nearest_even(const T arg)
- {
- const auto floor_arg = std::floor(arg);
- const auto diff = arg - floor_arg;
- if (diff < 0.5f || (diff == 0.5f && static_cast<int>(floor_arg) % 2 == 0))
- {
- return floor_arg;
- }
- else
- {
- return floor_arg + 1.0f;
- }
- }
-
- template <typename T>
- void round(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; ++i)
- {
- out[i] = round_to_nearest_even(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstring>
-
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename DataType, typename IndicesType>
- void scatter_elem_update(const DataType* input_data,
- const IndicesType* indices,
- const DataType* updates,
- const int64_t& axis,
- DataType* out_buf,
- const Shape& data_shape,
- const Shape& indices_shape)
- {
- // Copy inputs to out
- std::memcpy(out_buf, input_data, sizeof(DataType) * shape_size(data_shape));
-
- // 3D example
- // output[indices[i][j][k]][j][k] = updates[i][j][k] if axis = 0,
- // output[i][indices[i][j][k]][k] = updates[i][j][k] if axis = 1,
- // output[i][j][indices[i][j][k]] = updates[i][j][k] if axis = 2
-
- CoordinateTransform indices_transform{indices_shape};
- CoordinateTransform data_transform{data_shape};
-
- for (const Coordinate& indices_cord : indices_transform)
- {
- const size_t indices_idx = indices_transform.index(indices_cord);
- Coordinate out_cord(indices_cord);
- out_cord.at(axis) = indices[indices_idx];
- NGRAPH_CHECK(data_transform.has_source_coordinate(out_cord),
- "Provided index coordinates are out of input data bounds: ",
- out_cord,
- ".");
- out_buf[data_transform.index(out_cord)] = updates[indices_idx];
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-#include <iostream>
-
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void select(const char* arg0,
- const T* arg1,
- const T* arg2,
- T* out,
- size_t count) // TODO: using char for bool, is this right?
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] ? arg1[i] : arg2[i];
- }
- }
-
- template <typename T>
- void select(const char* arg0,
- const T* arg1,
- const T* arg2,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const Shape& arg2_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_select(
- arg0,
- arg1,
- arg2,
- out,
- arg0_shape,
- arg1_shape,
- arg2_shape,
- broadcast_spec,
- [](char s, T x, T y) -> T { return static_cast<T>(s ? x : y); });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- inline void shape_of(const Shape& arg_shape, T* out)
- {
- for (size_t i = 0; i < arg_shape.size(); i++)
- {
- out[i] = static_cast<T>(arg_shape[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sigmoid(const T* arg, T* out, size_t count)
- {
- T exp_value;
- for (size_t i = 0; i < count; i++)
- {
- exp_value = std::exp(-arg[i]);
- out[i] = 1 / (1 + exp_value);
- }
- }
-
- template <typename T>
- void sigmoid_backprop(const T* arg, const T* delta_arg, T* out, size_t count)
- {
- T exp_value;
- T func_x;
- for (size_t i = 0; i < count; i++)
- {
- exp_value = std::exp(-arg[i]);
- func_x = 1 / (1 + exp_value);
- out[i] = delta_arg[i] * func_x * (1 - func_x);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sign(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = (arg[i] < T(0) ? T(-1) : (arg[i] > T(0) ? T(1) : T(0)));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sin(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::sin(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sinh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::sinh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/type/element_type.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- void slice(const char* arg,
- char* out,
- const Shape& arg_shape,
- const Coordinate& lower_bounds,
- const Coordinate& upper_bounds,
- const Strides& strides,
- const Shape& out_shape,
- size_t elem_size);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/reference/max.hpp"
-#include "ngraph/runtime/reference/sum.hpp"
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void softmax(const T* arg, T* out, const Shape& shape, const AxisSet& axes)
- {
- auto temp_shape = reduce(shape, axes, true);
- auto temp_elements = shape_size(temp_shape);
- auto temp_ptr = new T[temp_elements];
-
- max(arg, temp_ptr, shape, axes, true);
-
- CoordinateTransform transform(shape);
- CoordinateTransform temp_transform(temp_shape);
- for (const Coordinate& coord : transform)
- {
- Coordinate temp_coord = reduce(coord, axes, true);
- out[transform.index(coord)] = std::exp(
- arg[transform.index(coord)] - temp_ptr[temp_transform.index(temp_coord)]);
- }
-
- sum(out, temp_ptr, shape, axes, true);
-
- for (const Coordinate& coord : transform)
- {
- Coordinate temp_coord = reduce(coord, axes, true);
- out[transform.index(coord)] /= temp_ptr[temp_transform.index(temp_coord)];
- }
-
- delete[] temp_ptr;
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void sqrt(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::sqrt(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/check.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/runtime/host_tensor.hpp"
-#include "ngraph/runtime/opt_kernel/reshape.hpp"
-#include "ngraph/runtime/reference/reverse.hpp"
-#include "ngraph/runtime/reference/slice.hpp"
-#include "ngraph/slice_plan.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- void strided_slice(const char* arg,
- char* out,
- const Shape& arg_shape,
- const SlicePlan& sp,
- size_t elem_type);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void subtract(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg0[i] - arg1[i];
- }
- }
-
- template <typename T>
- void subtract(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return x - y;
- });
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape_util.hpp"
-#include "ngraph/type/bfloat16.hpp"
-#include "ngraph/type/float16.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // Windows doesn't seem to like it if we directly use std::isfinite on integer types,
- // so we will roll our own thing here.
- template <typename T>
- typename std::enable_if<std::is_floating_point<T>::value, bool>::type is_finite(T x)
- {
- return std::isfinite(x);
- }
-
- template <typename T>
- typename std::enable_if<std::is_same<T, bfloat16>::value ||
- std::is_same<T, float16>::value,
- bool>::type
- is_finite(T x)
- {
- return std::isfinite(static_cast<float>(x));
- }
-
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, bool>::type is_finite(T /* x */)
- {
- return true;
- }
-
- template <typename T>
- void sum(const T* arg,
- T* out,
- const Shape& in_shape,
- const AxisSet& reduction_axes,
- bool keep_dims)
- {
- auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
- CoordinateTransform output_transform(out_shape);
- std::vector<T> cs(shape_size(out_shape));
-
- for (const Coordinate& output_coord : output_transform)
- {
- out[output_transform.index(output_coord)] = 0;
- cs[output_transform.index(output_coord)] = 0;
- }
-
- CoordinateTransform input_transform(in_shape);
-
- for (const Coordinate& input_coord : input_transform)
- {
- Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
-
- T x = arg[input_transform.index(input_coord)];
- T& z = out[output_transform.index(output_coord)];
-
- if (is_finite(x) && is_finite(z))
- {
- T& c = cs[output_transform.index(output_coord)];
- T t = z + (x - c);
- c = (t - z) - (x - c);
- z = t;
- }
- else
- {
- z = z + x;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void swish(const T* arg, const T* beta, T* out, size_t count)
- {
- T beta_value = static_cast<T>(1.0);
- if (beta != nullptr)
- {
- beta_value = beta[0];
- }
- for (size_t i = 0; i < count; i++)
- {
- out[i] = arg[i] / (1.0 + std::exp(-arg[i] * beta_value));
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void tan(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::tan(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-#include <cstddef>
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void tanh(const T* arg, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = std::tanh(arg[i]);
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cmath>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/type/element_type.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- void tile(const char* arg,
- char* out,
- const Shape& in_shape,
- const Shape& out_shape,
- size_t elem_size);
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <algorithm>
-#include <cmath>
-#include <numeric>
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/op/topk.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- // Had to split out these two functions. They used to be lambda expressions but
- // MSVC had difficulty compiling. This way is more explicit.
- template <typename T, typename U>
- inline bool compare_max(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
- {
-// this is intentional to be able to compare floats directly
-// without using relative or absolute tolerance
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
-#endif
- if (std::get<0>(a) == std::get<0>(b))
- {
- return std::get<1>(a) < std::get<1>(b);
- }
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
- return a > b;
- }
-
- template <typename T, typename U>
- inline bool compare_min(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
- {
- return a < b;
- }
-
- template <typename T, typename U>
- inline bool sort_indices_descending(const std::tuple<T, U>& a,
- const std::tuple<T, U>& b)
- {
- return std::get<1>(a) < std::get<1>(b);
- }
-
- template <typename T, typename U>
- inline bool sort_indices_ascending(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
- {
- return std::get<1>(a) > std::get<1>(b);
- }
-
- template <typename T, typename U>
- void topk(const T* arg,
- U* out_indices,
- T* out_values,
- const Shape& in_shape,
- const Shape& out_shape,
- size_t axis,
- size_t k,
- bool compute_max,
- op::TopK::SortType sort = op::TopK::SortType::NONE)
- {
- using namespace std;
- // reorder source axis visit order and make "axis" inner most
- size_t ndim = static_cast<size_t>(in_shape.size());
- Coordinate start_corner(ndim, 0);
- Coordinate end_corner(in_shape);
- end_corner[axis] = 1;
- Strides strides(ndim, 1);
- AxisVector axis_order(ndim);
- iota(axis_order.begin(), axis_order.end(), 0);
- axis_order.erase(axis_order.begin() + axis);
- axis_order.push_back(axis);
- // Create CoordinateTransforms that visits only the first element along "axis"
- CoordinateTransform input_transform(
- in_shape, start_corner, end_corner, strides, axis_order);
- CoordinateTransform output_transform(
- out_shape, start_corner, end_corner, strides, axis_order);
- // Create temp vector for sorting.
- vector<tuple<T, U>> workspace(in_shape[axis]);
- vector<size_t> in_strides = ngraph::row_major_strides(in_shape);
- vector<size_t> out_strides = ngraph::row_major_strides(out_shape);
- auto in_axis_stride = in_strides[axis];
- auto out_axis_stride = out_strides[axis];
- for (const Coordinate& coord : input_transform)
- {
- auto arg_index = input_transform.index(coord);
- auto out_index = output_transform.index(coord);
- // Fill the temp vector
- U i = 0;
- for (tuple<T, U>& entry : workspace)
- {
- get<0>(entry) = arg[arg_index];
- get<1>(entry) = i;
- arg_index += in_axis_stride;
- i++;
- }
- // Sort the temp vector
- if (compute_max)
- {
- nth_element(workspace.begin(),
- workspace.begin() + k,
- workspace.end(),
- compare_max<T, U>);
- }
- else
- {
- nth_element(workspace.begin(),
- workspace.begin() + k,
- workspace.end(),
- compare_min<T, U>);
- }
- // Write temp vector to output
- if (compute_max)
- {
- switch (sort)
- {
- case op::TopK::SortType::NONE: break;
- case op::TopK::SortType::SORT_INDICES:
- std::sort(workspace.begin(),
- workspace.begin() + k,
- sort_indices_descending<T, U>);
- break;
- case op::TopK::SortType::SORT_VALUES:
- std::sort(workspace.begin(), workspace.begin() + k, compare_max<T, U>);
- break;
- }
- }
- else
- {
- switch (sort)
- {
- case op::TopK::SortType::NONE: break;
- case op::TopK::SortType::SORT_INDICES:
- std::sort(workspace.begin(),
- workspace.begin() + k,
- sort_indices_ascending<T, U>);
- break;
- case op::TopK::SortType::SORT_VALUES:
- std::sort(workspace.begin(), workspace.begin() + k, compare_min<T, U>);
- break;
- }
- }
- for (size_t j = 0; j < k; j++)
- {
- tuple<T, U> entry = workspace[j];
- out_values[out_index] = get<0>(entry);
- out_indices[out_index] = get<1>(entry);
- out_index += out_axis_stride;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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.
-//*****************************************************************************
-
-#pragma once
-
-#include <cstddef>
-
-#include "ngraph/op/util/attr_types.hpp"
-#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T>
- void logical_xor(const T* arg0, const T* arg1, T* out, size_t count)
- {
- for (size_t i = 0; i < count; i++)
- {
- out[i] = static_cast<T>((arg0[i] || arg1[i]) && !(arg0[i] && arg1[i]));
- }
- }
-
- template <typename T>
- void logical_xor(const T* arg0,
- const T* arg1,
- T* out,
- const Shape& arg0_shape,
- const Shape& arg1_shape,
- const op::AutoBroadcastSpec& broadcast_spec)
- {
- autobroadcast_binop(
- arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
- return static_cast<T>((x || y) && !(x && y));
- });
- }
- }
- }
-}
--- /dev/null
+# ******************************************************************************
+# Copyright 2017-2020 Intel Corporation
+#
+# 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.
+# ******************************************************************************
+
+set(TARGET_NAME "ngraph_reference")
+
+file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
+file(GLOB_RECURSE PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
+
+set(REF_IMPL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/ CACHE INTERNAL "")
+
+# Create named folders for the sources within the .vcproj
+# Empty name lists them directly under the .vcproj
+
+source_group("src" FILES ${LIBRARY_SRC})
+source_group("include" FILES ${PUBLIC_HEADERS})
+
+# Create shared library
+add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS})
+
+# Defines macro in C++ to load backend plugin
+target_include_directories(${TARGET_NAME} PUBLIC ${REF_IMPL_INCLUDE_DIR})
+target_include_directories(${TARGET_NAME} PRIVATE ${NGRAPH_INCLUDE_PATH}
+ ${REF_IMPL_INCLUDE_DIR}/ngraph)
+
+#Add an alias so that library can be used inside the build tree, e.g. when testing
+add_library(ngraph::reference ALIAS ${TARGET_NAME})
+
+# developer package
+
+openvino_developer_export_targets(ngraph::reference)
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/coordinate.hpp"
+#include "ngraph/coordinate_diff.hpp"
+#include "ngraph/shape.hpp"
+#include "ngraph/strides.hpp"
+
+namespace ngraph
+{
+ /// \brief A useful class that allows to iterate over the tensor coordinates.
+ /// For example, for tensor with dimensions {2, 3} this iterator
+ /// produces the following coordinates:
+ /// {0,0}, {0,1}, {0,2},
+ /// {1,0}, {1,1}, {2,2}
+ class NGRAPH_API CoordinateIterator
+ {
+ public:
+ /// \brief Coordinates iterator constructor
+ /// \param target_shape The target shape for coordinates iteration
+ /// \param is_end The flag indicates that the coordinate iterator is the last.
+ CoordinateIterator(const Shape& target_shape, bool is_end = false);
+
+ /// \brief The postfix operation increment the iterator by one.
+ void operator++();
+
+ /// \brief The prefix operation increment the iterator by one.
+ CoordinateIterator operator++(int);
+
+ /// \brief Increments iterator n times.
+ /// \param n number of elements it should be advanced
+ void operator+=(size_t n);
+
+ /// \brief Iterator dereferencing operator returns reference to current pointed coordinate.
+ const Coordinate& operator*() const noexcept;
+
+ /// \brief Checks for iterator inequality.
+ /// \param it second iterator to compare
+ bool operator!=(const CoordinateIterator& it) const noexcept;
+
+ /// \brief Checks for iterator equality.
+ /// \param it second iterator to compare
+ bool operator==(const CoordinateIterator& it) const noexcept;
+
+ /// \brief Increments iterator using specified axis of the shape n times.
+ /// \param axis index used for iteration
+ size_t advance(size_t axis) noexcept;
+
+ /// \brief Useful function to build the last iterator.
+ /// Returns a singleton that points to the last iterator.
+ static const CoordinateIterator& end();
+
+ private:
+ const Shape& m_target_shape;
+ Coordinate m_coordinate;
+ bool m_oob;
+ };
+
+ /// \brief Class which allows to calculate item index with given coordinates in tensor
+ /// and helps to iterate over all coordinates.
+ /// Tensor items should be placed in memory in row-major order.
+ class NGRAPH_API CoordinateTransformBasic
+ {
+ public:
+ using Iterator = CoordinateIterator;
+
+ CoordinateTransformBasic(const Shape& source_shape);
+
+ /// \brief The tensor element index calculation by given coordinate.
+ /// \param c tensor element coordinate
+ size_t index(const Coordinate& c) const noexcept;
+
+ /// \brief Returns an iterator to the first coordinate of the tensor.
+ CoordinateIterator begin() const noexcept;
+
+ /// \brief Returns an iterator to the coordinate following the last element of the tensor.
+ const CoordinateIterator& end() const noexcept;
+
+ protected:
+ Shape m_source_shape;
+ };
+
+ /// \brief Class which allows to calculate item index with given coordinates in tensor
+ /// and helps to iterate over the subset of coordinates.
+ /// Tensor items should be placed in memory in row-major order.
+ class NGRAPH_API CoordinateTransform : protected CoordinateTransformBasic
+ {
+ public:
+ using Iterator = CoordinateIterator;
+
+ CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order,
+ const CoordinateDiff& target_padding_below,
+ const CoordinateDiff& target_padding_above,
+ const Strides& source_dilation_strides);
+
+ CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order,
+ const CoordinateDiff& target_padding_below,
+ const CoordinateDiff& target_padding_above);
+
+ CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order);
+
+ CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides);
+
+ CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner);
+
+ CoordinateTransform(const Shape& source_shape);
+
+ /// \brief The tensor element index calculation by given coordinate.
+ /// \param c tensor element coordinate
+ size_t index(const Coordinate& c) const;
+
+ /// \brief Checks that coordinate belongs to given coordinates subset.
+ /// \param c tensor element coordinate
+ bool has_source_coordinate(const Coordinate& c) const;
+
+ /// \brief Convert a target-space coordinate to a source-space coordinate.
+ /// \param c tensor element coordinate
+ Coordinate to_source_coordinate(const Coordinate& c) const;
+
+ const Shape& get_source_shape() const noexcept;
+ const Shape& get_target_shape() const noexcept;
+ const Coordinate& get_source_start_corner() const noexcept;
+ const Coordinate& get_source_end_corner() const noexcept;
+ const Strides& get_source_strides() const noexcept;
+ const AxisVector& get_source_axis_order() const noexcept;
+ const Strides& get_target_dilation_strides() const noexcept;
+
+ /// \brief Returns an iterator to the first coordinate of the tensor.
+ CoordinateIterator begin() const noexcept;
+
+ /// \brief Returns an iterator to the coordinate following the last element of the tensor.
+ const CoordinateIterator& end() const noexcept;
+
+ private:
+ Coordinate m_source_start_corner;
+ Coordinate m_source_end_corner;
+ Strides m_source_strides;
+ AxisVector m_source_axis_order;
+ CoordinateDiff m_target_padding_below;
+ CoordinateDiff m_target_padding_above;
+ Strides m_target_dilation_strides;
+
+ Shape m_target_shape;
+ size_t m_n_axes;
+ };
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <utility>
+
+#include "ngraph/runtime/reference/broadcast.hpp"
+#include "ngraph/shape_util.hpp"
+#include "ngraph/util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace opt_kernel
+ {
+ template <typename T>
+ void broadcast_2d(
+ const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
+ {
+ size_t index[2];
+ size_t& in_index = index[out_axis];
+ auto out_strides = row_major_strides(out_shape);
+ for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
+ {
+ for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
+ {
+ // clang-format off
+ out[index[0] * out_strides[0] +
+ index[1]] =
+ in[in_index];
+ // clang-format on
+ }
+ }
+ }
+
+ // #define PARALLEL
+ template <typename T>
+ void broadcast_3d(
+ const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
+ {
+ size_t index[3];
+ size_t& in_index = index[out_axis];
+ auto out_strides = row_major_strides(out_shape);
+ for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
+ {
+ for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
+ {
+ for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
+ {
+ // clang-format off
+ out[index[0] * out_strides[0] +
+ index[1] * out_strides[1] +
+ index[2]] =
+ in[in_index];
+ // clang-format on
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void broadcast_4d(
+ const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
+ {
+ size_t index[4];
+ size_t& in_index = index[out_axis];
+ auto out_strides = row_major_strides(out_shape);
+ for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
+ {
+ for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
+ {
+ for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
+ {
+ for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
+ {
+ // clang-format off
+ out[index[0] * out_strides[0] +
+ index[1] * out_strides[1] +
+ index[2] * out_strides[2] +
+ index[3]] =
+ in[in_index];
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void broadcast_5d(
+ const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
+ {
+ size_t index[5];
+ size_t& in_index = index[out_axis];
+ auto out_strides = row_major_strides(out_shape);
+ for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
+ {
+ for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
+ {
+ for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
+ {
+ for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
+ {
+ for (index[4] = 0; index[4] < out_shape[4]; ++index[4])
+ {
+ // clang-format off
+ out[index[0] * out_strides[0] +
+ index[1] * out_strides[1] +
+ index[2] * out_strides[2] +
+ index[3] * out_strides[3] +
+ index[4]] =
+ in[in_index];
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void broadcast_6d(
+ const T* in, T* out, const Shape& in_shape, const Shape& out_shape, size_t out_axis)
+ {
+ size_t index[6];
+ size_t& in_index = index[out_axis];
+ auto out_strides = row_major_strides(out_shape);
+ for (index[0] = 0; index[0] < out_shape[0]; ++index[0])
+ {
+ for (index[1] = 0; index[1] < out_shape[1]; ++index[1])
+ {
+ for (index[2] = 0; index[2] < out_shape[2]; ++index[2])
+ {
+ for (index[3] = 0; index[3] < out_shape[3]; ++index[3])
+ {
+ for (index[4] = 0; index[4] < out_shape[4]; ++index[4])
+ {
+ for (index[5] = 0; index[5] < out_shape[5]; ++index[5])
+ {
+ // clang-format off
+ out[index[0] * out_strides[0] +
+ index[1] * out_strides[1] +
+ index[2] * out_strides[2] +
+ index[3] * out_strides[3] +
+ index[4] * out_strides[4] +
+ index[5]] =
+ in[in_index];
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void broadcast(const T* in,
+ T* out,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ const AxisSet& broadcast_axes)
+ {
+ if (is_scalar(in_shape))
+ {
+ for (size_t i = 0; i < shape_size(out_shape); ++i)
+ {
+ out[i] = in[0];
+ }
+ }
+ else if (in_shape.size() == 1)
+ {
+ size_t output_axis = 0;
+ for (size_t i = 0; i < out_shape.size(); i++)
+ {
+ if (broadcast_axes.count(i) == 0)
+ {
+ output_axis = i;
+ break;
+ }
+ }
+ switch (out_shape.size())
+ {
+ case 2: broadcast_2d<T>(in, out, in_shape, out_shape, output_axis); break;
+ case 3: broadcast_3d<T>(in, out, in_shape, out_shape, output_axis); break;
+ case 4: broadcast_4d<T>(in, out, in_shape, out_shape, output_axis); break;
+ case 5: broadcast_5d<T>(in, out, in_shape, out_shape, output_axis); break;
+ case 6: broadcast_6d<T>(in, out, in_shape, out_shape, output_axis); break;
+ default:
+ runtime::reference::broadcast<T>(
+ in, out, in_shape, out_shape, broadcast_axes);
+ break;
+ }
+ }
+ else
+ {
+ runtime::reference::broadcast<T>(in, out, in_shape, out_shape, broadcast_axes);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/runtime/reference/reshape.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace opt_kernel
+ {
+ void reshape(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void abs(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ // TODO: generic "abs" doesn't work here for some reason.
+ out[i] = (arg[i] < T(0) ? T(-arg[i]) : arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void acos(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::acos(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void acosh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::acosh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void add(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] + arg1[i];
+ }
+ }
+
+ template <typename T>
+ void add(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x + y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void logical_and(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = static_cast<T>(arg0[i] && arg1[i]);
+ }
+ }
+
+ template <typename T>
+ void logical_and(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return static_cast<T>(x && y);
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ static inline void any(const char* arg,
+ char* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ CoordinateTransform output_transform(reduce(in_shape, reduction_axes, keep_dims));
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 0;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+ out[output_transform.index(output_coord)] =
+ out[output_transform.index(output_coord)] ||
+ arg[input_transform.index(input_coord)];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void asin(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::asin(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void asinh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::asinh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void atan(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::atan(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename X, typename Y, typename Z>
+ void atan2(const X* py, const Y* px, Z* pout, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ *pout++ = static_cast<Z>(std::atan2(*py++, *px++));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void atanh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::atanh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include <utility>
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ namespace internal
+ {
+ inline void
+ row_major_strides(const Shape& shape, size_t* strides, size_t size) noexcept
+ {
+ size_t* st = strides + size - 1;
+ size_t s = 1;
+ for (auto d = shape.rbegin(); d != shape.rend(); d++)
+ {
+ *st-- = s;
+ s *= *d;
+ }
+ std::fill(strides, st + 1, s);
+ }
+
+ template <typename C, typename T>
+ inline T value_with_padding_or(const C& arr,
+ size_t padding,
+ size_t idx,
+ T&& default_value)
+ {
+ return idx < padding ? std::forward<T>(default_value) : arr[idx - padding];
+ }
+
+ template <int A0, int A1, typename T, typename U, typename Functor>
+ inline void numpy_autobroadcast_binop(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& shape0,
+ const Shape& shape1,
+ const size_t* strides0,
+ const size_t* strides1,
+ const size_t padding0,
+ const size_t padding1,
+ const Shape& output_shape,
+ const size_t axis,
+ const size_t stride,
+ Functor elementwise_functor)
+ {
+ for (CoordinateIterator it(output_shape), ite = CoordinateIterator::end();;)
+ {
+ for (size_t i = 0; i < stride; ++i)
+ *out++ = elementwise_functor(arg0[i * A0], arg1[i * A1]);
+
+ arg0 += A0 ? stride : 1;
+ arg1 += A1 ? stride : 1;
+
+ auto p = it.advance(axis);
+
+ if (it == ite)
+ break;
+
+ if (value_with_padding_or(shape0, padding0, p, 1) == 1)
+ arg0 -= strides0[p];
+
+ if (value_with_padding_or(shape1, padding1, p, 1) == 1)
+ arg1 -= strides1[p];
+ }
+ }
+
+ inline size_t calculate_fixed_axis(size_t axis, const size_t* strides)
+ {
+ while (axis > 0 && strides[axis - 1] == 1)
+ --axis;
+ return axis;
+ }
+ }
+
+ /// \brief Helper function to implement autobroadcasting elementwise binop references.
+ ///
+ /// \tparam T Element type of the input tensors.
+ /// \tparam U Element type of the output tensor.
+ /// \tparam Functor Type of the functor for the elementwise operation. Must support
+ /// operator()(T,T), and operator()(T,T) must return a value of type
+ /// U.
+ ///
+ /// \param arg0 Pointer to the buffer for left operand input tensor.
+ /// \param arg1 Pointer to the buffer for right operand input tensor.
+ /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
+ /// the caller, and must be large enough to hold a tensor of the correct
+ /// shape.
+ /// \param broadcast_spec Specification of the auto-broadcasting scheme.
+ /// \param elementwise_functor Functor implementing the elementwise operation to be
+ /// applied across the input tensors. Must accept two
+ /// arguments of type T, and return a value of type U.
+ template <typename T, typename U, typename Functor>
+ void autobroadcast_binop(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec,
+ Functor elementwise_functor)
+ {
+ switch (broadcast_spec.m_type)
+ {
+ case op::AutoBroadcastType::NONE:
+ for (size_t i = 0; i < shape_size(arg0_shape); i++)
+ {
+ out[i] = elementwise_functor(arg0[i], arg1[i]);
+ }
+ break;
+ case op::AutoBroadcastType::NUMPY:
+ // We'll be using CoordinateTransform to handle the broadcasting. The general
+ // procedure is as follows:
+ //
+ // (1) Left pad the shorter of the two shapes with ones.
+ // (2) Squeeze (remove ones from) both shapes, and record the squeezed axis
+ // indices.
+ // (3) Using CoordinateTransform, broadcast both args to the final output
+ // shape. The "broadcasted axes" will be those that were squeezed in step
+ // 2.
+ //
+ // Example:
+ //
+ // Input shape->Padded shape->Squeezed Shape/Squeezed Axes
+ // ----------- ------------ ----------------------------
+ // a: [ 3, 2, 1] [ 3, 2, 1] [ 3, 2 ] {2}
+ // b: [ 1, 6] [ 1, 1, 6] [ 6] {0,1}
+ // | | |
+ // v v v
+ // Output shape
+ // ------------
+ // [ 3, 2, 6]
+ {
+ using namespace internal;
+
+ size_t const shape_rank =
+ std::max(arg0_shape.size(), arg1_shape.size()) + 1;
+
+ // TODO: Use compiler-specific alloca() or variable-length array
+ std::vector<size_t> tmp(shape_rank * 2);
+
+ size_t* strides0 = tmp.data();
+ size_t* strides1 = tmp.data() + shape_rank;
+
+ row_major_strides(arg0_shape, strides0, shape_rank);
+ row_major_strides(arg1_shape, strides1, shape_rank);
+
+ size_t const padding0 = shape_rank - arg0_shape.size();
+ size_t const padding1 = shape_rank - arg1_shape.size();
+
+ Shape output_shape(shape_rank, 0);
+
+ size_t axis = 0;
+
+ for (size_t i = 0; i < shape_rank; i++)
+ {
+ auto const dim0 = value_with_padding_or(arg0_shape, padding0, i, 1);
+ auto const dim1 = value_with_padding_or(arg1_shape, padding1, i, 1);
+
+ output_shape[i] = std::max(dim0, dim1);
+
+ if (dim0 != dim1)
+ axis = std::max(axis, i);
+ }
+#if 0
+ // Universal function without optimisations
+ CoordinateTransformBasic arg0_transform(arg0_shape);
+ CoordinateTransformBasic arg1_transform(arg1_shape);
+ U *dst = out;
+
+ for(CoordinateIterator it(output_shape),
+ ite = CoordinateIterator::end();
+ it != ite;
+ ++it)
+ {
+ const Coordinate& output_coord = *it;
+ size_t const idx0 = arg0_transform.index(output_coord);
+ size_t const idx1 = arg1_transform.index(output_coord);
+ *dst++ = elementwise_functor(arg0[idx0], arg1[idx1]);
+ }
+#else
+
+ if (axis == 0)
+ {
+ for (size_t i = 0, end = strides0[0]; i < end; ++i)
+ out[i] = elementwise_functor(arg0[i], arg1[i]);
+ }
+ else if (strides0[axis] == 1 &&
+ value_with_padding_or(arg0_shape, padding0, axis, 1) == 1)
+ {
+ axis = calculate_fixed_axis(axis, strides0);
+
+ numpy_autobroadcast_binop<0, 1>(arg0,
+ arg1,
+ out,
+ arg0_shape,
+ arg1_shape,
+ strides0,
+ strides1,
+ padding0,
+ padding1,
+ output_shape,
+ axis,
+ strides1[axis],
+ elementwise_functor);
+ }
+ else if (strides1[axis] == 1 &&
+ value_with_padding_or(arg1_shape, padding1, axis, 1) == 1)
+ {
+ axis = calculate_fixed_axis(axis, strides1);
+
+ numpy_autobroadcast_binop<1, 0>(arg0,
+ arg1,
+ out,
+ arg0_shape,
+ arg1_shape,
+ strides0,
+ strides1,
+ padding0,
+ padding1,
+ output_shape,
+ axis,
+ strides0[axis],
+ elementwise_functor);
+ }
+ else
+ numpy_autobroadcast_binop<1, 1>(arg0,
+ arg1,
+ out,
+ arg0_shape,
+ arg1_shape,
+ strides0,
+ strides1,
+ padding0,
+ padding1,
+ output_shape,
+ axis,
+ strides0[axis],
+ elementwise_functor);
+#endif
+ }
+ break;
+ case op::AutoBroadcastType::PDPD:
+ // We'll be using CoordinateTransform to handle the broadcasting. No need to
+ // process arg0 and output shape will be the same as arg0. We need to process
+ // arg1 and the general procedure is as follows:
+ //
+ // (1) Trim trailing ones from arg1 shape.
+ // (2) Left and right pad arg1 to match arg0 shape. Axis is the index start
+ // to align between arg0 and arg1.
+ // (3) Squeeze (remove ones from) arg1 shape, and record the squeezed axis
+ // indices.
+ // (3) Using CoordinateTransform, broadcast arg1 to the final output
+ // shape. The "broadcasted axes" will be those that were squeezed in step
+ // 23.
+ //
+ // Example:
+ //
+ // Input shape-> Padded shape-> Squeezed Shape/Squeezed Axes
+ // ----------- ------------ ----------------------------
+ // a: [ 3, 4, 5, 6] [ 3, 4, 5, 6] [ 3, 4, 5, 6]
+ // b: [ 4, 5, ] [ 1, 4, 5, 1] [ 4, 5 ] {0,3}
+ // | | |
+ // v v v
+ // Output shape
+ // ------------
+ // [ 3, 4, 5, 6]
+ {
+ int64_t axis = broadcast_spec.m_axis;
+ if (axis == -1)
+ {
+ axis = arg0_shape.size() - arg1_shape.size();
+ }
+
+ Shape arg1_padded_shape = arg1_shape;
+ // Trim trailing ones
+ while (arg1_padded_shape.size() > 0 && arg1_padded_shape.back() == 1)
+ {
+ arg1_padded_shape.pop_back();
+ }
+
+ for (int64_t i = 0; i < axis; ++i)
+ {
+ arg1_padded_shape.insert(arg1_padded_shape.begin(), 1);
+ }
+
+ while (arg1_padded_shape.size() < arg0_shape.size())
+ {
+ arg1_padded_shape.insert(arg1_padded_shape.end(), 1);
+ }
+
+ Shape arg1_squeezed_shape;
+ AxisSet arg1_squeezed_axes;
+
+ for (size_t i = 0; i < arg0_shape.size(); i++)
+ {
+ if (arg1_padded_shape[i] == 1)
+ {
+ arg1_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg1_squeezed_shape.push_back(arg1_padded_shape[i]);
+ }
+ }
+
+ CoordinateTransform arg0_transform(arg0_shape);
+ CoordinateTransform arg1_transform(arg1_squeezed_shape);
+ CoordinateTransform output_transform(arg0_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ Coordinate arg1_coord = reduce(output_coord, arg1_squeezed_axes, false);
+ out[output_transform.index(output_coord)] =
+ elementwise_functor(arg0[arg0_transform.index(output_coord)],
+ arg1[arg1_transform.index(arg1_coord)]);
+ }
+ }
+ }
+ }
+
+ /// \brief Helper function to implement autobroadcasting elementwise ternaryop
+ /// references.
+ ///
+ /// \tparam U Element type of the selector tensor.
+ /// \tparam T Element type of the input tensors.
+ /// \tparam Functor Type of the functor for the elementwise operation. Must support
+ /// operator()(U,T,T), and operator()(U,T,T) must return a value of type
+ /// T.
+ ///
+ /// \param arg0 Pointer to the buffer for selector tensor.
+ /// \param arg1 Pointer to the buffer for left operand input tensor.
+ /// \param arg2 Pointer to the buffer for right operand input tensor.
+ /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
+ /// the caller, and must be large enough to hold a tensor of the correct
+ /// shape.
+ /// \param broadcast_spec Specification of the auto-broadcasting scheme.
+ /// \param elementwise_functor Functor implementing the elementwise operation to be
+ /// applied across the input tensors. Must accept an argument
+ /// of
+ /// type U and two of type T, and return a value of type T.
+ template <typename T, typename U, typename Functor>
+ void autobroadcast_select(const U* arg0,
+ const T* arg1,
+ const T* arg2,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const Shape& arg2_shape,
+ const op::AutoBroadcastSpec& broadcast_spec,
+ Functor elementwise_functor)
+ {
+ switch (broadcast_spec.m_type)
+ {
+ case op::AutoBroadcastType::NONE:
+ for (size_t i = 0; i < shape_size(arg0_shape); i++)
+ {
+ out[i] = elementwise_functor(arg0[i], arg1[i], arg2[i]);
+ }
+ break;
+ case op::AutoBroadcastType::NUMPY:
+ // Uses same approach as autobroadcast_binop.
+ {
+ Shape arg0_padded_shape = arg0_shape;
+ Shape arg1_padded_shape = arg1_shape;
+ Shape arg2_padded_shape = arg2_shape;
+
+ while (arg1_padded_shape.size() < arg2_padded_shape.size())
+ {
+ arg1_padded_shape.insert(arg1_padded_shape.begin(), 1);
+ }
+
+ while (arg2_padded_shape.size() < arg1_padded_shape.size())
+ {
+ arg2_padded_shape.insert(arg2_padded_shape.begin(), 1);
+ }
+
+ while (arg0_padded_shape.size() < arg1_padded_shape.size())
+ {
+ arg0_padded_shape.insert(arg0_padded_shape.begin(), 1);
+ }
+
+ Shape arg0_squeezed_shape;
+ Shape arg1_squeezed_shape;
+ Shape arg2_squeezed_shape;
+ AxisSet arg0_squeezed_axes;
+ AxisSet arg1_squeezed_axes;
+ AxisSet arg2_squeezed_axes;
+ Shape output_shape;
+
+ for (size_t i = 0; i < arg1_padded_shape.size(); i++)
+ {
+ if (arg1_padded_shape[i] == 1)
+ {
+ arg1_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg1_squeezed_shape.push_back(arg1_padded_shape[i]);
+ }
+
+ if (arg2_padded_shape[i] == 1)
+ {
+ arg2_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg2_squeezed_shape.push_back(arg2_padded_shape[i]);
+ }
+
+ if (arg0_padded_shape[i] == 1)
+ {
+ arg0_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg0_squeezed_shape.push_back(arg0_padded_shape[i]);
+ }
+
+ output_shape.push_back(arg1_padded_shape[i] == 1
+ ? arg2_padded_shape[i]
+ : arg1_padded_shape[i]);
+ }
+
+ CoordinateTransform arg0_transform(arg0_squeezed_shape);
+ CoordinateTransform arg1_transform(arg1_squeezed_shape);
+ CoordinateTransform arg2_transform(arg2_squeezed_shape);
+ CoordinateTransform output_transform(output_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
+ Coordinate arg1_coord = reduce(output_coord, arg1_squeezed_axes, false);
+ Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
+ out[output_transform.index(output_coord)] =
+ elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
+ arg1[arg1_transform.index(arg1_coord)],
+ arg2[arg2_transform.index(arg2_coord)]);
+ }
+ }
+ break;
+ case op::AutoBroadcastType::PDPD:
+ {
+ // arg0 and arg2 are broadcast to arg1 shape
+ int64_t axis = broadcast_spec.m_axis;
+ if (axis == -1)
+ {
+ axis = arg1_shape.size() - arg2_shape.size();
+ }
+
+ Shape arg0_padded_shape = arg0_shape;
+ Shape arg2_padded_shape = arg2_shape;
+ // Trim trailing ones
+ while (arg0_padded_shape.size() > 0 && arg0_padded_shape.back() == 1)
+ {
+ arg0_padded_shape.pop_back();
+ }
+
+ for (int64_t i = 0; i < axis; ++i)
+ {
+ arg0_padded_shape.insert(arg0_padded_shape.begin(), 1);
+ }
+
+ while (arg0_padded_shape.size() < arg1_shape.size())
+ {
+ arg0_padded_shape.insert(arg0_padded_shape.end(), 1);
+ }
+
+ while (arg2_padded_shape.size() > 0 && arg2_padded_shape.back() == 1)
+ {
+ arg2_padded_shape.pop_back();
+ }
+
+ for (int64_t i = 0; i < axis; ++i)
+ {
+ arg2_padded_shape.insert(arg2_padded_shape.begin(), 1);
+ }
+
+ while (arg2_padded_shape.size() < arg1_shape.size())
+ {
+ arg2_padded_shape.insert(arg2_padded_shape.end(), 1);
+ }
+
+ Shape arg0_squeezed_shape;
+ AxisSet arg0_squeezed_axes;
+ Shape arg2_squeezed_shape;
+ AxisSet arg2_squeezed_axes;
+
+ for (size_t i = 0; i < arg1_shape.size(); i++)
+ {
+ if (arg0_padded_shape[i] == 1)
+ {
+ arg0_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg0_squeezed_shape.push_back(arg0_padded_shape[i]);
+ }
+ if (arg2_padded_shape[i] == 1)
+ {
+ arg2_squeezed_axes.insert(i);
+ }
+ else
+ {
+ arg2_squeezed_shape.push_back(arg2_padded_shape[i]);
+ }
+ }
+
+ CoordinateTransform arg0_transform(arg0_squeezed_shape);
+ CoordinateTransform arg1_transform(arg1_shape);
+ CoordinateTransform arg2_transform(arg2_squeezed_shape);
+ CoordinateTransform output_transform(arg1_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
+ Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
+ out[output_transform.index(output_coord)] =
+ elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
+ arg1[arg1_transform.index(output_coord)],
+ arg2[arg2_transform.index(arg2_coord)]);
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cfenv>
+#include <cmath>
+#include <numeric>
+#include <stdexcept>
+#include <vector>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void avg_pool_backprop(const T* delta,
+ T* out,
+ const Shape& delta_shape,
+ const Shape& out_shape,
+ const Shape& window_shape,
+ const Strides& window_movement_strides,
+ const Shape& padding_below,
+ const Shape& padding_above,
+ bool include_padding_in_avg_computation)
+ {
+ CoordinateTransform out_transform(out_shape);
+
+ for (const Coordinate& out_coord : out_transform)
+ {
+ out[out_transform.index(out_coord)] = 0;
+ }
+
+ CoordinateTransform delta_transform(delta_shape);
+
+ for (const Coordinate& delta_coord : delta_transform)
+ {
+ size_t img_index = delta_coord[0];
+ size_t channel = delta_coord[1];
+
+ size_t n_image_dimensions = out_shape.size() - 2;
+ Coordinate source_window_transform_start(2 + n_image_dimensions);
+ Coordinate source_window_transform_end(2 + n_image_dimensions);
+ Strides source_window_transform_source_strides(2 + n_image_dimensions, 1);
+ AxisVector source_window_transform_source_axis_order(2 + n_image_dimensions);
+ CoordinateDiff source_window_transform_padding_below(2 + n_image_dimensions);
+ CoordinateDiff source_window_transform_padding_above(2 + n_image_dimensions);
+
+ source_window_transform_start[0] = img_index;
+ source_window_transform_end[0] = img_index + 1;
+ source_window_transform_start[1] = channel;
+ source_window_transform_end[1] = channel + 1;
+ source_window_transform_padding_below[0] = 0;
+ source_window_transform_padding_below[1] = 0;
+ source_window_transform_padding_above[0] = 0;
+ source_window_transform_padding_above[1] = 0;
+
+ for (size_t i = 2; i < n_image_dimensions + 2; i++)
+ {
+ size_t window_shape_this_dim = window_shape[i - 2];
+ size_t movement_stride = window_movement_strides[i - 2];
+
+ source_window_transform_start[i] = movement_stride * delta_coord[i];
+ source_window_transform_end[i] =
+ source_window_transform_start[i] + window_shape_this_dim;
+ source_window_transform_padding_below[i] = padding_below[i - 2];
+ source_window_transform_padding_above[i] = padding_above[i - 2];
+ }
+ std::iota(begin(source_window_transform_source_axis_order),
+ end(source_window_transform_source_axis_order),
+ 0);
+
+ CoordinateTransform source_window_transform(
+ out_shape,
+ source_window_transform_start,
+ source_window_transform_end,
+ source_window_transform_source_strides,
+ source_window_transform_source_axis_order,
+ source_window_transform_padding_below,
+ source_window_transform_padding_above);
+
+ size_t num_elements_in_window = 0;
+
+ for (const Coordinate& source_window_coord : source_window_transform)
+ {
+ if (source_window_transform.has_source_coordinate(source_window_coord) ||
+ include_padding_in_avg_computation)
+ {
+ num_elements_in_window++;
+ }
+ }
+
+ for (const Coordinate& source_window_coord : source_window_transform)
+ {
+ if (source_window_transform.has_source_coordinate(source_window_coord))
+ {
+ size_t out_index = source_window_transform.index(source_window_coord);
+ out[out_index] +=
+ delta[delta_transform.index(delta_coord)] / num_elements_in_window;
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void avg_pool(const T* arg,
+ T* out,
+ const Shape& arg_shape,
+ const Shape& out_shape,
+ const Shape& window_shape,
+ const Strides& window_movement_strides,
+ const Shape& padding_below,
+ const Shape& padding_above,
+ bool include_padding_in_avg_computation)
+ {
+ auto old_mode = std::fegetround();
+ std::fesetround(FE_TONEAREST);
+ // At the outermost level we will walk over every output coordinate O.
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& out_coord : output_transform)
+ {
+ // Our output coordinate O will have the form:
+ //
+ // (N,chan,i_1,...,i_n)
+
+ size_t batch_index = out_coord[0];
+ size_t channel = out_coord[1];
+
+ // For the input data we need to iterate the coordinate:
+ //
+ // I:
+ //
+ // over the range (noninclusive on the right):
+ //
+ // (N,chan,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
+ //
+ // (N+1,chan+1,s_1*i_1 + window_shape_1,...,s_n*i_n + window_shape_n)
+ //
+ // with unit stride.
+ //
+ // We iterate this over the *padded* data, so below we will need to check for
+ // coordinates that fall in the padding area.
+
+ size_t n_spatial_dimensions = arg_shape.size() - 2;
+
+ Coordinate input_batch_transform_start(2 + n_spatial_dimensions);
+ Coordinate input_batch_transform_end(2 + n_spatial_dimensions);
+ Strides input_batch_transform_source_strides(2 + n_spatial_dimensions, 1);
+ AxisVector input_batch_transform_source_axis_order(2 + n_spatial_dimensions);
+ CoordinateDiff input_batch_transform_padding_below(2 + n_spatial_dimensions);
+ CoordinateDiff input_batch_transform_padding_above(2 + n_spatial_dimensions);
+
+ input_batch_transform_start[0] = batch_index;
+ input_batch_transform_end[0] = batch_index + 1;
+ input_batch_transform_start[1] = channel;
+ input_batch_transform_end[1] = channel + 1;
+ input_batch_transform_padding_below[0] = 0;
+ input_batch_transform_padding_below[1] = 0;
+ input_batch_transform_padding_above[0] = 0;
+ input_batch_transform_padding_above[1] = 0;
+
+ for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
+ {
+ size_t window_shape_this_dim = window_shape[i - 2];
+ size_t movement_stride = window_movement_strides[i - 2];
+
+ input_batch_transform_start[i] = movement_stride * out_coord[i];
+ input_batch_transform_end[i] =
+ input_batch_transform_start[i] + window_shape_this_dim;
+ input_batch_transform_padding_below[i] = padding_below[i - 2];
+ input_batch_transform_padding_above[i] = padding_above[i - 2];
+ }
+
+ for (size_t i = 0; i < arg_shape.size(); i++)
+ {
+ input_batch_transform_source_axis_order[i] = i;
+ }
+
+ CoordinateTransform input_batch_transform(
+ arg_shape,
+ input_batch_transform_start,
+ input_batch_transform_end,
+ input_batch_transform_source_strides,
+ input_batch_transform_source_axis_order,
+ input_batch_transform_padding_below,
+ input_batch_transform_padding_above);
+
+ // As we go, we compute the sum value:
+ //
+ // output[O] := output[O] + arg[I]
+ //
+ // and the number of elements:
+ //
+ // n_elements := n_elements + 1
+
+ T result = 0;
+ size_t n_elements = 0;
+
+ for (const Coordinate& input_batch_coord : input_batch_transform)
+ {
+ bool in_bounds =
+ input_batch_transform.has_source_coordinate(input_batch_coord);
+
+ if (in_bounds || include_padding_in_avg_computation)
+ {
+ T v =
+ in_bounds ? arg[input_batch_transform.index(input_batch_coord)] : 0;
+ result += v;
+ n_elements++;
+ }
+ }
+
+ if (n_elements == 0)
+ {
+ throw std::runtime_error("AvgPool elements == 0, must be non-zero");
+ }
+
+ if (std::is_same<T, int8_t>::value || std::is_same<T, uint8_t>::value)
+ {
+ out[output_transform.index(out_coord)] =
+ static_cast<T>(std::nearbyint(static_cast<float>(result) / n_elements));
+ }
+ else
+ {
+ out[output_transform.index(out_coord)] = result / n_elements;
+ }
+ std::fesetround(old_mode);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <vector>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/add.hpp"
+#include "ngraph/runtime/reference/broadcast.hpp"
+#include "ngraph/runtime/reference/divide.hpp"
+#include "ngraph/runtime/reference/multiply.hpp"
+#include "ngraph/runtime/reference/sum.hpp"
+#include "ngraph/shape.hpp"
+#include "ngraph/util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void batch_norm_inference(float eps,
+ const T* gamma,
+ const T* beta,
+ const T* input,
+ const T* mean,
+ const T* variance,
+ T* normed_input,
+ const Shape& input_shape)
+ {
+ auto eps_casted = static_cast<T>(eps);
+ CoordinateTransform input_transform(input_shape);
+
+ for (Coordinate input_coord : input_transform)
+ {
+ auto channel_num = input_coord[1];
+ auto channel_gamma = gamma[channel_num];
+ auto channel_beta = beta[channel_num];
+ auto channel_mean = mean[channel_num];
+ auto channel_var = variance[channel_num];
+
+ auto input_index = input_transform.index(input_coord);
+ auto normalized =
+ (input[input_index] - channel_mean) / (std::sqrt(channel_var + eps_casted));
+ normed_input[input_index] = normalized * channel_gamma + channel_beta;
+ }
+ }
+
+ template <typename T>
+ void batch_norm_training(float eps,
+ const T* gamma,
+ const T* beta,
+ const T* input,
+ T* normed_input,
+ T* mean,
+ T* variance,
+ const Shape& input_shape)
+ {
+ auto eps_casted = static_cast<T>(eps);
+ auto channels = input_shape[1];
+
+ // We use these objects to iterate over the indices in a channel.
+ // The start and end points for the channel axis are modified in the loop.
+ Coordinate start_corner;
+ Coordinate end_corner;
+ for (size_t i = 0; i < input_shape.size(); i++)
+ {
+ start_corner.push_back(0);
+ end_corner.push_back(input_shape[i]);
+ }
+
+ for (size_t c = 0; c < channels; c++)
+ {
+ T channel_sum = 0;
+
+ start_corner[1] = c;
+ end_corner[1] = c + 1;
+
+ // Compute the mean
+ CoordinateTransform input_transform(input_shape, start_corner, end_corner);
+ for (Coordinate input_coord : input_transform)
+ {
+ channel_sum += input[input_transform.index(input_coord)];
+ }
+ T channel_mean = channel_sum / (shape_size(input_shape) / channels);
+ mean[c] = channel_mean;
+
+ T channel_diff_square_sum = 0;
+ for (Coordinate input_coord : input_transform)
+ {
+ auto centered = input[input_transform.index(input_coord)] - channel_mean;
+ channel_diff_square_sum += centered * centered;
+ }
+ T channel_var = channel_diff_square_sum / (shape_size(input_shape) / channels);
+ variance[c] = channel_var;
+
+ auto channel_gamma = gamma[c];
+ auto channel_beta = beta[c];
+ T scale = channel_gamma / std::sqrt(channel_var + eps_casted);
+
+ // Compute the normalized output
+ for (Coordinate input_coord : input_transform)
+ {
+ auto input_index = input_transform.index(input_coord);
+ normed_input[input_index] =
+ (input[input_index] - channel_mean) * scale + channel_beta;
+ }
+ }
+ }
+
+ template <typename T>
+ void batch_norm_backprop(float eps,
+ const T* gamma,
+ const T* /* beta */,
+ const T* input,
+ const T* mean,
+ const T* variance,
+ const T* delta_normed,
+ T* delta_input,
+ T* delta_gamma,
+ T* delta_beta,
+ const Shape& input_shape)
+ {
+ size_t channel_axis = 1;
+ auto num_channels = input_shape[channel_axis];
+ Shape moment_shape = Shape{num_channels};
+ auto input_num_elements = shape_size(input_shape);
+ auto elements_per_channel = input_num_elements / num_channels;
+
+ Coordinate start_corner;
+ Coordinate end_corner;
+ for (size_t i = 0; i < input_shape.size(); i++)
+ {
+ start_corner.push_back(0);
+ end_corner.push_back(input_shape[i]);
+ }
+ // The forward computation in gory detail
+ // input[., C, ...]
+ // gamma[C]
+ // beta[C]
+ // mu[c:C] = sum(input[., c, ...])/elements_per_channel
+ // var[c:C] = sum(input[., c, ...]^2 - mu[c])/elements_per_channel
+ // inv_sqrt[c:C] = 1/sqrt(var[c]+epsilon)
+ // gammad[c:C] = gamma[c]*inv_sqrt[c]
+ // normed[., c:C, ...] = (input[., c, ...]-mu)*gammad[c]+beta[c]
+
+ for (uint64_t c = 0; c < num_channels; ++c)
+ {
+ start_corner[channel_axis] = c;
+ end_corner[channel_axis] = c + 1;
+
+ CoordinateTransform input_transform(input_shape, start_corner, end_corner);
+ T delta_beta_sum = 0;
+ T var = variance[c];
+ T mu = mean[c];
+ T var_eps = var + static_cast<T>(eps);
+ T sqrt_var_eps = std::sqrt(var_eps);
+ T inv_sqrt_var_eps = 1 / sqrt_var_eps;
+ T gammad = gamma[c] * inv_sqrt_var_eps;
+ T delta_gammad = 0;
+ T delta_mu = 0;
+ for (Coordinate input_coord : input_transform)
+ {
+ auto idx = input_transform.index(input_coord);
+ auto delta_idx = delta_normed[idx];
+ auto input_idx = input[idx];
+ delta_beta_sum += delta_idx;
+ delta_gammad += (input_idx - mu) * delta_idx;
+ T delta_centered = gammad * delta_idx;
+ delta_input[idx] = delta_centered;
+ delta_mu -= delta_centered;
+ }
+ delta_beta[c] = delta_beta_sum;
+ delta_gamma[c] = delta_gammad * inv_sqrt_var_eps;
+ T delta_inv_sqrt = gamma[c] * delta_gammad;
+ // y = x^(-1/2)
+ // dy = -(1/2)x^(-3/2) = -y/(2x) dx
+ T delta_var = -delta_inv_sqrt * inv_sqrt_var_eps / (2 * var_eps);
+ T delta_two_var_sum = 2 * delta_var / elements_per_channel;
+ T delta_mu_over_n = delta_mu / elements_per_channel;
+ for (Coordinate input_coord : input_transform)
+ {
+ // v = 1/N sum(x_i - mu)^2
+ // dv = 2/N sum[(x_i - mu)dx_i] - 2/N sum[(x_i - mu) dmu]
+ // = 2/N sum[(x_i - mu)dx_i] - 2/N (Nmu-Nmu) dmu
+ // = 2/N sum[(x_i - mu)dx_i]
+ auto idx = input_transform.index(input_coord);
+ // These two values mostly cancel out so add them first
+ auto val = delta_input[idx] + delta_mu_over_n;
+ delta_input[idx] = val + (input[idx] - mu) * delta_two_var_sum;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void broadcast(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ const AxisSet& broadcast_axes)
+ {
+ // Remove all broadcast axes from in_shape
+ Shape adjusted_in_shape;
+ for (auto length : in_shape)
+ {
+ if (length != 1)
+ {
+ adjusted_in_shape.push_back(length);
+ }
+ }
+ // Remove 1s from out_shape
+ AxisSet adjusted_axes(broadcast_axes);
+ for (uint64_t axis = 0; axis < out_shape.size(); ++axis)
+ {
+ auto length = out_shape.at(axis);
+ if (length == 1)
+ {
+ adjusted_axes.insert(axis);
+ }
+ }
+ CoordinateTransform input_transform(adjusted_in_shape);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ Coordinate input_coord = reduce(output_coord, adjusted_axes, false);
+ out[output_transform.index(output_coord)] =
+ arg[input_transform.index(input_coord)];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void ceiling(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::ceil(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void clamp(const T* arg, T* out, T min, T max, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ if (arg[i] < min)
+ {
+ out[i] = min;
+ }
+ else if (arg[i] > max)
+ {
+ out[i] = max;
+ }
+ else
+ {
+ out[i] = arg[i];
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void concat(const std::vector<const T*>& args,
+ T* out,
+ const std::vector<Shape>& in_shapes,
+ const Shape& out_shape,
+ int64_t concatenation_axis)
+ {
+ // We will copy the inputs to the output one at a time. As we go, we will move out
+ // along the concatenation axis, starting at 0.
+ size_t concatenation_pos = 0;
+ for (size_t i = 0; i < args.size(); i++)
+ {
+ // CoordinateTransform gets confused when the last input has a zero-size dim, so
+ // we will just skip for zero-element tensors.
+ if (shape_size(in_shapes[i]) == 0)
+ {
+ continue;
+ }
+
+ // The start coordinate for the copy is (0,...,0) except at the concatenation
+ // axis.
+ Coordinate out_start_coord(out_shape.size(), 0);
+ out_start_coord[concatenation_axis] = concatenation_pos;
+
+ // The end coordinate for the copy is the same as the output shape except at the
+ // concatenation axis.
+ Coordinate out_end_coord = out_shape;
+ out_end_coord[concatenation_axis] =
+ concatenation_pos + in_shapes[i][concatenation_axis];
+
+ CoordinateTransform input_transform(in_shapes[i]);
+ CoordinateTransform output_chunk_transform(
+ out_shape, out_start_coord, out_end_coord);
+
+ NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
+ shape_size(output_chunk_transform.get_target_shape()));
+
+ CoordinateTransform::Iterator output_chunk_it = output_chunk_transform.begin();
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ size_t input_index = input_transform.index(input_coord);
+ size_t output_chunk_index = output_chunk_transform.index(*output_chunk_it);
+ ++output_chunk_it;
+
+ out[output_chunk_index] = args[i][input_index];
+ }
+
+ concatenation_pos += in_shapes[i][concatenation_axis];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void constant(const T* arg0, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename TI, typename TO>
+ void convert(const TI* arg, TO* out, size_t count)
+ {
+ for (size_t i = 0; i < count; ++i)
+ {
+ out[i] = static_cast<TO>(arg[i]);
+ }
+ }
+
+ template <typename T>
+ void convert_to_bool(const T* arg, char* out, size_t count)
+ {
+ for (size_t i = 0; i < count; ++i)
+ {
+ out[i] = static_cast<char>(static_cast<bool>(arg[i]));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cfenv>
+#include <cmath>
+#include <functional>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/reverse.hpp"
+#include "ngraph/util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ struct widen
+ {
+ using type = T;
+ };
+
+ template <>
+ struct widen<float>
+ {
+ using type = double;
+ };
+
+ template <>
+ struct widen<double>
+ {
+ using type = long double;
+ };
+
+ // in: NC_I...
+ // filter: C_OC_I...
+ // out: NC_O...
+ template <typename INPUT,
+ typename FILTER,
+ typename OUTPUT,
+ typename ACCUMULATION = typename widen<OUTPUT>::type>
+ void general_convolution(const INPUT* in,
+ const FILTER* filter,
+ OUTPUT* out,
+ const Shape& in_shape,
+ const Shape& filter_shape,
+ const Shape& out_shape,
+ const Strides& stride,
+ const Strides& filter_dilation,
+ const CoordinateDiff& in_pad_below,
+ const CoordinateDiff& in_pad_above,
+ const Strides& in_dilation,
+ size_t in_batch_axis,
+ size_t in_channel_axis,
+ size_t filter_out_channel_axis,
+ size_t filter_in_channel_axis,
+ size_t out_batch_axis,
+ size_t out_channel_axis,
+ const float* input_scale = nullptr,
+ const INPUT* input_zero_point = nullptr,
+ const float* filter_scale = nullptr,
+ const FILTER* filter_zero_point = nullptr,
+ const float* output_scale = nullptr,
+ const OUTPUT* output_zero_point = nullptr)
+ {
+ bool is_quantized = false;
+ if (input_scale && input_zero_point && filter_scale && filter_zero_point &&
+ output_scale && output_zero_point)
+ {
+ is_quantized = true;
+ }
+
+ auto old_mode = std::fegetround();
+ std::fesetround(FE_TONEAREST);
+ // Comments throughout assume without loss of generality that:
+ //
+ // * batch axes for both in and out are 0
+ // * in channel axes for both in and filter are 1
+ // * out channel axes for filter is 0
+ // * out channel axis for out is 1
+
+ // At the outermost level we will walk over every out coordinate O.
+ CoordinateTransform out_transform(out_shape);
+
+ for (const Coordinate& out_coord : out_transform)
+ {
+ // Our out coordinate O will have the form:
+ //
+ // (N,chan_out,i_1,...,i_n)
+
+ size_t batch_index = out_coord[out_batch_axis];
+ size_t out_channel = out_coord[out_channel_axis];
+
+ // For the in we need to iterate the coordinate:
+ //
+ // I:
+ //
+ // over the range (noninclusive on the right):
+ //
+ // (N,0,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
+ //
+ // (N+1,
+ // chans_in_count,
+ // s_1*i_1+ l_1*filter_dims_1,
+ /// ...,
+ /// s_n*i_n +l_n*filter_dims_n)
+ //
+ // with strides:
+ //
+ // (1,l_1,...,l_n).
+ //
+ // Note that we are iterating within the *padded* and *dilated* in batch, so
+ // further down we must check the current coordinate is in the pad or dilation
+ // gap.
+
+ size_t n_spatial_dimensions = in_shape.size() - 2;
+ size_t n_in_channels = in_shape[in_channel_axis];
+
+ Coordinate in_transform_start(2 + n_spatial_dimensions);
+ Coordinate in_transform_end(2 + n_spatial_dimensions);
+ Strides in_transform_movement_strides(2 + n_spatial_dimensions, 1);
+ CoordinateDiff in_transform_pad_below(2 + n_spatial_dimensions, 0);
+ CoordinateDiff in_transform_pad_above(2 + n_spatial_dimensions, 0);
+ Strides in_transform_dilation_strides(2 + n_spatial_dimensions, 1);
+
+ in_transform_start[in_batch_axis] = batch_index;
+ in_transform_end[in_batch_axis] = batch_index + 1;
+ in_transform_start[in_channel_axis] = 0;
+ in_transform_end[in_channel_axis] = 1;
+
+ for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
+ {
+ size_t filter_dilation_stride = filter_dilation[i - 2];
+ size_t filter_movement_stride = stride[i - 2];
+ std::ptrdiff_t below_pad = in_pad_below[i - 2];
+ std::ptrdiff_t above_pad = in_pad_above[i - 2];
+ size_t in_dilation_stride = in_dilation[i - 2];
+
+ in_transform_start[i] = filter_movement_stride * out_coord[i];
+ in_transform_end[i] = in_transform_start[i] +
+ (filter_shape[i] - 1) * filter_dilation_stride + 1;
+ in_transform_movement_strides[i] = filter_dilation_stride;
+ in_transform_pad_below[i] = below_pad;
+ in_transform_pad_above[i] = above_pad;
+ in_transform_dilation_strides[i] = in_dilation_stride;
+ }
+
+ AxisVector in_transform_axis_order(2 + n_spatial_dimensions);
+ for (size_t i = 0; i < in_transform_axis_order.size(); i++)
+ {
+ in_transform_axis_order[i] = i;
+ }
+ CoordinateTransform in_transform(in_shape,
+ in_transform_start,
+ in_transform_end,
+ in_transform_movement_strides,
+ in_transform_axis_order,
+ in_transform_pad_below,
+ in_transform_pad_above,
+ in_transform_dilation_strides);
+
+ // Simultaneously with iterating I, for the filter we need to iterate the
+ // coordinate:
+ //
+ // F
+ //
+ // over the range (noninclusive on the right):
+ //
+ // (chan_out,0,0,...,0) ->
+ // (chan_out+1,
+ // chans_in_count,
+ // filter_dims_1,
+ // ...,
+ // filter_dims_n)
+ //
+ // with unit stride.
+
+ Shape filter_transform_start(2 + n_spatial_dimensions);
+ Shape filter_transform_end(2 + n_spatial_dimensions);
+
+ filter_transform_start[filter_out_channel_axis] = out_channel;
+ filter_transform_end[filter_out_channel_axis] = out_channel + 1;
+ filter_transform_start[filter_in_channel_axis] = 0;
+ filter_transform_end[filter_in_channel_axis] = 1;
+
+ for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
+ {
+ filter_transform_start[i] = 0;
+ filter_transform_end[i] = filter_shape[i];
+ }
+
+ CoordinateTransform filter_transform(
+ filter_shape, filter_transform_start, filter_transform_end);
+
+ // As we go, we sum up:
+ //
+ // out[O] += in[I] * filter[F].
+
+ ACCUMULATION result = 0;
+
+ CoordinateTransform::Iterator in_it = in_transform.begin();
+ CoordinateTransform::Iterator filter_it = filter_transform.begin();
+ CoordinateTransform::Iterator in_it_end = in_transform.end();
+ CoordinateTransform::Iterator filter_it_end = filter_transform.end();
+
+ size_t in_channel_stride = row_major_strides(in_shape).at(in_channel_axis);
+ size_t filter_in_channel_stride =
+ row_major_strides(filter_shape).at(filter_in_channel_axis);
+
+ while (in_it != in_it_end && filter_it != filter_it_end)
+ {
+ const Coordinate& in_coord = *in_it;
+ if (in_transform.has_source_coordinate(in_coord))
+ {
+ size_t in_idx = in_transform.index(in_coord);
+ const Coordinate& filter_coord = *filter_it;
+ size_t filter_idx = filter_transform.index(filter_coord);
+ for (size_t in_channel = 0; in_channel < n_in_channels; ++in_channel)
+ {
+ ACCUMULATION in_v = static_cast<ACCUMULATION>(in[in_idx]);
+ ACCUMULATION f_v = static_cast<ACCUMULATION>(filter[filter_idx]);
+ if (is_quantized)
+ {
+ in_v = in_v - static_cast<ACCUMULATION>(*input_zero_point);
+ f_v = f_v - static_cast<ACCUMULATION>(*filter_zero_point);
+ }
+ result += in_v * f_v;
+ in_idx += in_channel_stride;
+ filter_idx += filter_in_channel_stride;
+ }
+ }
+ ++in_it;
+ ++filter_it;
+ }
+ if (is_quantized)
+ {
+ float scale = *input_scale * *filter_scale / *output_scale;
+ out[out_transform.index(out_coord)] =
+ static_cast<OUTPUT>(std::round(static_cast<float>(result) * scale)) +
+ *output_zero_point;
+ }
+ else
+ {
+ out[out_transform.index(out_coord)] = result;
+ }
+ }
+ std::fesetround(old_mode);
+ }
+
+ template <typename INPUT,
+ typename FILTER,
+ typename OUTPUT,
+ typename ACCUMULATION = typename widen<OUTPUT>::type>
+ void convolution(const INPUT* in,
+ const FILTER* filter,
+ OUTPUT* out,
+ const Shape& in_shape,
+ const Shape& filter_shape,
+ const Shape& out_shape,
+ const Strides& stride,
+ const Strides& filter_dilation,
+ const CoordinateDiff& in_pad_below,
+ const CoordinateDiff& in_pad_above,
+ const Strides& in_dilation,
+ const float* input_scale = nullptr,
+ const INPUT* input_zero_point = nullptr,
+ const float* filter_scale = nullptr,
+ const FILTER* filter_zero_point = nullptr,
+ const float* output_scale = nullptr,
+ const OUTPUT* output_zero_point = nullptr)
+
+ {
+ general_convolution<INPUT, FILTER, OUTPUT, ACCUMULATION>(in,
+ filter,
+ out,
+ in_shape,
+ filter_shape,
+ out_shape,
+ stride,
+ filter_dilation,
+ in_pad_below,
+ in_pad_above,
+ in_dilation,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ input_scale,
+ input_zero_point,
+ filter_scale,
+ filter_zero_point,
+ output_scale,
+ output_zero_point);
+ }
+
+ template <typename INPUT,
+ typename OUTPUT,
+ typename FILTER,
+ typename ACCUMULATION = typename widen<FILTER>::type>
+ void convolution_backprop_filter(const INPUT* in,
+ const OUTPUT* delta_out,
+ FILTER* delta_filter,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ const Shape& filter_shape,
+ const Strides& filter_dilation,
+ const Strides& stride,
+ const CoordinateDiff& in_pad_below,
+ const CoordinateDiff& backprop_in_pad_above,
+ const Strides& in_dilation)
+ {
+ general_convolution<INPUT, OUTPUT, FILTER, ACCUMULATION>(in,
+ delta_out,
+ delta_filter,
+ in_shape,
+ out_shape,
+ filter_shape,
+ filter_dilation,
+ stride,
+ in_pad_below,
+ backprop_in_pad_above,
+ in_dilation,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0);
+ }
+
+ template <typename OUTPUT,
+ typename FILTER,
+ typename INPUT,
+ typename ACCUMULATION = typename widen<INPUT>::type>
+ void convolution_backprop_in(const OUTPUT* delta_out,
+ const FILTER* filter,
+ INPUT* delta_in,
+ const Shape& out_shape,
+ const Shape& filter_shape,
+ const Shape& in_shape,
+ const Strides& in_dilation,
+ const Strides& filter_dilation,
+ const CoordinateDiff& backward_delta_out_pad_below,
+ const CoordinateDiff& backward_delta_out_pad_above,
+ const Strides& stride)
+ {
+ // Note that we only reverse the spatial dimensions here (loop
+ // starts at 2)
+ std::vector<INPUT> reversed(shape_size(filter_shape));
+ AxisSet reverse_axes;
+ for (size_t i = 2; i < filter_shape.size(); ++i)
+ {
+ reverse_axes.insert(i);
+ }
+ reverse(reinterpret_cast<const char*>(filter),
+ reinterpret_cast<char*>(&reversed[0]),
+ filter_shape,
+ filter_shape,
+ reverse_axes,
+ sizeof(FILTER));
+
+ general_convolution<OUTPUT, FILTER, INPUT, ACCUMULATION>(
+ delta_out,
+ &reversed[0],
+ delta_in,
+ out_shape,
+ filter_shape,
+ in_shape,
+ in_dilation,
+ filter_dilation,
+ backward_delta_out_pad_below,
+ backward_delta_out_pad_above,
+ stride,
+ 0,
+ 1,
+ 1,
+ 0,
+ 0,
+ 1);
+ }
+ } // namespace reference
+ } // namespace runtime
+} // namespace ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void copy(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void cos(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::cos(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void cosh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::cosh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <math.h>
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void CTCLoss(const T* logits,
+ const Shape& logitsShape,
+ const U* logitsLength,
+ const U* labels,
+ const U* labelsLength,
+ const U* blankIndexP,
+ const bool preprocessCollapseRepeated,
+ const bool ctcMergeRepeated,
+ const bool unique,
+ T* output)
+ {
+ const size_t batchNum = logitsShape[0];
+ const size_t maxTime = logitsShape[1];
+ const size_t classesNum = logitsShape[2];
+ U blankIndex = classesNum - 1;
+ if (blankIndexP != nullptr)
+ {
+ blankIndex = blankIndexP[0];
+ }
+
+ std::vector<U> targetD(maxTime);
+ std::vector<U> pathS(maxTime);
+
+ const size_t TC = maxTime * classesNum;
+
+ for (size_t b = 0; b < batchNum; b++)
+ {
+ U actualLogitLen = logitsLength[b];
+ U actualTargetLen = labelsLength[b];
+ if (actualLogitLen >= maxTime || actualTargetLen >= maxTime ||
+ actualTargetLen > actualLogitLen)
+ {
+ throw ngraph_error(
+ std::string("Logit or label length cannot be more than max sequence"
+ "length. Also a label length cannot be greater than a"
+ "logit length.\nMaxSeqLen: ") +
+ std::to_string(maxTime) + "; Logit len: " +
+ std::to_string(actualLogitLen) + "; Label len: " +
+ std::to_string(actualTargetLen));
+ }
+
+ const U* target = &labels[b * maxTime];
+ // Decoding target:
+ // merge repeated characters if preprocess_collapse_repeated == True,
+ // find unique elemnts if unique == True
+ size_t decodedTargetLen = 0lu;
+ if (unique)
+ {
+ std::unordered_set<U> uniqVals;
+ for (size_t t = 0lu; t < actualTargetLen; t++)
+ {
+ if (uniqVals.find(target[t]) != uniqVals.end())
+ {
+ continue;
+ }
+ uniqVals.insert(target[t]);
+ targetD[decodedTargetLen++] = target[t];
+ }
+ }
+ else if (preprocessCollapseRepeated)
+ {
+ U prevValue = target[0];
+ targetD[decodedTargetLen++] = target[0];
+ for (size_t t = 1lu; t < actualTargetLen; t++)
+ {
+ if (target[t] == prevValue)
+ {
+ continue;
+ }
+ targetD[decodedTargetLen++] = target[t];
+ prevValue = target[t];
+ }
+ }
+ else
+ {
+ std::copy(target, target + actualTargetLen, targetD.data());
+ decodedTargetLen = actualTargetLen;
+ }
+
+ const size_t BTC = b * TC;
+
+ std::vector<T> kExp(actualLogitLen, 0);
+ for (size_t t = 0; t < actualLogitLen; t++)
+ {
+ size_t btcT = BTC + classesNum * t;
+ for (size_t c = 0; c < classesNum; c++)
+ {
+ kExp[t] += std::exp(logits[btcT + c]);
+ }
+ }
+
+ T res = -std::numeric_limits<T>::infinity();
+
+ // Looking for aligned paths
+ std::function<void(size_t targetIdx, size_t start, size_t end)> findPaths = [&](
+ size_t targetIdx, size_t start, size_t end) {
+ if (end > actualLogitLen)
+ {
+ T prod = 0;
+ for (size_t t = 0; t < actualLogitLen; t++)
+ {
+ prod += std::log(std::exp(logits[BTC + classesNum * t + pathS[t]]) /
+ kExp[t]);
+ }
+ if (res == -std::numeric_limits<T>::infinity())
+ res = prod;
+ else if (prod != -std::numeric_limits<T>::infinity())
+ res = res + std::log1pf(std::exp(prod - res));
+
+ return;
+ }
+
+ size_t nextIdx = targetIdx + 1;
+ int64_t st64 = start;
+ if (!ctcMergeRepeated)
+ {
+ for (size_t pos = start; pos < end; pos++)
+ {
+ for (size_t bl = start; bl < pos; bl++)
+ {
+ pathS[bl] = blankIndex;
+ }
+ pathS[pos] = targetD[targetIdx];
+ findPaths(nextIdx, pos + 1, end + 1);
+ }
+ }
+ else
+ {
+ for (size_t pos = start; pos < end; pos++)
+ {
+ for (size_t bl = start; bl < pos; bl++)
+ {
+ pathS[bl] = blankIndex;
+ }
+ for (int64_t bl = pos; bl >= st64; bl--)
+ {
+ pathS[bl] = targetD[targetIdx];
+ if (end == actualLogitLen)
+ {
+ for (int64_t ble = pos + 1; ble < actualLogitLen; ble++)
+ {
+ pathS[ble] = blankIndex;
+ }
+ }
+ size_t next_start = pos + 1;
+ if (targetIdx < decodedTargetLen - 1 &&
+ targetD[targetIdx] == targetD[targetIdx + 1])
+ {
+ pathS[next_start++] = blankIndex;
+ }
+ findPaths(nextIdx, next_start, end + 1);
+ }
+ }
+ }
+ }; // findPaths
+
+ findPaths(0lu, 0lu, actualLogitLen - decodedTargetLen + 1lu);
+
+ output[b] = -res;
+
+ } // for (size_t b = 0; b < batchNum; b++)
+ } // CTCLoss
+ } // reference
+ } // runtime
+} // ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/bfloat16.hpp"
+#include "ngraph/type/float16.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename P>
+ void cumsum(const T* arg,
+ const P* axis_tensor,
+ T* out,
+ const Shape& tensor_shape,
+ const bool exclusive,
+ const bool reverse)
+ {
+ CoordinateTransform temp_transform(tensor_shape);
+ for (const Coordinate& output_coord : temp_transform)
+ {
+ out[temp_transform.index(output_coord)] = 0;
+ }
+
+ P axis = axis_tensor[0];
+ P rank = tensor_shape.size();
+
+ if (axis < -rank || axis > rank)
+ {
+ throw ngraph_error("axis must be in the range [-rank, rank]");
+ }
+ axis = axis < 0 ? rank + axis : axis;
+
+ auto get_key = [&, axis](const Coordinate& coord) -> Coordinate {
+ Coordinate result(coord.size(), 0);
+ result[axis] = coord[axis];
+
+ for (size_t i = 0; i < coord.size(); i++)
+ {
+ result[i] = coord[i] - result[i];
+ }
+ return result;
+ };
+
+ auto update_output_buffer =
+ [&](size_t input_index,
+ size_t output_index,
+ T& prev,
+ std::vector<std::pair<size_t, T>>& tensor_vec) -> void {
+
+ tensor_vec[input_index].second = prev + tensor_vec[input_index].second;
+ out[tensor_vec[output_index].first] = tensor_vec[input_index].second;
+
+ // update prev to hold the last result value to compute ruuning sum for
+ // subsequent iter
+ prev = out[tensor_vec[output_index].first];
+ };
+
+ auto cum_sum =
+ [&, exclusive, reverse](std::vector<std::pair<size_t, T>>& tensor_vec) {
+ if (!reverse)
+ {
+ T prev = 0;
+ for (size_t i = 0; i < tensor_vec.size(); i++)
+ {
+ if (exclusive && i == 0)
+ {
+ out[tensor_vec[i].first] = prev;
+ continue;
+ }
+ // we will compute running sum of j-1 elements if exlusive=1 or else
+ // for j elements if exclusive = 0
+ size_t arg_index = exclusive == 1 ? i - 1 : i;
+ update_output_buffer(arg_index, i, prev, tensor_vec);
+ }
+ }
+ else // reverse == true
+ {
+ T prev = 0;
+ for (size_t i = tensor_vec.size(); i-- > 0;)
+ {
+ if (exclusive && i == tensor_vec.size() - 1)
+ {
+ out[tensor_vec[i].first] = prev;
+ continue;
+ }
+ // we will compute running sum of j-1 elements if exlusive=1 or else
+ // for j elements if exclusive = 0
+ size_t arg_index = exclusive == 1 ? i + 1 : i;
+ update_output_buffer(arg_index, i, prev, tensor_vec);
+ }
+ }
+ };
+
+ // Map to collect tensor elements belonging to the same axis
+ std::map<Coordinate, std::vector<std::pair<size_t, T>>> map_cooord_to_val;
+ CoordinateTransform input_transform(tensor_shape);
+ for (const Coordinate& input_coord : input_transform)
+ {
+ // points to the current element in the input tensor
+ T current = arg[input_transform.index(input_coord)];
+ auto key = get_key(input_coord);
+ auto index = input_transform.index(input_coord);
+ if (map_cooord_to_val.find(key) != map_cooord_to_val.end())
+ {
+ map_cooord_to_val[key].push_back(std::make_pair(index, current));
+ }
+ else
+ {
+ map_cooord_to_val.insert({key, std::vector<std::pair<size_t, T>>()});
+ map_cooord_to_val[key].push_back(std::make_pair(index, current));
+ }
+ }
+ // iterate the map and perform cumulative sum over the give axis
+ for (auto& it : map_cooord_to_val)
+ {
+ cum_sum(it.second);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/axis_set.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename QUANT, typename REAL>
+ void dequantize(const QUANT* input,
+ const REAL* scale,
+ const QUANT* zero_point,
+ REAL* output,
+ const Shape& input_shape,
+ const Shape& scale_zero_point_shape,
+ const AxisSet& axes)
+ {
+ CoordinateTransform input_transform(input_shape);
+ CoordinateTransform scale_zero_point_transform(scale_zero_point_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate scale_zero_point_coord = project(input_coord, axes);
+
+ output[input_transform.index(input_coord)] =
+ static_cast<REAL>((
+ input[input_transform.index(input_coord)] -
+ zero_point[scale_zero_point_transform.index(scale_zero_point_coord)])) *
+ scale[scale_zero_point_transform.index(scale_zero_point_coord)];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <cstddef>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ enum
+ {
+ idxLocation,
+ idxConfidence,
+ idxPriors,
+ idxArmConfidence,
+ idxArmLocation,
+ numInputs
+ };
+
+ template <typename dataType>
+ class referenceDetectionOutput
+ {
+ private:
+ struct NormalizedBBox
+ {
+ dataType xmin = 0;
+ dataType ymin = 0;
+ dataType xmax = 0;
+ dataType ymax = 0;
+ dataType size = 0;
+ };
+ using LabelBBox = std::map<int, std::vector<NormalizedBBox>>;
+
+ ngraph::op::DetectionOutputAttrs attrs;
+ size_t numImages;
+ size_t priorSize;
+ size_t numPriors;
+ size_t numLocClasses;
+ size_t offset;
+
+ void GetLocPredictions(const dataType* locData, std::vector<LabelBBox>& locations)
+ {
+ locations.resize(numImages);
+ for (size_t i = 0; i < numImages; ++i)
+ {
+ LabelBBox& labelBbox = locations[i];
+ for (size_t p = 0; p < numPriors; ++p)
+ {
+ size_t startIdx = p * numLocClasses * 4;
+ for (size_t c = 0; c < numLocClasses; ++c)
+ {
+ int label = attrs.share_location ? -1 : c;
+ if (labelBbox.find(label) == labelBbox.end())
+ {
+ labelBbox[label].resize(numPriors);
+ }
+ labelBbox[label][p].xmin = locData[startIdx + c * 4];
+ labelBbox[label][p].ymin = locData[startIdx + c * 4 + 1];
+ labelBbox[label][p].xmax = locData[startIdx + c * 4 + 2];
+ labelBbox[label][p].ymax = locData[startIdx + c * 4 + 3];
+ }
+ }
+ locData += numPriors * numLocClasses * 4;
+ }
+ }
+
+ void GetConfidenceScores(
+ const dataType* confData,
+ std::vector<std::map<int, std::vector<dataType>>>& confPreds)
+ {
+ confPreds.resize(numImages);
+ for (int i = 0; i < numImages; ++i)
+ {
+ std::map<int, std::vector<dataType>>& labelScores = confPreds[i];
+ for (int p = 0; p < numPriors; ++p)
+ {
+ int startIdx = p * attrs.num_classes;
+ for (int c = 0; c < attrs.num_classes; ++c)
+ {
+ labelScores[c].push_back(confData[startIdx + c]);
+ }
+ }
+ confData += numPriors * attrs.num_classes;
+ }
+ }
+
+ void OSGetConfidenceScores(
+ const dataType* confData,
+ const dataType* armConfData,
+ std::vector<std::map<int, std::vector<dataType>>>& confPreds)
+ {
+ confPreds.resize(numImages);
+ for (int i = 0; i < numImages; ++i)
+ {
+ std::map<int, std::vector<dataType>>& labelScores = confPreds[i];
+ for (int p = 0; p < numPriors; ++p)
+ {
+ int startIdx = p * attrs.num_classes;
+ if (armConfData[p * 2 + 1] < attrs.objectness_score)
+ {
+ for (int c = 0; c < attrs.num_classes; ++c)
+ {
+ c == attrs.background_label_id ? labelScores[c].push_back(1)
+ : labelScores[c].push_back(0);
+ }
+ }
+ else
+ {
+ for (int c = 0; c < attrs.num_classes; ++c)
+ {
+ labelScores[c].push_back(confData[startIdx + c]);
+ }
+ }
+ }
+ confData += numPriors * attrs.num_classes;
+ armConfData += numPriors * 2;
+ }
+ }
+
+ dataType BBoxSize(const NormalizedBBox& bbox)
+ {
+ if (bbox.xmax < bbox.xmin || bbox.ymax < bbox.ymin)
+ {
+ return 0;
+ }
+ else
+ {
+ dataType width = bbox.xmax - bbox.xmin;
+ dataType height = bbox.ymax - bbox.ymin;
+ return width * height;
+ }
+ }
+
+ void GetPriorBBoxes(const dataType* priorData,
+ std::vector<std::vector<NormalizedBBox>>& priorBboxes,
+ std::vector<std::vector<std::vector<dataType>>>& priorVariances)
+ {
+ priorBboxes.resize(numImages);
+ priorVariances.resize(numImages);
+ for (int n = 0; n < numImages; n++)
+ {
+ priorData += attrs.variance_encoded_in_target
+ ? n * numPriors * priorSize
+ : 2 * n * numPriors * priorSize;
+ std::vector<NormalizedBBox>& currPrBbox = priorBboxes[n];
+ std::vector<std::vector<dataType>>& currPrVar = priorVariances[n];
+ for (int i = 0; i < numPriors; ++i)
+ {
+ int start_idx = i * priorSize;
+ NormalizedBBox bbox;
+ bbox.xmin = priorData[start_idx + 0 + offset];
+ bbox.ymin = priorData[start_idx + 1 + offset];
+ bbox.xmax = priorData[start_idx + 2 + offset];
+ bbox.ymax = priorData[start_idx + 3 + offset];
+ dataType bbox_size = BBoxSize(bbox);
+ bbox.size = bbox_size;
+ currPrBbox.push_back(bbox);
+ }
+ if (!attrs.variance_encoded_in_target)
+ {
+ const dataType* priorVar = priorData + numPriors * priorSize;
+ for (int i = 0; i < numPriors; ++i)
+ {
+ int start_idx = i * 4;
+ std::vector<dataType> var;
+ for (int j = 0; j < 4; ++j)
+ {
+ var.push_back(priorVar[start_idx + j]);
+ }
+ currPrVar.push_back(var);
+ }
+ }
+ }
+ }
+
+ void DecodeBBox(const NormalizedBBox& priorBboxes,
+ const std::vector<dataType>& priorVariances,
+ const NormalizedBBox& bbox,
+ NormalizedBBox& decodeBbox)
+ {
+ dataType priorXmin = priorBboxes.xmin;
+ dataType priorYmin = priorBboxes.ymin;
+ dataType priorXmax = priorBboxes.xmax;
+ dataType priorYmax = priorBboxes.ymax;
+
+ if (!attrs.normalized)
+ {
+ priorXmin /= attrs.input_width;
+ priorYmin /= attrs.input_height;
+ priorXmax /= attrs.input_width;
+ priorYmax /= attrs.input_height;
+ }
+ if (attrs.code_type == "caffe.PriorBoxParameter.CORNER")
+ {
+ if (attrs.variance_encoded_in_target)
+ {
+ decodeBbox.xmin = priorXmin + bbox.xmin;
+ decodeBbox.ymin = priorYmin + bbox.ymin;
+ decodeBbox.xmax = priorXmax + bbox.xmax;
+ decodeBbox.ymax = priorYmax + bbox.ymax;
+ }
+ else
+ {
+ decodeBbox.xmin = priorXmin + priorVariances[0] * bbox.xmin;
+ decodeBbox.ymin = priorYmin + priorVariances[1] * bbox.ymin;
+ decodeBbox.xmax = priorXmax + priorVariances[2] * bbox.xmax;
+ decodeBbox.ymax = priorYmax + priorVariances[3] * bbox.ymax;
+ }
+ }
+ else if (attrs.code_type == "caffe.PriorBoxParameter.CENTER_SIZE")
+ {
+ dataType priorWidth = priorXmax - priorXmin;
+ dataType priorHeight = priorYmax - priorYmin;
+ dataType priorCenterX = (priorXmin + priorXmax) / 2;
+ dataType priorCenterY = (priorYmin + priorYmax) / 2;
+ dataType decodeBboxCenterX, decodeBboxCenterY;
+ dataType decodeBboxWidth, decodeBboxHeight;
+ if (attrs.variance_encoded_in_target)
+ {
+ decodeBboxCenterX = bbox.xmin * priorWidth + priorCenterX;
+ decodeBboxCenterY = bbox.ymin * priorHeight + priorCenterY;
+ decodeBboxWidth = std::exp(bbox.xmax) * priorWidth;
+ decodeBboxHeight = std::exp(bbox.ymax) * priorHeight;
+ }
+ else
+ {
+ decodeBboxCenterX =
+ priorVariances[0] * bbox.xmin * priorWidth + priorCenterX;
+ decodeBboxCenterY =
+ priorVariances[1] * bbox.ymin * priorHeight + priorCenterY;
+ decodeBboxWidth = std::exp(priorVariances[2] * bbox.xmax) * priorWidth;
+ decodeBboxHeight =
+ std::exp(priorVariances[3] * bbox.ymax) * priorHeight;
+ }
+ decodeBbox.xmin = decodeBboxCenterX - decodeBboxWidth / 2;
+ decodeBbox.ymin = decodeBboxCenterY - decodeBboxHeight / 2;
+ decodeBbox.xmax = decodeBboxCenterX + decodeBboxWidth / 2;
+ decodeBbox.ymax = decodeBboxCenterY + decodeBboxHeight / 2;
+ }
+ if (attrs.clip_before_nms)
+ {
+ decodeBbox.xmin =
+ std::max<dataType>(0, std::min<dataType>(1, decodeBbox.xmin));
+ decodeBbox.ymin =
+ std::max<dataType>(0, std::min<dataType>(1, decodeBbox.ymin));
+ decodeBbox.xmax =
+ std::max<dataType>(0, std::min<dataType>(1, decodeBbox.xmax));
+ decodeBbox.ymax =
+ std::max<dataType>(0, std::min<dataType>(1, decodeBbox.ymax));
+ }
+ dataType bboxSize = BBoxSize(decodeBbox);
+ decodeBbox.size = bboxSize;
+ }
+
+ void DecodeBBoxes(const std::vector<NormalizedBBox>& priorBboxes,
+ const std::vector<std::vector<dataType>>& priorVariances,
+ const std::vector<NormalizedBBox>& labelLocPreds,
+ std::vector<NormalizedBBox>& decodeBboxes)
+ {
+ int numBboxes = priorBboxes.size();
+ for (int i = 0; i < numBboxes; ++i)
+ {
+ NormalizedBBox decodeBbox;
+ DecodeBBox(priorBboxes[i], priorVariances[i], labelLocPreds[i], decodeBbox);
+ decodeBboxes.push_back(decodeBbox);
+ }
+ }
+
+ void DecodeBBoxesAll(
+ const std::vector<LabelBBox>& locPreds,
+ const std::vector<std::vector<NormalizedBBox>>& priorBboxes,
+ const std::vector<std::vector<std::vector<dataType>>>& priorVariances,
+ std::vector<LabelBBox>& decodeBboxes)
+ {
+ decodeBboxes.resize(numImages);
+ for (int i = 0; i < numImages; ++i)
+ {
+ LabelBBox& decodeBboxesImage = decodeBboxes[i];
+ const std::vector<NormalizedBBox>& currPrBbox = priorBboxes[i];
+ const std::vector<std::vector<dataType>>& currPrVar = priorVariances[i];
+ for (int c = 0; c < numLocClasses; ++c)
+ {
+ int label = attrs.share_location ? -1 : c;
+ if (label == attrs.background_label_id)
+ {
+ continue;
+ }
+ const std::vector<NormalizedBBox>& labelLocPreds =
+ locPreds[i].find(label)->second;
+ DecodeBBoxes(
+ currPrBbox, currPrVar, labelLocPreds, decodeBboxesImage[label]);
+ }
+ }
+ }
+
+ void CasRegDecodeBBoxesAll(
+ const std::vector<LabelBBox>& locPreds,
+ const std::vector<std::vector<NormalizedBBox>>& priorBboxes,
+ const std::vector<std::vector<std::vector<dataType>>>& priorVariances,
+ std::vector<LabelBBox>& decodeBboxes,
+ const std::vector<LabelBBox>& armLocPreds)
+ {
+ decodeBboxes.resize(numImages);
+ for (int i = 0; i < numImages; ++i)
+ {
+ LabelBBox& decodeBboxesImage = decodeBboxes[i];
+ const std::vector<NormalizedBBox>& currPrBbox = priorBboxes[i];
+ const std::vector<std::vector<dataType>>& currPrVar = priorVariances[i];
+ for (int c = 0; c < numLocClasses; ++c)
+ {
+ int label = attrs.share_location ? -1 : c;
+ if (label == attrs.background_label_id)
+ {
+ continue;
+ }
+ const std::vector<NormalizedBBox>& labelArmLocPreds =
+ armLocPreds[i].find(label)->second;
+ std::vector<NormalizedBBox> decodePriorBboxes;
+ DecodeBBoxes(
+ currPrBbox, currPrVar, labelArmLocPreds, decodePriorBboxes);
+ const std::vector<NormalizedBBox>& labelLocPreds =
+ locPreds[i].find(label)->second;
+ DecodeBBoxes(decodePriorBboxes,
+ currPrVar,
+ labelLocPreds,
+ decodeBboxesImage[label]);
+ }
+ }
+ }
+
+ template <typename T>
+ static bool SortScorePairDescend(const std::pair<dataType, T>& pair1,
+ const std::pair<dataType, T>& pair2)
+ {
+ return pair1.first > pair2.first;
+ }
+
+ void GetMaxScoreIndex(const std::vector<dataType>& scores,
+ const dataType threshold,
+ const int topK,
+ std::vector<std::pair<dataType, int>>& scoreIndexVec)
+ {
+ for (int i = 0; i < scores.size(); ++i)
+ {
+ if (scores[i] > threshold)
+ {
+ scoreIndexVec.push_back(std::make_pair(scores[i], i));
+ }
+ }
+
+ std::stable_sort(
+ scoreIndexVec.begin(), scoreIndexVec.end(), SortScorePairDescend<int>);
+ if (topK > -1 && topK < scoreIndexVec.size())
+ {
+ scoreIndexVec.resize(topK);
+ }
+ }
+
+ void IntersectBBox(const NormalizedBBox& bbox1,
+ const NormalizedBBox& bbox2,
+ NormalizedBBox& intersectBbox)
+ {
+ if (bbox2.xmin > bbox1.xmax || bbox2.xmax < bbox1.xmin ||
+ bbox2.ymin > bbox1.ymax || bbox2.ymax < bbox1.ymin)
+ {
+ intersectBbox.xmin = 0;
+ intersectBbox.ymin = 0;
+ intersectBbox.xmax = 0;
+ intersectBbox.ymax = 0;
+ }
+ else
+ {
+ intersectBbox.xmin = std::max<dataType>(bbox1.xmin, bbox2.xmin);
+ intersectBbox.ymin = std::max<dataType>(bbox1.ymin, bbox2.ymin);
+ intersectBbox.xmax = std::min<dataType>(bbox1.xmax, bbox2.xmax);
+ intersectBbox.ymax = std::min<dataType>(bbox1.ymax, bbox2.ymax);
+ }
+ }
+
+ dataType JaccardOverlap(const NormalizedBBox& bbox1, const NormalizedBBox& bbox2)
+ {
+ NormalizedBBox intersectBbox;
+ IntersectBBox(bbox1, bbox2, intersectBbox);
+ dataType intersectWidth, intersectHeight;
+ intersectWidth = intersectBbox.xmax - intersectBbox.xmin;
+ intersectHeight = intersectBbox.ymax - intersectBbox.ymin;
+ if (intersectWidth > 0 && intersectHeight > 0)
+ {
+ dataType intersect_size = intersectWidth * intersectHeight;
+ dataType bbox1_size = BBoxSize(bbox1);
+ dataType bbox2_size = BBoxSize(bbox2);
+
+ return intersect_size / (bbox1_size + bbox2_size - intersect_size);
+ }
+ else
+ {
+ return 0.0f;
+ }
+ }
+
+ void caffeNMS(const std::vector<NormalizedBBox>& bboxes,
+ const std::vector<dataType>& scores,
+ std::vector<int>& indices)
+ {
+ std::vector<std::pair<dataType, int>> scoreIndexVec;
+ GetMaxScoreIndex(
+ scores, attrs.confidence_threshold, attrs.top_k, scoreIndexVec);
+ while (scoreIndexVec.size() != 0)
+ {
+ const int idx = scoreIndexVec.front().second;
+ bool keep = true;
+ for (int k = 0; k < indices.size(); ++k)
+ {
+ const int kept_idx = indices[k];
+ dataType overlap = JaccardOverlap(bboxes[idx], bboxes[kept_idx]);
+ if (overlap > attrs.nms_threshold)
+ {
+ keep = false;
+ break;
+ }
+ }
+ if (keep)
+ {
+ indices.push_back(idx);
+ }
+ scoreIndexVec.erase(scoreIndexVec.begin());
+ }
+ }
+
+ void mxNetNms(const LabelBBox& decodeBboxesImage,
+ const std::map<int, std::vector<dataType>>& confScores,
+ std::map<int, std::vector<int>>& indices)
+ {
+ std::vector<std::pair<dataType, std::pair<int, int>>> scoreIndexPairs;
+ for (int p = 0; p < numPriors; p++)
+ {
+ dataType conf = -1;
+ int id = 0;
+ for (int c = 1; c < attrs.num_classes; c++)
+ {
+ dataType temp = confScores.at(c)[p];
+ if (temp > conf)
+ {
+ conf = temp;
+ id = c;
+ }
+ }
+ if (id > 0 && conf >= attrs.confidence_threshold)
+ {
+ scoreIndexPairs.push_back(std::make_pair(conf, std::make_pair(id, p)));
+ }
+ }
+ std::sort(scoreIndexPairs.begin(),
+ scoreIndexPairs.end(),
+ SortScorePairDescend<std::pair<int, int>>);
+
+ if (attrs.top_k != -1)
+ if (scoreIndexPairs.size() > attrs.top_k)
+ scoreIndexPairs.resize(attrs.top_k);
+
+ while (scoreIndexPairs.size() != 0)
+ {
+ const int cls = scoreIndexPairs.front().second.first;
+ const int prior = scoreIndexPairs.front().second.second;
+ std::vector<int>& currInd = indices[cls];
+ bool keep = true;
+ for (int i = 0; i < currInd.size(); i++)
+ {
+ const int keptIdx = currInd[i];
+ auto currBbox = attrs.share_location ? decodeBboxesImage.at(-1)
+ : decodeBboxesImage.at(cls);
+ dataType overlap = JaccardOverlap(currBbox[prior], currBbox[keptIdx]);
+ if (overlap > attrs.nms_threshold)
+ {
+ keep = false;
+ break;
+ }
+ }
+ if (keep)
+ {
+ currInd.push_back(prior);
+ }
+ scoreIndexPairs.erase(scoreIndexPairs.begin());
+ }
+ }
+
+ public:
+ referenceDetectionOutput(const ngraph::op::DetectionOutputAttrs& _attrs,
+ const ngraph::Shape& locShape,
+ const ngraph::Shape& priorsShape)
+ : attrs(_attrs)
+ {
+ numImages = locShape[0];
+ priorSize = _attrs.normalized ? 4 : 5;
+ offset = _attrs.normalized ? 0 : 1;
+ numPriors = priorsShape[2] / priorSize;
+ numLocClasses =
+ _attrs.share_location ? 1 : static_cast<size_t>(_attrs.num_classes);
+ }
+
+ void run(const dataType* _location,
+ const dataType* _confidence,
+ const dataType* _priors,
+ const dataType* _armConfidence,
+ const dataType* _armLocation,
+ dataType* result)
+ {
+ bool withAddBoxPred = _armConfidence != nullptr && _armLocation != nullptr;
+ std::vector<LabelBBox> armLocPreds;
+ if (withAddBoxPred)
+ {
+ GetLocPredictions(_armLocation, armLocPreds);
+ }
+ std::vector<LabelBBox> locPreds;
+ GetLocPredictions(_location, locPreds);
+ std::vector<std::map<int, std::vector<dataType>>> confPreds;
+ if (withAddBoxPred)
+ {
+ OSGetConfidenceScores(_confidence, _armConfidence, confPreds);
+ }
+ else
+ {
+ GetConfidenceScores(_confidence, confPreds);
+ }
+ std::vector<std::vector<NormalizedBBox>> priorBboxes;
+ std::vector<std::vector<std::vector<dataType>>> priorVariances;
+ GetPriorBBoxes(_priors, priorBboxes, priorVariances);
+ std::vector<LabelBBox> decodeBboxes;
+ if (withAddBoxPred)
+ {
+ CasRegDecodeBBoxesAll(
+ locPreds, priorBboxes, priorVariances, decodeBboxes, armLocPreds);
+ }
+ else
+ {
+ DecodeBBoxesAll(locPreds, priorBboxes, priorVariances, decodeBboxes);
+ }
+
+ int numKept = 0;
+ std::vector<std::map<int, std::vector<int>>> allIndices;
+ for (int i = 0; i < numImages; ++i)
+ {
+ const LabelBBox& decodeBboxesImage = decodeBboxes[i];
+ const std::map<int, std::vector<dataType>>& confScores = confPreds[i];
+ std::map<int, std::vector<int>> indices;
+ int numDet = 0;
+ if (!attrs.decrease_label_id)
+ {
+ // Caffe style
+ for (int c = 0; c < attrs.num_classes; ++c)
+ {
+ if (c == attrs.background_label_id)
+ {
+ continue;
+ }
+ const std::vector<dataType>& scores = confScores.find(c)->second;
+ int label = attrs.share_location ? -1 : c;
+ const std::vector<NormalizedBBox>& bboxes =
+ decodeBboxesImage.find(label)->second;
+ caffeNMS(bboxes, scores, indices[c]);
+ numDet += indices[c].size();
+ }
+ }
+ else
+ {
+ // MXNet style
+ mxNetNms(decodeBboxesImage, confScores, indices);
+ for (auto it = indices.begin(); it != indices.end(); it++)
+ numDet += it->second.size();
+ }
+ if (attrs.keep_top_k[0] > -1 && numDet > attrs.keep_top_k[0])
+ {
+ std::vector<std::pair<dataType, std::pair<int, int>>> scoreIndexPairs;
+ for (auto it = indices.begin(); it != indices.end(); ++it)
+ {
+ int label = it->first;
+ const std::vector<int>& labelIndices = it->second;
+ const std::vector<dataType>& scores =
+ confScores.find(label)->second;
+ for (int j = 0; j < labelIndices.size(); ++j)
+ {
+ int idx = labelIndices[j];
+ scoreIndexPairs.push_back(
+ std::make_pair(scores[idx], std::make_pair(label, idx)));
+ }
+ }
+ std::sort(scoreIndexPairs.begin(),
+ scoreIndexPairs.end(),
+ SortScorePairDescend<std::pair<int, int>>);
+ scoreIndexPairs.resize(attrs.keep_top_k[0]);
+ std::map<int, std::vector<int>> newIndices;
+ for (int j = 0; j < scoreIndexPairs.size(); ++j)
+ {
+ int label = scoreIndexPairs[j].second.first;
+ int idx = scoreIndexPairs[j].second.second;
+ newIndices[label].push_back(idx);
+ }
+ allIndices.push_back(newIndices);
+ numKept += attrs.top_k;
+ }
+ else
+ {
+ allIndices.push_back(indices);
+ numKept += numDet;
+ }
+ }
+
+ int count = 0;
+ for (int i = 0; i < numImages; ++i)
+ {
+ const std::map<int, std::vector<dataType>>& confScores = confPreds[i];
+ const LabelBBox& decodeBboxesImage = decodeBboxes[i];
+ for (auto it = allIndices[i].begin(); it != allIndices[i].end(); ++it)
+ {
+ int label = it->first;
+ const std::vector<dataType>& scores = confScores.find(label)->second;
+ int loc_label = attrs.share_location ? -1 : label;
+ const std::vector<NormalizedBBox>& bboxes =
+ decodeBboxesImage.find(loc_label)->second;
+ std::vector<int>& indices = it->second;
+ for (int j = 0; j < indices.size(); ++j)
+ {
+ int idx = indices[j];
+ result[count * 7 + 0] = i;
+ result[count * 7 + 1] =
+ attrs.decrease_label_id ? (label - 1) : label;
+ result[count * 7 + 2] = scores[idx];
+ const NormalizedBBox& bbox = bboxes[idx];
+
+ dataType xmin = bbox.xmin;
+ dataType ymin = bbox.ymin;
+ dataType xmax = bbox.xmax;
+ dataType ymax = bbox.ymax;
+
+ if (attrs.clip_after_nms)
+ {
+ xmin = std::max<dataType>(0, std::min<dataType>(1, xmin));
+ ymin = std::max<dataType>(0, std::min<dataType>(1, ymin));
+ xmax = std::max<dataType>(0, std::min<dataType>(1, xmax));
+ ymax = std::max<dataType>(0, std::min<dataType>(1, ymax));
+ }
+
+ result[count * 7 + 3] = xmin;
+ result[count * 7 + 4] = ymin;
+ result[count * 7 + 5] = xmax;
+ result[count * 7 + 6] = ymax;
+ ++count;
+ }
+ }
+ }
+ if (count < numImages * attrs.keep_top_k[0])
+ {
+ result[count * 7 + 0] = -1;
+ }
+ }
+ };
+ } // namespace reference
+ } // namespace runtime
+} // namespace ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+#include <stdexcept>
+#include <type_traits>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+#include "ngraph/type/bfloat16.hpp"
+#include "ngraph/type/float16.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // NOTE: Execution throws `std::domain_error` if either a non-integral value or an
+ // out-of-bounds value is detected in the input tensor.
+
+ // In English: return type is void and T must be an integral type.
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value>::type
+ divide(const T* arg0, const T* arg1, T* out, size_t count, bool pythondiv)
+ {
+ if (pythondiv)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ if (arg1[i] == 0)
+ {
+ throw std::domain_error("integer division by zero");
+ }
+ T quot = arg0[i] / arg1[i];
+ T rem = arg0[i] % arg1[i];
+ if ((rem != 0) && ((arg0[i] < 0) != (arg1[i] < 0)))
+ {
+ out[i] = quot - 1;
+ }
+ else
+ {
+ out[i] = quot;
+ }
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ if (arg1[i] == 0)
+ {
+ throw std::domain_error("integer division by zero");
+ }
+ out[i] = arg0[i] / arg1[i];
+ }
+ }
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value>::type
+ divide(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec,
+ bool pythondiv)
+ {
+ auto functor = [pythondiv](T x, T y) -> T {
+ if (pythondiv)
+ {
+ if (y == 0)
+ {
+ throw std::domain_error("integer division by zero");
+ }
+ T quot = x / y;
+ T rem = x % y;
+ if ((rem != 0) && ((x < 0) != (y < 0)))
+ {
+ return quot - 1;
+ }
+ else
+ {
+ return quot;
+ }
+ }
+ else
+ {
+ if (y == 0)
+ {
+ throw std::domain_error("integer division by zero");
+ }
+ return x / y;
+ }
+ };
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, functor);
+ }
+
+ // In English: return type is void and T must be a standard floating point type, or
+ // bfloat16, or float16.
+ template <typename T>
+ typename std::enable_if<std::is_floating_point<T>::value ||
+ std::is_same<T, bfloat16>::value ||
+ std::is_same<T, float16>::value>::type
+ divide(const T* arg0, const T* arg1, T* out, size_t count, bool pythondiv)
+ {
+ (void)pythondiv;
+ for (size_t i = 0; i < count; i++)
+ {
+ // TODO: Here we do not check for div by zero, so we'll get +-inf here
+ // if arg1[i] == 0. Is that the right thing to do? Jury's still out.
+ out[i] = arg0[i] / arg1[i];
+ }
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_floating_point<T>::value ||
+ std::is_same<T, bfloat16>::value ||
+ std::is_same<T, float16>::value>::type
+ divide(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec,
+ bool pythondiv)
+ {
+ (void)pythondiv;
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x / y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <utility>
+
+#include <cfenv>
+#include <functional>
+#include "convolution.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename INPUT0,
+ typename INPUT1,
+ typename OUTPUT,
+ typename ACCUMULATION = typename widen<OUTPUT>::type>
+ void dot(const INPUT0* arg0,
+ const INPUT1* arg1,
+ OUTPUT* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const Shape& out_shape,
+ size_t reduction_axes_count,
+ const float* input0_scale = nullptr,
+ const INPUT0* input0_zero_point = nullptr,
+ const float* input1_scale = nullptr,
+ const INPUT1* input1_zero_point = nullptr,
+ const float* output_scale = nullptr,
+ const OUTPUT* output_zero_point = nullptr)
+ {
+ bool is_quantized = false;
+ if (input0_scale && input0_zero_point && input1_scale && input1_zero_point &&
+ output_scale && output_zero_point)
+ {
+ is_quantized = true;
+ }
+
+ auto old_mode = std::fegetround();
+ std::fesetround(FE_TONEAREST);
+ // Get the sizes of the dot axes. It's easiest to pull them from arg1 because
+ // they're right up front.
+ Shape dot_axis_sizes(reduction_axes_count);
+ std::copy(arg1_shape.begin(),
+ arg1_shape.begin() + reduction_axes_count,
+ dot_axis_sizes.begin());
+
+ CoordinateTransform arg0_transform(arg0_shape);
+ CoordinateTransform arg1_transform(arg1_shape);
+ CoordinateTransform output_transform(out_shape);
+
+ // Create coordinate transforms for arg0 and arg1 that throw away the dotted axes.
+ size_t arg0_projected_rank = arg0_shape.size() - reduction_axes_count;
+ size_t arg1_projected_rank = arg1_shape.size() - reduction_axes_count;
+
+ Shape arg0_projected_shape(arg0_projected_rank);
+ std::copy(arg0_shape.begin(),
+ arg0_shape.begin() + arg0_projected_rank,
+ arg0_projected_shape.begin());
+
+ Shape arg1_projected_shape(arg1_projected_rank);
+ std::copy(arg1_shape.begin() + reduction_axes_count,
+ arg1_shape.end(),
+ arg1_projected_shape.begin());
+
+ CoordinateTransform arg0_projected_transform(arg0_projected_shape);
+ CoordinateTransform arg1_projected_transform(arg1_projected_shape);
+
+ // Create a coordinate transform that allows us to iterate over all possible values
+ // for the dotted axes.
+ CoordinateTransform dot_axes_transform(dot_axis_sizes);
+
+ for (const Coordinate& arg0_projected_coord : arg0_projected_transform)
+ {
+ for (const Coordinate& arg1_projected_coord : arg1_projected_transform)
+ {
+ // The output coordinate is just the concatenation of the projected
+ // coordinates.
+ Coordinate out_coord(arg0_projected_coord.size() +
+ arg1_projected_coord.size());
+
+ auto out_coord_it = std::copy(arg0_projected_coord.begin(),
+ arg0_projected_coord.end(),
+ out_coord.begin());
+ std::copy(
+ arg1_projected_coord.begin(), arg1_projected_coord.end(), out_coord_it);
+
+ // Zero out to start the sum.
+ ACCUMULATION sum = 0;
+
+ size_t out_index = output_transform.index(out_coord);
+
+ // Walk along the dotted axes.
+ Coordinate arg0_coord(arg0_shape.size());
+ Coordinate arg1_coord(arg1_shape.size());
+ auto arg0_it = std::copy(arg0_projected_coord.begin(),
+ arg0_projected_coord.end(),
+ arg0_coord.begin());
+ for (const Coordinate& dot_axis_positions : dot_axes_transform)
+ {
+ // In order to find the points to multiply together, we need to inject
+ // our current positions along the dotted axes back into the projected
+ // arg0 and arg1 coordinates.
+ std::copy(
+ dot_axis_positions.begin(), dot_axis_positions.end(), arg0_it);
+
+ auto arg1_it = std::copy(dot_axis_positions.begin(),
+ dot_axis_positions.end(),
+ arg1_coord.begin());
+ std::copy(
+ arg1_projected_coord.begin(), arg1_projected_coord.end(), arg1_it);
+
+ // Multiply and add to the sum.
+ if (is_quantized)
+ {
+ sum = sum + ((static_cast<ACCUMULATION>(
+ arg0[arg0_transform.index(arg0_coord)]) -
+ static_cast<ACCUMULATION>(*input0_zero_point)) *
+ (static_cast<ACCUMULATION>(
+ arg1[arg1_transform.index(arg1_coord)]) -
+ static_cast<ACCUMULATION>(*input1_zero_point)));
+ }
+ else
+ {
+ sum = sum + (static_cast<ACCUMULATION>(
+ arg0[arg0_transform.index(arg0_coord)]) *
+ static_cast<ACCUMULATION>(
+ arg1[arg1_transform.index(arg1_coord)]));
+ }
+ }
+
+ if (is_quantized)
+ {
+ float scale = *input0_scale * *input1_scale / *output_scale;
+ // Write the sum back.
+ out[out_index] =
+ static_cast<OUTPUT>(std::round(static_cast<float>(sum) * scale)) +
+ *output_zero_point;
+ }
+ else
+ {
+ out[out_index] = sum;
+ }
+ }
+ std::fesetround(old_mode);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void elu(const T* arg, T* out, size_t count, double alpha)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i] < 0 ? alpha * (std::exp(arg[i]) - 1.0) : arg[i];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void embeddingBagOffsetsSum(const T* emb_table,
+ const U* indices,
+ const U* offsets,
+ const U* default_index,
+ const T* weights,
+ T* out,
+ const size_t indices_count,
+ const Shape& outShape)
+ {
+ const size_t offsets_size = outShape[0];
+ std::vector<U> default_indices;
+ if (default_index)
+ default_indices.push_back(default_index[0]);
+
+ size_t embDepth = 1;
+ for (size_t i = 1; i < outShape.size(); i++)
+ {
+ embDepth *= outShape[i];
+ }
+ memset(out, 0, shape_size(outShape) * sizeof(T));
+
+ auto get_indices = [&](size_t emb_index,
+ const U*& indices_ref,
+ size_t& indices_num,
+ size_t& weights_idx,
+ bool& with_weights) {
+ if (emb_index >= offsets_size)
+ throw ngraph_error("Invalid embedding bag index.");
+ if (offsets[emb_index] >= indices_count)
+ throw ngraph_error(
+ std::string(
+ "Offset value exceeds indices size in the model.\noffset: ") +
+ std::to_string(offsets[emb_index]) + "; indices size: " +
+ std::to_string(indices_count));
+
+ indices_ref = nullptr;
+ indices_num = 0lu;
+ with_weights = (weights != nullptr);
+
+ if (emb_index == offsets_size - 1lu)
+ indices_num = indices_count - offsets[emb_index];
+ else
+ indices_num = offsets[emb_index + 1lu] - offsets[emb_index];
+
+ if (indices_num != 0lu)
+ {
+ indices_ref = indices + offsets[emb_index];
+ }
+ else
+ {
+ // Empty or default bag
+ with_weights = false;
+ if (default_indices.size() == 1lu)
+ {
+ indices_ref = default_indices.data();
+ indices_num = 1lu;
+ }
+ return;
+ }
+
+ if (with_weights)
+ weights_idx = offsets[emb_index];
+ };
+
+ size_t indices_size = 0lu;
+ const U* indices_emb = nullptr;
+ size_t weights_idx = 0lu;
+ bool with_weights_b = (weights != nullptr);
+ bool with_weights = with_weights_b;
+
+ for (size_t obi = 0lu; obi < outShape.at(0); obi++)
+ {
+ size_t dst_index = obi * embDepth;
+ get_indices(obi, indices_emb, indices_size, weights_idx, with_weights);
+ if (indices_emb != nullptr)
+ {
+ with_weights = with_weights_b & with_weights;
+ for (size_t in_idx = 0lu; in_idx < indices_size; in_idx++)
+ {
+ size_t src_index = indices_emb[in_idx] * embDepth;
+
+ if (with_weights)
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] +=
+ emb_table[src_index + i] * weights[weights_idx];
+ }
+ weights_idx++;
+ }
+ else
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] += emb_table[src_index + i];
+ }
+ }
+ }
+ }
+ }
+
+ } // embeddingBagOffsetsSum
+
+ } // reference
+ } // runtime
+} // ngraph
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void embeddingBagPackedSum(const T* emb_table,
+ const U* indices,
+ const T* weights,
+ T* out,
+ const Shape& indicesShape,
+ const Shape& outShape)
+ {
+ const size_t indices_per_bag = indicesShape[1];
+
+ size_t embDepth = 1lu;
+ for (size_t i = 1; i < outShape.size(); i++)
+ {
+ embDepth *= outShape[i];
+ }
+ memset(out, 0, shape_size(outShape) * sizeof(T));
+
+ bool with_weights = (weights != nullptr);
+ size_t idx_idx = 0lu;
+
+ for (size_t obi = 0lu; obi < outShape.at(0); obi++)
+ {
+ size_t dst_index = obi * embDepth;
+ for (size_t in_idx = 0lu; in_idx < indices_per_bag; in_idx++, idx_idx++)
+ {
+ size_t src_index = indices[idx_idx] * embDepth;
+
+ if (with_weights)
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] += emb_table[src_index + i] * weights[idx_idx];
+ }
+ }
+ else
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] += emb_table[src_index + i];
+ }
+ }
+ }
+ }
+
+ } // embeddingBagPackedSum
+
+ } // reference
+ } // runtime
+} // ngraph
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void embeddingSegmentsSum(const T* embTable,
+ const U* indices,
+ const U* segmentIds,
+ const U* defaultIndex,
+ const T* weights,
+ T* out,
+ const Shape& embTableShape,
+ const Shape& indicesShape,
+ const Shape& outShape)
+ {
+ const size_t indices_len = indicesShape[0];
+ const size_t segments_num = outShape[0];
+ const size_t inDimsSize = outShape.size();
+ const size_t embDimsNum = outShape.size() - 1;
+
+ size_t embDepth = 1lu;
+ for (size_t i = 1; i < outShape.size(); i++)
+ {
+ embDepth *= outShape[i];
+ }
+ memset(out, 0, shape_size(outShape) * sizeof(T));
+
+ bool with_weights = (weights != nullptr);
+
+ for (size_t index = 0; index < indices_len; index++)
+ {
+ size_t obi = segmentIds[index];
+ if (obi >= segments_num)
+ throw ngraph_error("Segment index could not be more than segments number");
+ size_t dst_index = obi * embDepth;
+ size_t src_index = indices[index] * embDepth;
+
+ if (with_weights)
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] += embTable[src_index + i] * weights[index];
+ }
+ }
+ else
+ {
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] += embTable[src_index + i];
+ }
+ }
+ }
+
+ if (defaultIndex != nullptr)
+ {
+ U defIndex = defaultIndex[0];
+ if (defIndex < U(0) && defIndex >= embTableShape[0])
+ throw ngraph_error(std::string("Invalid default index") +
+ std::to_string(defIndex));
+ for (size_t obi = 0; obi < segments_num; obi++)
+ {
+ bool found = false;
+ for (size_t index = 0; index < indices_len; index++)
+ {
+ if (segmentIds[index] == obi)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ size_t src_index = defIndex * embDepth;
+ size_t dst_index = obi * embDepth;
+ for (size_t i = 0lu; i < embDepth; i++)
+ {
+ out[dst_index + i] = embTable[src_index + i];
+ }
+ }
+ }
+ } // embeddingSegmentsSum
+
+ } // reference
+ } // runtime
+} // ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void equal(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] == arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void equal(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x == y;
+ });
+ }
+ }
+ }
+}
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void erf(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::erf(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/runtime/host_tensor.hpp"
+
+namespace ngraph
+{
+ namespace eval
+ {
+ AxisSet extract_reduction_axes(const HostTensorPtr& axes, const char* op_name);
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void exp(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::exp(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void extractImagePatches(const op::ExtractImagePatches* extImgPatches,
+ const T* input,
+ T* out,
+ const Shape& inShape,
+ const Shape& outShape)
+ {
+ const size_t dimsSize = inShape.size();
+ const size_t BATCH = 0, CHANNEL = 1, HIGHT = 0, WIDTH = 1;
+
+ const int64_t KH = extImgPatches->get_sizes()[HIGHT];
+ const int64_t KW = extImgPatches->get_sizes()[WIDTH];
+ const int64_t SH = extImgPatches->get_strides()[HIGHT];
+ const int64_t SW = extImgPatches->get_strides()[WIDTH];
+ const int64_t RH = extImgPatches->get_rates()[HIGHT];
+ const int64_t RW = extImgPatches->get_rates()[WIDTH];
+ const auto auto_pad = extImgPatches->get_auto_pad();
+
+ const int64_t IB = inShape[BATCH];
+ const int64_t IC = inShape[CHANNEL];
+ const int64_t IH = inShape[dimsSize - 2];
+ const int64_t IW = inShape[dimsSize - 1];
+
+ const int64_t OB = outShape[BATCH];
+ const int64_t OC = outShape[CHANNEL];
+ const int64_t OH = outShape[dimsSize - 2];
+ const int64_t OW = outShape[dimsSize - 1];
+
+ int64_t ihStart = 0;
+ int64_t iwStart = 0;
+
+ int64_t iwStep = KW + (RW - 1) * (KW - 1);
+ int64_t ihStep = KH + (RH - 1) * (KH - 1);
+
+ const int64_t OH_OW = OH * OW;
+ const int64_t OC_OH_OW = OC * OH_OW;
+ const int64_t OB_OC_OH_OW = OC_OH_OW * OB;
+ const int64_t IH_IW = IH * IW;
+ const int64_t IC_IH_IW = IC * IH_IW;
+ const int64_t IB_IC_IH_IW = IC_IH_IW * IB;
+ const int64_t KH_KW = KH * KW;
+
+ int64_t PL = 0, PT = 0;
+
+ if (auto_pad != op::PadType::VALID)
+ {
+ int64_t PW = (std::ceil(1.f * IW / SW) - 1) * SW + iwStep - IW;
+ int64_t PH = (std::ceil(1.f * IH / SH) - 1) * SH + ihStep - IH;
+
+ if ((PW > 0) && (PW < iwStep))
+ {
+ if (PW % 2 == 1)
+ {
+ if (auto_pad == op::PadType::SAME_LOWER)
+ {
+ PL = (PW + 1) / 2;
+ }
+ else if (auto_pad == op::PadType::SAME_UPPER)
+ {
+ PL = (PW - 1) / 2;
+ }
+ }
+ else
+ {
+ PL = PW / 2;
+ }
+ }
+ if ((PH > 0) && (PH < ihStep))
+ {
+ if (PH % 2 == 1)
+ {
+ if (auto_pad == op::PadType::SAME_LOWER)
+ {
+ PT = (PH + 1) / 2;
+ }
+ else if (auto_pad == op::PadType::SAME_UPPER)
+ {
+ PT = (PH - 1) / 2;
+ }
+ }
+ else
+ {
+ PT = PH / 2;
+ }
+ }
+ }
+
+ for (int64_t ob = 0; ob < OB; ob++)
+ {
+ const int64_t ib_ICIHIW = ob * IC_IH_IW;
+ const int64_t ob_OCOHOW = ob * OC_OH_OW;
+ for (int64_t oh = 0; oh < OH; oh++)
+ {
+ const int64_t ob_OCOHOW_ohOW = ob_OCOHOW + oh * OW;
+ int64_t ih0 = oh * SH - PT;
+ for (int64_t ow = 0; ow < OW; ow++)
+ {
+ const int64_t ob_OCOHOW_ohOW_ow = ob_OCOHOW_ohOW + ow;
+ int64_t iw0 = ow * SW - PL;
+ int64_t oc = 0;
+
+ for (int64_t kh = 0; kh < KH; kh++)
+ {
+ int64_t ihKH = ih0 + kh * RH;
+ int64_t ib_ICIHIW_ihKH_IW = ib_ICIHIW + ihKH * IW;
+ for (int64_t kw = 0; kw < KW; kw++)
+ {
+ for (int64_t ic = 0; ic < IC; ic++, oc++)
+ {
+ int64_t iwKW = iw0 + kw * RW;
+ int64_t dst_idx = ob_OCOHOW_ohOW_ow + oc * OH_OW;
+ if (dst_idx >= OB_OC_OH_OW)
+ throw ngraph_error(
+ "ExtractImagePatches. Destination index is out of "
+ "bounds.");
+ if (ihKH < 0 || ihKH >= IH || iwKW < 0 || iwKW >= IW)
+ {
+ out[dst_idx] = T(0);
+ }
+ else
+ {
+ int64_t src_idx = ib_ICIHIW_ihKH_IW + ic * IH_IW + iwKW;
+ if (src_idx >= IB_IC_IH_IW)
+ throw ngraph_error(
+ "ExtractImagePatches. Source index is out of "
+ "bounds.");
+ out[dst_idx] = input[src_idx];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } // extractImagePatches
+
+ } // reference
+ } // runtime
+} // ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void floor(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::floor(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/gather_nd.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // Implement gather by calling gather_nd on sub-problems
+ // # prepare constant shapes for tensors used for sub problems
+ // indices'.shape = indices.shape[-1] + [1]
+ // params'.shape = params.shape[axis:]
+ // out'.shape = params'.shape
+ // out'.shape[0] = indices.shape[-1]
+ // # call sub-problems
+ // foreach (params_index, out_index) in outer "axis" dimensions
+ // # params_prime is shared by inner loop
+ // params' = param[params_index] # rank(params') == rank(params) - axis
+ // foreach indices_index in outer N-1 dimensions
+ // indices' = indices[indices_index] # rank(indices') == 2
+ // out_index = out_index + indices_index
+ // out' = out[out_index] # rank(out') == rank(params')
+ // gather_nd(params', indices'', out')
+ template <typename T, typename U>
+ void gather(const T* params,
+ const U* indices,
+ T* out,
+ const Shape& params_shape,
+ const Shape& indices_shape,
+ const Shape& out_shape,
+ size_t axis)
+ {
+ using namespace std;
+ // prepare shape of params_prime (remove first "axis" dimensions)
+ Shape params_prime_shape(params_shape);
+ params_prime_shape.erase(params_prime_shape.begin(),
+ params_prime_shape.begin() + axis);
+ // prepare shape of indices_prime
+ size_t indices_ndim = static_cast<size_t>(indices_shape.size());
+ Shape indices_prime_shape;
+ // prepare shape of out_prime (same as params_prime except for first dim)
+ Shape out_prime_shape(params_prime_shape);
+ if (indices_ndim > 0)
+ {
+ out_prime_shape[0] = indices_shape[indices_ndim - 1];
+ indices_prime_shape.emplace_back(indices_shape[indices_ndim - 1]);
+ }
+ else
+ {
+ out_prime_shape[0] = 1;
+ }
+ indices_prime_shape.emplace_back(1);
+
+ // Create a CoordinateTransform for "out" that visits the outer "axis" dimensions
+ size_t out_ndim = static_cast<size_t>(out_shape.size());
+ Coordinate out_outer_start_corner(out_ndim, 0);
+ Coordinate out_outer_end_corner(out_shape);
+ for (size_t i = axis; i < out_ndim; i++)
+ {
+ out_outer_end_corner[i] = 1;
+ }
+ Strides out_outer_strides(out_ndim, 1);
+ AxisVector out_outer_axis_order(out_ndim);
+ std::iota(out_outer_axis_order.begin(), out_outer_axis_order.end(), 0);
+ CoordinateTransform out_outer_transform(out_shape,
+ out_outer_start_corner,
+ out_outer_end_corner,
+ out_outer_strides,
+ out_outer_axis_order);
+
+ // Create a CoordinateTransform for "params" that visits the outer "axis" dimensions
+ size_t params_ndim = static_cast<size_t>(params_shape.size());
+ Coordinate params_outer_start_corner(params_ndim, 0);
+ Coordinate params_outer_end_corner(params_shape);
+ for (size_t i = axis; i < params_ndim; i++)
+ {
+ params_outer_end_corner[i] = 1;
+ }
+ Strides params_outer_strides(params_ndim, 1);
+ AxisVector params_outer_axis_order(params_ndim);
+ std::iota(params_outer_axis_order.begin(), params_outer_axis_order.end(), 0);
+ CoordinateTransform params_outer_transform(params_shape,
+ params_outer_start_corner,
+ params_outer_end_corner,
+ params_outer_strides,
+ params_outer_axis_order);
+
+ // Create a CoordinateTransform for "indices" that visits only the first element
+ // along inner most axis
+ Coordinate indices_outer_start_corner(indices_ndim, 0);
+ Coordinate indices_outer_end_corner(indices_shape);
+ if (indices_ndim > 0)
+ {
+ indices_outer_end_corner[indices_ndim - 1] = 1;
+ }
+ Strides indices_outer_strides(indices_ndim, 1);
+ AxisVector indices_outer_axis_order(indices_ndim);
+ std::iota(indices_outer_axis_order.begin(), indices_outer_axis_order.end(), 0);
+ CoordinateTransform indices_outer_transform(indices_shape,
+ indices_outer_start_corner,
+ indices_outer_end_corner,
+ indices_outer_strides,
+ indices_outer_axis_order);
+
+ // Create an inner CoordinateTransfrom for "out"
+ size_t out_inner_ndim = out_ndim - axis;
+ Shape out_inner_shape(out_shape);
+ out_inner_shape.erase(out_inner_shape.begin(), out_inner_shape.begin() + axis);
+ Coordinate out_inner_start_corner(out_inner_ndim, 0);
+ Coordinate out_inner_end_corner(out_inner_shape);
+ if (indices_ndim > 0)
+ {
+ out_inner_end_corner[indices_ndim - 1] = 1;
+ }
+ for (size_t i = indices_ndim; i < out_inner_ndim; i++)
+ {
+ out_inner_end_corner[i] = 1;
+ }
+ Strides out_inner_strides(out_inner_ndim, 1);
+ AxisVector out_inner_axis_order(out_inner_ndim);
+ std::iota(out_inner_axis_order.begin(), out_inner_axis_order.end(), 0);
+ CoordinateTransform out_inner_transform(out_inner_shape,
+ out_inner_start_corner,
+ out_inner_end_corner,
+ out_inner_strides,
+ out_inner_axis_order);
+
+ auto out_outer_coord_iter = out_outer_transform.begin();
+ for (const Coordinate& params_outer_coord : params_outer_transform)
+ {
+ const T* params_prime =
+ ¶ms[params_outer_transform.index(params_outer_coord)];
+ T* out_outer = &out[out_outer_transform.index(*out_outer_coord_iter)];
+
+ auto out_inner_coord_iter = out_inner_transform.begin();
+ for (const Coordinate& indices_outer_coord : indices_outer_transform)
+ {
+ const U* indices_prime =
+ &indices[indices_outer_transform.index(indices_outer_coord)];
+ T* out_prime = &out_outer[out_inner_transform.index(*out_inner_coord_iter)];
+ gather_nd<T, U>(params_prime,
+ indices_prime,
+ out_prime,
+ params_prime_shape,
+ indices_prime_shape,
+ out_prime_shape);
+ out_inner_coord_iter++;
+ }
+ out_outer_coord_iter++;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // foreach leaf_vector_index in indices.shape[:-1]
+ // vector = indices[leaf_vector_index]
+ // out[leaf_vector_index:] = params[vector]
+ template <typename T, typename U>
+ void gather_nd(const T* params,
+ const U* indices,
+ T* out,
+ const Shape& params_shape,
+ const Shape& indices_shape,
+ const Shape& out_shape)
+ {
+ using namespace std;
+ // Create a CoordinateTransform for "indices" that visits only the first element
+ // along inner most axis
+ size_t indices_ndim = static_cast<size_t>(indices_shape.size());
+ Coordinate indices_outer_start_corner(indices_ndim, 0);
+ Coordinate indices_outer_end_corner(indices_shape);
+ size_t slice_rank = indices_shape[indices_ndim - 1];
+ indices_outer_end_corner[indices_ndim - 1] = 1;
+ Strides indices_strides(indices_ndim, 1);
+ AxisVector indices_axis_order(indices_ndim);
+ std::iota(indices_axis_order.begin(), indices_axis_order.end(), 0);
+ CoordinateTransform indices_outer_transform(indices_shape,
+ indices_outer_start_corner,
+ indices_outer_end_corner,
+ indices_strides,
+ indices_axis_order);
+
+ // Create a matching CoordinateTransform for "out" that visits the same outer
+ // coordinates
+ size_t out_ndim = static_cast<size_t>(out_shape.size());
+ Coordinate out_start_corner(out_ndim, 0);
+ Coordinate out_end_corner(out_shape);
+ for (size_t i = indices_ndim - 1; i < out_ndim; i++)
+ {
+ out_end_corner[i] = 1;
+ }
+ Strides out_strides(out_ndim, 1);
+ AxisVector out_axis_order(out_ndim);
+ std::iota(out_axis_order.begin(), out_axis_order.end(), 0);
+ CoordinateTransform out_transform(
+ out_shape, out_start_corner, out_end_corner, out_strides, out_axis_order);
+ size_t params_ndim = static_cast<size_t>(params_shape.size());
+ Strides params_strides(params_ndim, 1);
+ AxisVector params_axis_order(params_ndim);
+ std::iota(params_axis_order.begin(), params_axis_order.end(), 0);
+
+ // Gather slices from "params" and copy to "out"
+ auto out_coord_iter = out_transform.begin();
+ for (const Coordinate& indices_coord : indices_outer_transform)
+ {
+ Coordinate params_start_corner(params_ndim, 0);
+ Coordinate params_end_corner(params_shape);
+ auto indices_index = indices_outer_transform.index(indices_coord);
+ for (size_t i = 0; i < slice_rank; i++)
+ {
+ U index = indices[indices_index];
+ // take care of negative indices
+ index = index >= 0 ? index : index + params_shape[i];
+ params_start_corner[i] = index;
+ params_end_corner[i] = index + 1;
+ indices_index++;
+ }
+ CoordinateTransform params_transform(params_shape,
+ params_start_corner,
+ params_end_corner,
+ params_strides,
+ params_axis_order);
+ auto out_index = out_transform.index(*out_coord_iter);
+ for (const Coordinate& params_coord : params_transform)
+ {
+ out[out_index] = params[params_transform.index(params_coord)];
+ out_index++;
+ }
+ out_coord_iter++;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void greater(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] > arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void greater(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x > y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void greater_eq(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] >= arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void greater_eq(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x >= y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void less(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] < arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void less(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x < y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void less_eq(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] <= arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void less_eq(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x <= y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void log(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::log(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/any.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ static inline void reduce_logical_and(const char* arg,
+ char* out,
+ const Shape& input_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ CoordinateTransform output_transform(
+ reduce(input_shape, reduction_axes, keep_dims));
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 1;
+ }
+
+ CoordinateTransform input_transform(input_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+ out[output_transform.index(output_coord)] =
+ out[output_transform.index(output_coord)] &&
+ arg[input_transform.index(input_coord)];
+ }
+ }
+
+ static inline void reduce_logical_or(const char* arg,
+ char* out,
+ const Shape& input_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ runtime::reference::any(arg, out, input_shape, reduction_axes, keep_dims);
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sum_region_across_axes(const T* arg,
+ size_t current_axis_index,
+ const std::vector<size_t>& axes,
+ Coordinate& sum_coord,
+ T& square_sum,
+ const std::vector<size_t>& begin_area,
+ const std::vector<size_t>& end_area,
+ const CoordinateTransform& input_transform)
+ {
+ // all nested axes were visited
+ if (current_axis_index == axes.size())
+ {
+ square_sum += arg[input_transform.index(sum_coord)] *
+ arg[input_transform.index(sum_coord)];
+ return;
+ }
+ auto current_axis = axes[current_axis_index];
+ for (auto current_axis_coord = begin_area[current_axis];
+ current_axis_coord < end_area[current_axis];
+ ++current_axis_coord)
+ {
+ sum_coord.at(current_axis) = current_axis_coord;
+ sum_region_across_axes(arg,
+ current_axis_index + 1,
+ axes,
+ sum_coord,
+ square_sum,
+ begin_area,
+ end_area,
+ input_transform);
+ }
+ }
+
+ template <typename T>
+ void lrn(const T* arg,
+ const AxisSet& axes,
+ T* out,
+ const Shape& arg_shape,
+ double dalpha,
+ double dbeta,
+ double dbias,
+ size_t size)
+ {
+ T alpha = static_cast<T>(dalpha);
+ T beta = static_cast<T>(dbeta);
+ T bias = static_cast<T>(dbias);
+
+ std::vector<size_t> begin_area(arg_shape.size());
+ std::vector<size_t> end_area(arg_shape.size());
+
+ CoordinateTransform input_transform(arg_shape);
+ for (const Coordinate& in_coord : input_transform)
+ {
+ // area determined by in_coord local neighborhood
+ for (const auto& axis_coord : axes)
+ {
+ begin_area[axis_coord] =
+ std::max<int>(0, in_coord.at(axis_coord) - (size - 1) / 2);
+ end_area[axis_coord] = std::min<int>(
+ arg_shape.at(axis_coord), in_coord.at(axis_coord) + (size - 1) / 2 + 1);
+ }
+
+ T square_sum = 0;
+ auto sum_coord = in_coord;
+ auto axes_vec = std::vector<size_t>(axes.begin(), axes.end());
+ sum_region_across_axes(arg,
+ 0,
+ axes_vec,
+ sum_coord,
+ square_sum,
+ begin_area,
+ end_area,
+ input_transform);
+
+ T x = arg[input_transform.index(in_coord)];
+ out[input_transform.index(in_coord)] =
+ x / (std::pow(bias + (alpha / size) * square_sum, beta));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <numeric>
+#include <utility>
+#include <vector>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/builder/autobroadcast.hpp"
+#include "ngraph/runtime/opt_kernel/reshape.hpp"
+#include "ngraph/runtime/reference/broadcast.hpp"
+#include "ngraph/runtime/reference/dot.hpp"
+#include "ngraph/shape_util.hpp"
+
+using namespace std;
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ /// \brief Reference kernel for matmul computation.
+ ///
+ /// \tparam T Type of input and output tensors.
+ ///
+ /// \param arg0 Pointer to the buffer for left operand input tensor.
+ /// \param arg1 Pointer to the buffer for right operand input tensor.
+ /// \param out Pointer to the buffer for output tensor. This must be pre-allocated by
+ /// the caller, and must be large enough to hold a tensor of the correct
+ /// shape.
+ /// \param arg0_shape Shape of arg0.
+ /// \param arg1_shape Shape of arg1.
+ /// \param out_shape Shape of out.
+ /// \param transpose_arg0 Flag to indicate if transpose on arg0.
+ /// \param transpose_arg1 Flag to indicate if transpose on arg1.
+ template <typename T>
+ void matmul(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const Shape& out_shape,
+ bool transpose_arg0,
+ bool transpose_arg1)
+ {
+ // Steps to compute matmul:
+ // 1) Check inputs and perform transpose on arg if applicable
+ // 2) If ranks of both args are 2D and below (no batch dim),
+ // perform dot and return result; otherwise, continue next
+ // 3) Check if auto broadcast is needed on args or transposed args,
+ // and perform broadcast if applicable
+ // 4) Perform dot on the args or updated args and return result
+
+ size_t arg0_rank = arg0_shape.size();
+ size_t arg1_rank = arg1_shape.size();
+ size_t out_rank = out_shape.size();
+
+ // vector vars to hold pontential intermediate transpose,
+ // broadcast result
+ vector<T> arg0_transpose_vec;
+ vector<T> arg1_transpose_vec;
+ vector<T> arg0_broadcast_vec;
+ vector<T> arg1_broadcast_vec;
+
+ // pointers to updated inputs
+ const T* arg0_update = arg0;
+ const T* arg1_update = arg1;
+
+ // vars for updated inputs shapes
+ Shape wip_arg0_shape = arg0_shape;
+ Shape wip_arg1_shape = arg1_shape;
+
+ auto get_transpose_order = [](const Shape& input_shape) {
+ size_t rank = input_shape.size();
+ NGRAPH_CHECK(rank > 1, "Invalid input for transpose");
+ vector<size_t> axes_order(rank);
+ iota(axes_order.begin(), axes_order.end(), 0);
+ swap(axes_order[rank - 1], axes_order[rank - 2]);
+ return AxisVector{begin(axes_order), end(axes_order)};
+ };
+
+ auto get_broadcast_axes = [](const Shape& marker_shape, const Shape& target_shape) {
+ NGRAPH_CHECK(marker_shape.size() == target_shape.size(),
+ "Incompatible input shapes");
+ AxisSet broadcast_axes;
+ for (size_t i = 0; i < marker_shape.size(); i++)
+ {
+ if (marker_shape[i] == 1 && target_shape[i] != 1)
+ {
+ broadcast_axes.insert(i);
+ }
+ }
+ return broadcast_axes;
+ };
+
+ // Perform transpose if requested
+ if (transpose_arg0 && arg0_rank > 1)
+ {
+ arg0_transpose_vec.reserve(shape_size(arg0_shape));
+ auto axis_vector = get_transpose_order(arg0_shape);
+ swap(wip_arg0_shape[arg0_rank - 1], wip_arg0_shape[arg0_rank - 2]);
+ opt_kernel::reshape(reinterpret_cast<const char*>(arg0),
+ reinterpret_cast<char*>(arg0_transpose_vec.data()),
+ arg0_shape,
+ axis_vector,
+ wip_arg0_shape,
+ sizeof(T));
+
+ arg0_update = arg0_transpose_vec.data();
+ }
+
+ if (transpose_arg1 && arg1_rank > 1)
+ {
+ arg1_transpose_vec.reserve(shape_size(arg1_shape));
+ auto axis_vector = get_transpose_order(arg1_shape);
+ swap(wip_arg1_shape[arg1_rank - 1], wip_arg1_shape[arg1_rank - 2]);
+ opt_kernel::reshape(reinterpret_cast<const char*>(arg1),
+ reinterpret_cast<char*>(arg1_transpose_vec.data()),
+ arg1_shape,
+ axis_vector,
+ wip_arg1_shape,
+ sizeof(T));
+
+ arg1_update = arg1_transpose_vec.data();
+ }
+
+ // Inputs are 2D and below, perform dot directly
+ if (arg0_rank <= 2 && arg1_rank <= 2)
+ {
+ return dot(arg0_update,
+ arg1_update,
+ out,
+ wip_arg0_shape,
+ wip_arg1_shape,
+ out_shape,
+ 1);
+ }
+
+ // Check and perform auto-broadcast if needed
+ // If one of the arg is 2D or below, no need to
+ // do broadcast on it, just use its value for
+ // every batch of dot compuatation later
+
+ if (arg0_rank > 2 && arg1_rank > 2)
+ {
+ const auto& broadcast_shapes = builder::get_numpy_broadcast_shapes(
+ {Shape{begin(wip_arg0_shape), next(end(wip_arg0_shape), -2)},
+ Shape{begin(wip_arg1_shape), next(end(wip_arg1_shape), -2)}});
+
+ Shape arg0_br_target_shape = broadcast_shapes.first;
+ Shape arg1_br_target_shape = broadcast_shapes.first;
+ Shape arg0_br_marker_shape = broadcast_shapes.second.at(0);
+ Shape arg1_br_marker_shape = broadcast_shapes.second.at(1);
+
+ arg0_br_target_shape.insert(
+ end(arg0_br_target_shape),
+ next(begin(wip_arg0_shape), wip_arg0_shape.size() - 2),
+ end(wip_arg0_shape));
+ arg1_br_target_shape.insert(
+ end(arg1_br_target_shape),
+ next(begin(wip_arg1_shape), wip_arg1_shape.size() - 2),
+ end(wip_arg1_shape));
+
+ arg0_br_marker_shape.insert(
+ end(arg0_br_marker_shape),
+ next(begin(wip_arg0_shape), wip_arg0_shape.size() - 2),
+ end(wip_arg0_shape));
+ arg1_br_marker_shape.insert(
+ end(arg1_br_marker_shape),
+ next(begin(wip_arg1_shape), wip_arg1_shape.size() - 2),
+ end(wip_arg1_shape));
+
+ if (arg0_br_target_shape != wip_arg0_shape)
+ {
+ auto broadcast_axes =
+ get_broadcast_axes(arg0_br_marker_shape, arg0_br_target_shape);
+ if (!broadcast_axes.empty())
+ {
+ arg0_broadcast_vec.reserve(shape_size(arg0_br_target_shape));
+ broadcast(arg0_update,
+ arg0_broadcast_vec.data(),
+ wip_arg0_shape,
+ arg0_br_target_shape,
+ broadcast_axes);
+
+ arg0_update = arg0_broadcast_vec.data();
+ wip_arg0_shape = arg0_br_target_shape;
+ arg0_rank = wip_arg0_shape.size();
+ }
+ }
+
+ if (arg1_br_target_shape != wip_arg1_shape)
+ {
+ auto broadcast_axes =
+ get_broadcast_axes(arg1_br_marker_shape, arg1_br_target_shape);
+ if (!broadcast_axes.empty())
+ {
+ arg1_broadcast_vec.reserve(shape_size(arg1_br_target_shape));
+ broadcast(arg1_update,
+ arg1_broadcast_vec.data(),
+ wip_arg1_shape,
+ arg1_br_target_shape,
+ broadcast_axes);
+
+ arg1_update = arg1_broadcast_vec.data();
+ wip_arg1_shape = arg1_br_target_shape;
+ arg1_rank = wip_arg1_shape.size();
+ }
+ }
+ }
+
+ // Perform batched dot
+
+ size_t output_batch_size = 1;
+
+ // Calculate number of batches
+ if (out_rank < 3)
+ {
+ // Output is {batch_size, dot_result}, i.e.,
+ // arg 0 shape {2}, arg1 shape {3, 2, 1}, output shape {3, 1}
+ output_batch_size = out_shape[0];
+ }
+ else
+ {
+ for (size_t i = 0; i < (out_rank - 2); i++)
+ {
+ output_batch_size *= out_shape[i];
+ }
+ }
+
+ Shape dot_arg0_shape = (arg0_rank > 2) ? Shape{wip_arg0_shape[arg0_rank - 2],
+ wip_arg0_shape[arg0_rank - 1]}
+ : wip_arg0_shape;
+ Shape dot_arg1_shape = (arg1_rank > 2) ? Shape{wip_arg1_shape[arg1_rank - 2],
+ wip_arg1_shape[arg1_rank - 1]}
+ : wip_arg1_shape;
+ Shape dot_output_shape =
+ (out_rank > 2) ? Shape{out_shape[out_rank - 2], out_shape[out_rank - 1]}
+ : Shape{out_shape[out_rank - 1]};
+
+ const size_t arg0_offset = (arg0_rank > 2) ? shape_size(dot_arg0_shape) : 0;
+ const size_t arg1_offset = (arg1_rank > 2) ? shape_size(dot_arg1_shape) : 0;
+ const size_t output_offset = shape_size(dot_output_shape);
+ for (size_t i = 0; i < output_batch_size; i++)
+ {
+ dot(arg0_update + i * arg0_offset,
+ arg1_update + i * arg1_offset,
+ out + i * output_offset,
+ dot_arg0_shape,
+ dot_arg1_shape,
+ dot_output_shape,
+ 1);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <limits>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void max(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ T minval = std::numeric_limits<T>::has_infinity
+ ? T(-std::numeric_limits<T>::infinity())
+ : std::numeric_limits<T>::min();
+
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = minval;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ T x = arg[input_transform.index(input_coord)];
+ T max = out[output_transform.index(output_coord)];
+ if (x > max)
+ {
+ out[output_transform.index(output_coord)] = x;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void max_pool_backprop(const T* arg_forward,
+ const T* delta,
+ T* out,
+ const Shape& delta_shape,
+ const Shape& out_shape, // same as arg_forward_shape
+ const Shape& window_shape,
+ const Strides& window_movement_strides,
+ const Shape& padding_below,
+ const Shape& padding_above)
+ {
+ CoordinateTransform out_transform(out_shape);
+
+ for (const Coordinate& out_coord : out_transform)
+ {
+ out[out_transform.index(out_coord)] = 0;
+ }
+
+ CoordinateTransform delta_transform(delta_shape);
+
+ for (const Coordinate& delta_coord : delta_transform)
+ {
+ size_t img_index = delta_coord[0];
+ size_t channel = delta_coord[1];
+
+ size_t n_image_dimensions = out_shape.size() - 2;
+ Coordinate source_window_transform_start(2 + n_image_dimensions);
+ Coordinate source_window_transform_end(2 + n_image_dimensions);
+ Strides source_window_transform_source_strides(2 + n_image_dimensions, 1);
+ AxisVector source_window_transform_source_axis_order(2 + n_image_dimensions);
+ CoordinateDiff source_window_transform_padding_below(2 + n_image_dimensions);
+ CoordinateDiff source_window_transform_padding_above(2 + n_image_dimensions);
+
+ source_window_transform_start[0] = img_index;
+ source_window_transform_end[0] = img_index + 1;
+ source_window_transform_start[1] = channel;
+ source_window_transform_end[1] = channel + 1;
+ source_window_transform_padding_below[0] = 0;
+ source_window_transform_padding_below[1] = 0;
+ source_window_transform_padding_above[0] = 0;
+ source_window_transform_padding_above[1] = 0;
+
+ for (size_t i = 2; i < n_image_dimensions + 2; i++)
+ {
+ size_t window_shape_this_dim = window_shape[i - 2];
+ size_t movement_stride = window_movement_strides[i - 2];
+
+ source_window_transform_start[i] = movement_stride * delta_coord[i];
+ source_window_transform_end[i] =
+ source_window_transform_start[i] + window_shape_this_dim;
+ source_window_transform_padding_below[i] = padding_below[i - 2];
+ source_window_transform_padding_above[i] = padding_above[i - 2];
+ }
+ std::iota(begin(source_window_transform_source_axis_order),
+ end(source_window_transform_source_axis_order),
+ 0);
+
+ CoordinateTransform source_window_transform(
+ out_shape,
+ source_window_transform_start,
+ source_window_transform_end,
+ source_window_transform_source_strides,
+ source_window_transform_source_axis_order,
+ source_window_transform_padding_below,
+ source_window_transform_padding_above);
+
+ Coordinate argmax_coord;
+ bool argmax_coord_valid = false;
+ T max_val = 0; // just initializing to keep compiler happy, this 0 is ignored
+
+ for (const Coordinate& source_window_coord : source_window_transform)
+ {
+ if (source_window_transform.has_source_coordinate(source_window_coord))
+ {
+ T candidate =
+ arg_forward[source_window_transform.index(source_window_coord)];
+
+ if (!argmax_coord_valid || candidate > max_val)
+ {
+ max_val = candidate;
+ argmax_coord = source_window_coord;
+ argmax_coord_valid = true;
+ }
+ }
+ }
+
+ if (argmax_coord_valid)
+ {
+ out[source_window_transform.index(argmax_coord)] +=
+ delta[delta_transform.index(delta_coord)];
+ }
+ }
+ }
+
+ template <typename T>
+ void max_pool(const T* arg,
+ T* out,
+ const Shape& arg_shape,
+ const Shape& out_shape,
+ const Shape& window_shape,
+ const Strides& window_movement_strides,
+ const Shape& padding_below,
+ const Shape& padding_above)
+ {
+ // At the outermost level we will walk over every output coordinate O.
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& out_coord : output_transform)
+ {
+ // Our output coordinate O will have the form:
+ //
+ // (N,chan,i_1,...,i_n)
+
+ size_t batch_index = out_coord[0];
+ size_t channel = out_coord[1];
+
+ // For the input data we need to iterate the coordinate:
+ //
+ // I:
+ //
+ // over the range (noninclusive on the right):
+ //
+ // (N,chan,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
+ //
+ // (N+1,chan+1,s_1*i_1 + window_shape_1,...,s_n*i_n + window_shape_n)
+ //
+ // with unit stride.
+ //
+ // We iterate this over the *padded* data, so below we will need to check for
+ // coordinates that fall in the padding area.
+
+ size_t n_spatial_dimensions = arg_shape.size() - 2;
+
+ Coordinate input_batch_transform_start(2 + n_spatial_dimensions);
+ Coordinate input_batch_transform_end(2 + n_spatial_dimensions);
+ Strides input_batch_transform_source_strides(2 + n_spatial_dimensions, 1);
+ AxisVector input_batch_transform_source_axis_order(2 + n_spatial_dimensions);
+ CoordinateDiff input_batch_transform_padding_below(2 + n_spatial_dimensions);
+ CoordinateDiff input_batch_transform_padding_above(2 + n_spatial_dimensions);
+
+ input_batch_transform_start[0] = batch_index;
+ input_batch_transform_end[0] = batch_index + 1;
+ input_batch_transform_start[1] = channel;
+ input_batch_transform_end[1] = channel + 1;
+ input_batch_transform_padding_below[0] = 0;
+ input_batch_transform_padding_below[1] = 0;
+ input_batch_transform_padding_above[0] = 0;
+ input_batch_transform_padding_above[1] = 0;
+
+ for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
+ {
+ size_t window_shape_this_dim = window_shape[i - 2];
+ size_t movement_stride = window_movement_strides[i - 2];
+
+ input_batch_transform_start[i] = movement_stride * out_coord[i];
+ input_batch_transform_end[i] =
+ input_batch_transform_start[i] + window_shape_this_dim;
+ input_batch_transform_padding_below[i] = padding_below[i - 2];
+ input_batch_transform_padding_above[i] = padding_above[i - 2];
+ }
+
+ for (size_t i = 0; i < arg_shape.size(); i++)
+ {
+ input_batch_transform_source_axis_order[i] = i;
+ }
+
+ CoordinateTransform input_batch_transform(
+ arg_shape,
+ input_batch_transform_start,
+ input_batch_transform_end,
+ input_batch_transform_source_strides,
+ input_batch_transform_source_axis_order,
+ input_batch_transform_padding_below,
+ input_batch_transform_padding_above);
+
+ // As we go, we compute the maximum value:
+ //
+ // output[O] = max(output[O],arg[I])
+
+ T result = std::numeric_limits<T>::lowest();
+
+ for (const Coordinate& input_batch_coord : input_batch_transform)
+ {
+ if (input_batch_transform.has_source_coordinate(input_batch_coord))
+ {
+ T x = arg[input_batch_transform.index(input_batch_coord)];
+ result = x > result ? x : result;
+ }
+ }
+
+ out[output_transform.index(out_coord)] = result;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void maximum(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] > arg1[i] ? arg0[i] : arg1[i];
+ }
+ }
+
+ template <typename T>
+ void maximum(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x > y ? x : y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <map>
+#include <vector>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/sum.hpp"
+#include "ngraph/shape_util.hpp"
+#include "ngraph/type/bfloat16.hpp"
+#include "ngraph/type/float16.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void mean(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+ std::vector<T> cs(shape_size(out_shape));
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 0;
+ cs[output_transform.index(output_coord)] = 0;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+ std::map<size_t, int> index_to_count_map;
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ T x = arg[input_transform.index(input_coord)];
+ T& z = out[output_transform.index(output_coord)];
+ auto index = output_transform.index(output_coord);
+ if (index_to_count_map.find(index) == index_to_count_map.end())
+ {
+ index_to_count_map[index] = 1;
+ }
+ else
+ {
+ index_to_count_map[index]++;
+ }
+
+ if (is_finite(x) && is_finite(z))
+ {
+ T& c = cs[output_transform.index(output_coord)];
+ T t = z + (x - c);
+ c = (t - z) - (x - c);
+ z = t;
+ }
+ else
+ {
+ z = z + x;
+ }
+ }
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ auto count = index_to_count_map[output_transform.index(output_coord)];
+ out[output_transform.index(output_coord)] =
+ out[output_transform.index(output_coord)] / count;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <limits>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+#ifdef _WIN32
+#undef min
+#endif
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void min(const T* arg, T* out, const Shape& in_shape, const AxisSet& reduction_axes)
+ {
+ T minval = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity()
+ : std::numeric_limits<T>::max();
+
+ auto out_shape = reduce(in_shape, reduction_axes, false);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = minval;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, false);
+
+ T x = arg[input_transform.index(input_coord)];
+ T min = out[output_transform.index(output_coord)];
+ if (x < min)
+ {
+ out[output_transform.index(output_coord)] = x;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void minimum(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] < arg1[i] ? arg0[i] : arg1[i];
+ }
+ }
+
+ template <typename T>
+ void minimum(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x < y ? x : y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void mish(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i] * std::tanh(std::log((std::exp(arg[i]) + 1.0)));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void multiply(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] * arg1[i];
+ }
+ }
+
+ template <typename T>
+ void multiply(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x * y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void negate(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = -arg[i];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ /// \brief Return number of non-zero entries in the input argument.
+ ///
+ /// \param arg Input tensor
+ /// \param arg_shape Input tensor shape
+ /// Output number of non-zero entries in arg
+ template <typename T>
+ size_t non_zero_get_count(const T* arg, const Shape& arg_shape)
+ {
+ T zero = 0;
+ size_t arg_rank = arg_shape.size();
+ size_t arg_count = shape_size(arg_shape);
+ size_t non_zero_count = 0;
+
+ // Input arg is scalar
+ if (arg_rank == 0)
+ {
+ if (*arg != zero)
+ {
+ non_zero_count = 1;
+ }
+ }
+ else // Input is non scalar case
+ {
+ for (size_t i = 0; i < arg_count; i++)
+ {
+ if (arg[i] != zero)
+ {
+ non_zero_count++;
+ }
+ }
+ }
+
+ return non_zero_count;
+ }
+
+ /// \brief Return indices of non-zero entries in input argument.
+ ///
+ /// \param arg Input tensor
+ /// \param arg_shape Input tensor shape
+ /// \param out Output containing indices of non-zero entries in arg
+ template <typename T, typename U>
+ void non_zero(const T* arg, U* out, const Shape& arg_shape)
+ {
+ T zero = 0;
+ size_t arg_rank = arg_shape.size();
+ size_t arg_count = shape_size(arg_shape);
+
+ size_t non_zero_count = non_zero_get_count(arg, arg_shape);
+
+ // Input arg only contains 0s
+ if (non_zero_count == 0)
+ {
+ return;
+ }
+
+ // Input arg is non-zero scalar
+ if (arg_rank == 0)
+ {
+ out[0] = static_cast<U>(0);
+ return;
+ }
+
+ // Dimensional size for the arg_shape. This is used to map one-dimentional
+ // arg array indices to corresponding arg_rank-dimentional shape indices.
+ // i.e., arg_shape {2, 3, 2} => elem_per_axis {6, 2, 1}.
+ // Array index 4 in arg (arg[4]) correspond to 3-D index of [0][2][0]
+ std::vector<size_t> elem_per_axis;
+ elem_per_axis.reserve(arg_rank);
+
+ size_t temp = arg_count;
+ for (size_t i = 0; i < arg_rank; i++)
+ {
+ temp = temp / arg_shape[i];
+ elem_per_axis.push_back(temp);
+ }
+
+ // Column index in out to record a non-zero entry
+ size_t col_index = 0;
+
+ // Array index in out to write non-zero index value
+ size_t out_index = 0;
+
+ // Find non-zero entries in arg and write the indices info in out.
+ // For a non-zero entry, map its array index to corresponding indices
+ // in arg_shape, then, write each of the arg_shape index value to
+ // out array at the position that is determined by entry's dimension
+ // distance and number of non-zero entries prior to it.
+ // i,e., Given input with shape{2, 3, 2}, rank = 3
+ // input [[[0, 2], [0, 0], [3, 4]],
+ // [[5, 0], [6, 0], [7, 8]]]
+ //
+ // output shape {3, 7}, rank = 2
+ // output [[0, 0, 0, 1, 1, 1, 1],
+ // [0, 2, 2, 0, 1, 2, 2],
+ // [1, 0, 1, 0, 0, 0, 1]]
+ //
+ // input[0][2][0] = 3 is arg[4]
+ // output for this entry out[1] = 0, out[8] = 2, out[15] = 0
+ for (size_t i = 0; i < arg_count; i++)
+ {
+ if (arg[i] != zero)
+ {
+ temp = i;
+
+ for (size_t j = 0; j < arg_rank; j++)
+ {
+ out_index = j * non_zero_count + col_index;
+ out[out_index] = static_cast<U>(temp / elem_per_axis[j]);
+
+ temp = temp % elem_per_axis[j];
+ }
+
+ col_index++;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void logical_not(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = static_cast<T>(!(arg[i]));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void not_equal(const T* arg0,
+ const T* arg1,
+ char* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] != arg1[i];
+ }
+ }
+
+ template <typename T, typename U>
+ void not_equal(const T* arg0,
+ const T* arg1,
+ U* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x != y;
+ });
+ }
+ }
+ }
+}
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename INDICES_TYPE, typename OUTPUT_TYPE>
+ void one_hot(const INDICES_TYPE* arg,
+ OUTPUT_TYPE* out,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ size_t one_hot_axis,
+ const OUTPUT_TYPE on_value,
+ const OUTPUT_TYPE off_value)
+ {
+ // Step 1: Set off_value to the output.
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = off_value;
+ }
+
+ // Step 2: Write off_value at needed positions, throwing exceptions when invalid
+ // conditions are encountered.
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ INDICES_TYPE val = arg[input_transform.index(input_coord)];
+
+ if (std::floor(val) < val || std::floor(val) > val)
+ {
+ continue;
+ }
+
+ size_t one_hot_pos = static_cast<size_t>(val);
+
+ if (one_hot_pos >= out_shape[one_hot_axis])
+ {
+ continue;
+ }
+
+ Coordinate one_hot_coord = inject(input_coord, one_hot_axis, one_hot_pos);
+
+ out[output_transform.index(one_hot_coord)] = on_value;
+ }
+ }
+
+ template <typename T>
+ void one_hot(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ size_t one_hot_axis)
+ {
+ const T on_value = 1;
+ const T off_value = 0;
+ one_hot<T, T>(arg, out, in_shape, out_shape, one_hot_axis, on_value, off_value);
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void logical_or(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = static_cast<T>(arg0[i] || arg1[i]);
+ }
+ }
+
+ template <typename T>
+ void logical_or(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return static_cast<T>(x || y);
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/pad.hpp" // for op::PadMode
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void pad(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& out_shape,
+ const CoordinateDiff& padding_below,
+ const CoordinateDiff& padding_above,
+ op::PadMode pad_mode)
+ {
+ Coordinate input_start(arg0_shape.size(), 0); // start at (0,0,...,0)
+ Coordinate input_end = out_shape; // end at (d'0,d'1,...,d'n), the outer corner of
+ // the post-padding shape
+
+ Strides input_strides(arg0_shape.size(), 1);
+
+ AxisVector input_axis_order(arg0_shape.size());
+ for (size_t i = 0; i < arg0_shape.size(); i++)
+ {
+ input_axis_order[i] = i;
+ }
+
+ CoordinateTransform input_transform(arg0_shape,
+ input_start,
+ input_end,
+ input_strides,
+ input_axis_order,
+ padding_below,
+ padding_above);
+ CoordinateTransform output_transform(out_shape);
+
+ CoordinateTransform::Iterator output_it = output_transform.begin();
+
+ NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
+ shape_size(output_transform.get_target_shape()));
+
+ for (const Coordinate& in_coord : input_transform)
+ {
+ const Coordinate& out_coord = *output_it;
+
+ T v(0);
+
+ switch (pad_mode)
+ {
+ case op::PadMode::CONSTANT:
+ // If the coordinate is out of bounds, substitute *arg1.
+ v = input_transform.has_source_coordinate(in_coord)
+ ? arg0[input_transform.index(in_coord)]
+ : *arg1;
+ break;
+ case op::PadMode::EDGE:
+ {
+ Coordinate c = in_coord; // have to copy because in_coord is const
+
+ // Truncate each out-of-bound dimension.
+ for (size_t i = 0; i < c.size(); i++)
+ {
+ if (static_cast<ptrdiff_t>(c[i]) < padding_below[i])
+ {
+ c[i] = padding_below[i];
+ }
+
+ if (static_cast<ptrdiff_t>(c[i]) >=
+ (padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i])))
+ {
+ c[i] = static_cast<size_t>(
+ padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i]) - 1);
+ }
+ }
+ v = arg0[input_transform.index(c)];
+ break;
+ }
+ case op::PadMode::REFLECT:
+ {
+ // clang-format off
+ // The algorithm here is a bit complicated because if the padding is
+ // bigger than the tensor, we may reflect multiple times.
+ //
+ // Example:
+ //
+ // Input shape: [2]
+ // Padding: 6 below, 6 above
+ // Output shape: [14]
+ //
+ // Input: a b
+ // Expected output: a b a b a b a b a b a b a b
+ //
+ // Computation for coordinate 13 of output:
+ //
+ // . . . . . . a b . . . . .[.] -> (oob above by 6 spaces, so reflection is at top-6)
+ // .[.]. . . . a b . . . . . . -> (oob below by 5 spaces, so reflection is at bottom+5)
+ // . . . . . . a b . . .[.]. . -> (oob above by 4 spaces, so reflection is at top-4)
+ // . . .[.]. . a b . . . . . . -> (oob below by 3 spaces, so reflection is at bottom+3)
+ // . . . . . . a b .[.]. . . . -> (oob above by 2 spaces, so reflection is at top-2)
+ // . . . . .[.]a b . . . . . . -> (oob below by 1 space, so reflection is at bottom+1)
+ // . . . . . . a[b]. . . . . . -> (no longer oob, so copy from here)
+ //
+ // Note that this algorithm works because REFLECT padding only makes sense
+ // if each dim is >= 2.
+ // clang-format on
+ Coordinate c = in_coord; // have to copy because in_coord is const
+
+ for (size_t i = 0; i < c.size(); i++)
+ {
+ ptrdiff_t new_dim = c[i];
+ bool done_reflecting = false;
+
+ while (!done_reflecting)
+ {
+ if (new_dim < padding_below[i])
+ {
+ ptrdiff_t distance_oob = padding_below[i] - new_dim;
+ new_dim = padding_below[i] + distance_oob;
+ }
+ else if (new_dim >=
+ padding_below[i] + static_cast<ptrdiff_t>(arg0_shape[i]))
+ {
+ ptrdiff_t distance_oob =
+ new_dim - padding_below[i] -
+ (static_cast<ptrdiff_t>(arg0_shape[i]) - 1);
+ new_dim = padding_below[i] +
+ static_cast<ptrdiff_t>(arg0_shape[i]) - distance_oob -
+ 1;
+ }
+ else
+ {
+ done_reflecting = true;
+ }
+ }
+
+ c[i] = static_cast<size_t>(new_dim);
+ }
+ v = arg0[input_transform.index(c)];
+ break;
+ }
+ case op::PadMode::SYMMETRIC:
+ {
+ Coordinate c = in_coord; // have to copy because in_coord is const
+ for (size_t i = 0; i < c.size(); i++)
+ {
+ ptrdiff_t pos = padding_below[i] - (c[i] + 1);
+ if (pos >= 0)
+ {
+ c[i] = static_cast<size_t>(pos + padding_below[i]);
+ }
+ else
+ {
+ pos = -(pos + 1);
+ ptrdiff_t src_dim = static_cast<ptrdiff_t>(arg0_shape[i]);
+ if (pos < src_dim)
+ {
+ c[i] = static_cast<size_t>(pos + padding_below[i]);
+ }
+ else
+ {
+ c[i] = static_cast<size_t>(padding_below[i] + src_dim +
+ padding_above[i] - pos);
+ }
+ }
+ }
+ v = arg0[input_transform.index(c)];
+ break;
+ }
+ }
+
+ out[output_transform.index(out_coord)] = v;
+
+ ++output_it;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void power(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::pow(arg0[i], arg1[i]);
+ }
+ }
+
+ template <typename T>
+ void power(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return std::pow(x, y);
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+#include <op/util/attr_types.hpp>
+#include <shape.hpp>
+
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void prelu(const T* arg,
+ const T* slope,
+ T* out,
+ const Shape& arg_shape,
+ const Shape& slope_shape)
+ {
+ int cnt = 0;
+ for (size_t i = 0; i < shape_size(arg_shape); ++i)
+ {
+ out[i] =
+ arg[i] < T(0) ? T(arg[i] * slope[cnt++ % shape_size(slope_shape)]) : arg[i];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/prior_box.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ static inline float clip_great(float x, float threshold)
+ {
+ return x < threshold ? x : threshold;
+ }
+
+ static inline float clip_less(float x, float threshold)
+ {
+ return x > threshold ? x : threshold;
+ }
+
+ template <typename T>
+ void prior_box(const T* data,
+ const T* img,
+ float* dst_data,
+ const Shape& out_shape,
+ const op::PriorBoxAttrs& attrs)
+ {
+ const int64_t W = data[1];
+ const int64_t H = data[0];
+ const int64_t IW = img[1];
+ const int64_t IH = img[0];
+
+ const int64_t OH = out_shape[1];
+ const int64_t OW = 1;
+
+ std::vector<float> aspect_ratios = {1.0f};
+ for (const auto& aspect_ratio : attrs.aspect_ratio)
+ {
+ bool exist = false;
+ for (const auto existed_value : aspect_ratios)
+ exist |= std::fabs(aspect_ratio - existed_value) < 1e-6;
+
+ if (!exist)
+ {
+ aspect_ratios.push_back(aspect_ratio);
+ if (attrs.flip)
+ {
+ aspect_ratios.push_back(1.0f / aspect_ratio);
+ }
+ }
+ }
+
+ std::vector<float> variance = attrs.variance;
+ NGRAPH_CHECK(variance.size() == 1 || variance.size() == 4 || variance.empty());
+ if (variance.empty())
+ variance.push_back(0.1f);
+
+ int64_t num_priors = op::PriorBox::number_of_priors(attrs);
+
+ float step = attrs.step;
+ auto min_size = attrs.min_size;
+ if (!attrs.scale_all_sizes)
+ {
+ // mxnet-like PriorBox
+ if (step == -1)
+ step = 1.f * IH / H;
+ else
+ step *= IH;
+ for (auto& size : min_size)
+ size *= IH;
+ }
+
+ int64_t idx = 0;
+ float center_x, center_y, box_width, box_height, step_x, step_y;
+ float IWI = 1.0f / static_cast<float>(IW);
+ float IHI = 1.0f / static_cast<float>(IH);
+
+ if (step == 0)
+ {
+ step_x = static_cast<float>(IW) / W;
+ step_y = static_cast<float>(IH) / H;
+ }
+ else
+ {
+ step_x = step;
+ step_y = step;
+ }
+
+ auto calculate_data = [&dst_data, &IWI, &IHI, &idx](
+ float center_x, float center_y, float box_width, float box_height, bool clip) {
+ if (clip)
+ {
+ // order: xmin, ymin, xmax, ymax
+ dst_data[idx++] = clip_less((center_x - box_width) * IWI, 0);
+ dst_data[idx++] = clip_less((center_y - box_height) * IHI, 0);
+ dst_data[idx++] = clip_great((center_x + box_width) * IWI, 1);
+ dst_data[idx++] = clip_great((center_y + box_height) * IHI, 1);
+ }
+ else
+ {
+ dst_data[idx++] = (center_x - box_width) * IWI;
+ dst_data[idx++] = (center_y - box_height) * IHI;
+ dst_data[idx++] = (center_x + box_width) * IWI;
+ dst_data[idx++] = (center_y + box_height) * IHI;
+ }
+ };
+
+ for (int64_t h = 0; h < H; ++h)
+ {
+ for (int64_t w = 0; w < W; ++w)
+ {
+ if (step == 0)
+ {
+ center_x = (w + 0.5f) * step_x;
+ center_y = (h + 0.5f) * step_y;
+ }
+ else
+ {
+ center_x = (attrs.offset + w) * step;
+ center_y = (attrs.offset + h) * step;
+ }
+
+ for (size_t s = 0; s < attrs.fixed_size.size(); ++s)
+ {
+ auto fixed_size_ = static_cast<size_t>(attrs.fixed_size[s]);
+ box_width = box_height = fixed_size_ * 0.5f;
+
+ if (!attrs.fixed_ratio.empty())
+ {
+ for (float ar : attrs.fixed_ratio)
+ {
+ auto density_ = static_cast<int64_t>(attrs.density[s]);
+ auto shift =
+ static_cast<int64_t>(attrs.fixed_size[s] / density_);
+ ar = std::sqrt(ar);
+ float box_width_ratio = attrs.fixed_size[s] * 0.5f * ar;
+ float box_height_ratio = attrs.fixed_size[s] * 0.5f / ar;
+ for (size_t r = 0; r < density_; ++r)
+ {
+ for (size_t c = 0; c < density_; ++c)
+ {
+ float center_x_temp = center_x - fixed_size_ / 2 +
+ shift / 2.f + c * shift;
+ float center_y_temp = center_y - fixed_size_ / 2 +
+ shift / 2.f + r * shift;
+ calculate_data(center_x_temp,
+ center_y_temp,
+ box_width_ratio,
+ box_height_ratio,
+ true);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!attrs.density.empty())
+ {
+ auto density_ = static_cast<int64_t>(attrs.density[s]);
+ auto shift =
+ static_cast<int64_t>(attrs.fixed_size[s] / density_);
+ for (int64_t r = 0; r < density_; ++r)
+ {
+ for (int64_t c = 0; c < density_; ++c)
+ {
+ float center_x_temp = center_x - fixed_size_ / 2 +
+ shift / 2.f + c * shift;
+ float center_y_temp = center_y - fixed_size_ / 2 +
+ shift / 2.f + r * shift;
+ calculate_data(center_x_temp,
+ center_y_temp,
+ box_width,
+ box_height,
+ true);
+ }
+ }
+ }
+ // Rest of priors
+ for (float ar : aspect_ratios)
+ {
+ if (fabs(ar - 1.) < 1e-6)
+ {
+ continue;
+ }
+
+ auto density_ = static_cast<int64_t>(attrs.density[s]);
+ auto shift =
+ static_cast<int64_t>(attrs.fixed_size[s] / density_);
+ ar = std::sqrt(ar);
+ float box_width_ratio = attrs.fixed_size[s] * 0.5f * ar;
+ float box_height_ratio = attrs.fixed_size[s] * 0.5f / ar;
+ for (int64_t r = 0; r < density_; ++r)
+ {
+ for (int64_t c = 0; c < density_; ++c)
+ {
+ float center_x_temp = center_x - fixed_size_ / 2 +
+ shift / 2.f + c * shift;
+ float center_y_temp = center_y - fixed_size_ / 2 +
+ shift / 2.f + r * shift;
+ calculate_data(center_x_temp,
+ center_y_temp,
+ box_width_ratio,
+ box_height_ratio,
+ true);
+ }
+ }
+ }
+ }
+ }
+
+ for (size_t ms_idx = 0; ms_idx < min_size.size(); ms_idx++)
+ {
+ box_width = min_size[ms_idx] * 0.5f;
+ box_height = min_size[ms_idx] * 0.5f;
+ calculate_data(center_x, center_y, box_width, box_height, false);
+
+ if (attrs.max_size.size() > ms_idx)
+ {
+ box_width = box_height =
+ std::sqrt(min_size[ms_idx] * attrs.max_size[ms_idx]) * 0.5f;
+ calculate_data(center_x, center_y, box_width, box_height, false);
+ }
+
+ if (attrs.scale_all_sizes ||
+ (!attrs.scale_all_sizes && (ms_idx == min_size.size() - 1)))
+ {
+ size_t s_idx = attrs.scale_all_sizes ? ms_idx : 0;
+ for (float ar : aspect_ratios)
+ {
+ if (std::fabs(ar - 1.0f) < 1e-6)
+ {
+ continue;
+ }
+
+ ar = std::sqrt(ar);
+ box_width = min_size[s_idx] * 0.5f * ar;
+ box_height = min_size[s_idx] * 0.5f / ar;
+ calculate_data(
+ center_x, center_y, box_width, box_height, false);
+ }
+ }
+ }
+ }
+ }
+
+ if (attrs.clip)
+ {
+ for (uint64_t i = 0; i < H * W * num_priors * 4; ++i)
+ {
+ dst_data[i] = (std::min)((std::max)(dst_data[i], 0.0f), 1.0f);
+ }
+ }
+
+ uint64_t channel_size = OH * OW;
+ if (variance.size() == 1)
+ {
+ for (uint64_t i = 0; i < channel_size; ++i)
+ {
+ dst_data[i + channel_size] = variance[0];
+ }
+ }
+ else
+ {
+ for (uint64_t i = 0; i < H * W * num_priors; ++i)
+ {
+ for (size_t j = 0; j < 4; ++j)
+ {
+ dst_data[i * 4 + j + channel_size] = variance[j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/prior_box_clustered.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void prior_box_clustered(const T* data,
+ const T* img,
+ float* dst_data,
+ const Shape& out_shape,
+ const op::PriorBoxClusteredAttrs& attrs)
+ {
+ size_t num_priors_ = attrs.widths.size();
+
+ auto variances = attrs.variances;
+ if (variances.empty())
+ variances.push_back(0.1f);
+
+ // Execute
+ const int64_t layer_width = data[1];
+ const int64_t layer_height = data[0];
+
+ int64_t img_width = img[1];
+ int64_t img_height = img[0];
+
+ // TODO: Uncomment after PriorBoxClustered is aligned with the specification.
+
+ // int img_width = img_w_ == 0 ? img[1] : img_w_;
+ // int img_height = img_h_ == 0 ? img[0] : img_h_;
+
+ // float step_w = attrs.step_widths == 0 ? step_ : attrs.step_widths;
+ // float step_h = attrs.step_heights == 0 ? step_ :
+ // attrs.step_heights;
+
+ float step_w = attrs.step_widths;
+ float step_h = attrs.step_heights;
+
+ if (step_w == 0 && step_h == 0)
+ {
+ step_w = static_cast<float>(img_width) / layer_width;
+ step_h = static_cast<float>(img_height) / layer_height;
+ }
+
+ size_t var_size = variances.size();
+ for (int64_t h = 0; h < layer_height; ++h)
+ {
+ for (int64_t w = 0; w < layer_width; ++w)
+ {
+ float center_x = (w + attrs.offset) * step_w;
+ float center_y = (h + attrs.offset) * step_h;
+
+ for (size_t s = 0; s < num_priors_; ++s)
+ {
+ float box_width = attrs.widths[s];
+ float box_height = attrs.heights[s];
+
+ float xmin = (center_x - box_width / 2.0f) / img_width;
+ float ymin = (center_y - box_height / 2.0f) / img_height;
+ float xmax = (center_x + box_width / 2.0f) / img_width;
+ float ymax = (center_y + box_height / 2.0f) / img_height;
+
+ if (attrs.clip)
+ {
+ xmin = (std::min)((std::max)(xmin, 0.0f), 1.0f);
+ ymin = (std::min)((std::max)(ymin, 0.0f), 1.0f);
+ xmax = (std::min)((std::max)(xmax, 0.0f), 1.0f);
+ ymax = (std::min)((std::max)(ymax, 0.0f), 1.0f);
+ }
+
+ auto get_idx = [&](uint64_t cnt) -> uint64_t {
+ return h * layer_width * num_priors_ * cnt + w * num_priors_ * cnt +
+ s * cnt;
+ };
+
+ uint64_t idx = get_idx(4);
+ dst_data[idx + 0] = xmin;
+ dst_data[idx + 1] = ymin;
+ dst_data[idx + 2] = xmax;
+ dst_data[idx + 3] = ymax;
+
+ idx = get_idx(var_size);
+ for (size_t j = 0; j < var_size; j++)
+ dst_data[idx + j + out_shape[1]] = variances[j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void product(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 1;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ size_t output_index = output_transform.index(output_coord);
+
+ out[output_index] = out[output_index] * arg[input_transform.index(input_coord)];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/quantize.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename REAL, typename QUANT>
+ void quantize(const REAL* input,
+ const REAL* scale,
+ const QUANT* zero_point,
+ QUANT* output,
+ const Shape& input_shape,
+ const Shape& scale_zero_point_shape,
+ const AxisSet& axes,
+ op::Quantize::RoundMode round_mode)
+ {
+ CoordinateTransform input_transform(input_shape);
+ CoordinateTransform scale_zero_point_transform(scale_zero_point_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate scale_zero_point_coord = project(input_coord, axes);
+
+ // apply scale
+ REAL qvalue = input[input_transform.index(input_coord)] /
+ scale[scale_zero_point_transform.index(scale_zero_point_coord)];
+
+ // round
+ if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY)
+ {
+ REAL abs_qvalue = std::fabs(qvalue);
+ REAL abs_qvalue_toward_inf =
+ std::floor(abs_qvalue + static_cast<REAL>(0.5));
+ qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
+ : abs_qvalue_toward_inf;
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_ZERO)
+ {
+ auto abs_qvalue = std::fabs(qvalue);
+ auto abs_qvalue_toward_zero =
+ std::ceil(abs_qvalue - static_cast<REAL>(0.5));
+ qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
+ : abs_qvalue_toward_zero;
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_UPWARD)
+ {
+ qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_DOWNWARD)
+ {
+ qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN)
+ {
+ auto up_qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
+ auto dn_qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
+ auto rem = std::fmod(up_qvalue, 2.0);
+ qvalue = (rem == 0.0) ? up_qvalue : dn_qvalue;
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_INFINITY)
+ {
+ auto abs_qvalue = std::fabs(qvalue);
+ auto abs_qvalue_toward_inf = std::ceil(abs_qvalue);
+ qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
+ : abs_qvalue_toward_inf;
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_ZERO)
+ {
+ auto abs_qvalue = std::fabs(qvalue);
+ auto abs_qvalue_toward_zero = std::floor(abs_qvalue);
+ qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
+ : abs_qvalue_toward_zero;
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_UP)
+ {
+ qvalue = std::ceil(qvalue);
+ }
+ else if (round_mode == op::Quantize::RoundMode::ROUND_DOWN)
+ {
+ qvalue = std::floor(qvalue);
+ }
+
+ // apply zero_point
+ qvalue += zero_point[scale_zero_point_transform.index(scale_zero_point_coord)];
+
+ // clamp
+ qvalue = std::max<REAL>(qvalue,
+ static_cast<REAL>(std::numeric_limits<QUANT>::min()));
+ qvalue = std::min<REAL>(qvalue,
+ static_cast<REAL>(std::numeric_limits<QUANT>::max()));
+
+ // cast
+ output[input_transform.index(input_coord)] = static_cast<QUANT>(qvalue);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <type_traits>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/bfloat16.hpp"
+#include "ngraph/type/float16.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // Return type is `void`, only enabled if `T` is a built-in FP
+ // type, or nGraph's `bfloat16` or `float16` type.
+ template <typename T>
+ typename std::enable_if<std::is_floating_point<T>::value ||
+ std::is_same<T, bfloat16>::value ||
+ std::is_same<T, float16>::value>::type
+ range(const T* start, const T* step, const Shape& out_shape, T* out)
+ {
+ for (size_t i = 0; i < shape_size(out_shape); i++)
+ {
+ out[i] = *start + (static_cast<T>(i) * (*step));
+ }
+ }
+
+ // Return type is `void`, only enabled if `T` is `is_integral`.
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value>::type
+ range(const T* start, const T* step, const Shape& out_shape, T* out)
+ {
+ T val = *start;
+
+ for (size_t i = 0; i < shape_size(out_shape); i++)
+ {
+ out[i] = val;
+ val += *step;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void reduce_l1(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 0;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ size_t output_index = output_transform.index(output_coord);
+
+ out[output_index] =
+ out[output_index] + abs(arg[input_transform.index(input_coord)]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void reduce_l2(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 0;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ size_t output_index = output_transform.index(output_coord);
+
+ out[output_index] = out[output_index] +
+ arg[input_transform.index(input_coord)] *
+ arg[input_transform.index(input_coord)];
+ }
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] =
+ sqrt(out[output_transform.index(output_coord)]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void relu(const T* arg, T* out, size_t count)
+ {
+ T zero = 0;
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i] > zero ? arg[i] : zero;
+ }
+ }
+ template <typename T>
+ void relu_backprop(const T* arg, const T* delta_arg, T* out, size_t count)
+ {
+ T zero = 0;
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i] > zero ? delta_arg[i] : zero;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void replace_slice(const T* arg0, // replacement context
+ const T* arg1, // replacement value
+ T* out,
+ const Shape& arg1_shape,
+ const Coordinate& lower_bounds,
+ const Coordinate& upper_bounds,
+ const Strides& strides,
+ const Shape& out_shape)
+ {
+ // Step 1: Copy the entire replacement context to the output.
+ CoordinateTransform copy_transform(out_shape);
+
+ for (Coordinate copy_coord : copy_transform)
+ {
+ out[copy_transform.index(copy_coord)] = arg0[copy_transform.index(copy_coord)];
+ }
+
+ // Step 2: Overwrite the slice for replacement.
+ CoordinateTransform input_transform(arg1_shape);
+ CoordinateTransform output_transform(
+ out_shape, lower_bounds, upper_bounds, strides);
+
+ NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
+ shape_size(output_transform.get_target_shape()));
+
+ CoordinateTransform::Iterator output_it = output_transform.begin();
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ const Coordinate& output_coord = *output_it;
+
+ out[output_transform.index(output_coord)] =
+ arg1[input_transform.index(input_coord)];
+
+ ++output_it;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/element_type.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void reshape(const char* arg,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <numeric>
+#include <vector>
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void result(const T* arg, T* out, size_t count)
+ {
+ memcpy(out, arg, sizeof(T) * count);
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void reverse(const char* arg,
+ char* out,
+ const Shape& arg_shape,
+ const Shape& out_shape,
+ const AxisSet& reversed_axes,
+ size_t elem_size);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T, typename U>
+ void reverse_sequence(const T* arg,
+ T* out,
+ const Shape& arg_shape,
+ size_t batch_axis,
+ size_t sequence_axis,
+ const U* sequence_lengths)
+ {
+ CoordinateTransform input_transform(arg_shape);
+ for (const Coordinate& in_coord : input_transform)
+ {
+ size_t batch_index = in_coord[batch_axis];
+ auto orig_seq_index = static_cast<size_t>(sequence_lengths[batch_index]);
+
+ if (orig_seq_index > arg_shape.at(sequence_axis))
+ {
+ throw ngraph_error(
+ "One of the elements of sequence lengths is greater than sequence axis "
+ "dimension");
+ }
+
+ if (orig_seq_index == 0)
+ {
+ orig_seq_index = 1;
+ }
+
+ size_t sequence_index = in_coord[sequence_axis] < orig_seq_index
+ ? orig_seq_index - in_coord[sequence_axis] - 1
+ : in_coord[sequence_axis];
+
+ // make a copy of in_coord and update sequence_index
+ Coordinate out_coord = in_coord;
+ out_coord[sequence_axis] = sequence_index;
+ out[input_transform.index(out_coord)] = arg[input_transform.index(in_coord)];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ T round_to_nearest_even(const T arg)
+ {
+ const auto floor_arg = std::floor(arg);
+ const auto diff = arg - floor_arg;
+ if (diff < 0.5f || (diff == 0.5f && static_cast<int>(floor_arg) % 2 == 0))
+ {
+ return floor_arg;
+ }
+ else
+ {
+ return floor_arg + 1.0f;
+ }
+ }
+
+ template <typename T>
+ void round(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; ++i)
+ {
+ out[i] = round_to_nearest_even(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstring>
+
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename DataType, typename IndicesType>
+ void scatter_elem_update(const DataType* input_data,
+ const IndicesType* indices,
+ const DataType* updates,
+ const int64_t& axis,
+ DataType* out_buf,
+ const Shape& data_shape,
+ const Shape& indices_shape)
+ {
+ // Copy inputs to out
+ std::memcpy(out_buf, input_data, sizeof(DataType) * shape_size(data_shape));
+
+ // 3D example
+ // output[indices[i][j][k]][j][k] = updates[i][j][k] if axis = 0,
+ // output[i][indices[i][j][k]][k] = updates[i][j][k] if axis = 1,
+ // output[i][j][indices[i][j][k]] = updates[i][j][k] if axis = 2
+
+ CoordinateTransform indices_transform{indices_shape};
+ CoordinateTransform data_transform{data_shape};
+
+ for (const Coordinate& indices_cord : indices_transform)
+ {
+ const size_t indices_idx = indices_transform.index(indices_cord);
+ Coordinate out_cord(indices_cord);
+ out_cord.at(axis) = indices[indices_idx];
+ NGRAPH_CHECK(data_transform.has_source_coordinate(out_cord),
+ "Provided index coordinates are out of input data bounds: ",
+ out_cord,
+ ".");
+ out_buf[data_transform.index(out_cord)] = updates[indices_idx];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape.hpp"
+
+using namespace ngraph;
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename dataType, typename indicesType>
+ void scatterNdUpdate(const dataType* inputData,
+ const indicesType* indices,
+ const dataType* updates,
+ dataType* outBuf,
+ const Shape& dataShape,
+ const Shape& indicesShape,
+ const Shape& updatesShape)
+ {
+ size_t numSlices = 1;
+ size_t sliceSize = 1;
+ for (size_t i = 0; i < indicesShape.size() - 1; i++)
+ {
+ numSlices *= indicesShape[i];
+ }
+ for (size_t i = indicesShape.size() - 1; i < updatesShape.size(); i++)
+ {
+ sliceSize *= updatesShape[i];
+ }
+
+ const size_t k = indicesShape.back();
+ std::memcpy(outBuf, inputData, sizeof(dataType) * shape_size(dataShape));
+ CoordinateTransform dataTransform{dataShape};
+
+ for (size_t i = 0; i < numSlices; i++)
+ {
+ Coordinate coord;
+ for (size_t j = 0; j < k; j++)
+ {
+ coord.push_back(indices[i * k + j]);
+ }
+ for (size_t j = k; j < dataShape.size(); j++)
+ {
+ coord.push_back(0);
+ }
+
+ const size_t startDataIdx = dataTransform.index(coord);
+ for (size_t j = 0; j < sliceSize; j++)
+ {
+ outBuf[startDataIdx + j] = updates[i * sliceSize + j];
+ }
+ }
+ }
+ } // namespace reference
+ } // namespace runtime
+} // namespace ngraph
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <string>
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape.hpp"
+
+using namespace ngraph;
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename dataType, typename indicesType, typename axisType>
+ void scatterUpdate(const dataType* inputData,
+ const indicesType* indices,
+ const dataType* updates,
+ const axisType* _axis,
+ dataType* outBuf,
+ const Shape& dataShape,
+ const Shape& indicesShape,
+ const Shape& updatesShape)
+ {
+ int rank = static_cast<int>(dataShape.size());
+ if (_axis[0] < -rank || _axis[0] > rank - 1)
+ {
+ std::string error =
+ std::string("ScatterUpdate layer has out of bounds axis value: ") +
+ std::to_string(_axis[0]);
+ throw ngraph_error(error);
+ }
+ size_t axis = _axis[0] < 0 ? _axis[0] + rank : _axis[0];
+ CoordinateTransform indicesTransform{indicesShape};
+
+ Shape dataShapeIter = dataShape;
+ dataShapeIter.erase(dataShapeIter.begin() + axis);
+ CoordinateTransform dataTransfIter{dataShapeIter};
+
+ CoordinateTransform updateTransform{updatesShape};
+ CoordinateTransform dataTransform{dataShape};
+
+ std::memcpy(outBuf, inputData, sizeof(dataType) * shape_size(dataShape));
+
+ for (const Coordinate& indicesCoordIt : indicesTransform)
+ {
+ const size_t indicesIdx = indicesTransform.index(indicesCoordIt);
+
+ if (indices[indicesIdx] < 0)
+ {
+ std::string error =
+ std::string("ScatterUpdate layer has negative index value: ") +
+ std::to_string(indices[indicesIdx]);
+ throw ngraph_error(error);
+ }
+ const size_t idx = static_cast<size_t>(indices[indicesIdx]);
+ if (dataShape[axis] <= idx)
+ {
+ std::string error =
+ std::string("ScatterUpdate layer has out of bounds coordinate: ") +
+ std::to_string(idx) + " on 'data' input on " + std::to_string(axis) +
+ "th axis";
+ throw ngraph_error(error);
+ }
+
+ for (const Coordinate& dataCoordIt : dataTransfIter)
+ {
+ Coordinate dataCoord = dataCoordIt;
+ dataCoord.insert(dataCoord.begin() + axis, idx);
+ const size_t startIndices = dataTransform.index(dataCoord);
+
+ auto updCoord = dataCoordIt;
+ updCoord.insert(
+ updCoord.begin() + axis, indicesCoordIt.begin(), indicesCoordIt.end());
+ const size_t startUpd = updateTransform.index(updCoord);
+ outBuf[startIndices] = updates[startUpd];
+ }
+ }
+ }
+ } // namespace reference
+ } // namespace runtime
+} // namespace ngraph
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+#include <iostream>
+
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void select(const char* arg0,
+ const T* arg1,
+ const T* arg2,
+ T* out,
+ size_t count) // TODO: using char for bool, is this right?
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] ? arg1[i] : arg2[i];
+ }
+ }
+
+ template <typename T>
+ void select(const char* arg0,
+ const T* arg1,
+ const T* arg2,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const Shape& arg2_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_select(
+ arg0,
+ arg1,
+ arg2,
+ out,
+ arg0_shape,
+ arg1_shape,
+ arg2_shape,
+ broadcast_spec,
+ [](char s, T x, T y) -> T { return static_cast<T>(s ? x : y); });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ inline void shape_of(const Shape& arg_shape, T* out)
+ {
+ for (size_t i = 0; i < arg_shape.size(); i++)
+ {
+ out[i] = static_cast<T>(arg_shape[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sigmoid(const T* arg, T* out, size_t count)
+ {
+ T exp_value;
+ for (size_t i = 0; i < count; i++)
+ {
+ exp_value = std::exp(-arg[i]);
+ out[i] = 1 / (1 + exp_value);
+ }
+ }
+
+ template <typename T>
+ void sigmoid_backprop(const T* arg, const T* delta_arg, T* out, size_t count)
+ {
+ T exp_value;
+ T func_x;
+ for (size_t i = 0; i < count; i++)
+ {
+ exp_value = std::exp(-arg[i]);
+ func_x = 1 / (1 + exp_value);
+ out[i] = delta_arg[i] * func_x * (1 - func_x);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sign(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = (arg[i] < T(0) ? T(-1) : (arg[i] > T(0) ? T(1) : T(0)));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sin(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::sin(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sinh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::sinh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/element_type.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void slice(const char* arg,
+ char* out,
+ const Shape& arg_shape,
+ const Coordinate& lower_bounds,
+ const Coordinate& upper_bounds,
+ const Strides& strides,
+ const Shape& out_shape,
+ size_t elem_size);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/reference/max.hpp"
+#include "ngraph/runtime/reference/sum.hpp"
+#include "ngraph/shape_util.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void softmax(const T* arg, T* out, const Shape& shape, const AxisSet& axes)
+ {
+ auto temp_shape = reduce(shape, axes, true);
+ auto temp_elements = shape_size(temp_shape);
+ auto temp_ptr = new T[temp_elements];
+
+ max(arg, temp_ptr, shape, axes, true);
+
+ CoordinateTransform transform(shape);
+ CoordinateTransform temp_transform(temp_shape);
+ for (const Coordinate& coord : transform)
+ {
+ Coordinate temp_coord = reduce(coord, axes, true);
+ out[transform.index(coord)] = std::exp(
+ arg[transform.index(coord)] - temp_ptr[temp_transform.index(temp_coord)]);
+ }
+
+ sum(out, temp_ptr, shape, axes, true);
+
+ for (const Coordinate& coord : transform)
+ {
+ Coordinate temp_coord = reduce(coord, axes, true);
+ out[transform.index(coord)] /= temp_ptr[temp_transform.index(temp_coord)];
+ }
+
+ delete[] temp_ptr;
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void sqrt(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::sqrt(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/check.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/runtime/host_tensor.hpp"
+#include "ngraph/runtime/opt_kernel/reshape.hpp"
+#include "ngraph/runtime/reference/reverse.hpp"
+#include "ngraph/runtime/reference/slice.hpp"
+#include "ngraph/slice_plan.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void strided_slice(const char* arg,
+ char* out,
+ const Shape& arg_shape,
+ const SlicePlan& sp,
+ size_t elem_type);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void subtract(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg0[i] - arg1[i];
+ }
+ }
+
+ template <typename T>
+ void subtract(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return x - y;
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/shape_util.hpp"
+#include "ngraph/type/bfloat16.hpp"
+#include "ngraph/type/float16.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // Windows doesn't seem to like it if we directly use std::isfinite on integer types,
+ // so we will roll our own thing here.
+ template <typename T>
+ typename std::enable_if<std::is_floating_point<T>::value, bool>::type is_finite(T x)
+ {
+ return std::isfinite(x);
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_same<T, bfloat16>::value ||
+ std::is_same<T, float16>::value,
+ bool>::type
+ is_finite(T x)
+ {
+ return std::isfinite(static_cast<float>(x));
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value, bool>::type is_finite(T /* x */)
+ {
+ return true;
+ }
+
+ template <typename T>
+ void sum(const T* arg,
+ T* out,
+ const Shape& in_shape,
+ const AxisSet& reduction_axes,
+ bool keep_dims)
+ {
+ auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
+ CoordinateTransform output_transform(out_shape);
+ std::vector<T> cs(shape_size(out_shape));
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ out[output_transform.index(output_coord)] = 0;
+ cs[output_transform.index(output_coord)] = 0;
+ }
+
+ CoordinateTransform input_transform(in_shape);
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
+
+ T x = arg[input_transform.index(input_coord)];
+ T& z = out[output_transform.index(output_coord)];
+
+ if (is_finite(x) && is_finite(z))
+ {
+ T& c = cs[output_transform.index(output_coord)];
+ T t = z + (x - c);
+ c = (t - z) - (x - c);
+ z = t;
+ }
+ else
+ {
+ z = z + x;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void swish(const T* arg, const T* beta, T* out, size_t count)
+ {
+ T beta_value = static_cast<T>(1.0);
+ if (beta != nullptr)
+ {
+ beta_value = beta[0];
+ }
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = arg[i] / (1.0 + std::exp(-arg[i] * beta_value));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void tan(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::tan(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+#include <cstddef>
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void tanh(const T* arg, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = std::tanh(arg[i]);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cmath>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/element_type.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void tile(const char* arg,
+ char* out,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ size_t elem_size);
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <numeric>
+
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/op/topk.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ // Had to split out these two functions. They used to be lambda expressions but
+ // MSVC had difficulty compiling. This way is more explicit.
+ template <typename T, typename U>
+ inline bool compare_max(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
+ {
+// this is intentional to be able to compare floats directly
+// without using relative or absolute tolerance
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ if (std::get<0>(a) == std::get<0>(b))
+ {
+ return std::get<1>(a) < std::get<1>(b);
+ }
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+ return a > b;
+ }
+
+ template <typename T, typename U>
+ inline bool compare_min(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
+ {
+ return a < b;
+ }
+
+ template <typename T, typename U>
+ inline bool sort_indices_descending(const std::tuple<T, U>& a,
+ const std::tuple<T, U>& b)
+ {
+ return std::get<1>(a) < std::get<1>(b);
+ }
+
+ template <typename T, typename U>
+ inline bool sort_indices_ascending(const std::tuple<T, U>& a, const std::tuple<T, U>& b)
+ {
+ return std::get<1>(a) > std::get<1>(b);
+ }
+
+ template <typename T, typename U>
+ void topk(const T* arg,
+ U* out_indices,
+ T* out_values,
+ const Shape& in_shape,
+ const Shape& out_shape,
+ size_t axis,
+ size_t k,
+ bool compute_max,
+ op::TopK::SortType sort = op::TopK::SortType::NONE)
+ {
+ using namespace std;
+ // reorder source axis visit order and make "axis" inner most
+ size_t ndim = static_cast<size_t>(in_shape.size());
+ Coordinate start_corner(ndim, 0);
+ Coordinate end_corner(in_shape);
+ end_corner[axis] = 1;
+ Strides strides(ndim, 1);
+ AxisVector axis_order(ndim);
+ iota(axis_order.begin(), axis_order.end(), 0);
+ axis_order.erase(axis_order.begin() + axis);
+ axis_order.push_back(axis);
+ // Create CoordinateTransforms that visits only the first element along "axis"
+ CoordinateTransform input_transform(
+ in_shape, start_corner, end_corner, strides, axis_order);
+ CoordinateTransform output_transform(
+ out_shape, start_corner, end_corner, strides, axis_order);
+ // Create temp vector for sorting.
+ vector<tuple<T, U>> workspace(in_shape[axis]);
+ vector<size_t> in_strides = ngraph::row_major_strides(in_shape);
+ vector<size_t> out_strides = ngraph::row_major_strides(out_shape);
+ auto in_axis_stride = in_strides[axis];
+ auto out_axis_stride = out_strides[axis];
+ for (const Coordinate& coord : input_transform)
+ {
+ auto arg_index = input_transform.index(coord);
+ auto out_index = output_transform.index(coord);
+ // Fill the temp vector
+ U i = 0;
+ for (tuple<T, U>& entry : workspace)
+ {
+ get<0>(entry) = arg[arg_index];
+ get<1>(entry) = i;
+ arg_index += in_axis_stride;
+ i++;
+ }
+ // Sort the temp vector
+ if (compute_max)
+ {
+ nth_element(workspace.begin(),
+ workspace.begin() + k,
+ workspace.end(),
+ compare_max<T, U>);
+ }
+ else
+ {
+ nth_element(workspace.begin(),
+ workspace.begin() + k,
+ workspace.end(),
+ compare_min<T, U>);
+ }
+ // Write temp vector to output
+ if (compute_max)
+ {
+ switch (sort)
+ {
+ case op::TopK::SortType::NONE: break;
+ case op::TopK::SortType::SORT_INDICES:
+ std::sort(workspace.begin(),
+ workspace.begin() + k,
+ sort_indices_descending<T, U>);
+ break;
+ case op::TopK::SortType::SORT_VALUES:
+ std::sort(workspace.begin(), workspace.begin() + k, compare_max<T, U>);
+ break;
+ }
+ }
+ else
+ {
+ switch (sort)
+ {
+ case op::TopK::SortType::NONE: break;
+ case op::TopK::SortType::SORT_INDICES:
+ std::sort(workspace.begin(),
+ workspace.begin() + k,
+ sort_indices_ascending<T, U>);
+ break;
+ case op::TopK::SortType::SORT_VALUES:
+ std::sort(workspace.begin(), workspace.begin() + k, compare_min<T, U>);
+ break;
+ }
+ }
+ for (size_t j = 0; j < k; j++)
+ {
+ tuple<T, U> entry = workspace[j];
+ out_values[out_index] = get<0>(entry);
+ out_indices[out_index] = get<1>(entry);
+ out_index += out_axis_stride;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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.
+//*****************************************************************************
+
+#pragma once
+
+#include <cstddef>
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/runtime/reference/autobroadcast_binop.hpp"
+#include "ngraph/shape.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ template <typename T>
+ void logical_xor(const T* arg0, const T* arg1, T* out, size_t count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ out[i] = static_cast<T>((arg0[i] || arg1[i]) && !(arg0[i] && arg1[i]));
+ }
+ }
+
+ template <typename T>
+ void logical_xor(const T* arg0,
+ const T* arg1,
+ T* out,
+ const Shape& arg0_shape,
+ const Shape& arg1_shape,
+ const op::AutoBroadcastSpec& broadcast_spec)
+ {
+ autobroadcast_binop(
+ arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T {
+ return static_cast<T>((x || y) && !(x && y));
+ });
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <algorithm>
+#include <cstdio>
+#include <iostream>
+#include <numeric>
+#include <sstream>
+#include <vector>
+
+#include "ngraph/axis_vector.hpp"
+#include "ngraph/coordinate_diff.hpp"
+#include "ngraph/coordinate_transform.hpp"
+#include "ngraph/except.hpp"
+#include "ngraph/shape.hpp"
+#include "ngraph/strides.hpp"
+#include "ngraph/util.hpp"
+
+using namespace ngraph;
+
+namespace
+{
+ Strides default_strides(size_t n_axes) { return Strides(n_axes, 1); }
+ CoordinateDiff default_padding(size_t n_axes) { return CoordinateDiff(n_axes, 0); }
+ AxisVector default_axis_order(size_t n_axes)
+ {
+ AxisVector result(n_axes);
+ std::iota(result.begin(), result.end(), 0);
+ return result;
+ }
+
+ Coordinate default_source_start_corner(size_t n_axes) { return Coordinate(n_axes, 0); }
+ Coordinate default_source_end_corner(const Shape& source_shape) { return source_shape; }
+}
+
+CoordinateTransformBasic::CoordinateTransformBasic(const Shape& source_shape)
+ : m_source_shape(source_shape)
+{
+}
+
+// Compute the index of a source-space coordinate in the buffer.
+size_t CoordinateTransformBasic::index(const Coordinate& c) const noexcept
+{
+ size_t index = 0;
+ size_t stride = 1;
+ size_t const padding = c.size() - m_source_shape.size();
+
+ for (size_t axis = m_source_shape.size(); axis-- > 0;)
+ {
+ if (m_source_shape[axis] > 1)
+ {
+ index += c[axis + padding] * stride;
+ stride *= m_source_shape[axis];
+ }
+ }
+
+ return index;
+}
+
+CoordinateIterator CoordinateTransformBasic::begin() const noexcept
+{
+ return CoordinateIterator(m_source_shape);
+}
+
+const CoordinateIterator& CoordinateTransformBasic::end() const noexcept
+{
+ return CoordinateIterator::end();
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order,
+ const CoordinateDiff& target_padding_below,
+ const CoordinateDiff& target_padding_above,
+ const Strides& target_dilation_strides)
+ : CoordinateTransformBasic(source_shape)
+ , m_source_start_corner(source_start_corner)
+ , m_source_end_corner(source_end_corner)
+ , m_source_strides(source_strides)
+ , m_source_axis_order(source_axis_order)
+ , m_target_padding_below(target_padding_below)
+ , m_target_padding_above(target_padding_above)
+ , m_target_dilation_strides(target_dilation_strides)
+{
+ m_n_axes = source_shape.size();
+
+ if (m_n_axes != source_start_corner.size())
+ {
+ throw std::domain_error(
+ "Source start corner does not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != source_end_corner.size())
+ {
+ throw std::domain_error(
+ "Source end corner does not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != source_strides.size())
+ {
+ throw std::domain_error(
+ "Source strides do not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != source_axis_order.size())
+ {
+ // Note: this check is NOT redundant with the is_permutation check below, though you might
+ // think it is. If the lengths don't match then is_permutation won't catch that; it'll
+ // either stop short or walk off the end of source_axis_order.
+ throw std::domain_error(
+ "Source axis order does not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != target_padding_below.size())
+ {
+ throw std::domain_error(
+ "Padding-below shape does not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != target_padding_above.size())
+ {
+ throw std::domain_error(
+ "Padding-above shape does not have the same number of axes as the source space shape");
+ }
+ if (m_n_axes != target_dilation_strides.size())
+ {
+ throw std::domain_error(
+ "Target dilation strides do not have the same number of axes as the source shape");
+ }
+
+ AxisVector all_axes(m_n_axes);
+ for (size_t i = 0; i < all_axes.size(); i++)
+ {
+ all_axes[i] = i;
+ }
+
+ if (!std::is_permutation(all_axes.begin(), all_axes.end(), source_axis_order.begin()))
+ {
+ throw std::domain_error(
+ "Source axis order is not a permutation of {0,...,n-1} where n is the number of axes "
+ "in the source space shape");
+ }
+
+ for (size_t i = 0; i < m_n_axes; i++)
+ {
+ if (target_dilation_strides[i] == 0)
+ {
+ std::stringstream ss;
+
+ ss << "The target dilation stride is 0 at axis " << i;
+ throw std::domain_error(ss.str());
+ }
+ }
+
+ std::vector<std::ptrdiff_t> padded_upper_bounds;
+
+ for (size_t i = 0; i < m_n_axes; i++)
+ {
+ std::ptrdiff_t padded_upper_bound =
+ subtract_or_zero(source_shape[i], size_t(1)) * target_dilation_strides[i] + 1 +
+ target_padding_below[i] + target_padding_above[i];
+
+ if (padded_upper_bound < 0)
+ {
+ std::stringstream ss;
+
+ ss << "The end corner is out of bounds at axis " << i;
+ throw std::domain_error(ss.str());
+ }
+
+ padded_upper_bounds.push_back(padded_upper_bound);
+ }
+
+ for (size_t i = 0; i < m_n_axes; i++)
+ {
+ if (static_cast<int64_t>(source_start_corner[i]) >= padded_upper_bounds[i] &&
+ source_start_corner[i] != source_shape[i])
+ {
+ std::stringstream ss;
+
+ ss << "The start corner is out of bounds at axis " << i;
+ throw std::domain_error(ss.str());
+ }
+
+ if (static_cast<int64_t>(source_end_corner[i]) > padded_upper_bounds[i])
+ {
+ std::stringstream ss;
+
+ ss << "The end corner is out of bounds at axis " << i;
+ throw std::domain_error(ss.str());
+ }
+ }
+
+ for (size_t i = 0; i < m_n_axes; i++)
+ {
+ if (source_strides[i] == 0)
+ {
+ std::stringstream ss;
+
+ ss << "The source stride is 0 at axis " << i;
+ throw std::domain_error(ss.str());
+ }
+ }
+
+ for (size_t axis = 0; axis < m_n_axes; axis++)
+ {
+ m_target_shape.push_back(ceil_div(source_end_corner[source_axis_order[axis]] -
+ source_start_corner[source_axis_order[axis]],
+ source_strides[source_axis_order[axis]]));
+ }
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order,
+ const CoordinateDiff& target_padding_below,
+ const CoordinateDiff& target_padding_above)
+ : CoordinateTransform(source_shape,
+ source_start_corner,
+ source_end_corner,
+ source_strides,
+ source_axis_order,
+ target_padding_below,
+ target_padding_above,
+ default_strides(source_shape.size()))
+{
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides,
+ const AxisVector& source_axis_order)
+ : CoordinateTransform(source_shape,
+ source_start_corner,
+ source_end_corner,
+ source_strides,
+ source_axis_order,
+ default_padding(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_strides(source_shape.size()))
+{
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner,
+ const Strides& source_strides)
+ : CoordinateTransform(source_shape,
+ source_start_corner,
+ source_end_corner,
+ source_strides,
+ default_axis_order(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_strides(source_shape.size()))
+{
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape,
+ const Coordinate& source_start_corner,
+ const Coordinate& source_end_corner)
+ : CoordinateTransform(source_shape,
+ source_start_corner,
+ source_end_corner,
+ default_strides(source_shape.size()),
+ default_axis_order(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_strides(source_shape.size()))
+{
+}
+
+CoordinateTransform::CoordinateTransform(const Shape& source_shape)
+ : CoordinateTransform(source_shape,
+ default_source_start_corner(source_shape.size()),
+ default_source_end_corner(source_shape),
+ default_strides(source_shape.size()),
+ default_axis_order(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_padding(source_shape.size()),
+ default_strides(source_shape.size()))
+{
+}
+
+// Compute the index of a target-space coordinate in thebuffer.
+size_t CoordinateTransform::index(const Coordinate& c) const
+{
+ return CoordinateTransformBasic::index(to_source_coordinate(c));
+}
+
+// Convert a target-space coordinate to a source-space coordinate.
+Coordinate CoordinateTransform::to_source_coordinate(const Coordinate& c_target) const
+{
+ if (c_target.size() != m_n_axes)
+ {
+ throw std::domain_error(
+ "Target coordinate rank does not match the coordinate transform rank");
+ }
+
+ Coordinate c_source(c_target.size());
+
+ for (size_t target_axis = 0; target_axis < m_n_axes; target_axis++)
+ {
+ size_t source_axis = m_source_axis_order[target_axis];
+
+ size_t target_pos = c_target[target_axis];
+ size_t pos_destrided = target_pos * m_source_strides[source_axis];
+ size_t pos_deshifted = pos_destrided + m_source_start_corner[source_axis];
+ size_t pos_depadded = pos_deshifted - m_target_padding_below[target_axis];
+ size_t pos_dedilated = pos_depadded / m_target_dilation_strides[target_axis];
+ c_source[source_axis] = pos_dedilated;
+ }
+
+ return c_source;
+}
+
+// A point in the target space is considered not to have a source coordinate if it was inserted due
+// to padding or dilation, or if it is out of the bounds of the target space.
+bool CoordinateTransform::has_source_coordinate(const Coordinate& c_target) const
+{
+ if (c_target.size() != m_n_axes)
+ {
+ throw std::domain_error(
+ "Target coordinate rank does not match the coordinate transform rank");
+ }
+
+ for (size_t target_axis = 0; target_axis < m_n_axes; target_axis++)
+ {
+ // Is this coordinate out of bounds of the target space?
+ if (c_target[target_axis] >= m_target_shape[target_axis])
+ {
+ return false;
+ }
+
+ // The rest of this is a replay of the corresponding logic in `to_source_coordinate`, with
+ // bounds and divisibility checking.
+ std::ptrdiff_t source_axis = m_source_axis_order[target_axis];
+
+ std::ptrdiff_t target_pos = c_target[target_axis];
+ std::ptrdiff_t pos_destrided = target_pos * m_source_strides[source_axis];
+ std::ptrdiff_t pos_deshifted = pos_destrided + m_source_start_corner[source_axis];
+
+ // If we are in the below-padding or the above-padding.
+ if (pos_deshifted < m_target_padding_below[target_axis])
+ {
+ return false;
+ }
+ std::ptrdiff_t pos_depadded = pos_deshifted - m_target_padding_below[target_axis];
+
+ // If we are in the above-padding, we have no source coordinate.
+ if (m_source_shape[source_axis] == 0 ||
+ (pos_depadded >= ((static_cast<int64_t>(m_source_shape[source_axis]) - 1) *
+ static_cast<int64_t>(m_target_dilation_strides[target_axis])) +
+ 1))
+ {
+ return false;
+ }
+
+ // If we are in a dilation gap, we have no source coordinate.
+ if (pos_depadded % m_target_dilation_strides[target_axis] != 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const Shape& CoordinateTransform::get_source_shape() const noexcept
+{
+ return m_source_shape;
+}
+
+const Shape& CoordinateTransform::get_target_shape() const noexcept
+{
+ return m_target_shape;
+}
+
+const Coordinate& CoordinateTransform::get_source_start_corner() const noexcept
+{
+ return m_source_start_corner;
+}
+
+const Coordinate& CoordinateTransform::get_source_end_corner() const noexcept
+{
+ return m_source_end_corner;
+}
+
+const Strides& CoordinateTransform::get_source_strides() const noexcept
+{
+ return m_source_strides;
+}
+
+const AxisVector& CoordinateTransform::get_source_axis_order() const noexcept
+{
+ return m_source_axis_order;
+}
+
+const Strides& CoordinateTransform::get_target_dilation_strides() const noexcept
+{
+ return m_target_dilation_strides;
+}
+
+CoordinateIterator CoordinateTransform::begin() const noexcept
+{
+ return CoordinateIterator(m_target_shape);
+}
+
+const CoordinateIterator& CoordinateTransform::end() const noexcept
+{
+ return CoordinateIterator::end();
+}
+
+// The "is_end" parameter is true if we want the "end()" iterator.
+CoordinateIterator::CoordinateIterator(const Shape& target_shape, bool is_end)
+ : m_target_shape(target_shape)
+ , m_coordinate(target_shape.size(), 0)
+{
+ // The case where we have a zero-length axis is a bit special, in that
+ // the iterator always starts out of bounds.
+ bool const empty = std::find(target_shape.begin(), target_shape.end(), 0) != target_shape.end();
+
+ m_oob = is_end || empty;
+}
+
+void CoordinateIterator::operator++()
+{
+ advance(m_target_shape.size() - 1);
+}
+
+size_t CoordinateIterator::advance(size_t axis) noexcept
+{
+ m_oob |= m_target_shape.empty();
+
+ if (m_oob)
+ return m_target_shape.size();
+
+ bool carry_out = false;
+
+ // Increment the target coordinate.
+ do
+ {
+ m_coordinate[axis]++;
+
+ if (m_coordinate[axis] < m_target_shape[axis])
+ {
+ // No carry-out, so we are done.
+ return axis;
+ }
+ else
+ {
+ m_coordinate[axis] = 0;
+ carry_out = true;
+ }
+ } while (axis-- > 0);
+
+ // If we are still here there was carry-out from the most significant axis. We are now out of
+ // bounds.
+ m_oob = true;
+
+ return m_target_shape.size();
+}
+
+CoordinateIterator CoordinateIterator::operator++(int)
+{
+ CoordinateIterator temp = *this;
+ ++(*this);
+ return temp;
+}
+
+void CoordinateIterator::operator+=(size_t n)
+{
+ for (size_t i = 0; i < n; i++)
+ {
+ ++(*this);
+ }
+}
+
+const Coordinate& CoordinateIterator::operator*() const noexcept
+{
+ return m_coordinate;
+}
+
+bool CoordinateIterator::operator!=(const CoordinateIterator& it) const noexcept
+{
+ return !(*this == it);
+}
+
+bool CoordinateIterator::operator==(const CoordinateIterator& it) const noexcept
+{
+ if (it.m_oob)
+ {
+ // Out-of-bounds iterators are always equal; in other words, an iterator is always equal to
+ // end() even if the internally stored coordinates are different.
+
+ // If one iterator is out of bounds and the other is not, they are unequal even if their
+ // target coordinates happen to match.
+ return m_oob;
+ }
+ else if (m_oob)
+ {
+ return false;
+ }
+
+ if (m_target_shape != it.m_target_shape)
+ {
+ return false;
+ }
+
+ // Check axis-wise if the iterators are on the same target coordinate.
+ for (size_t axis = 0; axis < m_target_shape.size(); axis++)
+ {
+ if (m_coordinate[axis] != it.m_coordinate[axis])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const CoordinateIterator& CoordinateIterator::end()
+{
+ static const CoordinateIterator it(Shape(), true);
+ return it;
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/opt_kernel/reshape.hpp"
+
+using namespace ngraph;
+
+namespace
+{
+ void reshape_in0(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ memcpy(out, in, elem_size);
+ }
+
+ void reshape_in1(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[1];
+ size_t in_index[1];
+ size_t* map_index[1];
+ for (size_t i = 0; i < 1; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ memcpy(out, in + *map_index[0] * elem_size, elem_size);
+ out += elem_size;
+ }
+ }
+
+ void reshape_in2(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[2];
+ size_t in_index[2];
+ size_t* map_index[2];
+ for (size_t i = 0; i < 2; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
+ {
+ // clang-format off
+ memcpy(out,
+ in + (*map_index[0] * in_shape[1] +
+ *map_index[1]) * elem_size,
+ elem_size);
+ out += elem_size;
+ // clang-format on
+ }
+ }
+ }
+
+ void reshape_in3(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[3];
+ size_t in_index[3];
+ size_t* map_index[3];
+ for (size_t i = 0; i < 3; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
+ {
+ for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
+ {
+ // clang-format off
+ memcpy(out,
+ in + (*map_index[0] * in_shape[1] * in_shape[2] +
+ *map_index[1] * in_shape[2] +
+ *map_index[2]) * elem_size,
+ elem_size);
+ out += elem_size;
+ // clang-format on
+ }
+ }
+ }
+ }
+
+ void reshape_in4(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[4];
+ size_t in_index[4];
+ size_t* map_index[4];
+ for (size_t i = 0; i < 4; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
+ {
+ for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
+ {
+ for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
+ {
+ // clang-format off
+ memcpy(out,
+ in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] +
+ *map_index[1] * in_shape[2] * in_shape[3] +
+ *map_index[2] * in_shape[3] +
+ *map_index[3]) * elem_size,
+ elem_size);
+ out += elem_size;
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+
+ void reshape_in5(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[5];
+ size_t in_index[5];
+ size_t* map_index[5];
+ for (size_t i = 0; i < 5; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
+ {
+ for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
+ {
+ for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
+ {
+ for (in_index[4] = 0; in_index[4] < size[4]; ++in_index[4])
+ {
+ // clang-format off
+ memcpy(out,
+ in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] * in_shape[4] +
+ *map_index[1] * in_shape[2] * in_shape[3] * in_shape[4] +
+ *map_index[2] * in_shape[3] * in_shape[4] +
+ *map_index[3] * in_shape[4] +
+ *map_index[4]) * elem_size,
+ elem_size);
+ out += elem_size;
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void reshape_in6(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ size_t size[6];
+ size_t in_index[6];
+ size_t* map_index[6];
+ for (size_t i = 0; i < 6; i++)
+ {
+ size[i] = in_shape[in_axis_order[i]];
+ map_index[in_axis_order[i]] = &in_index[i];
+ }
+ for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
+ {
+ for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
+ {
+ for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
+ {
+ for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
+ {
+ for (in_index[4] = 0; in_index[4] < size[4]; ++in_index[4])
+ {
+ for (in_index[5] = 0; in_index[5] < size[5]; ++in_index[5])
+ {
+ // clang-format off
+ memcpy(out,
+ in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] * in_shape[4] * in_shape[5] +
+ *map_index[1] * in_shape[2] * in_shape[3] * in_shape[4] * in_shape[5] +
+ *map_index[2] * in_shape[3] * in_shape[4] * in_shape[5] +
+ *map_index[3] * in_shape[4] * in_shape[5] +
+ *map_index[4] * in_shape[5] +
+ *map_index[5]) * elem_size,
+ elem_size);
+ out += elem_size;
+ // clang-format on
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+void runtime::opt_kernel::reshape(const char* in,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+{
+ switch (in_shape.size())
+ {
+ case 0: reshape_in0(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 1: reshape_in1(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 2: reshape_in2(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 3: reshape_in3(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 4: reshape_in4(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 5: reshape_in5(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ case 6: reshape_in6(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ default: reference::reshape(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <algorithm>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/eval_helpers.hpp"
+
+namespace ngraph
+{
+ namespace eval
+ {
+ AxisSet extract_reduction_axes(const HostTensorPtr& axes, const char* op_name)
+ {
+ const auto axes_count = axes->get_element_count();
+ const auto axes_buffer = axes->get_data_ptr<int64_t>();
+
+ const bool negative_axis_received = std::any_of(
+ axes_buffer, axes_buffer + axes_count, [](const int64_t axis) { return axis < 0; });
+
+ NGRAPH_CHECK(!negative_axis_received,
+ "Negative axis value received in the ",
+ op_name,
+ " evaluation. This case is not supported.");
+
+ return AxisSet(std::vector<AxisSet::value_type>(axes_buffer, axes_buffer + axes_count));
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/reshape.hpp"
+
+using namespace ngraph;
+
+void runtime::reference::reshape(const char* arg,
+ char* out,
+ const Shape& in_shape,
+ const AxisVector& in_axis_order,
+ const Shape& out_shape,
+ size_t elem_size)
+{
+ // Unfortunately we don't yet have a constructor for CoordinateTransform that lets
+ // us pass only source_space_shape
+ // and source_axis_order so we have to construct the defaults here.
+ Shape in_start_corner(in_shape.size(), 0); // (0,...0)
+ Strides in_strides(in_shape.size(), 1); // (1,...,1)
+
+ CoordinateTransform input_transform(
+ in_shape, in_start_corner, in_shape, in_strides, in_axis_order);
+ CoordinateTransform output_transform(out_shape);
+
+ NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
+ shape_size(output_transform.get_target_shape()));
+
+ CoordinateTransform::Iterator output_it = output_transform.begin();
+
+ for (const Coordinate& input_coord : input_transform)
+ {
+ const Coordinate& output_coord = *output_it;
+
+ memcpy(out + output_transform.index(output_coord) * elem_size,
+ arg + input_transform.index(input_coord) * elem_size,
+ elem_size);
+
+ ++output_it;
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/reverse.hpp"
+
+using namespace ngraph;
+
+void runtime::reference::reverse(const char* arg,
+ char* out,
+ const Shape& arg_shape,
+ const Shape& out_shape,
+ const AxisSet& reversed_axes,
+ size_t elem_size)
+{
+ // In fact arg_shape == out_shape, but we'll use both for stylistic consistency with
+ // other kernels.
+ CoordinateTransform arg_transform(arg_shape);
+ CoordinateTransform output_transform(out_shape);
+
+ for (Coordinate out_coord : output_transform)
+ {
+ Coordinate arg_coord = out_coord;
+
+ for (size_t i = 0; i < arg_coord.size(); i++)
+ {
+ if (reversed_axes.count(i) != 0)
+ {
+ arg_coord[i] = arg_shape[i] - arg_coord[i] - 1;
+ }
+ }
+
+ memcpy(out + output_transform.index(out_coord) * elem_size,
+ arg + arg_transform.index(arg_coord) * elem_size,
+ elem_size);
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/slice.hpp"
+
+namespace ngraph
+{
+ namespace runtime
+ {
+ namespace reference
+ {
+ void slice(const char* arg,
+ char* out,
+ const Shape& arg_shape,
+ const Coordinate& lower_bounds,
+ const Coordinate& upper_bounds,
+ const Strides& strides,
+ const Shape& out_shape,
+ size_t elem_size)
+ {
+ CoordinateTransform input_transform(arg_shape, lower_bounds, upper_bounds, strides);
+ CoordinateTransform output_transform(out_shape);
+
+ CoordinateTransform::Iterator output_it = output_transform.begin();
+
+ NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
+ shape_size(output_transform.get_target_shape()));
+
+ for (const Coordinate& in_coord : input_transform)
+ {
+ const Coordinate& out_coord = *output_it;
+
+ memcpy(out + output_transform.index(out_coord) * elem_size,
+ arg + input_transform.index(in_coord) * elem_size,
+ elem_size);
+
+ ++output_it;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/aligned_buffer.hpp"
+#include "ngraph/runtime/reference/strided_slice.hpp"
+
+using namespace ngraph;
+
+void runtime::reference::strided_slice(
+ const char* arg, char* out, const Shape& arg_shape, const SlicePlan& sp, size_t elem_type)
+{
+ runtime::AlignedBuffer slice_out_buffer(shape_size(sp.reshape_in_shape) * elem_type);
+ slice(reinterpret_cast<const char*>(arg),
+ slice_out_buffer.get_ptr<char>(),
+ arg_shape,
+ Coordinate(sp.begins.begin(), sp.begins.end()),
+ Coordinate(sp.ends.begin(), sp.ends.end()),
+ Strides(sp.strides.begin(), sp.strides.end()),
+ sp.reshape_in_shape,
+ elem_type);
+
+ runtime::AlignedBuffer reshape_out_buffer(shape_size(sp.reshape_out_shape) * elem_type);
+ opt_kernel::reshape(slice_out_buffer.get_ptr<char>(),
+ reshape_out_buffer.get_ptr<char>(),
+ sp.reshape_in_shape,
+ get_default_order(sp.reshape_in_shape.size()),
+ sp.reshape_out_shape,
+ elem_type);
+
+ reverse(reshape_out_buffer.get_ptr<char>(),
+ out,
+ sp.reshape_out_shape,
+ sp.reshape_out_shape,
+ sp.reverse_axes,
+ elem_type);
+}
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// 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 <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/tile.hpp"
+
+using namespace ngraph;
+
+void runtime::reference::tile(
+ const char* arg, char* out, const Shape& in_shape, const Shape& out_shape, size_t elem_size)
+{
+ Shape in_shape_expanded(in_shape);
+ in_shape_expanded.insert(in_shape_expanded.begin(), out_shape.size() - in_shape.size(), 1);
+ CoordinateTransform input_transform(in_shape_expanded);
+ CoordinateTransform output_transform(out_shape);
+
+ for (const Coordinate& output_coord : output_transform)
+ {
+ std::vector<size_t> coord;
+ for (auto i = 0; i < output_coord.size(); i++)
+ {
+ auto val = output_coord[i] % in_shape_expanded[i];
+ coord.push_back(val);
+ }
+ Coordinate input_coord(coord);
+
+ memcpy(out + output_transform.index(output_coord) * elem_size,
+ arg + input_transform.index(input_coord) * elem_size,
+ elem_size);
+ }
+}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <algorithm>
-#include <cstdio>
-#include <iostream>
-#include <numeric>
-#include <sstream>
-#include <vector>
-
-#include "ngraph/axis_vector.hpp"
-#include "ngraph/coordinate_diff.hpp"
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/except.hpp"
-#include "ngraph/shape.hpp"
-#include "ngraph/strides.hpp"
-#include "ngraph/util.hpp"
-
-using namespace ngraph;
-
-namespace
-{
- Strides default_strides(size_t n_axes) { return Strides(n_axes, 1); }
- CoordinateDiff default_padding(size_t n_axes) { return CoordinateDiff(n_axes, 0); }
- AxisVector default_axis_order(size_t n_axes)
- {
- AxisVector result(n_axes);
- std::iota(result.begin(), result.end(), 0);
- return result;
- }
-
- Coordinate default_source_start_corner(size_t n_axes) { return Coordinate(n_axes, 0); }
- Coordinate default_source_end_corner(const Shape& source_shape) { return source_shape; }
-}
-
-CoordinateTransformBasic::CoordinateTransformBasic(const Shape& source_shape)
- : m_source_shape(source_shape)
-{
-}
-
-// Compute the index of a source-space coordinate in the buffer.
-size_t CoordinateTransformBasic::index(const Coordinate& c) const noexcept
-{
- size_t index = 0;
- size_t stride = 1;
- size_t const padding = c.size() - m_source_shape.size();
-
- for (size_t axis = m_source_shape.size(); axis-- > 0;)
- {
- if (m_source_shape[axis] > 1)
- {
- index += c[axis + padding] * stride;
- stride *= m_source_shape[axis];
- }
- }
-
- return index;
-}
-
-CoordinateIterator CoordinateTransformBasic::begin() const noexcept
-{
- return CoordinateIterator(m_source_shape);
-}
-
-const CoordinateIterator& CoordinateTransformBasic::end() const noexcept
-{
- return CoordinateIterator::end();
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order,
- const CoordinateDiff& target_padding_below,
- const CoordinateDiff& target_padding_above,
- const Strides& target_dilation_strides)
- : CoordinateTransformBasic(source_shape)
- , m_source_start_corner(source_start_corner)
- , m_source_end_corner(source_end_corner)
- , m_source_strides(source_strides)
- , m_source_axis_order(source_axis_order)
- , m_target_padding_below(target_padding_below)
- , m_target_padding_above(target_padding_above)
- , m_target_dilation_strides(target_dilation_strides)
-{
- m_n_axes = source_shape.size();
-
- if (m_n_axes != source_start_corner.size())
- {
- throw std::domain_error(
- "Source start corner does not have the same number of axes as the source space shape");
- }
- if (m_n_axes != source_end_corner.size())
- {
- throw std::domain_error(
- "Source end corner does not have the same number of axes as the source space shape");
- }
- if (m_n_axes != source_strides.size())
- {
- throw std::domain_error(
- "Source strides do not have the same number of axes as the source space shape");
- }
- if (m_n_axes != source_axis_order.size())
- {
- // Note: this check is NOT redundant with the is_permutation check below, though you might
- // think it is. If the lengths don't match then is_permutation won't catch that; it'll
- // either stop short or walk off the end of source_axis_order.
- throw std::domain_error(
- "Source axis order does not have the same number of axes as the source space shape");
- }
- if (m_n_axes != target_padding_below.size())
- {
- throw std::domain_error(
- "Padding-below shape does not have the same number of axes as the source space shape");
- }
- if (m_n_axes != target_padding_above.size())
- {
- throw std::domain_error(
- "Padding-above shape does not have the same number of axes as the source space shape");
- }
- if (m_n_axes != target_dilation_strides.size())
- {
- throw std::domain_error(
- "Target dilation strides do not have the same number of axes as the source shape");
- }
-
- AxisVector all_axes(m_n_axes);
- for (size_t i = 0; i < all_axes.size(); i++)
- {
- all_axes[i] = i;
- }
-
- if (!std::is_permutation(all_axes.begin(), all_axes.end(), source_axis_order.begin()))
- {
- throw std::domain_error(
- "Source axis order is not a permutation of {0,...,n-1} where n is the number of axes "
- "in the source space shape");
- }
-
- for (size_t i = 0; i < m_n_axes; i++)
- {
- if (target_dilation_strides[i] == 0)
- {
- std::stringstream ss;
-
- ss << "The target dilation stride is 0 at axis " << i;
- throw std::domain_error(ss.str());
- }
- }
-
- std::vector<std::ptrdiff_t> padded_upper_bounds;
-
- for (size_t i = 0; i < m_n_axes; i++)
- {
- std::ptrdiff_t padded_upper_bound =
- subtract_or_zero(source_shape[i], size_t(1)) * target_dilation_strides[i] + 1 +
- target_padding_below[i] + target_padding_above[i];
-
- if (padded_upper_bound < 0)
- {
- std::stringstream ss;
-
- ss << "The end corner is out of bounds at axis " << i;
- throw std::domain_error(ss.str());
- }
-
- padded_upper_bounds.push_back(padded_upper_bound);
- }
-
- for (size_t i = 0; i < m_n_axes; i++)
- {
- if (static_cast<int64_t>(source_start_corner[i]) >= padded_upper_bounds[i] &&
- source_start_corner[i] != source_shape[i])
- {
- std::stringstream ss;
-
- ss << "The start corner is out of bounds at axis " << i;
- throw std::domain_error(ss.str());
- }
-
- if (static_cast<int64_t>(source_end_corner[i]) > padded_upper_bounds[i])
- {
- std::stringstream ss;
-
- ss << "The end corner is out of bounds at axis " << i;
- throw std::domain_error(ss.str());
- }
- }
-
- for (size_t i = 0; i < m_n_axes; i++)
- {
- if (source_strides[i] == 0)
- {
- std::stringstream ss;
-
- ss << "The source stride is 0 at axis " << i;
- throw std::domain_error(ss.str());
- }
- }
-
- for (size_t axis = 0; axis < m_n_axes; axis++)
- {
- m_target_shape.push_back(ceil_div(source_end_corner[source_axis_order[axis]] -
- source_start_corner[source_axis_order[axis]],
- source_strides[source_axis_order[axis]]));
- }
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order,
- const CoordinateDiff& target_padding_below,
- const CoordinateDiff& target_padding_above)
- : CoordinateTransform(source_shape,
- source_start_corner,
- source_end_corner,
- source_strides,
- source_axis_order,
- target_padding_below,
- target_padding_above,
- default_strides(source_shape.size()))
-{
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides,
- const AxisVector& source_axis_order)
- : CoordinateTransform(source_shape,
- source_start_corner,
- source_end_corner,
- source_strides,
- source_axis_order,
- default_padding(source_shape.size()),
- default_padding(source_shape.size()),
- default_strides(source_shape.size()))
-{
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner,
- const Strides& source_strides)
- : CoordinateTransform(source_shape,
- source_start_corner,
- source_end_corner,
- source_strides,
- default_axis_order(source_shape.size()),
- default_padding(source_shape.size()),
- default_padding(source_shape.size()),
- default_strides(source_shape.size()))
-{
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape,
- const Coordinate& source_start_corner,
- const Coordinate& source_end_corner)
- : CoordinateTransform(source_shape,
- source_start_corner,
- source_end_corner,
- default_strides(source_shape.size()),
- default_axis_order(source_shape.size()),
- default_padding(source_shape.size()),
- default_padding(source_shape.size()),
- default_strides(source_shape.size()))
-{
-}
-
-CoordinateTransform::CoordinateTransform(const Shape& source_shape)
- : CoordinateTransform(source_shape,
- default_source_start_corner(source_shape.size()),
- default_source_end_corner(source_shape),
- default_strides(source_shape.size()),
- default_axis_order(source_shape.size()),
- default_padding(source_shape.size()),
- default_padding(source_shape.size()),
- default_strides(source_shape.size()))
-{
-}
-
-// Compute the index of a target-space coordinate in thebuffer.
-size_t CoordinateTransform::index(const Coordinate& c) const
-{
- return CoordinateTransformBasic::index(to_source_coordinate(c));
-}
-
-// Convert a target-space coordinate to a source-space coordinate.
-Coordinate CoordinateTransform::to_source_coordinate(const Coordinate& c_target) const
-{
- if (c_target.size() != m_n_axes)
- {
- throw std::domain_error(
- "Target coordinate rank does not match the coordinate transform rank");
- }
-
- Coordinate c_source(c_target.size());
-
- for (size_t target_axis = 0; target_axis < m_n_axes; target_axis++)
- {
- size_t source_axis = m_source_axis_order[target_axis];
-
- size_t target_pos = c_target[target_axis];
- size_t pos_destrided = target_pos * m_source_strides[source_axis];
- size_t pos_deshifted = pos_destrided + m_source_start_corner[source_axis];
- size_t pos_depadded = pos_deshifted - m_target_padding_below[target_axis];
- size_t pos_dedilated = pos_depadded / m_target_dilation_strides[target_axis];
- c_source[source_axis] = pos_dedilated;
- }
-
- return c_source;
-}
-
-// A point in the target space is considered not to have a source coordinate if it was inserted due
-// to padding or dilation, or if it is out of the bounds of the target space.
-bool CoordinateTransform::has_source_coordinate(const Coordinate& c_target) const
-{
- if (c_target.size() != m_n_axes)
- {
- throw std::domain_error(
- "Target coordinate rank does not match the coordinate transform rank");
- }
-
- for (size_t target_axis = 0; target_axis < m_n_axes; target_axis++)
- {
- // Is this coordinate out of bounds of the target space?
- if (c_target[target_axis] >= m_target_shape[target_axis])
- {
- return false;
- }
-
- // The rest of this is a replay of the corresponding logic in `to_source_coordinate`, with
- // bounds and divisibility checking.
- std::ptrdiff_t source_axis = m_source_axis_order[target_axis];
-
- std::ptrdiff_t target_pos = c_target[target_axis];
- std::ptrdiff_t pos_destrided = target_pos * m_source_strides[source_axis];
- std::ptrdiff_t pos_deshifted = pos_destrided + m_source_start_corner[source_axis];
-
- // If we are in the below-padding or the above-padding.
- if (pos_deshifted < m_target_padding_below[target_axis])
- {
- return false;
- }
- std::ptrdiff_t pos_depadded = pos_deshifted - m_target_padding_below[target_axis];
-
- // If we are in the above-padding, we have no source coordinate.
- if (m_source_shape[source_axis] == 0 ||
- (pos_depadded >= ((static_cast<int64_t>(m_source_shape[source_axis]) - 1) *
- static_cast<int64_t>(m_target_dilation_strides[target_axis])) +
- 1))
- {
- return false;
- }
-
- // If we are in a dilation gap, we have no source coordinate.
- if (pos_depadded % m_target_dilation_strides[target_axis] != 0)
- {
- return false;
- }
- }
-
- return true;
-}
-
-const Shape& CoordinateTransform::get_source_shape() const noexcept
-{
- return m_source_shape;
-}
-
-const Shape& CoordinateTransform::get_target_shape() const noexcept
-{
- return m_target_shape;
-}
-
-const Coordinate& CoordinateTransform::get_source_start_corner() const noexcept
-{
- return m_source_start_corner;
-}
-
-const Coordinate& CoordinateTransform::get_source_end_corner() const noexcept
-{
- return m_source_end_corner;
-}
-
-const Strides& CoordinateTransform::get_source_strides() const noexcept
-{
- return m_source_strides;
-}
-
-const AxisVector& CoordinateTransform::get_source_axis_order() const noexcept
-{
- return m_source_axis_order;
-}
-
-const Strides& CoordinateTransform::get_target_dilation_strides() const noexcept
-{
- return m_target_dilation_strides;
-}
-
-CoordinateIterator CoordinateTransform::begin() const noexcept
-{
- return CoordinateIterator(m_target_shape);
-}
-
-const CoordinateIterator& CoordinateTransform::end() const noexcept
-{
- return CoordinateIterator::end();
-}
-
-// The "is_end" parameter is true if we want the "end()" iterator.
-CoordinateIterator::CoordinateIterator(const Shape& target_shape, bool is_end)
- : m_target_shape(target_shape)
- , m_coordinate(target_shape.size(), 0)
-{
- // The case where we have a zero-length axis is a bit special, in that
- // the iterator always starts out of bounds.
- bool const empty = std::find(target_shape.begin(), target_shape.end(), 0) != target_shape.end();
-
- m_oob = is_end || empty;
-}
-
-void CoordinateIterator::operator++()
-{
- advance(m_target_shape.size() - 1);
-}
-
-size_t CoordinateIterator::advance(size_t axis) noexcept
-{
- m_oob |= m_target_shape.empty();
-
- if (m_oob)
- return m_target_shape.size();
-
- bool carry_out = false;
-
- // Increment the target coordinate.
- do
- {
- m_coordinate[axis]++;
-
- if (m_coordinate[axis] < m_target_shape[axis])
- {
- // No carry-out, so we are done.
- return axis;
- }
- else
- {
- m_coordinate[axis] = 0;
- carry_out = true;
- }
- } while (axis-- > 0);
-
- // If we are still here there was carry-out from the most significant axis. We are now out of
- // bounds.
- m_oob = true;
-
- return m_target_shape.size();
-}
-
-CoordinateIterator CoordinateIterator::operator++(int)
-{
- CoordinateIterator temp = *this;
- ++(*this);
- return temp;
-}
-
-void CoordinateIterator::operator+=(size_t n)
-{
- for (size_t i = 0; i < n; i++)
- {
- ++(*this);
- }
-}
-
-const Coordinate& CoordinateIterator::operator*() const noexcept
-{
- return m_coordinate;
-}
-
-bool CoordinateIterator::operator!=(const CoordinateIterator& it) const noexcept
-{
- return !(*this == it);
-}
-
-bool CoordinateIterator::operator==(const CoordinateIterator& it) const noexcept
-{
- if (it.m_oob)
- {
- // Out-of-bounds iterators are always equal; in other words, an iterator is always equal to
- // end() even if the internally stored coordinates are different.
-
- // If one iterator is out of bounds and the other is not, they are unequal even if their
- // target coordinates happen to match.
- return m_oob;
- }
- else if (m_oob)
- {
- return false;
- }
-
- if (m_target_shape != it.m_target_shape)
- {
- return false;
- }
-
- // Check axis-wise if the iterators are on the same target coordinate.
- for (size_t axis = 0; axis < m_target_shape.size(); axis++)
- {
- if (m_coordinate[axis] != it.m_coordinate[axis])
- {
- return false;
- }
- }
-
- return true;
-}
-
-const CoordinateIterator& CoordinateIterator::end()
-{
- static const CoordinateIterator it(Shape(), true);
- return it;
-}
//*****************************************************************************
#include "ngraph/op/prelu.hpp"
-#include <runtime/reference/prelu.hpp>
+#include <ngraph/runtime/reference/prelu.hpp>
#include "ngraph/itt.hpp"
#include "ngraph/builder/autobroadcast.hpp"
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/opt_kernel/reshape.hpp"
-
-using namespace ngraph;
-
-namespace
-{
- void reshape_in0(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- memcpy(out, in, elem_size);
- }
-
- void reshape_in1(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[1];
- size_t in_index[1];
- size_t* map_index[1];
- for (size_t i = 0; i < 1; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- memcpy(out, in + *map_index[0] * elem_size, elem_size);
- out += elem_size;
- }
- }
-
- void reshape_in2(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[2];
- size_t in_index[2];
- size_t* map_index[2];
- for (size_t i = 0; i < 2; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
- {
- // clang-format off
- memcpy(out,
- in + (*map_index[0] * in_shape[1] +
- *map_index[1]) * elem_size,
- elem_size);
- out += elem_size;
- // clang-format on
- }
- }
- }
-
- void reshape_in3(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[3];
- size_t in_index[3];
- size_t* map_index[3];
- for (size_t i = 0; i < 3; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
- {
- for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
- {
- // clang-format off
- memcpy(out,
- in + (*map_index[0] * in_shape[1] * in_shape[2] +
- *map_index[1] * in_shape[2] +
- *map_index[2]) * elem_size,
- elem_size);
- out += elem_size;
- // clang-format on
- }
- }
- }
- }
-
- void reshape_in4(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[4];
- size_t in_index[4];
- size_t* map_index[4];
- for (size_t i = 0; i < 4; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
- {
- for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
- {
- for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
- {
- // clang-format off
- memcpy(out,
- in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] +
- *map_index[1] * in_shape[2] * in_shape[3] +
- *map_index[2] * in_shape[3] +
- *map_index[3]) * elem_size,
- elem_size);
- out += elem_size;
- // clang-format on
- }
- }
- }
- }
- }
-
- void reshape_in5(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[5];
- size_t in_index[5];
- size_t* map_index[5];
- for (size_t i = 0; i < 5; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
- {
- for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
- {
- for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
- {
- for (in_index[4] = 0; in_index[4] < size[4]; ++in_index[4])
- {
- // clang-format off
- memcpy(out,
- in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] * in_shape[4] +
- *map_index[1] * in_shape[2] * in_shape[3] * in_shape[4] +
- *map_index[2] * in_shape[3] * in_shape[4] +
- *map_index[3] * in_shape[4] +
- *map_index[4]) * elem_size,
- elem_size);
- out += elem_size;
- // clang-format on
- }
- }
- }
- }
- }
- }
-
- void reshape_in6(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
- {
- size_t size[6];
- size_t in_index[6];
- size_t* map_index[6];
- for (size_t i = 0; i < 6; i++)
- {
- size[i] = in_shape[in_axis_order[i]];
- map_index[in_axis_order[i]] = &in_index[i];
- }
- for (in_index[0] = 0; in_index[0] < size[0]; ++in_index[0])
- {
- for (in_index[1] = 0; in_index[1] < size[1]; ++in_index[1])
- {
- for (in_index[2] = 0; in_index[2] < size[2]; ++in_index[2])
- {
- for (in_index[3] = 0; in_index[3] < size[3]; ++in_index[3])
- {
- for (in_index[4] = 0; in_index[4] < size[4]; ++in_index[4])
- {
- for (in_index[5] = 0; in_index[5] < size[5]; ++in_index[5])
- {
- // clang-format off
- memcpy(out,
- in + (*map_index[0] * in_shape[1] * in_shape[2] * in_shape[3] * in_shape[4] * in_shape[5] +
- *map_index[1] * in_shape[2] * in_shape[3] * in_shape[4] * in_shape[5] +
- *map_index[2] * in_shape[3] * in_shape[4] * in_shape[5] +
- *map_index[3] * in_shape[4] * in_shape[5] +
- *map_index[4] * in_shape[5] +
- *map_index[5]) * elem_size,
- elem_size);
- out += elem_size;
- // clang-format on
- }
- }
- }
- }
- }
- }
- }
-}
-void runtime::opt_kernel::reshape(const char* in,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
-{
- switch (in_shape.size())
- {
- case 0: reshape_in0(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 1: reshape_in1(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 2: reshape_in2(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 3: reshape_in3(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 4: reshape_in4(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 5: reshape_in5(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- case 6: reshape_in6(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- default: reference::reshape(in, out, in_shape, in_axis_order, out_shape, elem_size); break;
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <algorithm>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/reference/eval_helpers.hpp"
-
-namespace ngraph
-{
- namespace eval
- {
- AxisSet extract_reduction_axes(const HostTensorPtr& axes, const char* op_name)
- {
- const auto axes_count = axes->get_element_count();
- const auto axes_buffer = axes->get_data_ptr<int64_t>();
-
- const bool negative_axis_received = std::any_of(
- axes_buffer, axes_buffer + axes_count, [](const int64_t axis) { return axis < 0; });
-
- NGRAPH_CHECK(!negative_axis_received,
- "Negative axis value received in the ",
- op_name,
- " evaluation. This case is not supported.");
-
- return AxisSet(std::vector<AxisSet::value_type>(axes_buffer, axes_buffer + axes_count));
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/reference/reshape.hpp"
-
-using namespace ngraph;
-
-void runtime::reference::reshape(const char* arg,
- char* out,
- const Shape& in_shape,
- const AxisVector& in_axis_order,
- const Shape& out_shape,
- size_t elem_size)
-{
- // Unfortunately we don't yet have a constructor for CoordinateTransform that lets
- // us pass only source_space_shape
- // and source_axis_order so we have to construct the defaults here.
- Shape in_start_corner(in_shape.size(), 0); // (0,...0)
- Strides in_strides(in_shape.size(), 1); // (1,...,1)
-
- CoordinateTransform input_transform(
- in_shape, in_start_corner, in_shape, in_strides, in_axis_order);
- CoordinateTransform output_transform(out_shape);
-
- NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
- shape_size(output_transform.get_target_shape()));
-
- CoordinateTransform::Iterator output_it = output_transform.begin();
-
- for (const Coordinate& input_coord : input_transform)
- {
- const Coordinate& output_coord = *output_it;
-
- memcpy(out + output_transform.index(output_coord) * elem_size,
- arg + input_transform.index(input_coord) * elem_size,
- elem_size);
-
- ++output_it;
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/reference/reverse.hpp"
-
-using namespace ngraph;
-
-void runtime::reference::reverse(const char* arg,
- char* out,
- const Shape& arg_shape,
- const Shape& out_shape,
- const AxisSet& reversed_axes,
- size_t elem_size)
-{
- // In fact arg_shape == out_shape, but we'll use both for stylistic consistency with
- // other kernels.
- CoordinateTransform arg_transform(arg_shape);
- CoordinateTransform output_transform(out_shape);
-
- for (Coordinate out_coord : output_transform)
- {
- Coordinate arg_coord = out_coord;
-
- for (size_t i = 0; i < arg_coord.size(); i++)
- {
- if (reversed_axes.count(i) != 0)
- {
- arg_coord[i] = arg_shape[i] - arg_coord[i] - 1;
- }
- }
-
- memcpy(out + output_transform.index(out_coord) * elem_size,
- arg + arg_transform.index(arg_coord) * elem_size,
- elem_size);
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/reference/slice.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- void slice(const char* arg,
- char* out,
- const Shape& arg_shape,
- const Coordinate& lower_bounds,
- const Coordinate& upper_bounds,
- const Strides& strides,
- const Shape& out_shape,
- size_t elem_size)
- {
- CoordinateTransform input_transform(arg_shape, lower_bounds, upper_bounds, strides);
- CoordinateTransform output_transform(out_shape);
-
- CoordinateTransform::Iterator output_it = output_transform.begin();
-
- NGRAPH_CHECK(shape_size(input_transform.get_target_shape()) ==
- shape_size(output_transform.get_target_shape()));
-
- for (const Coordinate& in_coord : input_transform)
- {
- const Coordinate& out_coord = *output_it;
-
- memcpy(out + output_transform.index(out_coord) * elem_size,
- arg + input_transform.index(in_coord) * elem_size,
- elem_size);
-
- ++output_it;
- }
- }
- }
- }
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/aligned_buffer.hpp"
-#include "ngraph/runtime/reference/strided_slice.hpp"
-
-using namespace ngraph;
-
-void runtime::reference::strided_slice(
- const char* arg, char* out, const Shape& arg_shape, const SlicePlan& sp, size_t elem_type)
-{
- runtime::AlignedBuffer slice_out_buffer(shape_size(sp.reshape_in_shape) * elem_type);
- slice(reinterpret_cast<const char*>(arg),
- slice_out_buffer.get_ptr<char>(),
- arg_shape,
- Coordinate(sp.begins.begin(), sp.begins.end()),
- Coordinate(sp.ends.begin(), sp.ends.end()),
- Strides(sp.strides.begin(), sp.strides.end()),
- sp.reshape_in_shape,
- elem_type);
-
- runtime::AlignedBuffer reshape_out_buffer(shape_size(sp.reshape_out_shape) * elem_type);
- opt_kernel::reshape(slice_out_buffer.get_ptr<char>(),
- reshape_out_buffer.get_ptr<char>(),
- sp.reshape_in_shape,
- get_default_order(sp.reshape_in_shape.size()),
- sp.reshape_out_shape,
- elem_type);
-
- reverse(reshape_out_buffer.get_ptr<char>(),
- out,
- sp.reshape_out_shape,
- sp.reshape_out_shape,
- sp.reverse_axes,
- elem_type);
-}
+++ /dev/null
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// 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 <cmath>
-#include <stdio.h>
-
-#include "ngraph/check.hpp"
-#include "ngraph/runtime/reference/tile.hpp"
-
-using namespace ngraph;
-
-void runtime::reference::tile(
- const char* arg, char* out, const Shape& in_shape, const Shape& out_shape, size_t elem_size)
-{
- Shape in_shape_expanded(in_shape);
- in_shape_expanded.insert(in_shape_expanded.begin(), out_shape.size() - in_shape.size(), 1);
- CoordinateTransform input_transform(in_shape_expanded);
- CoordinateTransform output_transform(out_shape);
-
- for (const Coordinate& output_coord : output_transform)
- {
- std::vector<size_t> coord;
- for (auto i = 0; i < output_coord.size(); i++)
- {
- auto val = output_coord[i] % in_shape_expanded[i];
- coord.push_back(val);
- }
- Coordinate input_coord(coord);
-
- memcpy(out + output_transform.index(output_coord) * elem_size,
- arg + input_transform.index(input_coord) * elem_size,
- elem_size);
- }
-}
#include "gtest/gtest.h"
+#include <ngraph/coordinate_transform.hpp>
#include "ngraph/ngraph.hpp"
#include "util/ndarray.hpp"
#include "util/test_tools.hpp"
SHARED_LIB_PREFIX="${CMAKE_SHARED_LIBRARY_PREFIX}"
SHARED_LIB_SUFFIX="${IE_BUILD_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}"
)
-target_link_libraries(ngraph_backend PUBLIC ngraph)
+target_link_libraries(ngraph_backend PUBLIC ngraph
+ ngraph::reference)
if (NOT WIN32)
target_link_libraries(ngraph_backend PRIVATE dl)
endif()
#include "ngraph/runtime/reference/convolution.hpp"
#include "ngraph/runtime/reference/cos.hpp"
#include "ngraph/runtime/reference/cosh.hpp"
+#include "ngraph/runtime/reference/ctc_loss.hpp"
#include "ngraph/runtime/reference/cum_sum.hpp"
#include "ngraph/runtime/reference/dequantize.hpp"
+#include "ngraph/runtime/reference/detection_output.hpp"
#include "ngraph/runtime/reference/dot.hpp"
#include "ngraph/runtime/reference/elu.hpp"
#include "ngraph/runtime/reference/embedding_bag_offsets_sum.hpp"
#include "ngraph/runtime/reference/reverse.hpp"
#include "ngraph/runtime/reference/reverse_sequence.hpp"
#include "ngraph/runtime/reference/round.hpp"
+#include "ngraph/runtime/reference/scatter_nd_update.hpp"
+#include "ngraph/runtime/reference/scatter_update.hpp"
#include "ngraph/runtime/reference/select.hpp"
#include "ngraph/runtime/reference/sigmoid.hpp"
#include "ngraph/runtime/reference/sign.hpp"
#include "op/convolution.hpp"
#include "op/group_conv.hpp"
-#include "reference/ctc_loss.hpp"
-#include "reference/detection_output.hpp"
-#include "reference/scatter_nd_update.hpp"
-#include "reference/scatter_update.hpp"
-
namespace ngraph
{
namespace runtime
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include <math.h>
-#include "ngraph/shape_util.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename T, typename U>
- void CTCLoss(const T* logits,
- const Shape& logitsShape,
- const U* logitsLength,
- const U* labels,
- const U* labelsLength,
- const U* blankIndexP,
- const bool preprocessCollapseRepeated,
- const bool ctcMergeRepeated,
- const bool unique,
- T* output)
- {
- const size_t batchNum = logitsShape[0];
- const size_t maxTime = logitsShape[1];
- const size_t classesNum = logitsShape[2];
- U blankIndex = classesNum - 1;
- if (blankIndexP != nullptr)
- {
- blankIndex = blankIndexP[0];
- }
-
- std::vector<U> targetD(maxTime);
- std::vector<U> pathS(maxTime);
-
- const size_t TC = maxTime * classesNum;
-
- for (size_t b = 0; b < batchNum; b++)
- {
- U actualLogitLen = logitsLength[b];
- U actualTargetLen = labelsLength[b];
- if (actualLogitLen >= maxTime || actualTargetLen >= maxTime ||
- actualTargetLen > actualLogitLen)
- {
- throw ngraph_error(
- std::string("Logit or label length cannot be more than max sequence"
- "length. Also a label length cannot be greater than a"
- "logit length.\nMaxSeqLen: ") +
- std::to_string(maxTime) + "; Logit len: " +
- std::to_string(actualLogitLen) + "; Label len: " +
- std::to_string(actualTargetLen));
- }
-
- const U* target = &labels[b * maxTime];
- // Decoding target:
- // merge repeated characters if preprocess_collapse_repeated == True,
- // find unique elemnts if unique == True
- size_t decodedTargetLen = 0lu;
- if (unique)
- {
- std::unordered_set<U> uniqVals;
- for (size_t t = 0lu; t < actualTargetLen; t++)
- {
- if (uniqVals.find(target[t]) != uniqVals.end())
- {
- continue;
- }
- uniqVals.insert(target[t]);
- targetD[decodedTargetLen++] = target[t];
- }
- }
- else if (preprocessCollapseRepeated)
- {
- U prevValue = target[0];
- targetD[decodedTargetLen++] = target[0];
- for (size_t t = 1lu; t < actualTargetLen; t++)
- {
- if (target[t] == prevValue)
- {
- continue;
- }
- targetD[decodedTargetLen++] = target[t];
- prevValue = target[t];
- }
- }
- else
- {
- std::copy(target, target + actualTargetLen, targetD.data());
- decodedTargetLen = actualTargetLen;
- }
-
- const size_t BTC = b * TC;
-
- std::vector<T> kExp(actualLogitLen, 0);
- for (size_t t = 0; t < actualLogitLen; t++)
- {
- size_t btcT = BTC + classesNum * t;
- for (size_t c = 0; c < classesNum; c++)
- {
- kExp[t] += std::exp(logits[btcT + c]);
- }
- }
-
- T res = -std::numeric_limits<T>::infinity();
-
- // Looking for aligned paths
- std::function<void(size_t targetIdx, size_t start, size_t end)> findPaths = [&](
- size_t targetIdx, size_t start, size_t end) {
- if (end > actualLogitLen)
- {
- T prod = 0;
- for (size_t t = 0; t < actualLogitLen; t++)
- {
- prod += std::log(std::exp(logits[BTC + classesNum * t + pathS[t]]) /
- kExp[t]);
- }
- if (res == -std::numeric_limits<T>::infinity())
- res = prod;
- else if (prod != -std::numeric_limits<T>::infinity())
- res = res + std::log1pf(std::exp(prod - res));
-
- return;
- }
-
- size_t nextIdx = targetIdx + 1;
- int64_t st64 = start;
- if (!ctcMergeRepeated)
- {
- for (size_t pos = start; pos < end; pos++)
- {
- for (size_t bl = start; bl < pos; bl++)
- {
- pathS[bl] = blankIndex;
- }
- pathS[pos] = targetD[targetIdx];
- findPaths(nextIdx, pos + 1, end + 1);
- }
- }
- else
- {
- for (size_t pos = start; pos < end; pos++)
- {
- for (size_t bl = start; bl < pos; bl++)
- {
- pathS[bl] = blankIndex;
- }
- for (int64_t bl = pos; bl >= st64; bl--)
- {
- pathS[bl] = targetD[targetIdx];
- if (end == actualLogitLen)
- {
- for (int64_t ble = pos + 1; ble < actualLogitLen; ble++)
- {
- pathS[ble] = blankIndex;
- }
- }
- size_t next_start = pos + 1;
- if (targetIdx < decodedTargetLen - 1 &&
- targetD[targetIdx] == targetD[targetIdx + 1])
- {
- pathS[next_start++] = blankIndex;
- }
- findPaths(nextIdx, next_start, end + 1);
- }
- }
- }
- }; // findPaths
-
- findPaths(0lu, 0lu, actualLogitLen - decodedTargetLen + 1lu);
-
- output[b] = -res;
-
- } // for (size_t b = 0; b < batchNum; b++)
- } // CTCLoss
- } // reference
- } // runtime
-} // ngraph
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include <cstddef>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "ngraph/shape.hpp"
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- enum
- {
- idxLocation,
- idxConfidence,
- idxPriors,
- idxArmConfidence,
- idxArmLocation,
- numInputs
- };
-
- template <typename dataType>
- class referenceDetectionOutput
- {
- private:
- struct NormalizedBBox
- {
- dataType xmin = 0;
- dataType ymin = 0;
- dataType xmax = 0;
- dataType ymax = 0;
- dataType size = 0;
- };
- using LabelBBox = std::map<int, std::vector<NormalizedBBox>>;
-
- ngraph::op::DetectionOutputAttrs attrs;
- size_t numImages;
- size_t priorSize;
- size_t numPriors;
- size_t numLocClasses;
- size_t offset;
-
- void GetLocPredictions(const dataType* locData, std::vector<LabelBBox>& locations)
- {
- locations.resize(numImages);
- for (size_t i = 0; i < numImages; ++i)
- {
- LabelBBox& labelBbox = locations[i];
- for (size_t p = 0; p < numPriors; ++p)
- {
- size_t startIdx = p * numLocClasses * 4;
- for (size_t c = 0; c < numLocClasses; ++c)
- {
- int label = attrs.share_location ? -1 : c;
- if (labelBbox.find(label) == labelBbox.end())
- {
- labelBbox[label].resize(numPriors);
- }
- labelBbox[label][p].xmin = locData[startIdx + c * 4];
- labelBbox[label][p].ymin = locData[startIdx + c * 4 + 1];
- labelBbox[label][p].xmax = locData[startIdx + c * 4 + 2];
- labelBbox[label][p].ymax = locData[startIdx + c * 4 + 3];
- }
- }
- locData += numPriors * numLocClasses * 4;
- }
- }
-
- void GetConfidenceScores(
- const dataType* confData,
- std::vector<std::map<int, std::vector<dataType>>>& confPreds)
- {
- confPreds.resize(numImages);
- for (int i = 0; i < numImages; ++i)
- {
- std::map<int, std::vector<dataType>>& labelScores = confPreds[i];
- for (int p = 0; p < numPriors; ++p)
- {
- int startIdx = p * attrs.num_classes;
- for (int c = 0; c < attrs.num_classes; ++c)
- {
- labelScores[c].push_back(confData[startIdx + c]);
- }
- }
- confData += numPriors * attrs.num_classes;
- }
- }
-
- void OSGetConfidenceScores(
- const dataType* confData,
- const dataType* armConfData,
- std::vector<std::map<int, std::vector<dataType>>>& confPreds)
- {
- confPreds.resize(numImages);
- for (int i = 0; i < numImages; ++i)
- {
- std::map<int, std::vector<dataType>>& labelScores = confPreds[i];
- for (int p = 0; p < numPriors; ++p)
- {
- int startIdx = p * attrs.num_classes;
- if (armConfData[p * 2 + 1] < attrs.objectness_score)
- {
- for (int c = 0; c < attrs.num_classes; ++c)
- {
- c == attrs.background_label_id ? labelScores[c].push_back(1)
- : labelScores[c].push_back(0);
- }
- }
- else
- {
- for (int c = 0; c < attrs.num_classes; ++c)
- {
- labelScores[c].push_back(confData[startIdx + c]);
- }
- }
- }
- confData += numPriors * attrs.num_classes;
- armConfData += numPriors * 2;
- }
- }
-
- dataType BBoxSize(const NormalizedBBox& bbox)
- {
- if (bbox.xmax < bbox.xmin || bbox.ymax < bbox.ymin)
- {
- return 0;
- }
- else
- {
- dataType width = bbox.xmax - bbox.xmin;
- dataType height = bbox.ymax - bbox.ymin;
- return width * height;
- }
- }
-
- void GetPriorBBoxes(const dataType* priorData,
- std::vector<std::vector<NormalizedBBox>>& priorBboxes,
- std::vector<std::vector<std::vector<dataType>>>& priorVariances)
- {
- priorBboxes.resize(numImages);
- priorVariances.resize(numImages);
- for (int n = 0; n < numImages; n++)
- {
- priorData += attrs.variance_encoded_in_target
- ? n * numPriors * priorSize
- : 2 * n * numPriors * priorSize;
- std::vector<NormalizedBBox>& currPrBbox = priorBboxes[n];
- std::vector<std::vector<dataType>>& currPrVar = priorVariances[n];
- for (int i = 0; i < numPriors; ++i)
- {
- int start_idx = i * priorSize;
- NormalizedBBox bbox;
- bbox.xmin = priorData[start_idx + 0 + offset];
- bbox.ymin = priorData[start_idx + 1 + offset];
- bbox.xmax = priorData[start_idx + 2 + offset];
- bbox.ymax = priorData[start_idx + 3 + offset];
- dataType bbox_size = BBoxSize(bbox);
- bbox.size = bbox_size;
- currPrBbox.push_back(bbox);
- }
- if (!attrs.variance_encoded_in_target)
- {
- const dataType* priorVar = priorData + numPriors * priorSize;
- for (int i = 0; i < numPriors; ++i)
- {
- int start_idx = i * 4;
- std::vector<dataType> var;
- for (int j = 0; j < 4; ++j)
- {
- var.push_back(priorVar[start_idx + j]);
- }
- currPrVar.push_back(var);
- }
- }
- }
- }
-
- void DecodeBBox(const NormalizedBBox& priorBboxes,
- const std::vector<dataType>& priorVariances,
- const NormalizedBBox& bbox,
- NormalizedBBox& decodeBbox)
- {
- dataType priorXmin = priorBboxes.xmin;
- dataType priorYmin = priorBboxes.ymin;
- dataType priorXmax = priorBboxes.xmax;
- dataType priorYmax = priorBboxes.ymax;
-
- if (!attrs.normalized)
- {
- priorXmin /= attrs.input_width;
- priorYmin /= attrs.input_height;
- priorXmax /= attrs.input_width;
- priorYmax /= attrs.input_height;
- }
- if (attrs.code_type == "caffe.PriorBoxParameter.CORNER")
- {
- if (attrs.variance_encoded_in_target)
- {
- decodeBbox.xmin = priorXmin + bbox.xmin;
- decodeBbox.ymin = priorYmin + bbox.ymin;
- decodeBbox.xmax = priorXmax + bbox.xmax;
- decodeBbox.ymax = priorYmax + bbox.ymax;
- }
- else
- {
- decodeBbox.xmin = priorXmin + priorVariances[0] * bbox.xmin;
- decodeBbox.ymin = priorYmin + priorVariances[1] * bbox.ymin;
- decodeBbox.xmax = priorXmax + priorVariances[2] * bbox.xmax;
- decodeBbox.ymax = priorYmax + priorVariances[3] * bbox.ymax;
- }
- }
- else if (attrs.code_type == "caffe.PriorBoxParameter.CENTER_SIZE")
- {
- dataType priorWidth = priorXmax - priorXmin;
- dataType priorHeight = priorYmax - priorYmin;
- dataType priorCenterX = (priorXmin + priorXmax) / 2;
- dataType priorCenterY = (priorYmin + priorYmax) / 2;
- dataType decodeBboxCenterX, decodeBboxCenterY;
- dataType decodeBboxWidth, decodeBboxHeight;
- if (attrs.variance_encoded_in_target)
- {
- decodeBboxCenterX = bbox.xmin * priorWidth + priorCenterX;
- decodeBboxCenterY = bbox.ymin * priorHeight + priorCenterY;
- decodeBboxWidth = std::exp(bbox.xmax) * priorWidth;
- decodeBboxHeight = std::exp(bbox.ymax) * priorHeight;
- }
- else
- {
- decodeBboxCenterX =
- priorVariances[0] * bbox.xmin * priorWidth + priorCenterX;
- decodeBboxCenterY =
- priorVariances[1] * bbox.ymin * priorHeight + priorCenterY;
- decodeBboxWidth = std::exp(priorVariances[2] * bbox.xmax) * priorWidth;
- decodeBboxHeight =
- std::exp(priorVariances[3] * bbox.ymax) * priorHeight;
- }
- decodeBbox.xmin = decodeBboxCenterX - decodeBboxWidth / 2;
- decodeBbox.ymin = decodeBboxCenterY - decodeBboxHeight / 2;
- decodeBbox.xmax = decodeBboxCenterX + decodeBboxWidth / 2;
- decodeBbox.ymax = decodeBboxCenterY + decodeBboxHeight / 2;
- }
- if (attrs.clip_before_nms)
- {
- decodeBbox.xmin =
- std::max<dataType>(0, std::min<dataType>(1, decodeBbox.xmin));
- decodeBbox.ymin =
- std::max<dataType>(0, std::min<dataType>(1, decodeBbox.ymin));
- decodeBbox.xmax =
- std::max<dataType>(0, std::min<dataType>(1, decodeBbox.xmax));
- decodeBbox.ymax =
- std::max<dataType>(0, std::min<dataType>(1, decodeBbox.ymax));
- }
- dataType bboxSize = BBoxSize(decodeBbox);
- decodeBbox.size = bboxSize;
- }
-
- void DecodeBBoxes(const std::vector<NormalizedBBox>& priorBboxes,
- const std::vector<std::vector<dataType>>& priorVariances,
- const std::vector<NormalizedBBox>& labelLocPreds,
- std::vector<NormalizedBBox>& decodeBboxes)
- {
- int numBboxes = priorBboxes.size();
- for (int i = 0; i < numBboxes; ++i)
- {
- NormalizedBBox decodeBbox;
- DecodeBBox(priorBboxes[i], priorVariances[i], labelLocPreds[i], decodeBbox);
- decodeBboxes.push_back(decodeBbox);
- }
- }
-
- void DecodeBBoxesAll(
- const std::vector<LabelBBox>& locPreds,
- const std::vector<std::vector<NormalizedBBox>>& priorBboxes,
- const std::vector<std::vector<std::vector<dataType>>>& priorVariances,
- std::vector<LabelBBox>& decodeBboxes)
- {
- decodeBboxes.resize(numImages);
- for (int i = 0; i < numImages; ++i)
- {
- LabelBBox& decodeBboxesImage = decodeBboxes[i];
- const std::vector<NormalizedBBox>& currPrBbox = priorBboxes[i];
- const std::vector<std::vector<dataType>>& currPrVar = priorVariances[i];
- for (int c = 0; c < numLocClasses; ++c)
- {
- int label = attrs.share_location ? -1 : c;
- if (label == attrs.background_label_id)
- {
- continue;
- }
- const std::vector<NormalizedBBox>& labelLocPreds =
- locPreds[i].find(label)->second;
- DecodeBBoxes(
- currPrBbox, currPrVar, labelLocPreds, decodeBboxesImage[label]);
- }
- }
- }
-
- void CasRegDecodeBBoxesAll(
- const std::vector<LabelBBox>& locPreds,
- const std::vector<std::vector<NormalizedBBox>>& priorBboxes,
- const std::vector<std::vector<std::vector<dataType>>>& priorVariances,
- std::vector<LabelBBox>& decodeBboxes,
- const std::vector<LabelBBox>& armLocPreds)
- {
- decodeBboxes.resize(numImages);
- for (int i = 0; i < numImages; ++i)
- {
- LabelBBox& decodeBboxesImage = decodeBboxes[i];
- const std::vector<NormalizedBBox>& currPrBbox = priorBboxes[i];
- const std::vector<std::vector<dataType>>& currPrVar = priorVariances[i];
- for (int c = 0; c < numLocClasses; ++c)
- {
- int label = attrs.share_location ? -1 : c;
- if (label == attrs.background_label_id)
- {
- continue;
- }
- const std::vector<NormalizedBBox>& labelArmLocPreds =
- armLocPreds[i].find(label)->second;
- std::vector<NormalizedBBox> decodePriorBboxes;
- DecodeBBoxes(
- currPrBbox, currPrVar, labelArmLocPreds, decodePriorBboxes);
- const std::vector<NormalizedBBox>& labelLocPreds =
- locPreds[i].find(label)->second;
- DecodeBBoxes(decodePriorBboxes,
- currPrVar,
- labelLocPreds,
- decodeBboxesImage[label]);
- }
- }
- }
-
- template <typename T>
- static bool SortScorePairDescend(const std::pair<dataType, T>& pair1,
- const std::pair<dataType, T>& pair2)
- {
- return pair1.first > pair2.first;
- }
-
- void GetMaxScoreIndex(const std::vector<dataType>& scores,
- const dataType threshold,
- const int topK,
- std::vector<std::pair<dataType, int>>& scoreIndexVec)
- {
- for (int i = 0; i < scores.size(); ++i)
- {
- if (scores[i] > threshold)
- {
- scoreIndexVec.push_back(std::make_pair(scores[i], i));
- }
- }
-
- std::stable_sort(
- scoreIndexVec.begin(), scoreIndexVec.end(), SortScorePairDescend<int>);
- if (topK > -1 && topK < scoreIndexVec.size())
- {
- scoreIndexVec.resize(topK);
- }
- }
-
- void IntersectBBox(const NormalizedBBox& bbox1,
- const NormalizedBBox& bbox2,
- NormalizedBBox& intersectBbox)
- {
- if (bbox2.xmin > bbox1.xmax || bbox2.xmax < bbox1.xmin ||
- bbox2.ymin > bbox1.ymax || bbox2.ymax < bbox1.ymin)
- {
- intersectBbox.xmin = 0;
- intersectBbox.ymin = 0;
- intersectBbox.xmax = 0;
- intersectBbox.ymax = 0;
- }
- else
- {
- intersectBbox.xmin = std::max<dataType>(bbox1.xmin, bbox2.xmin);
- intersectBbox.ymin = std::max<dataType>(bbox1.ymin, bbox2.ymin);
- intersectBbox.xmax = std::min<dataType>(bbox1.xmax, bbox2.xmax);
- intersectBbox.ymax = std::min<dataType>(bbox1.ymax, bbox2.ymax);
- }
- }
-
- dataType JaccardOverlap(const NormalizedBBox& bbox1, const NormalizedBBox& bbox2)
- {
- NormalizedBBox intersectBbox;
- IntersectBBox(bbox1, bbox2, intersectBbox);
- dataType intersectWidth, intersectHeight;
- intersectWidth = intersectBbox.xmax - intersectBbox.xmin;
- intersectHeight = intersectBbox.ymax - intersectBbox.ymin;
- if (intersectWidth > 0 && intersectHeight > 0)
- {
- dataType intersect_size = intersectWidth * intersectHeight;
- dataType bbox1_size = BBoxSize(bbox1);
- dataType bbox2_size = BBoxSize(bbox2);
-
- return intersect_size / (bbox1_size + bbox2_size - intersect_size);
- }
- else
- {
- return 0.0f;
- }
- }
-
- void caffeNMS(const std::vector<NormalizedBBox>& bboxes,
- const std::vector<dataType>& scores,
- std::vector<int>& indices)
- {
- std::vector<std::pair<dataType, int>> scoreIndexVec;
- GetMaxScoreIndex(
- scores, attrs.confidence_threshold, attrs.top_k, scoreIndexVec);
- while (scoreIndexVec.size() != 0)
- {
- const int idx = scoreIndexVec.front().second;
- bool keep = true;
- for (int k = 0; k < indices.size(); ++k)
- {
- const int kept_idx = indices[k];
- dataType overlap = JaccardOverlap(bboxes[idx], bboxes[kept_idx]);
- if (overlap > attrs.nms_threshold)
- {
- keep = false;
- break;
- }
- }
- if (keep)
- {
- indices.push_back(idx);
- }
- scoreIndexVec.erase(scoreIndexVec.begin());
- }
- }
-
- void mxNetNms(const LabelBBox& decodeBboxesImage,
- const std::map<int, std::vector<dataType>>& confScores,
- std::map<int, std::vector<int>>& indices)
- {
- std::vector<std::pair<dataType, std::pair<int, int>>> scoreIndexPairs;
- for (int p = 0; p < numPriors; p++)
- {
- dataType conf = -1;
- int id = 0;
- for (int c = 1; c < attrs.num_classes; c++)
- {
- dataType temp = confScores.at(c)[p];
- if (temp > conf)
- {
- conf = temp;
- id = c;
- }
- }
- if (id > 0 && conf >= attrs.confidence_threshold)
- {
- scoreIndexPairs.push_back(std::make_pair(conf, std::make_pair(id, p)));
- }
- }
- std::sort(scoreIndexPairs.begin(),
- scoreIndexPairs.end(),
- SortScorePairDescend<std::pair<int, int>>);
-
- if (attrs.top_k != -1)
- if (scoreIndexPairs.size() > attrs.top_k)
- scoreIndexPairs.resize(attrs.top_k);
-
- while (scoreIndexPairs.size() != 0)
- {
- const int cls = scoreIndexPairs.front().second.first;
- const int prior = scoreIndexPairs.front().second.second;
- std::vector<int>& currInd = indices[cls];
- bool keep = true;
- for (int i = 0; i < currInd.size(); i++)
- {
- const int keptIdx = currInd[i];
- auto currBbox = attrs.share_location ? decodeBboxesImage.at(-1)
- : decodeBboxesImage.at(cls);
- dataType overlap = JaccardOverlap(currBbox[prior], currBbox[keptIdx]);
- if (overlap > attrs.nms_threshold)
- {
- keep = false;
- break;
- }
- }
- if (keep)
- {
- currInd.push_back(prior);
- }
- scoreIndexPairs.erase(scoreIndexPairs.begin());
- }
- }
-
- public:
- referenceDetectionOutput(const ngraph::op::DetectionOutputAttrs& _attrs,
- const ngraph::Shape& locShape,
- const ngraph::Shape& priorsShape)
- : attrs(_attrs)
- {
- numImages = locShape[0];
- priorSize = _attrs.normalized ? 4 : 5;
- offset = _attrs.normalized ? 0 : 1;
- numPriors = priorsShape[2] / priorSize;
- numLocClasses =
- _attrs.share_location ? 1 : static_cast<size_t>(_attrs.num_classes);
- }
-
- void run(const dataType* _location,
- const dataType* _confidence,
- const dataType* _priors,
- const dataType* _armConfidence,
- const dataType* _armLocation,
- dataType* result)
- {
- bool withAddBoxPred = _armConfidence != nullptr && _armLocation != nullptr;
- std::vector<LabelBBox> armLocPreds;
- if (withAddBoxPred)
- {
- GetLocPredictions(_armLocation, armLocPreds);
- }
- std::vector<LabelBBox> locPreds;
- GetLocPredictions(_location, locPreds);
- std::vector<std::map<int, std::vector<dataType>>> confPreds;
- if (withAddBoxPred)
- {
- OSGetConfidenceScores(_confidence, _armConfidence, confPreds);
- }
- else
- {
- GetConfidenceScores(_confidence, confPreds);
- }
- std::vector<std::vector<NormalizedBBox>> priorBboxes;
- std::vector<std::vector<std::vector<dataType>>> priorVariances;
- GetPriorBBoxes(_priors, priorBboxes, priorVariances);
- std::vector<LabelBBox> decodeBboxes;
- if (withAddBoxPred)
- {
- CasRegDecodeBBoxesAll(
- locPreds, priorBboxes, priorVariances, decodeBboxes, armLocPreds);
- }
- else
- {
- DecodeBBoxesAll(locPreds, priorBboxes, priorVariances, decodeBboxes);
- }
-
- int numKept = 0;
- std::vector<std::map<int, std::vector<int>>> allIndices;
- for (int i = 0; i < numImages; ++i)
- {
- const LabelBBox& decodeBboxesImage = decodeBboxes[i];
- const std::map<int, std::vector<dataType>>& confScores = confPreds[i];
- std::map<int, std::vector<int>> indices;
- int numDet = 0;
- if (!attrs.decrease_label_id)
- {
- // Caffe style
- for (int c = 0; c < attrs.num_classes; ++c)
- {
- if (c == attrs.background_label_id)
- {
- continue;
- }
- const std::vector<dataType>& scores = confScores.find(c)->second;
- int label = attrs.share_location ? -1 : c;
- const std::vector<NormalizedBBox>& bboxes =
- decodeBboxesImage.find(label)->second;
- caffeNMS(bboxes, scores, indices[c]);
- numDet += indices[c].size();
- }
- }
- else
- {
- // MXNet style
- mxNetNms(decodeBboxesImage, confScores, indices);
- for (auto it = indices.begin(); it != indices.end(); it++)
- numDet += it->second.size();
- }
- if (attrs.keep_top_k[0] > -1 && numDet > attrs.keep_top_k[0])
- {
- std::vector<std::pair<dataType, std::pair<int, int>>> scoreIndexPairs;
- for (auto it = indices.begin(); it != indices.end(); ++it)
- {
- int label = it->first;
- const std::vector<int>& labelIndices = it->second;
- const std::vector<dataType>& scores =
- confScores.find(label)->second;
- for (int j = 0; j < labelIndices.size(); ++j)
- {
- int idx = labelIndices[j];
- scoreIndexPairs.push_back(
- std::make_pair(scores[idx], std::make_pair(label, idx)));
- }
- }
- std::sort(scoreIndexPairs.begin(),
- scoreIndexPairs.end(),
- SortScorePairDescend<std::pair<int, int>>);
- scoreIndexPairs.resize(attrs.keep_top_k[0]);
- std::map<int, std::vector<int>> newIndices;
- for (int j = 0; j < scoreIndexPairs.size(); ++j)
- {
- int label = scoreIndexPairs[j].second.first;
- int idx = scoreIndexPairs[j].second.second;
- newIndices[label].push_back(idx);
- }
- allIndices.push_back(newIndices);
- numKept += attrs.top_k;
- }
- else
- {
- allIndices.push_back(indices);
- numKept += numDet;
- }
- }
-
- int count = 0;
- for (int i = 0; i < numImages; ++i)
- {
- const std::map<int, std::vector<dataType>>& confScores = confPreds[i];
- const LabelBBox& decodeBboxesImage = decodeBboxes[i];
- for (auto it = allIndices[i].begin(); it != allIndices[i].end(); ++it)
- {
- int label = it->first;
- const std::vector<dataType>& scores = confScores.find(label)->second;
- int loc_label = attrs.share_location ? -1 : label;
- const std::vector<NormalizedBBox>& bboxes =
- decodeBboxesImage.find(loc_label)->second;
- std::vector<int>& indices = it->second;
- for (int j = 0; j < indices.size(); ++j)
- {
- int idx = indices[j];
- result[count * 7 + 0] = i;
- result[count * 7 + 1] =
- attrs.decrease_label_id ? (label - 1) : label;
- result[count * 7 + 2] = scores[idx];
- const NormalizedBBox& bbox = bboxes[idx];
-
- dataType xmin = bbox.xmin;
- dataType ymin = bbox.ymin;
- dataType xmax = bbox.xmax;
- dataType ymax = bbox.ymax;
-
- if (attrs.clip_after_nms)
- {
- xmin = std::max<dataType>(0, std::min<dataType>(1, xmin));
- ymin = std::max<dataType>(0, std::min<dataType>(1, ymin));
- xmax = std::max<dataType>(0, std::min<dataType>(1, xmax));
- ymax = std::max<dataType>(0, std::min<dataType>(1, ymax));
- }
-
- result[count * 7 + 3] = xmin;
- result[count * 7 + 4] = ymin;
- result[count * 7 + 5] = xmax;
- result[count * 7 + 6] = ymax;
- ++count;
- }
- }
- }
- if (count < numImages * attrs.keep_top_k[0])
- {
- result[count * 7 + 0] = -1;
- }
- }
- };
- } // namespace reference
- } // namespace runtime
-} // namespace ngraph
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape.hpp"
-
-using namespace ngraph;
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename dataType, typename indicesType>
- void scatterNdUpdate(const dataType* inputData,
- const indicesType* indices,
- const dataType* updates,
- dataType* outBuf,
- const Shape& dataShape,
- const Shape& indicesShape,
- const Shape& updatesShape)
- {
- size_t numSlices = 1;
- size_t sliceSize = 1;
- for (size_t i = 0; i < indicesShape.size() - 1; i++)
- {
- numSlices *= indicesShape[i];
- }
- for (size_t i = indicesShape.size() - 1; i < updatesShape.size(); i++)
- {
- sliceSize *= updatesShape[i];
- }
-
- const size_t k = indicesShape.back();
- std::memcpy(outBuf, inputData, sizeof(dataType) * shape_size(dataShape));
- CoordinateTransform dataTransform{dataShape};
-
- for (size_t i = 0; i < numSlices; i++)
- {
- Coordinate coord;
- for (size_t j = 0; j < k; j++)
- {
- coord.push_back(indices[i * k + j]);
- }
- for (size_t j = k; j < dataShape.size(); j++)
- {
- coord.push_back(0);
- }
-
- const size_t startDataIdx = dataTransform.index(coord);
- for (size_t j = 0; j < sliceSize; j++)
- {
- outBuf[startDataIdx + j] = updates[i * sliceSize + j];
- }
- }
- }
- } // namespace reference
- } // namespace runtime
-} // namespace ngraph
+++ /dev/null
-// Copyright (C) 2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#pragma once
-
-#include <string>
-#include "ngraph/coordinate_transform.hpp"
-#include "ngraph/shape.hpp"
-
-using namespace ngraph;
-
-namespace ngraph
-{
- namespace runtime
- {
- namespace reference
- {
- template <typename dataType, typename indicesType, typename axisType>
- void scatterUpdate(const dataType* inputData,
- const indicesType* indices,
- const dataType* updates,
- const axisType* _axis,
- dataType* outBuf,
- const Shape& dataShape,
- const Shape& indicesShape,
- const Shape& updatesShape)
- {
- int rank = static_cast<int>(dataShape.size());
- if (_axis[0] < -rank || _axis[0] > rank - 1)
- {
- std::string error =
- std::string("ScatterUpdate layer has out of bounds axis value: ") +
- std::to_string(_axis[0]);
- throw ngraph_error(error);
- }
- size_t axis = _axis[0] < 0 ? _axis[0] + rank : _axis[0];
- CoordinateTransform indicesTransform{indicesShape};
-
- Shape dataShapeIter = dataShape;
- dataShapeIter.erase(dataShapeIter.begin() + axis);
- CoordinateTransform dataTransfIter{dataShapeIter};
-
- CoordinateTransform updateTransform{updatesShape};
- CoordinateTransform dataTransform{dataShape};
-
- std::memcpy(outBuf, inputData, sizeof(dataType) * shape_size(dataShape));
-
- for (const Coordinate& indicesCoordIt : indicesTransform)
- {
- const size_t indicesIdx = indicesTransform.index(indicesCoordIt);
-
- if (indices[indicesIdx] < 0)
- {
- std::string error =
- std::string("ScatterUpdate layer has negative index value: ") +
- std::to_string(indices[indicesIdx]);
- throw ngraph_error(error);
- }
- const size_t idx = static_cast<size_t>(indices[indicesIdx]);
- if (dataShape[axis] <= idx)
- {
- std::string error =
- std::string("ScatterUpdate layer has out of bounds coordinate: ") +
- std::to_string(idx) + " on 'data' input on " + std::to_string(axis) +
- "th axis";
- throw ngraph_error(error);
- }
-
- for (const Coordinate& dataCoordIt : dataTransfIter)
- {
- Coordinate dataCoord = dataCoordIt;
- dataCoord.insert(dataCoord.begin() + axis, idx);
- const size_t startIndices = dataTransform.index(dataCoord);
-
- auto updCoord = dataCoordIt;
- updCoord.insert(
- updCoord.begin() + axis, indicesCoordIt.begin(), indicesCoordIt.end());
- const size_t startUpd = updateTransform.index(updCoord);
- outBuf[startIndices] = updates[startUpd];
- }
- }
- }
- } // namespace reference
- } // namespace runtime
-} // namespace ngraph
cmake_minimum_required(VERSION 3.10)
-file(REMOVE "${CMAKE_BINARY_DIR}/openvino_targets_developer.cmake")
-
-unset(OpenVINODeveloperPackageTargets CACHE)
-
-function(openvino_developer_export_targets)
- set(OpenVINODeveloperPackageTargets "${OpenVINODeveloperPackageTargets};${ARGV}")
-
- # to allow exporting of aliased targets with the original names
- foreach(target_name ${OpenVINODeveloperPackageTargets})
- if(TARGET "${target_name}")
- get_target_property(original_name ${target_name} ALIASED_TARGET)
- if(TARGET "${original_name}")
- message(STATUS "The name ${target_name} is an ALIAS for ${original_name}. "
- "It will be exported to the InferenceEngineDeveloperPackage with the original name.")
- list(REMOVE_ITEM OpenVINODeveloperPackageTargets ${target_name})
- list(APPEND OpenVINODeveloperPackageTargets ${original_name})
- endif()
- endif()
- endforeach()
-
- list(REMOVE_DUPLICATES OpenVINODeveloperPackageTargets)
- set(OpenVINODeveloperPackageTargets "${OpenVINODeveloperPackageTargets}" CACHE INTERNAL
- "Paths to extra Inference Engine plugins" FORCE)
-endfunction()
-
add_subdirectory(itt)
openvino_developer_export_targets(openvino::itt)