Error.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: Error.cpp
  4. * Description: Error functions
  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. #include "Error.h"
  29. namespace Client {
  30. template <typename T>
  31. void assert_not_empty_generic(unsigned long nb, AnyPattern<T> &p)
  32. {
  33. if (p.nbSamples() == 0)
  34. {
  35. throw (Error(EMPTY_PATTERN_ERROR,nb));
  36. }
  37. if (p.ptr() == NULL)
  38. {
  39. throw (Error(EMPTY_PATTERN_ERROR,nb));
  40. }
  41. };
  42. template <>
  43. void assert_near_equal(unsigned long nb,float32_t pa, float32_t pb, float32_t threshold)
  44. {
  45. if (fabs(pa - pb) > threshold)
  46. {
  47. throw (Error(EQUAL_ERROR,nb));
  48. }
  49. };
  50. template <>
  51. void assert_near_equal(unsigned long nb,AnyPattern<float32_t> &pa, AnyPattern<float32_t> &pb, float32_t threshold)
  52. {
  53. ASSERT_NOT_EMPTY(pa);
  54. ASSERT_NOT_EMPTY(pb);
  55. if (pa.nbSamples() != pb.nbSamples())
  56. {
  57. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  58. }
  59. unsigned long i=0;
  60. float32_t *ptrA = pa.ptr();
  61. float32_t *ptrB = pb.ptr();
  62. for(i=0; i < pa.nbSamples(); i++)
  63. {
  64. if (fabs(ptrA[i] - ptrB[i]) > threshold)
  65. {
  66. throw (Error(NEAR_EQUAL_ERROR,nb));
  67. }
  68. }
  69. };
  70. void assert_not_empty(unsigned long nb, AnyPattern<float32_t> &p)
  71. {
  72. assert_not_empty_generic(nb,p);
  73. }
  74. void assert_not_empty(unsigned long nb, AnyPattern<q63_t> &p)
  75. {
  76. assert_not_empty_generic(nb,p);
  77. }
  78. void assert_not_empty(unsigned long nb, AnyPattern<q31_t> &p)
  79. {
  80. assert_not_empty_generic(nb,p);
  81. }
  82. void assert_not_empty(unsigned long nb, AnyPattern<q15_t> &p)
  83. {
  84. assert_not_empty_generic(nb,p);
  85. }
  86. void assert_not_empty(unsigned long nb, AnyPattern<q7_t> &p)
  87. {
  88. assert_not_empty_generic(nb,p);
  89. }
  90. void assert_relative_error(unsigned long nb,float32_t &a, float32_t &b, double threshold)
  91. {
  92. double rel,delta,average;
  93. delta=abs(a-b);
  94. average = (abs(a) + abs(b)) / 2.0f;
  95. if (average !=0)
  96. {
  97. rel = delta / average;
  98. //printf("%6.9f %6.9f %6.9f\n",a,b,rel);
  99. if (rel > threshold)
  100. {
  101. throw (Error(RELATIVE_ERROR,nb));
  102. }
  103. }
  104. };
  105. void assert_relative_error(unsigned long nb,AnyPattern<float32_t> &pa, AnyPattern<float32_t> &pb, double threshold)
  106. {
  107. ASSERT_NOT_EMPTY(pa);
  108. ASSERT_NOT_EMPTY(pb);
  109. if (pa.nbSamples() != pb.nbSamples())
  110. {
  111. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  112. }
  113. unsigned long i=0;
  114. float32_t *ptrA = pa.ptr();
  115. float32_t *ptrB = pb.ptr();
  116. for(i=0; i < pa.nbSamples(); i++)
  117. {
  118. assert_relative_error(nb,ptrA[i],ptrB[i],threshold);
  119. }
  120. };
  121. /**
  122. * @brief Calculation of SNR
  123. * @param float* Pointer to the reference buffer
  124. * @param float* Pointer to the test buffer
  125. * @param uint32_t total number of samples
  126. * @return float SNR
  127. * The function calculates signal to noise ratio for the reference output
  128. * and test output
  129. */
  130. /* If NaN, force SNR to 0.0 to ensure test will fail */
  131. #define IFNANRETURNZERO(val)\
  132. if (isnan((val))) \
  133. { \
  134. return(0.0); \
  135. }
  136. #define IFINFINITERETURN(val,def)\
  137. if (isinf((val))) \
  138. { \
  139. if ((val) > 0) \
  140. { \
  141. return(def); \
  142. } \
  143. else \
  144. { \
  145. return(-def); \
  146. } \
  147. }
  148. float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize)
  149. {
  150. float EnergySignal = 0.0, EnergyError = 0.0;
  151. uint32_t i;
  152. float SNR;
  153. for (i = 0; i < buffSize; i++)
  154. {
  155. /* Checking for a NAN value in pRef array */
  156. IFNANRETURNZERO(pRef[i]);
  157. /* Checking for a NAN value in pTest array */
  158. IFNANRETURNZERO(pTest[i]);
  159. EnergySignal += pRef[i] * pRef[i];
  160. EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
  161. }
  162. /* Checking for a NAN value in EnergyError */
  163. IFNANRETURNZERO(EnergyError);
  164. SNR = 10 * log10f (EnergySignal / EnergyError);
  165. /* Checking for a NAN value in SNR */
  166. IFNANRETURNZERO(SNR);
  167. IFINFINITERETURN(SNR,100000.0);
  168. return (SNR);
  169. }
  170. float arm_snr_q63(q63_t *pRef, q63_t *pTest, uint32_t buffSize)
  171. {
  172. double EnergySignal = 0.0, EnergyError = 0.0;
  173. uint32_t i;
  174. float SNR;
  175. double testVal,refVal;
  176. for (i = 0; i < buffSize; i++)
  177. {
  178. testVal = ((float32_t)pTest[i]) / 9223372036854775808.0;
  179. refVal = ((float32_t)pRef[i]) / 9223372036854775808.0;
  180. EnergySignal += refVal * refVal;
  181. EnergyError += (refVal - testVal) * (refVal - testVal);
  182. }
  183. SNR = 10 * log10 (EnergySignal / EnergyError);
  184. /* Checking for a NAN value in SNR */
  185. IFNANRETURNZERO(SNR);
  186. IFINFINITERETURN(SNR,100000.0);
  187. //printf("SNR = %f\n",SNR);
  188. return (SNR);
  189. }
  190. float arm_snr_q31(q31_t *pRef, q31_t *pTest, uint32_t buffSize)
  191. {
  192. float EnergySignal = 0.0, EnergyError = 0.0;
  193. uint32_t i;
  194. float SNR;
  195. float32_t testVal,refVal;
  196. for (i = 0; i < buffSize; i++)
  197. {
  198. testVal = ((float32_t)pTest[i]) / 2147483648.0f;
  199. refVal = ((float32_t)pRef[i]) / 2147483648.0f;
  200. EnergySignal += refVal * refVal;
  201. EnergyError += (refVal - testVal) * (refVal - testVal);
  202. }
  203. SNR = 10 * log10f (EnergySignal / EnergyError);
  204. /* Checking for a NAN value in SNR */
  205. IFNANRETURNZERO(SNR);
  206. IFINFINITERETURN(SNR,100000.0);
  207. //printf("SNR = %f\n",SNR);
  208. return (SNR);
  209. }
  210. float arm_snr_q15(q15_t *pRef, q15_t *pTest, uint32_t buffSize)
  211. {
  212. float EnergySignal = 0.0, EnergyError = 0.0;
  213. uint32_t i;
  214. float SNR;
  215. float32_t testVal,refVal;
  216. for (i = 0; i < buffSize; i++)
  217. {
  218. testVal = ((float32_t)pTest[i]) / 32768.0f;
  219. refVal = ((float32_t)pRef[i]) / 32768.0f;
  220. EnergySignal += refVal * refVal;
  221. EnergyError += (refVal - testVal) * (refVal - testVal);
  222. }
  223. SNR = 10 * log10f (EnergySignal / EnergyError);
  224. /* Checking for a NAN value in SNR */
  225. IFNANRETURNZERO(SNR);
  226. IFINFINITERETURN(SNR,100000.0);
  227. //printf("SNR = %f\n",SNR);
  228. return (SNR);
  229. }
  230. float arm_snr_q7(q7_t *pRef, q7_t *pTest, uint32_t buffSize)
  231. {
  232. float EnergySignal = 0.0, EnergyError = 0.0;
  233. uint32_t i;
  234. float SNR;
  235. float32_t testVal,refVal;
  236. for (i = 0; i < buffSize; i++)
  237. {
  238. testVal = ((float32_t)pTest[i]) / 128.0f;
  239. refVal = ((float32_t)pRef[i]) / 128.0f;
  240. EnergySignal += refVal * refVal;
  241. EnergyError += (refVal - testVal) * (refVal - testVal);
  242. }
  243. SNR = 10 * log10f (EnergySignal / EnergyError);
  244. IFNANRETURNZERO(SNR);
  245. IFINFINITERETURN(SNR,100000.0);
  246. return (SNR);
  247. }
  248. double arm_snr_f64(double *pRef, double *pTest, uint32_t buffSize)
  249. {
  250. double EnergySignal = 0.0, EnergyError = 0.0;
  251. uint32_t i;
  252. double SNR;
  253. for (i = 0; i < buffSize; i++)
  254. {
  255. /* Checking for a NAN value in pRef array */
  256. IFNANRETURNZERO(pRef[i]);
  257. /* Checking for a NAN value in pTest array */
  258. IFNANRETURNZERO(pTest[i]);
  259. EnergySignal += pRef[i] * pRef[i];
  260. EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
  261. }
  262. /* Checking for a NAN value in EnergyError */
  263. IFNANRETURNZERO(EnergyError);
  264. SNR = 10 * log10 (EnergySignal / EnergyError);
  265. /* Checking for a NAN value in SNR */
  266. IFNANRETURNZERO(SNR);
  267. IFINFINITERETURN(SNR,100000.0);
  268. return (SNR);
  269. }
  270. void assert_snr_error(unsigned long nb,AnyPattern<float32_t> &pa,AnyPattern<float32_t> &pb, float32_t threshold)
  271. {
  272. float32_t snr;
  273. ASSERT_NOT_EMPTY(pa);
  274. ASSERT_NOT_EMPTY(pb);
  275. if (pa.nbSamples() != pb.nbSamples())
  276. {
  277. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  278. }
  279. float32_t *ptrA = pa.ptr();
  280. float32_t *ptrB = pb.ptr();
  281. snr = arm_snr_f32(ptrA, ptrB, pa.nbSamples());
  282. //printf("SNR = %f\n",snr);
  283. if (snr < threshold)
  284. {
  285. throw (Error(SNR_ERROR,nb));
  286. }
  287. }
  288. void assert_snr_error(unsigned long nb,AnyPattern<q63_t> &pa,AnyPattern<q63_t> &pb, float32_t threshold)
  289. {
  290. float32_t snr;
  291. ASSERT_NOT_EMPTY(pa);
  292. ASSERT_NOT_EMPTY(pb);
  293. if (pa.nbSamples() != pb.nbSamples())
  294. {
  295. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  296. }
  297. q63_t *ptrA = pa.ptr();
  298. q63_t *ptrB = pb.ptr();
  299. snr = arm_snr_q63(ptrA, ptrB, pa.nbSamples());
  300. //printf("SNR = %f\n",snr);
  301. if (snr < threshold)
  302. {
  303. throw (Error(SNR_ERROR,nb));
  304. }
  305. }
  306. void assert_snr_error(unsigned long nb,AnyPattern<q31_t> &pa,AnyPattern<q31_t> &pb, float32_t threshold)
  307. {
  308. float32_t snr;
  309. ASSERT_NOT_EMPTY(pa);
  310. ASSERT_NOT_EMPTY(pb);
  311. if (pa.nbSamples() != pb.nbSamples())
  312. {
  313. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  314. }
  315. q31_t *ptrA = pa.ptr();
  316. q31_t *ptrB = pb.ptr();
  317. snr = arm_snr_q31(ptrA, ptrB, pa.nbSamples());
  318. if (snr < threshold)
  319. {
  320. throw (Error(SNR_ERROR,nb));
  321. }
  322. }
  323. void assert_snr_error(unsigned long nb,AnyPattern<q15_t> &pa,AnyPattern<q15_t> &pb, float32_t threshold)
  324. {
  325. float32_t snr;
  326. ASSERT_NOT_EMPTY(pa);
  327. ASSERT_NOT_EMPTY(pb);
  328. if (pa.nbSamples() != pb.nbSamples())
  329. {
  330. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  331. }
  332. q15_t *ptrA = pa.ptr();
  333. q15_t *ptrB = pb.ptr();
  334. snr = arm_snr_q15(ptrA, ptrB, pa.nbSamples());
  335. //printf("SNR = %f\n",snr);
  336. if (snr < threshold)
  337. {
  338. throw (Error(SNR_ERROR,nb));
  339. }
  340. }
  341. void assert_snr_error(unsigned long nb,AnyPattern<q7_t> &pa,AnyPattern<q7_t> &pb, float32_t threshold)
  342. {
  343. float32_t snr;
  344. ASSERT_NOT_EMPTY(pa);
  345. ASSERT_NOT_EMPTY(pb);
  346. if (pa.nbSamples() != pb.nbSamples())
  347. {
  348. throw (Error(DIFFERENT_LENGTH_ERROR,nb));
  349. }
  350. q7_t *ptrA = pa.ptr();
  351. q7_t *ptrB = pb.ptr();
  352. snr = arm_snr_q7(ptrA, ptrB, pa.nbSamples());
  353. //printf("SNR = %f\n",snr);
  354. if (snr < threshold)
  355. {
  356. throw (Error(SNR_ERROR,nb));
  357. }
  358. }
  359. void assert_true(unsigned long nb,bool cond)
  360. {
  361. if (!cond)
  362. {
  363. throw (Error(BOOL_ERROR,nb));
  364. }
  365. }
  366. void assert_false(unsigned long nb,bool cond)
  367. {
  368. if (cond)
  369. {
  370. throw (Error(BOOL_ERROR,nb));
  371. }
  372. }
  373. }