aboutsummaryrefslogtreecommitdiff
path: root/src/armnnUtils/QuantizeHelper.hpp
blob: a7f68c5ef0a6a5fb5d51a656811dc5d535b1b54c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include <armnn/ArmNN.hpp>
#include <armnn/TypesUtils.hpp>

#include <Half.hpp>

#include <initializer_list>
#include <iterator>
#include <vector>

#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>

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)
    {
        boost::ignore_unused(scale, offset);
        return value;
    }

    static float Dequantize(T value, float scale, int32_t offset)
    {
        boost::ignore_unused(scale, offset);
        return value;
    }
};

template<>
struct SelectiveQuantizer<armnn::Half, false>
{
    static armnn::Half Quantize(float value, float scale, int32_t offset)
    {
        boost::ignore_unused(scale, offset);
        return armnn::Half(value);
    }

    static float Dequantize(armnn::Half value, float scale, int32_t offset)
    {
        boost::ignore_unused(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(boost::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