1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Converter.h"
18
19 #include <algorithm>
20 #include <random>
21 #include <utility>
22 #include <vector>
23
24 namespace android::nn::fuzz {
25 namespace {
26
27 using namespace test_helper;
28 using namespace android_nn_fuzz;
29
30 constexpr uint32_t kMaxSize = 65536;
31
convert(OperandType type)32 TestOperandType convert(OperandType type) {
33 return static_cast<TestOperandType>(type);
34 }
35
convert(OperationType type)36 TestOperationType convert(OperationType type) {
37 return static_cast<TestOperationType>(type);
38 }
39
convert(OperandLifeTime lifetime)40 TestOperandLifeTime convert(OperandLifeTime lifetime) {
41 return static_cast<TestOperandLifeTime>(lifetime);
42 }
43
convert(const Scales & scales)44 std::vector<float> convert(const Scales& scales) {
45 const auto& repeatedScale = scales.scale();
46 return std::vector<float>(repeatedScale.begin(), repeatedScale.end());
47 }
48
convert(const SymmPerChannelQuantParams & params)49 TestSymmPerChannelQuantParams convert(const SymmPerChannelQuantParams& params) {
50 std::vector<float> scales = convert(params.scales());
51 const uint32_t channelDim = params.channel_dim();
52 return {.scales = std::move(scales), .channelDim = channelDim};
53 }
54
convert(const Dimensions & dimensions)55 std::vector<uint32_t> convert(const Dimensions& dimensions) {
56 const auto& repeatedDimension = dimensions.dimension();
57 return std::vector<uint32_t>(repeatedDimension.begin(), repeatedDimension.end());
58 }
59
convert(bool makeEmpty,const Buffer & buffer)60 TestBuffer convert(bool makeEmpty, const Buffer& buffer) {
61 if (makeEmpty) {
62 return TestBuffer();
63 }
64 const uint32_t randomSeed = buffer.random_seed();
65 std::default_random_engine generator{randomSeed};
66 std::uniform_int_distribution<uint32_t> dist{0, kMaxSize};
67 const uint32_t size = dist(generator);
68 return TestBuffer::createFromRng<uint32_t>(size, &generator);
69 }
70
convert(const Operand & operand)71 TestOperand convert(const Operand& operand) {
72 const TestOperandType type = convert(operand.type());
73 std::vector<uint32_t> dimensions = convert(operand.dimensions());
74 const float scale = operand.scale();
75 const int32_t zeroPoint = operand.zero_point();
76 const TestOperandLifeTime lifetime = convert(operand.lifetime());
77 auto channelQuant = convert(operand.channel_quant());
78 const bool isIgnored = false;
79 const bool makeEmpty = (lifetime == TestOperandLifeTime::NO_VALUE ||
80 lifetime == TestOperandLifeTime::TEMPORARY_VARIABLE);
81 TestBuffer data = convert(makeEmpty, operand.data());
82 return {.type = type,
83 .dimensions = std::move(dimensions),
84 .numberOfConsumers = 0,
85 .scale = scale,
86 .zeroPoint = zeroPoint,
87 .lifetime = lifetime,
88 .channelQuant = std::move(channelQuant),
89 .isIgnored = isIgnored,
90 .data = std::move(data)};
91 }
92
convert(const Operands & operands)93 std::vector<TestOperand> convert(const Operands& operands) {
94 std::vector<TestOperand> testOperands;
95 testOperands.reserve(operands.operand_size());
96 const auto& repeatedOperand = operands.operand();
97 std::transform(repeatedOperand.begin(), repeatedOperand.end(), std::back_inserter(testOperands),
98 [](const auto& operand) { return convert(operand); });
99 return testOperands;
100 }
101
convert(const Indexes & indexes)102 std::vector<uint32_t> convert(const Indexes& indexes) {
103 const auto& repeatedIndex = indexes.index();
104 return std::vector<uint32_t>(repeatedIndex.begin(), repeatedIndex.end());
105 }
106
convert(const Operation & operation)107 TestOperation convert(const Operation& operation) {
108 const TestOperationType type = convert(operation.type());
109 std::vector<uint32_t> inputs = convert(operation.inputs());
110 std::vector<uint32_t> outputs = convert(operation.outputs());
111 return {.type = type, .inputs = std::move(inputs), .outputs = std::move(outputs)};
112 }
113
convert(const Operations & operations)114 std::vector<TestOperation> convert(const Operations& operations) {
115 std::vector<TestOperation> testOperations;
116 testOperations.reserve(operations.operation_size());
117 const auto& repeatedOperation = operations.operation();
118 std::transform(repeatedOperation.begin(), repeatedOperation.end(),
119 std::back_inserter(testOperations),
120 [](const auto& operation) { return convert(operation); });
121 return testOperations;
122 }
123
convert(const Model & model)124 TestModel convert(const Model& model) {
125 std::vector<TestOperand> operands = convert(model.operands());
126 std::vector<TestOperation> operations = convert(model.operations());
127 std::vector<uint32_t> inputIndexes = convert(model.input_indexes());
128 std::vector<uint32_t> outputIndexes = convert(model.output_indexes());
129 const bool isRelaxed = model.is_relaxed();
130 return {.main = {.operands = std::move(operands),
131 .operations = std::move(operations),
132 .inputIndexes = std::move(inputIndexes),
133 .outputIndexes = std::move(outputIndexes)},
134 .isRelaxed = isRelaxed};
135 }
136
137 } // anonymous namespace
138
convertToTestModel(const Test & model)139 TestModel convertToTestModel(const Test& model) {
140 return convert(model.model());
141 }
142
143 } // namespace android::nn::fuzz
144