xref: /aosp_15_r20/system/media/tests/elementwise_op_basic_tests.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker  * Copyright (C) 2024 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker  *
4*b9df5ad1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker  *
8*b9df5ad1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker  *
10*b9df5ad1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker  * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker  */
16*b9df5ad1SAndroid Build Coastguard Worker 
17*b9df5ad1SAndroid Build Coastguard Worker #include <string>
18*b9df5ad1SAndroid Build Coastguard Worker 
19*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/template_utils.h>
20*b9df5ad1SAndroid Build Coastguard Worker #include <gtest/gtest.h>
21*b9df5ad1SAndroid Build Coastguard Worker #include <log/log.h>
22*b9df5ad1SAndroid Build Coastguard Worker #include <system/elementwise_op.h>
23*b9df5ad1SAndroid Build Coastguard Worker 
24*b9df5ad1SAndroid Build Coastguard Worker using android::audio_utils::elementwise_clamp;
25*b9df5ad1SAndroid Build Coastguard Worker using android::audio_utils::elementwise_max;
26*b9df5ad1SAndroid Build Coastguard Worker using android::audio_utils::elementwise_min;
27*b9df5ad1SAndroid Build Coastguard Worker using android::audio_utils::kMaxStructMember;
28*b9df5ad1SAndroid Build Coastguard Worker using android::audio_utils::op_tuple_elements;
29*b9df5ad1SAndroid Build Coastguard Worker 
30*b9df5ad1SAndroid Build Coastguard Worker enum class OpTestEnum { E1, E2, E3 };
31*b9df5ad1SAndroid Build Coastguard Worker 
32*b9df5ad1SAndroid Build Coastguard Worker struct OpTestSSS {
33*b9df5ad1SAndroid Build Coastguard Worker   double a;
34*b9df5ad1SAndroid Build Coastguard Worker   bool b;
35*b9df5ad1SAndroid Build Coastguard Worker };
36*b9df5ad1SAndroid Build Coastguard Worker 
37*b9df5ad1SAndroid Build Coastguard Worker struct OpTestSS {
38*b9df5ad1SAndroid Build Coastguard Worker   OpTestSSS sss;
39*b9df5ad1SAndroid Build Coastguard Worker   int c;
40*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> d;
41*b9df5ad1SAndroid Build Coastguard Worker   OpTestEnum e;
42*b9df5ad1SAndroid Build Coastguard Worker };
43*b9df5ad1SAndroid Build Coastguard Worker 
44*b9df5ad1SAndroid Build Coastguard Worker struct OpTestS {
45*b9df5ad1SAndroid Build Coastguard Worker   OpTestSS ss;
46*b9df5ad1SAndroid Build Coastguard Worker   int f;
47*b9df5ad1SAndroid Build Coastguard Worker   bool g;
48*b9df5ad1SAndroid Build Coastguard Worker   std::string h;
49*b9df5ad1SAndroid Build Coastguard Worker };
50*b9df5ad1SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const OpTestEnum & e)51*b9df5ad1SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const OpTestEnum& e) {
52*b9df5ad1SAndroid Build Coastguard Worker   switch (e) {
53*b9df5ad1SAndroid Build Coastguard Worker     case OpTestEnum::E1: {
54*b9df5ad1SAndroid Build Coastguard Worker       os << "E1";
55*b9df5ad1SAndroid Build Coastguard Worker       break;
56*b9df5ad1SAndroid Build Coastguard Worker     }
57*b9df5ad1SAndroid Build Coastguard Worker     case OpTestEnum::E2: {
58*b9df5ad1SAndroid Build Coastguard Worker       os << "E2";
59*b9df5ad1SAndroid Build Coastguard Worker       break;
60*b9df5ad1SAndroid Build Coastguard Worker     }
61*b9df5ad1SAndroid Build Coastguard Worker     case OpTestEnum::E3: {
62*b9df5ad1SAndroid Build Coastguard Worker       os << "E3";
63*b9df5ad1SAndroid Build Coastguard Worker       break;
64*b9df5ad1SAndroid Build Coastguard Worker     }
65*b9df5ad1SAndroid Build Coastguard Worker   }
66*b9df5ad1SAndroid Build Coastguard Worker   return os;
67*b9df5ad1SAndroid Build Coastguard Worker }
68*b9df5ad1SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const OpTestSSS & sss)69*b9df5ad1SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const OpTestSSS& sss) {
70*b9df5ad1SAndroid Build Coastguard Worker   os << "a: " << sss.a << ", b: " << sss.b;
71*b9df5ad1SAndroid Build Coastguard Worker   return os;
72*b9df5ad1SAndroid Build Coastguard Worker }
73*b9df5ad1SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const OpTestSS & ss)74*b9df5ad1SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const OpTestSS& ss) {
75*b9df5ad1SAndroid Build Coastguard Worker   os << ss.sss << ", c: " << ss.c << ", d: [";
76*b9df5ad1SAndroid Build Coastguard Worker   for (const auto& itor : ss.d) {
77*b9df5ad1SAndroid Build Coastguard Worker     os << itor << " ";
78*b9df5ad1SAndroid Build Coastguard Worker   }
79*b9df5ad1SAndroid Build Coastguard Worker   os << "], e: " << ss.e;
80*b9df5ad1SAndroid Build Coastguard Worker   return os;
81*b9df5ad1SAndroid Build Coastguard Worker }
82*b9df5ad1SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const OpTestS & s)83*b9df5ad1SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const OpTestS& s) {
84*b9df5ad1SAndroid Build Coastguard Worker   os << s.ss << ", f: " << s.f << ", g: " << s.g << ", h" << s.h;
85*b9df5ad1SAndroid Build Coastguard Worker   return os;
86*b9df5ad1SAndroid Build Coastguard Worker }
87*b9df5ad1SAndroid Build Coastguard Worker 
operator ==(const OpTestSSS & lhs,const OpTestSSS & rhs)88*b9df5ad1SAndroid Build Coastguard Worker constexpr bool operator==(const OpTestSSS& lhs, const OpTestSSS& rhs) {
89*b9df5ad1SAndroid Build Coastguard Worker   return lhs.a == rhs.a && lhs.b == rhs.b;
90*b9df5ad1SAndroid Build Coastguard Worker }
91*b9df5ad1SAndroid Build Coastguard Worker 
operator ==(const OpTestSS & lhs,const OpTestSS & rhs)92*b9df5ad1SAndroid Build Coastguard Worker constexpr bool operator==(const OpTestSS& lhs, const OpTestSS& rhs) {
93*b9df5ad1SAndroid Build Coastguard Worker   return lhs.sss == rhs.sss && lhs.c == rhs.c && lhs.d == rhs.d &&
94*b9df5ad1SAndroid Build Coastguard Worker          lhs.e == rhs.e;
95*b9df5ad1SAndroid Build Coastguard Worker }
96*b9df5ad1SAndroid Build Coastguard Worker 
operator ==(const OpTestS & lhs,const OpTestS & rhs)97*b9df5ad1SAndroid Build Coastguard Worker constexpr bool operator==(const OpTestS& lhs, const OpTestS& rhs) {
98*b9df5ad1SAndroid Build Coastguard Worker   return lhs.ss == rhs.ss && lhs.f == rhs.f && lhs.g == rhs.g && lhs.h == rhs.h;
99*b9df5ad1SAndroid Build Coastguard Worker }
100*b9df5ad1SAndroid Build Coastguard Worker 
101*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss1{.a = 1, .b = false};
102*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss2{.a = sss1.a + 1, .b = true};
103*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss3{.a = sss2.a + 1, .b = true};
104*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss_mixed{.a = sss1.a - 1, .b = true};
105*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss_clamped_1_3{.a = sss1.a, .b = true};
106*b9df5ad1SAndroid Build Coastguard Worker const OpTestSSS sss_clamped_2_3{.a = sss2.a, .b = true};
107*b9df5ad1SAndroid Build Coastguard Worker 
108*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss1{.sss = sss1, .c = 1, .d = {1.f}, .e = OpTestEnum::E1};
109*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss2{
110*b9df5ad1SAndroid Build Coastguard Worker     .sss = sss2, .c = ss1.c + 1, .d = {ss1.d[0] + 1}, .e = OpTestEnum::E2};
111*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss3{
112*b9df5ad1SAndroid Build Coastguard Worker     .sss = sss3, .c = ss2.c + 1, .d = {ss2.d[0] + 1}, .e = OpTestEnum::E3};
113*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss_mixed{
114*b9df5ad1SAndroid Build Coastguard Worker     .sss = sss_mixed, .c = ss1.c - 1, .d = {ss3.d[0] + 1}, .e = OpTestEnum::E3};
115*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss_clamped_1_3{
116*b9df5ad1SAndroid Build Coastguard Worker     .sss = sss_clamped_1_3, .c = ss1.c, .d = {ss3.d[0]}, .e = OpTestEnum::E3};
117*b9df5ad1SAndroid Build Coastguard Worker const OpTestSS ss_clamped_2_3{
118*b9df5ad1SAndroid Build Coastguard Worker     .sss = sss_clamped_2_3, .c = ss2.c, .d = {ss3.d[0]}, .e = OpTestEnum::E3};
119*b9df5ad1SAndroid Build Coastguard Worker 
120*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s1{.ss = ss1, .f = 1, .g = false, .h = "s1"};
121*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s2{.ss = ss2, .f = s1.f + 1, .g = false, .h = "s2"};
122*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s3{.ss = ss3, .f = s2.f + 1, .g = true, .h = "s3"};
123*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s_mixed{.ss = ss_mixed, .f = s1.f - 1, .g = true, .h = "mixed"};
124*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s_clamped_1_3{
125*b9df5ad1SAndroid Build Coastguard Worker     .ss = ss_clamped_1_3, .f = s1.f, .g = true, .h = "s1"};
126*b9df5ad1SAndroid Build Coastguard Worker const OpTestS s_clamped_2_3{
127*b9df5ad1SAndroid Build Coastguard Worker     .ss = ss_clamped_2_3, .f = s2.f, .g = true, .h = "s2"};
128*b9df5ad1SAndroid Build Coastguard Worker 
129*b9df5ad1SAndroid Build Coastguard Worker // clamp a structure with range of min == max
TEST(ClampOpTest,elementwise_clamp)130*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, elementwise_clamp) {
131*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
132*b9df5ad1SAndroid Build Coastguard Worker 
133*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s2, s1, s3);
134*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
135*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
136*b9df5ad1SAndroid Build Coastguard Worker 
137*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s1, s2, s3);
138*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
139*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
140*b9df5ad1SAndroid Build Coastguard Worker 
141*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s3, s1, s2);
142*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
143*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
144*b9df5ad1SAndroid Build Coastguard Worker }
145*b9df5ad1SAndroid Build Coastguard Worker 
146*b9df5ad1SAndroid Build Coastguard Worker // clamp a structure with range of min == max
TEST(ClampOpTest,clamp_same_min_max)147*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_same_min_max) {
148*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
149*b9df5ad1SAndroid Build Coastguard Worker 
150*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s1, s1, s1);
151*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
152*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s1);
153*b9df5ad1SAndroid Build Coastguard Worker 
154*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s2, s1, s1);
155*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
156*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s1);
157*b9df5ad1SAndroid Build Coastguard Worker 
158*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s3, s1, s1);
159*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
160*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s1);
161*b9df5ad1SAndroid Build Coastguard Worker 
162*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s1, s2, s2);
163*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
164*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
165*b9df5ad1SAndroid Build Coastguard Worker 
166*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s2, s2, s2);
167*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
168*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
169*b9df5ad1SAndroid Build Coastguard Worker 
170*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s3, s2, s2);
171*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
172*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
173*b9df5ad1SAndroid Build Coastguard Worker 
174*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s1, s3, s3);
175*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
176*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s3);
177*b9df5ad1SAndroid Build Coastguard Worker 
178*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s2, s3, s3);
179*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
180*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s3);
181*b9df5ad1SAndroid Build Coastguard Worker 
182*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s3, s3, s3);
183*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
184*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s3);
185*b9df5ad1SAndroid Build Coastguard Worker }
186*b9df5ad1SAndroid Build Coastguard Worker 
187*b9df5ad1SAndroid Build Coastguard Worker // clamp a structure with invalid range (min > max)
TEST(ClampOpTest,clamp_invalid_range)188*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_invalid_range) {
189*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_clamp(s1, s2, s1));
190*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_clamp(s2, s3, s2));
191*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_clamp(s3, s3, s1));
192*b9df5ad1SAndroid Build Coastguard Worker }
193*b9df5ad1SAndroid Build Coastguard Worker 
194*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.ss.sss.a
TEST(ClampOpTest,clamp_to_max_a)195*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_a) {
196*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
197*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
198*b9df5ad1SAndroid Build Coastguard Worker 
199*b9df5ad1SAndroid Build Coastguard Worker   p3.ss.sss.a = s1.ss.sss.a;
200*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
201*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
202*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.ss.sss.a is not clamped
203*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.sss.a, s1.ss.sss.a);
204*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
205*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.sss.a = s2.ss.sss.a;
206*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
207*b9df5ad1SAndroid Build Coastguard Worker }
208*b9df5ad1SAndroid Build Coastguard Worker 
209*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.ss.sss.b
TEST(ClampOpTest,clamp_to_max_b)210*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_b) {
211*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
212*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
213*b9df5ad1SAndroid Build Coastguard Worker 
214*b9df5ad1SAndroid Build Coastguard Worker   p3.ss.sss.b = s1.ss.sss.b;
215*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
216*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
217*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.ss.sss.b is not clamped
218*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.sss.b, s1.ss.sss.b);
219*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
220*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.sss.b = s2.ss.sss.b;
221*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
222*b9df5ad1SAndroid Build Coastguard Worker }
223*b9df5ad1SAndroid Build Coastguard Worker 
224*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.ss.c
TEST(ClampOpTest,clamp_to_max_c)225*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_c) {
226*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
227*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
228*b9df5ad1SAndroid Build Coastguard Worker 
229*b9df5ad1SAndroid Build Coastguard Worker   p3.ss.c = s1.ss.c;
230*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
231*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
232*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(p3.ss.c, s1.ss.c);
233*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.ss.c is not clamped
234*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.c, s1.ss.c);
235*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
236*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.c = s2.ss.c;
237*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
238*b9df5ad1SAndroid Build Coastguard Worker }
239*b9df5ad1SAndroid Build Coastguard Worker 
240*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.ss.d
TEST(ClampOpTest,clamp_to_max_d)241*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_d) {
242*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
243*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
244*b9df5ad1SAndroid Build Coastguard Worker 
245*b9df5ad1SAndroid Build Coastguard Worker   p3.ss.d = s1.ss.d;
246*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
247*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
248*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.ss.d is not clamped
249*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, s1.ss.d);
250*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
251*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.d = s2.ss.d;
252*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
253*b9df5ad1SAndroid Build Coastguard Worker }
254*b9df5ad1SAndroid Build Coastguard Worker 
255*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.ss.e
TEST(ClampOpTest,clamp_to_max_e)256*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_e) {
257*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
258*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
259*b9df5ad1SAndroid Build Coastguard Worker 
260*b9df5ad1SAndroid Build Coastguard Worker   p3.ss.e = s1.ss.e;
261*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
262*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
263*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.ss.e is not clamped
264*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.e, s1.ss.e);
265*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
266*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.e = s2.ss.e;
267*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
268*b9df5ad1SAndroid Build Coastguard Worker }
269*b9df5ad1SAndroid Build Coastguard Worker 
270*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.f
TEST(ClampOpTest,clamp_to_max_f)271*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_f) {
272*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
273*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
274*b9df5ad1SAndroid Build Coastguard Worker 
275*b9df5ad1SAndroid Build Coastguard Worker   p3.f = s1.f;
276*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
277*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
278*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.f is not clamped
279*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->f, s1.f);
280*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
281*b9df5ad1SAndroid Build Coastguard Worker   clamped->f = s2.f;
282*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
283*b9df5ad1SAndroid Build Coastguard Worker }
284*b9df5ad1SAndroid Build Coastguard Worker 
285*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.g
TEST(ClampOpTest,clamp_to_max_g)286*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_g) {
287*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
288*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
289*b9df5ad1SAndroid Build Coastguard Worker 
290*b9df5ad1SAndroid Build Coastguard Worker   p3.g = s1.g;
291*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
292*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
293*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.g is not clamped
294*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->g, s1.g);
295*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
296*b9df5ad1SAndroid Build Coastguard Worker   clamped->g = s2.g;
297*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
298*b9df5ad1SAndroid Build Coastguard Worker }
299*b9df5ad1SAndroid Build Coastguard Worker 
300*b9df5ad1SAndroid Build Coastguard Worker // all members in p3 clamped to s2 but p3.h
TEST(ClampOpTest,clamp_to_max_h)301*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_max_h) {
302*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p3 = s3;
303*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
304*b9df5ad1SAndroid Build Coastguard Worker 
305*b9df5ad1SAndroid Build Coastguard Worker   p3.h = s1.h;
306*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(p3, s1, s2);
307*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
308*b9df5ad1SAndroid Build Coastguard Worker   // ensure p3.g is not clamped
309*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->h, s1.h);
310*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
311*b9df5ad1SAndroid Build Coastguard Worker   clamped->h = s2.h;
312*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
313*b9df5ad1SAndroid Build Coastguard Worker }
314*b9df5ad1SAndroid Build Coastguard Worker 
315*b9df5ad1SAndroid Build Coastguard Worker // all members in p1 clamped to s2 except p1.ss.sss.a
TEST(ClampOpTest,clamp_to_min_a)316*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_a) {
317*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
318*b9df5ad1SAndroid Build Coastguard Worker   p1.ss.sss.a = s3.ss.sss.a;
319*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
320*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
321*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.ss.sss.a is not clamped
322*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.sss.a, s3.ss.sss.a);
323*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
324*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.sss.a = s2.ss.sss.a;
325*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
326*b9df5ad1SAndroid Build Coastguard Worker }
327*b9df5ad1SAndroid Build Coastguard Worker 
328*b9df5ad1SAndroid Build Coastguard Worker // all members in p1 clamped to s2 but p1.ss.sss.b
TEST(ClampOpTest,clamp_to_min_b)329*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_b) {
330*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
331*b9df5ad1SAndroid Build Coastguard Worker   p1.ss.sss.b = s3.ss.sss.b;
332*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
333*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
334*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.ss.sss.b is not clamped
335*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.sss.b, s3.ss.sss.b);
336*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
337*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.sss.b = s2.ss.sss.b;
338*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
339*b9df5ad1SAndroid Build Coastguard Worker }
340*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_c)341*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_c) {
342*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
343*b9df5ad1SAndroid Build Coastguard Worker   p1.ss.c = s3.ss.c;
344*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
345*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
346*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(p1.ss.c, s3.ss.c);
347*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.ss.c is not clamped
348*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.c, s3.ss.c);
349*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
350*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.c = s2.ss.c;
351*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
352*b9df5ad1SAndroid Build Coastguard Worker }
353*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_d)354*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_d) {
355*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
356*b9df5ad1SAndroid Build Coastguard Worker   p1.ss.d = s3.ss.d;
357*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
358*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
359*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.ss.d is not clamped
360*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, s3.ss.d);
361*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
362*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.d = s2.ss.d;
363*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
364*b9df5ad1SAndroid Build Coastguard Worker }
365*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_e)366*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_e) {
367*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
368*b9df5ad1SAndroid Build Coastguard Worker   p1.ss.e = s3.ss.e;
369*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
370*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
371*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.ss.e is not clamped
372*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.e, s3.ss.e);
373*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
374*b9df5ad1SAndroid Build Coastguard Worker   clamped->ss.e = s2.ss.e;
375*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
376*b9df5ad1SAndroid Build Coastguard Worker }
377*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_f)378*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_f) {
379*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
380*b9df5ad1SAndroid Build Coastguard Worker   p1.f = s3.f;
381*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
382*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
383*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.f is not clamped
384*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->f, s3.f);
385*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
386*b9df5ad1SAndroid Build Coastguard Worker   clamped->f = s2.f;
387*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
388*b9df5ad1SAndroid Build Coastguard Worker }
389*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_g)390*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_g) {
391*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
392*b9df5ad1SAndroid Build Coastguard Worker   p1.g = s3.g;
393*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
394*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
395*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.g is not clamped
396*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->g, s3.g);
397*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
398*b9df5ad1SAndroid Build Coastguard Worker   clamped->g = s2.g;
399*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
400*b9df5ad1SAndroid Build Coastguard Worker }
401*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_to_min_h)402*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_to_min_h) {
403*b9df5ad1SAndroid Build Coastguard Worker   OpTestS p1 = s1;
404*b9df5ad1SAndroid Build Coastguard Worker   p1.h = s3.h;
405*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped = elementwise_clamp(p1, s2, s3);
406*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
407*b9df5ad1SAndroid Build Coastguard Worker   // ensure p1.g is not clamped
408*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->h, s3.h);
409*b9df5ad1SAndroid Build Coastguard Worker   // ensure all other members correctly clamped to max
410*b9df5ad1SAndroid Build Coastguard Worker   clamped->h = s2.h;
411*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s2);
412*b9df5ad1SAndroid Build Coastguard Worker }
413*b9df5ad1SAndroid Build Coastguard Worker 
414*b9df5ad1SAndroid Build Coastguard Worker // test vector clamp with same size target and min/max
TEST(ClampOpTest,clamp_vector_same_size)415*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_vector_same_size) {
416*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
417*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
418*b9df5ad1SAndroid Build Coastguard Worker 
419*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {1, 11, 21};
420*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {10, 20, 30};
421*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {0, 30, 21};
422*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> expect = {1, 20, 21};
423*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
424*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
425*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, expect);
426*b9df5ad1SAndroid Build Coastguard Worker 
427*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {10, 11, 1};
428*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {10, 20, 30};
429*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {20, 20, 20};
430*b9df5ad1SAndroid Build Coastguard Worker   expect = {10, 20, 20};
431*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
432*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
433*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, expect);
434*b9df5ad1SAndroid Build Coastguard Worker 
435*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, min);
436*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
437*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, min);
438*b9df5ad1SAndroid Build Coastguard Worker 
439*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, max, max);
440*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
441*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, max);
442*b9df5ad1SAndroid Build Coastguard Worker }
443*b9df5ad1SAndroid Build Coastguard Worker 
444*b9df5ad1SAndroid Build Coastguard Worker // test vector clamp with one element min and max
TEST(ClampOpTest,clamp_vector_one_member_min_max)445*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_vector_one_member_min_max) {
446*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
447*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
448*b9df5ad1SAndroid Build Coastguard Worker 
449*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {10};
450*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {20};
451*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {0, 30, 20};
452*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> expect = {10, 20, 20};
453*b9df5ad1SAndroid Build Coastguard Worker 
454*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
455*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
456*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, expect);
457*b9df5ad1SAndroid Build Coastguard Worker }
458*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_vector_one_min)459*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_vector_one_min) {
460*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
461*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
462*b9df5ad1SAndroid Build Coastguard Worker 
463*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0};
464*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {20, 10, 30};
465*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {-1, 30, 20};
466*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> expect = {0, 10, 20};
467*b9df5ad1SAndroid Build Coastguard Worker 
468*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
469*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
470*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, expect);
471*b9df5ad1SAndroid Build Coastguard Worker }
472*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_vector_one_max)473*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_vector_one_max) {
474*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
475*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
476*b9df5ad1SAndroid Build Coastguard Worker 
477*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0, 10, 20};
478*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {20};
479*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {-1, 30, 20};
480*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> expect = {0, 20, 20};
481*b9df5ad1SAndroid Build Coastguard Worker 
482*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
483*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
484*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->ss.d, expect);
485*b9df5ad1SAndroid Build Coastguard Worker }
486*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_vector_invalid_range)487*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_vector_invalid_range) {
488*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
489*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
490*b9df5ad1SAndroid Build Coastguard Worker 
491*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {-1, 30, 20};
492*b9df5ad1SAndroid Build Coastguard Worker   std::vector<float> expect = {0, 20, 20};
493*b9df5ad1SAndroid Build Coastguard Worker 
494*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0, 10};
495*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {20};
496*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
497*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
498*b9df5ad1SAndroid Build Coastguard Worker 
499*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0, 10, 20};
500*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {};
501*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
502*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
503*b9df5ad1SAndroid Build Coastguard Worker 
504*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {};
505*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {0, 10, 20};
506*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
507*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
508*b9df5ad1SAndroid Build Coastguard Worker 
509*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0, 10, 20};
510*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {0, 10, 10};
511*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
512*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
513*b9df5ad1SAndroid Build Coastguard Worker 
514*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {0, 10, 5, 10};
515*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {0, 10, 10};
516*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
517*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
518*b9df5ad1SAndroid Build Coastguard Worker 
519*b9df5ad1SAndroid Build Coastguard Worker   min.ss.d = {};
520*b9df5ad1SAndroid Build Coastguard Worker   max.ss.d = {};
521*b9df5ad1SAndroid Build Coastguard Worker   target.ss.d = {};
522*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
523*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped, std::nullopt);
524*b9df5ad1SAndroid Build Coastguard Worker }
525*b9df5ad1SAndroid Build Coastguard Worker 
TEST(ClampOpTest,clamp_string)526*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_string) {
527*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
528*b9df5ad1SAndroid Build Coastguard Worker   OpTestS target = s2, min = s1, max = s3;
529*b9df5ad1SAndroid Build Coastguard Worker 
530*b9df5ad1SAndroid Build Coastguard Worker   min.h = "";
531*b9df5ad1SAndroid Build Coastguard Worker   max.h = "";
532*b9df5ad1SAndroid Build Coastguard Worker   target.h = "";
533*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
534*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, target);
535*b9df5ad1SAndroid Build Coastguard Worker 
536*b9df5ad1SAndroid Build Coastguard Worker   min.h = "apple";
537*b9df5ad1SAndroid Build Coastguard Worker   max.h = "pear";
538*b9df5ad1SAndroid Build Coastguard Worker   target.h = "orange";
539*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
540*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
541*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->h, std::clamp(target.h, min.h, max.h));
542*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, target);
543*b9df5ad1SAndroid Build Coastguard Worker 
544*b9df5ad1SAndroid Build Coastguard Worker   target.h = "aardvark";
545*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
546*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
547*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->h, std::clamp(target.h, min.h, max.h));
548*b9df5ad1SAndroid Build Coastguard Worker   target.h = clamped->h;
549*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, target);
550*b9df5ad1SAndroid Build Coastguard Worker 
551*b9df5ad1SAndroid Build Coastguard Worker   target.h = "zebra";
552*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(target, min, max);
553*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
554*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(clamped->h, std::clamp(target.h, min.h, max.h));
555*b9df5ad1SAndroid Build Coastguard Worker   target.h = clamped->h;
556*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, target);
557*b9df5ad1SAndroid Build Coastguard Worker }
558*b9df5ad1SAndroid Build Coastguard Worker 
559*b9df5ad1SAndroid Build Coastguard Worker // clamp a mixed structure in range
TEST(ClampOpTest,clamp_mixed)560*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_mixed) {
561*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
562*b9df5ad1SAndroid Build Coastguard Worker 
563*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s_mixed, s1, s3);
564*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
565*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s_clamped_1_3);
566*b9df5ad1SAndroid Build Coastguard Worker 
567*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s_mixed, s2, s3);
568*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
569*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s_clamped_2_3);
570*b9df5ad1SAndroid Build Coastguard Worker }
571*b9df5ad1SAndroid Build Coastguard Worker 
572*b9df5ad1SAndroid Build Coastguard Worker // clamp a mixed structure in range
TEST(ClampOpTest,clamp_primitive_type)573*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_primitive_type) {
574*b9df5ad1SAndroid Build Coastguard Worker   std::optional<OpTestS> clamped;
575*b9df5ad1SAndroid Build Coastguard Worker 
576*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s_mixed, s1, s3);
577*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
578*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s_clamped_1_3);
579*b9df5ad1SAndroid Build Coastguard Worker 
580*b9df5ad1SAndroid Build Coastguard Worker   clamped = elementwise_clamp(s_mixed, s2, s3);
581*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(clamped, std::nullopt);
582*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(*clamped, s_clamped_2_3);
583*b9df5ad1SAndroid Build Coastguard Worker }
584*b9df5ad1SAndroid Build Coastguard Worker 
585*b9df5ad1SAndroid Build Coastguard Worker // Template function to return an array of size N
586*b9df5ad1SAndroid Build Coastguard Worker template <size_t N>
getArrayN()587*b9df5ad1SAndroid Build Coastguard Worker auto getArrayN() {
588*b9df5ad1SAndroid Build Coastguard Worker   return std::array<int, N>{};
589*b9df5ad1SAndroid Build Coastguard Worker }
590*b9df5ad1SAndroid Build Coastguard Worker 
591*b9df5ad1SAndroid Build Coastguard Worker // Recursive function to make a tuple of arrays up to size N
592*b9df5ad1SAndroid Build Coastguard Worker template <std::size_t N>
makeTupleOfArrays()593*b9df5ad1SAndroid Build Coastguard Worker auto makeTupleOfArrays() {
594*b9df5ad1SAndroid Build Coastguard Worker   if constexpr (N == 1) {
595*b9df5ad1SAndroid Build Coastguard Worker     return std::make_tuple(getArrayN<1>());
596*b9df5ad1SAndroid Build Coastguard Worker   } else {
597*b9df5ad1SAndroid Build Coastguard Worker     return std::tuple_cat(makeTupleOfArrays<N - 1>(),
598*b9df5ad1SAndroid Build Coastguard Worker                           std::make_tuple(getArrayN<N>()));
599*b9df5ad1SAndroid Build Coastguard Worker   }
600*b9df5ad1SAndroid Build Coastguard Worker }
601*b9df5ad1SAndroid Build Coastguard Worker 
602*b9df5ad1SAndroid Build Coastguard Worker // test the clamp utility can handle structures with up to
603*b9df5ad1SAndroid Build Coastguard Worker // `android::audio_utils::kMaxStructMember` members
TEST(ClampOpTest,clamp_different_struct_members)604*b9df5ad1SAndroid Build Coastguard Worker TEST(ClampOpTest, clamp_different_struct_members) {
605*b9df5ad1SAndroid Build Coastguard Worker   auto clampVerifyOp = [](auto&& arr) {
606*b9df5ad1SAndroid Build Coastguard Worker     auto m1(arr), m2(arr), m3(arr);
607*b9df5ad1SAndroid Build Coastguard Worker     m1.fill(1);
608*b9df5ad1SAndroid Build Coastguard Worker     m2.fill(2);
609*b9df5ad1SAndroid Build Coastguard Worker     m3.fill(3);
610*b9df5ad1SAndroid Build Coastguard Worker 
611*b9df5ad1SAndroid Build Coastguard Worker     auto clamped = elementwise_clamp(m2, m1, m3);
612*b9df5ad1SAndroid Build Coastguard Worker     ASSERT_NE(clamped, std::nullopt);
613*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(*clamped, m2);
614*b9df5ad1SAndroid Build Coastguard Worker 
615*b9df5ad1SAndroid Build Coastguard Worker     clamped = elementwise_clamp(m1, m2, m3);
616*b9df5ad1SAndroid Build Coastguard Worker     ASSERT_NE(clamped, std::nullopt);
617*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(*clamped, m2);
618*b9df5ad1SAndroid Build Coastguard Worker 
619*b9df5ad1SAndroid Build Coastguard Worker     clamped = elementwise_clamp(m3, m1, m2);
620*b9df5ad1SAndroid Build Coastguard Worker     ASSERT_NE(clamped, std::nullopt);
621*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(*clamped, m2);
622*b9df5ad1SAndroid Build Coastguard Worker 
623*b9df5ad1SAndroid Build Coastguard Worker     // invalid range
624*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(elementwise_clamp(m3, m2, m1), std::nullopt);
625*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(elementwise_clamp(m3, m3, m1), std::nullopt);
626*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(elementwise_clamp(m3, m3, m2), std::nullopt);
627*b9df5ad1SAndroid Build Coastguard Worker   };
628*b9df5ad1SAndroid Build Coastguard Worker 
629*b9df5ad1SAndroid Build Coastguard Worker   auto arrays = makeTupleOfArrays<kMaxStructMember>();
630*b9df5ad1SAndroid Build Coastguard Worker   for (size_t i = 0; i < kMaxStructMember; i++) {
631*b9df5ad1SAndroid Build Coastguard Worker     op_tuple_elements(arrays, i, clampVerifyOp);
632*b9df5ad1SAndroid Build Coastguard Worker   }
633*b9df5ad1SAndroid Build Coastguard Worker }
634*b9df5ad1SAndroid Build Coastguard Worker 
635*b9df5ad1SAndroid Build Coastguard Worker template <typename T>
MinMaxOpTestHelper(const T & a,const T & b,const T & expectedLower,const T & expectedUpper,const std::optional<T> & unexpected=std::nullopt)636*b9df5ad1SAndroid Build Coastguard Worker void MinMaxOpTestHelper(const T& a, const T& b, const T& expectedLower,
637*b9df5ad1SAndroid Build Coastguard Worker                         const T& expectedUpper,
638*b9df5ad1SAndroid Build Coastguard Worker                         const std::optional<T>& unexpected = std::nullopt) {
639*b9df5ad1SAndroid Build Coastguard Worker   // lower
640*b9df5ad1SAndroid Build Coastguard Worker   auto result = elementwise_min(a, b);
641*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(unexpected, *result);
642*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(expectedLower, *result);
643*b9df5ad1SAndroid Build Coastguard Worker 
644*b9df5ad1SAndroid Build Coastguard Worker   result = elementwise_min(b, a);
645*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(unexpected, *result);
646*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(expectedLower, *result);
647*b9df5ad1SAndroid Build Coastguard Worker 
648*b9df5ad1SAndroid Build Coastguard Worker   result = elementwise_min(a, a);
649*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(a, elementwise_min(a, a));
650*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(b, elementwise_min(b, b));
651*b9df5ad1SAndroid Build Coastguard Worker 
652*b9df5ad1SAndroid Build Coastguard Worker   // upper
653*b9df5ad1SAndroid Build Coastguard Worker   result = elementwise_max(a, b);
654*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(unexpected, result);
655*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(expectedUpper, *result);
656*b9df5ad1SAndroid Build Coastguard Worker 
657*b9df5ad1SAndroid Build Coastguard Worker   result = elementwise_max(b, a);
658*b9df5ad1SAndroid Build Coastguard Worker   ASSERT_NE(unexpected, result);
659*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(expectedUpper, *result);
660*b9df5ad1SAndroid Build Coastguard Worker 
661*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(a, elementwise_max(a, a));
662*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(b, elementwise_max(b, b));
663*b9df5ad1SAndroid Build Coastguard Worker }
664*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,primitive_type_int)665*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, primitive_type_int) {
666*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(1, 2, 1, 2));
667*b9df5ad1SAndroid Build Coastguard Worker }
668*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,primitive_type_float)669*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, primitive_type_float) {
670*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(.1f, .2f, .1f, .2f));
671*b9df5ad1SAndroid Build Coastguard Worker }
672*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,primitive_type_string)673*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, primitive_type_string) {
674*b9df5ad1SAndroid Build Coastguard Worker   std::string a = "ab", b = "ba";
675*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
676*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(a, b, std::min(a, b), std::max(a, b)));
677*b9df5ad1SAndroid Build Coastguard Worker   a = "", b = "0";
678*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
679*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(a, b, std::min(a, b), std::max(a, b)));
680*b9df5ad1SAndroid Build Coastguard Worker   a = "abc", b = "1234";
681*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
682*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(a, b, std::min(a, b), std::max(a, b)));
683*b9df5ad1SAndroid Build Coastguard Worker }
684*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,primitive_type_enum)685*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, primitive_type_enum) {
686*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(OpTestEnum::E1, OpTestEnum::E2,
687*b9df5ad1SAndroid Build Coastguard Worker                                              OpTestEnum::E1, OpTestEnum::E2));
688*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(OpTestEnum::E3, OpTestEnum::E2,
689*b9df5ad1SAndroid Build Coastguard Worker                                              OpTestEnum::E2, OpTestEnum::E3));
690*b9df5ad1SAndroid Build Coastguard Worker }
691*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,vector_same_size)692*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, vector_same_size) {
693*b9df5ad1SAndroid Build Coastguard Worker   std::vector<int> v1, v2, expected_lower, expected_upper;
694*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
695*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
696*b9df5ad1SAndroid Build Coastguard Worker 
697*b9df5ad1SAndroid Build Coastguard Worker   v1 = {1}, v2 = {2}, expected_lower = {1}, expected_upper = {2};
698*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
699*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
700*b9df5ad1SAndroid Build Coastguard Worker 
701*b9df5ad1SAndroid Build Coastguard Worker   v1 = {3, 2, 3}, v2 = {2, 2, 2}, expected_lower = v2, expected_upper = v1;
702*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
703*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
704*b9df5ad1SAndroid Build Coastguard Worker 
705*b9df5ad1SAndroid Build Coastguard Worker   v1 = {3, 2, 3}, v2 = {1, 4, 1}, expected_lower = {1, 2, 1},
706*b9df5ad1SAndroid Build Coastguard Worker   expected_upper = {3, 4, 3};
707*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
708*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
709*b9df5ad1SAndroid Build Coastguard Worker }
710*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,vector_different_size_valid)711*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, vector_different_size_valid) {
712*b9df5ad1SAndroid Build Coastguard Worker   std::vector<int> v1, v2({1}), expected_lower, expected_upper({1});
713*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
714*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
715*b9df5ad1SAndroid Build Coastguard Worker 
716*b9df5ad1SAndroid Build Coastguard Worker   v1 = {1, 2, 3, 1, 0, 5}, v2 = {2}, expected_lower = {1, 2, 2, 1, 0, 2},
717*b9df5ad1SAndroid Build Coastguard Worker   expected_upper = {2, 2, 3, 2, 2, 5};
718*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(
719*b9df5ad1SAndroid Build Coastguard Worker       MinMaxOpTestHelper(v1, v2, expected_lower, expected_upper));
720*b9df5ad1SAndroid Build Coastguard Worker }
721*b9df5ad1SAndroid Build Coastguard Worker 
722*b9df5ad1SAndroid Build Coastguard Worker // invalid vector size combination, expect std::nullopt
TEST(MinMaxOpTest,invalid_vector_size)723*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, invalid_vector_size) {
724*b9df5ad1SAndroid Build Coastguard Worker   std::vector<int> v1 = {3, 2}, v2 = {2, 2, 2};
725*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(v1, v2));
726*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(v2, v1));
727*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(v1, v2));
728*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(v2, v1));
729*b9df5ad1SAndroid Build Coastguard Worker }
730*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,aggregate_type)731*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, aggregate_type) {
732*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(sss1, sss2, sss1, sss2));
733*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(sss2, sss3, sss2, sss3));
734*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(sss1, sss3, sss1, sss3));
735*b9df5ad1SAndroid Build Coastguard Worker 
736*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(ss1, ss2, ss1, ss2));
737*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(ss2, ss3, ss2, ss3));
738*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(ss1, ss3, ss1, ss3));
739*b9df5ad1SAndroid Build Coastguard Worker 
740*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(s1, s2, s1, s2));
741*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(s2, s3, s2, s3));
742*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_NO_FATAL_FAILURE(MinMaxOpTestHelper(s1, s3, s1, s3));
743*b9df5ad1SAndroid Build Coastguard Worker }
744*b9df5ad1SAndroid Build Coastguard Worker 
745*b9df5ad1SAndroid Build Coastguard Worker // invalid vector size combination in nested structure
TEST(MinMaxOpTest,invalid_vector_in_structure)746*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, invalid_vector_in_structure) {
747*b9df5ad1SAndroid Build Coastguard Worker   auto tt1 = ss1, tt2 = ss2;
748*b9df5ad1SAndroid Build Coastguard Worker   tt1.d = {.1f, .2f, .3f};
749*b9df5ad1SAndroid Build Coastguard Worker   tt2.d = {.1f, .2f, .3f, .4f, .5f};
750*b9df5ad1SAndroid Build Coastguard Worker 
751*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(tt1, tt2));
752*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(tt2, tt1));
753*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(tt1, tt2));
754*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(tt2, tt1));
755*b9df5ad1SAndroid Build Coastguard Worker 
756*b9df5ad1SAndroid Build Coastguard Worker   auto t1 = s1, t2 = s2;
757*b9df5ad1SAndroid Build Coastguard Worker   t1.ss = tt1, t2.ss = tt2;
758*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(t1, t2));
759*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_min(t2, t1));
760*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(t1, t2));
761*b9df5ad1SAndroid Build Coastguard Worker   EXPECT_EQ(std::nullopt, elementwise_max(t2, t1));
762*b9df5ad1SAndroid Build Coastguard Worker }
763*b9df5ad1SAndroid Build Coastguard Worker 
TEST(MinMaxOpTest,aggregate_different_members)764*b9df5ad1SAndroid Build Coastguard Worker TEST(MinMaxOpTest, aggregate_different_members) {
765*b9df5ad1SAndroid Build Coastguard Worker   auto boundaryVerifyOp = [](auto&& arr) {
766*b9df5ad1SAndroid Build Coastguard Worker     auto m1(arr), m2(arr);
767*b9df5ad1SAndroid Build Coastguard Worker     m1.fill(1);
768*b9df5ad1SAndroid Build Coastguard Worker     m2.fill(2);
769*b9df5ad1SAndroid Build Coastguard Worker 
770*b9df5ad1SAndroid Build Coastguard Worker     auto lower = elementwise_min(m1, m2);
771*b9df5ad1SAndroid Build Coastguard Worker     ASSERT_NE(lower, std::nullopt);
772*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(*lower, m1);
773*b9df5ad1SAndroid Build Coastguard Worker 
774*b9df5ad1SAndroid Build Coastguard Worker     auto upper = elementwise_max(m1, m2);
775*b9df5ad1SAndroid Build Coastguard Worker     ASSERT_NE(upper, std::nullopt);
776*b9df5ad1SAndroid Build Coastguard Worker     EXPECT_EQ(*upper, m2);
777*b9df5ad1SAndroid Build Coastguard Worker   };
778*b9df5ad1SAndroid Build Coastguard Worker 
779*b9df5ad1SAndroid Build Coastguard Worker   auto arrays = makeTupleOfArrays<kMaxStructMember>();
780*b9df5ad1SAndroid Build Coastguard Worker   for (size_t i = 0; i < kMaxStructMember; i++) {
781*b9df5ad1SAndroid Build Coastguard Worker     op_tuple_elements(arrays, i, boundaryVerifyOp);
782*b9df5ad1SAndroid Build Coastguard Worker   }
783*b9df5ad1SAndroid Build Coastguard Worker }