forked from Qortal/Brooklyn
133 lines
3.3 KiB
C++
133 lines
3.3 KiB
C++
//
|
|
// Copyright © 2017 Arm Ltd. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <armnn/utility/IgnoreUnused.hpp>
|
|
#include <armnn/utility/NumericCast.hpp>
|
|
#include <armnn/TypesUtils.hpp>
|
|
|
|
#include <BFloat16.hpp>
|
|
#include <Half.hpp>
|
|
|
|
#include <initializer_list>
|
|
#include <iterator>
|
|
#include <vector>
|
|
|
|
namespace armnnUtils
|
|
{
|
|
|
|
template<typename T, bool DoQuantize=true>
|
|
struct SelectiveQuantizer
|
|
{
|
|
static T Quantize(float value, float scale, int32_t offset)
|
|
{
|
|
return armnn::Quantize<T>(value, scale, offset);
|
|
}
|
|
|
|
static float Dequantize(T value, float scale, int32_t offset)
|
|
{
|
|
return armnn::Dequantize(value, scale, offset);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct SelectiveQuantizer<T, false>
|
|
{
|
|
static T Quantize(float value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return value;
|
|
}
|
|
|
|
static float Dequantize(T value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct SelectiveQuantizer<armnn::Half, false>
|
|
{
|
|
static armnn::Half Quantize(float value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return armnn::Half(value);
|
|
}
|
|
|
|
static float Dequantize(armnn::Half value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct SelectiveQuantizer<armnn::BFloat16, false>
|
|
{
|
|
static armnn::BFloat16 Quantize(float value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return armnn::BFloat16(value);
|
|
}
|
|
|
|
static float Dequantize(armnn::BFloat16 value, float scale, int32_t offset)
|
|
{
|
|
armnn::IgnoreUnused(scale, offset);
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
T SelectiveQuantize(float value, float scale, int32_t offset)
|
|
{
|
|
return SelectiveQuantizer<T, armnn::IsQuantizedType<T>()>::Quantize(value, scale, offset);
|
|
};
|
|
|
|
template<typename T>
|
|
float SelectiveDequantize(T value, float scale, int32_t offset)
|
|
{
|
|
return SelectiveQuantizer<T, armnn::IsQuantizedType<T>()>::Dequantize(value, scale, offset);
|
|
};
|
|
|
|
template<typename ItType>
|
|
struct IsFloatingPointIterator
|
|
{
|
|
static constexpr bool value=std::is_floating_point<typename std::iterator_traits<ItType>::value_type>::value;
|
|
};
|
|
|
|
template <typename T, typename FloatIt,
|
|
typename std::enable_if<IsFloatingPointIterator<FloatIt>::value, int>::type=0 // Makes sure fp iterator is valid.
|
|
>
|
|
std::vector<T> QuantizedVector(FloatIt first, FloatIt last, float qScale, int32_t qOffset)
|
|
{
|
|
std::vector<T> quantized;
|
|
quantized.reserve(armnn::numeric_cast<size_t>(std::distance(first, last)));
|
|
|
|
for (auto it = first; it != last; ++it)
|
|
{
|
|
auto f = *it;
|
|
T q = SelectiveQuantize<T>(f, qScale, qOffset);
|
|
quantized.push_back(q);
|
|
}
|
|
|
|
return quantized;
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> QuantizedVector(const std::vector<float>& array, float qScale = 1.f, int32_t qOffset = 0)
|
|
{
|
|
return QuantizedVector<T>(array.begin(), array.end(), qScale, qOffset);
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> QuantizedVector(std::initializer_list<float> array, float qScale = 1.f, int32_t qOffset = 0)
|
|
{
|
|
return QuantizedVector<T>(array.begin(), array.end(), qScale, qOffset);
|
|
}
|
|
|
|
} // namespace armnnUtils
|