aboutsummaryrefslogtreecommitdiff
path: root/src/armnnUtils/QuantizeHelper.hpp
blob: 231b8411cb7fb9b9d4472e3e0bfc40e52489dced (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//
// 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