1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        Error.h
4  * Description:  Error Header
5  *
6  * $Date:        20. June 2019
7  * $Revision:    V1.0.0
8  *
9  * Target Processor: Cortex-M cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 #ifndef _ASSERT_H_
29 #define _ASSERT_H_
30 #include "arm_math_types.h"
31 #include "arm_math_types_f16.h"
32 #include <exception>
33 #include "Test.h"
34 #include "Pattern.h"
35 
36 
37 #define UNKNOWN_ERROR 1
38 #define EQUAL_ERROR 2
39 #define NEAR_EQUAL_ERROR 3
40 #define RELATIVE_ERROR 4
41 #define SNR_ERROR 5
42 #define DIFFERENT_LENGTH_ERROR 6
43 #define BOOL_ERROR 7
44 #define MEMORY_ALLOCATION_ERROR 8
45 #define EMPTY_PATTERN_ERROR 9
46 #define TAIL_NOT_EMPTY_ERROR 10
47 #define CLOSE_ERROR 11
48 
49 namespace Client {
50 
51 // Exception used by tests and runner
52 // to report errors
53 class Error: public std::exception
54 {
55   public:
Error(Testing::errorID_t id,unsigned long nb)56     Error(Testing::errorID_t id,unsigned long nb)
57     {
58         this->errorID = id;
59         this->lineNumber = nb;
60         this->details[0]='\0';
61     };
62 
Error(Testing::errorID_t id,unsigned long nb,const char * details)63     Error(Testing::errorID_t id,unsigned long nb, const char *details)
64     {
65         this->errorID = id;
66         this->lineNumber = nb;
67         strcpy(this->details,details);
68     };
69 
70     Testing::errorID_t errorID;
71     unsigned long lineNumber;
72     char details[200];
73 };
74 
75 /*
76 
77 Several test functions to implement tests in the client.
78 They should not be called directly but through macro
79 to get the line number.
80 
81 (SNR functions to finish implementing)
82 
83 */
84 #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
85 extern void assert_relative_error(unsigned long nb,float16_t &a, float16_t &b, double threshold);
86 extern void assert_relative_error(unsigned long nb,AnyPattern<float16_t> &pa, AnyPattern<float16_t> &pb, double threshold);
87 #endif
88 
89 extern void assert_relative_error(unsigned long nb,float32_t &a, float32_t &b, double threshold);
90 extern void assert_relative_error(unsigned long nb,AnyPattern<float32_t> &pa, AnyPattern<float32_t> &pb, double threshold);
91 
92 extern void assert_relative_error(unsigned long nb,float64_t &a, float64_t &b, double threshold);
93 extern void assert_relative_error(unsigned long nb,AnyPattern<float64_t> &pa, AnyPattern<float64_t> &pb, double threshold);
94 
95 /* Similar to numpy isclose */
96 extern void assert_close_error(unsigned long nb,float64_t &ref, float64_t &val, double absthreshold, double relthreshold);
97 extern void assert_close_error(unsigned long nb,AnyPattern<float64_t> &pref, AnyPattern<float64_t> &pval, double absthreshold, double relthreshold);
98 
99 extern void assert_close_error(unsigned long nb,float32_t &ref, float32_t &val, double absthreshold, double relthreshold);
100 extern void assert_close_error(unsigned long nb,AnyPattern<float32_t> &pref, AnyPattern<float32_t> &pval, double absthreshold, double relthreshold);
101 
102 #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
103 extern void assert_close_error(unsigned long nb,float16_t &ref, float16_t &val, double absthreshold, double relthreshold);
104 extern void assert_close_error(unsigned long nb,AnyPattern<float16_t> &pref, AnyPattern<float16_t> &pval, double absthreshold, double relthreshold);
105 #endif
106 
107 extern void assert_snr_error(unsigned long nb,AnyPattern<float64_t> &pa,AnyPattern<float64_t> &pb, float64_t threshold);
108 extern void assert_snr_error(unsigned long nb,AnyPattern<float32_t> &pa,AnyPattern<float32_t> &pb, float32_t threshold);
109 
110 #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
111 extern void assert_snr_error(unsigned long nb,AnyPattern<float16_t> &pa,AnyPattern<float16_t> &pb, float32_t threshold);
112 #endif
113 
114 extern void assert_snr_error(unsigned long nb,AnyPattern<q63_t> &pa,AnyPattern<q63_t> &pb, float32_t threshold);
115 extern void assert_snr_error(unsigned long nb,AnyPattern<q31_t> &pa,AnyPattern<q31_t> &pb, float32_t threshold);
116 extern void assert_snr_error(unsigned long nb,AnyPattern<q15_t> &pa,AnyPattern<q15_t> &pb, float32_t threshold);
117 extern void assert_snr_error(unsigned long nb,AnyPattern<q7_t> &pa,AnyPattern<q7_t> &pb, float32_t threshold);
118 
119 extern void assert_snr_error(unsigned long nb,float64_t pa,float64_t pb, float64_t threshold);
120 extern void assert_snr_error(unsigned long nb,float32_t pa,float32_t pb, float32_t threshold);
121 
122 #if !defined (__CC_ARM) && defined(ARM_FLOAT16_SUPPORTED)
123 extern void assert_snr_error(unsigned long nb,float16_t pa,float16_t pb, float32_t threshold);
124 #endif
125 
126 extern void assert_snr_error(unsigned long nb,q63_t pa,q63_t pb, float32_t threshold);
127 extern void assert_snr_error(unsigned long nb,q31_t pa,q31_t pb, float32_t threshold);
128 extern void assert_snr_error(unsigned long nb,q15_t pa,q15_t pb, float32_t threshold);
129 extern void assert_snr_error(unsigned long nb,q7_t pa,q7_t pb, float32_t threshold);
130 
131 extern void assert_true(unsigned long nb,bool cond);
132 extern void assert_false(unsigned long nb,bool cond);
133 
134 extern void assert_not_empty(unsigned long nb, AnyPattern<float64_t> &p);
135 extern void assert_not_empty(unsigned long nb, AnyPattern<float32_t> &p);
136 
137 #if !defined( __CC_ARM ) && defined(ARM_FLOAT16_SUPPORTED)
138 extern void assert_not_empty(unsigned long nb, AnyPattern<float16_t> &p);
139 #endif
140 
141 extern void assert_not_empty(unsigned long nb, AnyPattern<q63_t> &p);
142 extern void assert_not_empty(unsigned long nb, AnyPattern<q31_t> &p);
143 extern void assert_not_empty(unsigned long nb, AnyPattern<q15_t> &p);
144 extern void assert_not_empty(unsigned long nb, AnyPattern<q7_t> &p);
145 extern void assert_not_empty(unsigned long nb, AnyPattern<uint32_t> &p);
146 extern void assert_not_empty(unsigned long nb, AnyPattern<uint16_t> &p);
147 extern void assert_not_empty(unsigned long nb, AnyPattern<uint8_t> &p);
148 
149 }
150 
151 /*
152 
153 Macros to use to implement tests.
154 
155 */
156 #define ASSERT_EQ(A,B) Client::assert_equal(__LINE__,A,B)
157 #define ASSERT_EQ_PARTIAL(NB,A,B) Client::assert_equal_partial(__LINE__,NB,A,B)
158 
159 #define ASSERT_NEAR_EQ(A,B,THRESH) Client::assert_near_equal(__LINE__,A,B,THRESH)
160 #define ASSERT_REL_ERROR(A,B,THRESH) Client::assert_relative_error(__LINE__,A,B,THRESH)
161 #define ASSERT_CLOSE_ERROR(A,B,ABSTHRESH,RELTHRESH) Client::assert_close_error(__LINE__,A,B,ABSTHRESH,RELTHRESH)
162 #define ASSERT_SNR(A,B,SNR) Client::assert_snr_error(__LINE__,A,B,SNR)
163 #define ASSERT_TRUE(A) Client::assert_true(__LINE__,A)
164 #define ASSERT_FALSE(A) Client::assert_false(__LINE__,A)
165 #define ASSERT_NOT_EMPTY(A) Client::assert_not_empty(__LINE__,A)
166 #define ASSERT_EMPTY_TAIL(A) if (!A.isTailEmpty()) throw (Client::Error(TAIL_NOT_EMPTY_ERROR,__LINE__))
167 
168 namespace Client {
169 
170 using namespace std;
171 
172 template <typename T>
assert_equal(unsigned long nb,T pa,T pb)173 void assert_equal(unsigned long nb,T pa, T pb)
174 {
175     if (pa != pb)
176     {
177          throw (Error(EQUAL_ERROR,nb));
178     }
179 
180 };
181 
182 template <typename T>
assert_equal_partial(unsigned long nb,unsigned long nbSamples,AnyPattern<T> & pa,AnyPattern<T> & pb)183 void assert_equal_partial(unsigned long nb,unsigned long nbSamples,AnyPattern<T> &pa, AnyPattern<T> &pb)
184 {
185     ASSERT_NOT_EMPTY(pa);
186     ASSERT_NOT_EMPTY(pb);
187 
188     if (pa.nbSamples() < nbSamples)
189     {
190         throw (Error(EQUAL_ERROR,nb));
191     }
192 
193     if (pb.nbSamples() < nbSamples)
194     {
195         throw (Error(EQUAL_ERROR,nb));
196     }
197 
198     unsigned long i=0;
199     char id[40];
200 
201     T *ptrA = pa.ptr();
202     T *ptrB = pb.ptr();
203 
204     for(i=0; i < nbSamples; i++)
205     {
206        try
207        {
208           assert_equal(nb,ptrA[i],ptrB[i]);
209        }
210        catch(Error &err)
211        {
212           sprintf(id," (nb=%lu)",i);
213           strcat(err.details,id);
214           throw(err);
215        }
216     }
217 };
218 
219 template <typename T>
assert_equal(unsigned long nb,AnyPattern<T> & pa,AnyPattern<T> & pb)220 void assert_equal(unsigned long nb,AnyPattern<T> &pa, AnyPattern<T> &pb)
221 {
222     ASSERT_NOT_EMPTY(pa);
223     ASSERT_NOT_EMPTY(pb);
224 
225     if (pa.nbSamples() != pb.nbSamples())
226     {
227         throw (Error(EQUAL_ERROR,nb));
228     }
229 
230     unsigned long i=0;
231     char id[40];
232 
233     T *ptrA = pa.ptr();
234     T *ptrB = pb.ptr();
235 
236     for(i=0; i < pa.nbSamples(); i++)
237     {
238        try
239        {
240           assert_equal(nb,ptrA[i],ptrB[i]);
241        }
242        catch(Error &err)
243        {
244           sprintf(id," (nb=%lu)",i);
245           strcat(err.details,id);
246           throw(err);
247        }
248     }
249 };
250 
251 template <typename T>
assert_near_equal(unsigned long nb,T pa,T pb,T threshold)252 void assert_near_equal(unsigned long nb,T pa, T pb, T threshold)
253 {
254     if (abs(pa - pb) > threshold)
255     {
256          throw (Error(NEAR_EQUAL_ERROR,nb));
257     }
258 };
259 
260 template <>
261 void assert_near_equal(unsigned long nb,double pa, double pb, double threshold);
262 template <>
263 void assert_near_equal(unsigned long nb,float32_t pa, float32_t pb, float32_t threshold);
264 template <>
265 void assert_near_equal(unsigned long nb,q63_t pa, q63_t pb, q63_t threshold);
266 template <>
267 void assert_near_equal(unsigned long nb,q31_t pa, q31_t pb, q31_t threshold);
268 template <>
269 void assert_near_equal(unsigned long nb,q15_t pa, q15_t pb, q15_t threshold);
270 template <>
271 void assert_near_equal(unsigned long nb,q7_t pa, q7_t pb, q7_t threshold);
272 
273 template <typename T>
assert_near_equal(unsigned long nb,AnyPattern<T> & pa,AnyPattern<T> & pb,T threshold)274 void assert_near_equal(unsigned long nb,AnyPattern<T> &pa, AnyPattern<T> &pb, T threshold)
275 {
276 
277     ASSERT_NOT_EMPTY(pa);
278     ASSERT_NOT_EMPTY(pb);
279 
280     if (pa.nbSamples() != pb.nbSamples())
281     {
282         throw (Error(NEAR_EQUAL_ERROR,nb));
283     }
284 
285     unsigned long i=0;
286     char id[40];
287 
288     T *ptrA = pa.ptr();
289     T *ptrB = pb.ptr();
290 
291     for(i=0; i < pa.nbSamples(); i++)
292     {
293 
294        try
295        {
296           assert_near_equal(nb,ptrA[i],ptrB[i],threshold);
297        }
298        catch(Error &err)
299        {
300           sprintf(id," (nb=%lu)",i);
301           strcat(err.details,id);
302           throw(err);
303        }
304     }
305 };
306 
307 
308 }
309 #endif
310