src/armnn/test/OpenClTimerTest.cpp \
src/armnn/test/ProfilingEventTest.cpp \
src/armnn/test/ObservableTest.cpp \
+ src/armnn/test/OptionalTest.cpp \
src/backends/test/IsLayerSupportedTest.cpp \
src/backends/test/Reference.cpp \
src/backends/test/WorkloadDataValidation.cpp \
include/armnn/IRuntime.hpp
include/armnn/ILayerSupport.hpp
include/armnn/INetwork.hpp
+ include/armnn/Optional.hpp
include/armnn/Tensor.hpp
include/armnn/TensorFwd.hpp
include/armnn/Types.hpp
src/armnn/test/GraphUtils.hpp
src/armnn/test/InstrumentTests.cpp
src/armnn/test/ObservableTest.cpp
+ src/armnn/test/OptionalTest.cpp
src/backends/test/IsLayerSupportedTest.cpp
src/backends/test/IsLayerSupportedTestImpl.hpp
src/backends/test/Reference.cpp
using Exception::Exception;
};
+class BadOptionalAccessException : public Exception
+{
+ using Exception::Exception;
+};
+
template <typename ExceptionType>
void ConditionalThrow(bool condition, const std::string& message)
{
#pragma once
#include <armnn/DescriptorsFwd.hpp>
-
-#include <boost/optional.hpp>
+#include <armnn/Optional.hpp>
#include <vector>
+#include <cctype>
namespace armnn
{
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported = nullptr,
size_t reasonIfUnsupportedMaxLength = 1024) const;
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported = nullptr,
size_t reasonIfUnsupportedMaxLength = 1024) const;
#include <armnn/DescriptorsFwd.hpp>
#include <armnn/Types.hpp>
#include <armnn/Tensor.hpp>
-
-#include <boost/optional.hpp>
+#include <armnn/Optional.hpp>
namespace armnn
{
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported = nullptr,
size_t reasonIfUnsupportedMaxLength = 1024);
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported = nullptr,
size_t reasonIfUnsupportedMaxLength = 1024);
--- /dev/null
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include "Exceptions.hpp"
+
+namespace armnn
+{
+
+// NOTE: the members of the Optional class don't follow the ArmNN
+// coding convention because the interface to be close to
+// the C++-17 interface so we can easily migrate to std::optional
+// later.
+
+template <typename T>
+class Optional final
+{
+public:
+ Optional(T&& value)
+ : m_HasValue{true}
+ {
+ new (m_Storage) T(value);
+ }
+
+ Optional(const T& value)
+ : m_HasValue{true}
+ {
+ new (m_Storage) T(value);
+ }
+
+ Optional(const Optional& other)
+ : m_HasValue{false}
+ {
+ *this = other;
+ }
+
+ Optional() noexcept
+ : m_HasValue{false}
+ {
+ }
+
+ ~Optional()
+ {
+ reset();
+ }
+
+ operator bool() const noexcept
+ {
+ return has_value();
+ }
+
+ Optional& operator=(T&& value)
+ {
+ reset();
+ new (m_Storage) T(value);
+ m_HasValue = true;
+ return *this;
+ }
+
+ Optional& operator=(const T& value)
+ {
+ reset();
+ new(m_Storage) T(value);
+ m_HasValue = true;
+ return *this;
+ }
+
+ Optional& operator=(const Optional& other)
+ {
+ reset();
+ if (other.has_value())
+ {
+ new (m_Storage) T(other.value());
+ m_HasValue = true;
+ }
+
+ return *this;
+ }
+
+ const T& value() const
+ {
+ if (!has_value())
+ {
+ throw BadOptionalAccessException("Optional has no value");
+ }
+
+ auto valuePtr = reinterpret_cast<const T*>(m_Storage);
+ return *valuePtr;
+ }
+
+ T& value()
+ {
+ if (!has_value())
+ {
+ throw BadOptionalAccessException("Optional has no value");
+ }
+
+ auto valuePtr = reinterpret_cast<T*>(m_Storage);
+ return *valuePtr;
+ }
+
+ bool has_value() const noexcept
+ {
+ return m_HasValue;
+ }
+
+ void reset()
+ {
+ if (has_value())
+ {
+ value().T::~T();
+ m_HasValue = false;
+ }
+ }
+
+private:
+ alignas(alignof(T)) unsigned char m_Storage[sizeof(T)];
+ bool m_HasValue;
+};
+
+}
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported,
size_t reasonIfUnsupportedMaxLength)
{
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported,
size_t reasonIfUnsupportedMaxLength)
{
--- /dev/null
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#include <boost/test/unit_test.hpp>
+
+#include <armnn/Optional.hpp>
+#include <string>
+
+BOOST_AUTO_TEST_SUITE(OptionalTests)
+
+BOOST_AUTO_TEST_CASE(SimpleStringTests)
+{
+ armnn::Optional<std::string> optionalString;
+ BOOST_TEST(optionalString == false);
+ BOOST_TEST(optionalString.has_value() == false);
+
+ optionalString = std::string("Hello World");
+ BOOST_TEST(optionalString == true);
+ BOOST_TEST(optionalString.has_value() == true);
+ BOOST_TEST(optionalString.value() == "Hello World");
+
+ armnn::Optional<std::string> otherString;
+ otherString = optionalString;
+ BOOST_TEST(otherString == true);
+ BOOST_TEST(otherString.value() == "Hello World");
+
+ optionalString.reset();
+ BOOST_TEST(optionalString == false);
+ BOOST_TEST(optionalString.has_value() == false);
+
+ const std::string stringValue("Hello World");
+ armnn::Optional<std::string> optionalString2(stringValue);
+ BOOST_TEST(optionalString2 == true);
+ BOOST_TEST(optionalString2.has_value() == true);
+ BOOST_TEST(optionalString2.value() == "Hello World");
+
+ armnn::Optional<std::string> optionalString3(std::move(optionalString2));
+ BOOST_TEST(optionalString3 == true);
+ BOOST_TEST(optionalString3.has_value() == true);
+ BOOST_TEST(optionalString3.value() == "Hello World");
+}
+
+BOOST_AUTO_TEST_CASE(SimpleIntTests)
+{
+ const int intValue = 123;
+
+ armnn::Optional<int> optionalInt;
+ BOOST_TEST(optionalInt == false);
+ BOOST_TEST(optionalInt.has_value() == false);
+
+ optionalInt = intValue;
+ BOOST_TEST(optionalInt == true);
+ BOOST_TEST(optionalInt.has_value() == true);
+ BOOST_TEST(optionalInt.value() == intValue);
+
+ armnn::Optional<int> otherOptionalInt;
+ otherOptionalInt = optionalInt;
+ BOOST_TEST(otherOptionalInt == true);
+ BOOST_TEST(otherOptionalInt.value() == intValue);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported,
size_t reasonIfUnsupportedMaxLength) const
{
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
char* reasonIfUnsupported,
size_t reasonIfUnsupportedMaxLength) const
{
const Convolution2dDescriptor& descriptor = cLayer->GetParameters();
// Construct optional biases object based on the value of m_BiasEnabled
- boost::optional<TensorInfo> biases(boost::none);
+ Optional<TensorInfo> biases;
if (descriptor.m_BiasEnabled)
{
- biases = boost::make_optional(
- OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType)));
+ biases =
+ OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType));
}
result = IsConvolution2dSupported(compute,
const DepthwiseConvolution2dDescriptor& descriptor = cLayer->GetParameters();
// Construct optional biases object based on the value of m_BiasEnabled
- boost::optional<TensorInfo> biases(boost::none);
+ Optional<TensorInfo> biases;
if (descriptor.m_BiasEnabled)
{
- biases = boost::make_optional(
- OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType)));
+ biases =
+ OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType));
}
result = IsDepthwiseConvolutionSupported(compute,
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
FORWARD_WORKLOAD_VALIDATE_FUNC(ClConvolution2dWorkloadValidate,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
FORWARD_WORKLOAD_VALIDATE_FUNC(ClDepthwiseConvolutionWorkloadValidate,
#include <armnn/Tensor.hpp>
#include <armnn/ArmNN.hpp>
-#include <boost/optional.hpp>
-
namespace armnn
{
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
bool IsDepthwiseConvolutionSupportedCl(const TensorInfo& input,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
bool IsDivisionSupportedCl(const TensorInfo& input0,
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases)
+ const Optional<TensorInfo>& biases)
{
const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
if (descriptor.m_BiasEnabled)
{
- BOOST_ASSERT(biases.is_initialized());
+ BOOST_ASSERT(biases.has_value());
- aclBiasesInfo = BuildArmComputeTensorInfo(biases.get(), descriptor.m_DataLayout);
+ aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
optionalAclBiasesInfo = &aclBiasesInfo;
}
#include <arm_compute/runtime/CL/functions/CLConvolutionLayer.h>
#include <arm_compute/runtime/MemoryManagerOnDemand.h>
-#include <boost/optional.hpp>
-
#include <memory>
namespace armnn
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases);
+ const Optional<TensorInfo>& biases);
class ClConvolution2dWorkload : public BaseWorkload<Convolution2dQueueDescriptor>
{
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases)
+ const Optional<TensorInfo>& biases)
{
const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
if (descriptor.m_BiasEnabled)
{
- BOOST_ASSERT(biases.is_initialized());
+ BOOST_ASSERT(biases.has_value());
- aclBiasesInfo = BuildArmComputeTensorInfo(biases.get(), descriptor.m_DataLayout);
+ aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
optionalAclBiasesInfo = &aclBiasesInfo;
}
#pragma once
#include <backends/Workload.hpp>
-#include <boost/optional.hpp>
#include <arm_compute/runtime/CL/CLFunctions.h>
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases);
+ const Optional<TensorInfo>& biases);
template<armnn::DataType... dataTypes>
class ClDepthwiseConvolutionBaseWorkload : public TypedWorkload<DepthwiseConvolution2dQueueDescriptor, dataTypes...>
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
#include <armnn/Types.hpp>
#include <armnn/Tensor.hpp>
-#include <boost/optional.hpp>
-
namespace armnn
{
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
bool IsDivisionSupportedNeon(const TensorInfo& input0,
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases)
+ const Optional<TensorInfo>& biases)
{
const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
if (descriptor.m_BiasEnabled)
{
- BOOST_ASSERT(biases.is_initialized());
+ BOOST_ASSERT(biases.has_value());
- aclBiasesInfo = BuildArmComputeTensorInfo(biases.get(), descriptor.m_DataLayout);
+ aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
optionalAclBiasesInfo = &aclBiasesInfo;
}
#include <arm_compute/runtime/MemoryManagerOnDemand.h>
-#include <boost/optional.hpp>
-
#include <memory>
namespace armnn
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases);
+ const Optional<TensorInfo>& biases);
template<armnn::DataType... dataTypes>
class NeonConvolution2dBaseWorkload : public TypedWorkload<Convolution2dQueueDescriptor, dataTypes...>
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases)
+ const Optional<TensorInfo>& biases)
{
const arm_compute::TensorInfo aclInputInfo =
armcomputetensorutils::BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
if (descriptor.m_BiasEnabled)
{
- BOOST_ASSERT(biases.is_initialized());
+ BOOST_ASSERT(biases.has_value());
- aclBiasesInfo = armcomputetensorutils::BuildArmComputeTensorInfo(biases.get(), descriptor.m_DataLayout);
+ aclBiasesInfo = armcomputetensorutils::BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
optionalAclBiasesInfo = &aclBiasesInfo;
}
#include <backends/neon/workloads/NeonWorkloadUtils.hpp>
-#include <boost/optional.hpp>
-
namespace armnn
{
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases);
+ const Optional<TensorInfo>& biases);
} // namespace armnn
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
ignore_unused(descriptor);
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported)
{
ignore_unused(output);
#include <armnn/Types.hpp>
#include <armnn/Tensor.hpp>
#include <layers/LstmLayer.hpp>
-#include <boost/optional.hpp>
-
-#include <boost/optional.hpp>
namespace armnn
{
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
bool IsDepthwiseConvolutionSupportedRef(const TensorInfo& input,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const boost::optional<TensorInfo>& biases,
+ const Optional<TensorInfo>& biases,
std::string* reasonIfUnsupported = nullptr);
bool IsDivisionSupportedRef(const TensorInfo& input0,