Christophe Favergeon | 1838377 | 2021-04-30 15:00:14 +0200 | [diff] [blame^] | 1 | import cmsisdsp as dsp |
| 2 | import numpy as np |
| 3 | from scipy import signal |
| 4 | from scipy.fftpack import dct |
| 5 | import fixedpoint as f |
| 6 | from pyquaternion import Quaternion |
| 7 | |
| 8 | import colorama |
| 9 | from colorama import init,Fore, Back, Style |
| 10 | import statsmodels.tsa.stattools |
| 11 | |
| 12 | import scipy.spatial |
| 13 | |
| 14 | |
| 15 | init() |
| 16 | |
| 17 | def printTitle(s): |
| 18 | print("\n" + Fore.GREEN + Style.BRIGHT + s + Style.RESET_ALL) |
| 19 | |
| 20 | def printSubTitle(s): |
| 21 | print("\n" + Style.BRIGHT + s + Style.RESET_ALL) |
| 22 | |
| 23 | |
| 24 | def imToReal2D(a): |
| 25 | ar=np.zeros(np.array(a.shape) * [1,2]) |
| 26 | ar[::,0::2]=a.real |
| 27 | ar[::,1::2]=a.imag |
| 28 | return(ar) |
| 29 | |
| 30 | def realToIm2D(ar): |
| 31 | return(ar[::,0::2] + 1j * ar[::,1::2]) |
| 32 | |
| 33 | def normalize(a): |
| 34 | return(a/np.max(np.abs(a))) |
| 35 | |
| 36 | def autocorr(x): |
| 37 | result = np.correlate(x, x, mode='full') |
| 38 | return result[result.size//2:] |
| 39 | |
| 40 | #################### MAX AND ABSMAX ################################## |
| 41 | printTitle("Max and AbsMax") |
| 42 | a=np.array([1.,-3.,4.,0.,-10.,8.]) |
| 43 | |
| 44 | printSubTitle("Float tests") |
| 45 | i=dsp.arm_max_f32(a) |
| 46 | print(i) |
| 47 | |
| 48 | i=dsp.arm_absmax_f32(a) |
| 49 | print(i) |
| 50 | |
| 51 | printSubTitle("Fixed point tests") |
| 52 | |
| 53 | # Normalize for fixed point tests |
| 54 | a = a / i[0] |
| 55 | |
| 56 | a31 = f.toQ31(a) |
| 57 | i=dsp.arm_absmax_q31(a31) |
| 58 | print(f.Q31toF32(i[0]),i[1]) |
| 59 | |
| 60 | a8 = f.toQ15(a) |
| 61 | i=dsp.arm_absmax_q15(a8) |
| 62 | print(f.Q15toF32(i[0]),i[1]) |
| 63 | |
| 64 | a7 = f.toQ7(a) |
| 65 | i=dsp.arm_absmax_q7(a7) |
| 66 | print(f.Q7toF32(i[0]),i[1]) |
| 67 | |
| 68 | ################### MIN AND ABSMIN ################################ |
| 69 | |
| 70 | printTitle("Min and AbsMin") |
| 71 | a=np.array([1.,-3.,4.,0.5,-10.,8.]) |
| 72 | |
| 73 | printSubTitle("Float tests") |
| 74 | i=dsp.arm_min_f32(a) |
| 75 | print(i) |
| 76 | |
| 77 | i=dsp.arm_absmin_f32(a) |
| 78 | print(i) |
| 79 | |
| 80 | printSubTitle("Fixed point tests") |
| 81 | |
| 82 | # Normalize for fixed point tests |
| 83 | idx=i[1] |
| 84 | i=dsp.arm_absmax_f32(a) |
| 85 | a = a / i[0] |
| 86 | print(a) |
| 87 | print(a[idx]) |
| 88 | |
| 89 | a31 = f.toQ31(a) |
| 90 | i=dsp.arm_absmin_q31(a31) |
| 91 | print(f.Q31toF32(i[0]),i[1]) |
| 92 | |
| 93 | a8 = f.toQ15(a) |
| 94 | i=dsp.arm_absmin_q15(a8) |
| 95 | print(f.Q15toF32(i[0]),i[1]) |
| 96 | |
| 97 | a7 = f.toQ7(a) |
| 98 | i=dsp.arm_absmin_q7(a7) |
| 99 | print(f.Q7toF32(i[0]),i[1]) |
| 100 | |
| 101 | ##################### CLIPPING ################### |
| 102 | printTitle("Clipping tests tests") |
| 103 | a=np.array([1.,-3.,4.,0.5,-10.,8.]) |
| 104 | i=dsp.arm_absmax_f32(a) |
| 105 | |
| 106 | minBound =-5.0 |
| 107 | maxBound =6.0 |
| 108 | b=dsp.arm_clip_f32(a,minBound,maxBound) |
| 109 | print(a) |
| 110 | print(b) |
| 111 | |
| 112 | a = a / i[0] |
| 113 | print(a) |
| 114 | minBound = minBound / i[0] |
| 115 | maxBound = maxBound / i[0] |
| 116 | print(minBound,maxBound) |
| 117 | |
| 118 | b=dsp.arm_clip_q31(f.toQ31(a),f.toQ31(minBound),f.toQ31(maxBound)) |
| 119 | print(f.Q31toF32(b)) |
| 120 | |
| 121 | b=dsp.arm_clip_q15(f.toQ15(a),f.toQ15(minBound),f.toQ15(maxBound)) |
| 122 | print(f.Q15toF32(b)) |
| 123 | |
| 124 | b=dsp.arm_clip_q7(f.toQ7(a),f.toQ7(minBound),f.toQ7(maxBound)) |
| 125 | print(f.Q7toF32(b)) |
| 126 | |
| 127 | ############### MAT VECTOR MULT |
| 128 | |
| 129 | printTitle("Matrix x Vector") |
| 130 | a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]]) |
| 131 | b=np.array([-2,-1,3,4]) |
| 132 | |
| 133 | c = np.dot(a,b) |
| 134 | print(c) |
| 135 | c = dsp.arm_mat_vec_mult_f32(a,b) |
| 136 | print(c) |
| 137 | |
| 138 | printSubTitle("Fixed point") |
| 139 | normalizationFactor=2.0*np.sqrt(np.max(np.abs(c))) |
| 140 | a=a/normalizationFactor |
| 141 | b=b/normalizationFactor |
| 142 | print(np.dot(a,b)) |
| 143 | |
| 144 | c=dsp.arm_mat_vec_mult_q31(f.toQ31(a),f.toQ31(b)) |
| 145 | print(f.Q31toF32(c)) |
| 146 | |
| 147 | c=dsp.arm_mat_vec_mult_q15(f.toQ15(a),f.toQ15(b)) |
| 148 | print(f.Q15toF32(c)) |
| 149 | |
| 150 | c=dsp.arm_mat_vec_mult_q7(f.toQ7(a),f.toQ7(b)) |
| 151 | print(f.Q7toF32(c)) |
| 152 | |
| 153 | ############### MATRIX MULTIPLY |
| 154 | |
| 155 | printTitle("Matrix x Matrix") |
| 156 | |
| 157 | a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]]) |
| 158 | b=np.array([[1.,2,3],[5.1,6,7],[9.1,10,11],[5,8,4]]) |
| 159 | print(np.dot(a , b)) |
| 160 | c=dsp.arm_mat_mult_f32(a,b) |
| 161 | print(c[1]) |
| 162 | |
| 163 | printSubTitle("Fixed point") |
| 164 | |
| 165 | normalizationFactor=2.0*np.sqrt(np.max(np.abs(c[1]))) |
| 166 | a = a / normalizationFactor |
| 167 | b = b / normalizationFactor |
| 168 | c=dsp.arm_mat_mult_f32(a,b) |
| 169 | print(c[1]) |
| 170 | |
| 171 | print("") |
| 172 | af = f.toQ31(a) |
| 173 | bf = f.toQ31(b) |
| 174 | c = dsp.arm_mat_mult_q31(af,bf) |
| 175 | print(f.Q31toF32(c[1])) |
| 176 | |
| 177 | print("") |
| 178 | af = f.toQ15(a) |
| 179 | bf = f.toQ15(b) |
| 180 | s=bf.shape |
| 181 | nb=s[0]*s[1] |
| 182 | tmp=np.zeros(nb) |
| 183 | c = dsp.arm_mat_mult_q15(af,bf,tmp) |
| 184 | print(f.Q15toF32(c[1])) |
| 185 | |
| 186 | print("") |
| 187 | af = f.toQ7(a) |
| 188 | bf = f.toQ7(b) |
| 189 | s=bf.shape |
| 190 | nb=s[0]*s[1] |
| 191 | tmp=np.zeros(nb) |
| 192 | c = dsp.arm_mat_mult_q7(af,bf,tmp) |
| 193 | print(f.Q7toF32(c[1])) |
| 194 | |
| 195 | ################# MAT TRANSPOSE ################# |
| 196 | |
| 197 | printTitle("Transposition") |
| 198 | a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]]) |
| 199 | normalizationFactor=np.max(np.abs(c[1])) |
| 200 | a = a / normalizationFactor |
| 201 | |
| 202 | print(np.transpose(a)) |
| 203 | print("") |
| 204 | r=dsp.arm_mat_trans_f32(a) |
| 205 | print(r[1]) |
| 206 | print("") |
| 207 | |
| 208 | r=dsp.arm_mat_trans_q31(f.toQ31(a)) |
| 209 | print(f.Q31toF32(r[1])) |
| 210 | print("") |
| 211 | |
| 212 | r=dsp.arm_mat_trans_q15(f.toQ15(a)) |
| 213 | print(f.Q15toF32(r[1])) |
| 214 | print("") |
| 215 | |
| 216 | r=dsp.arm_mat_trans_q7(f.toQ7(a)) |
| 217 | print(f.Q7toF32(r[1])) |
| 218 | print("") |
| 219 | |
| 220 | ################## FILL FUNCTIONS ################# |
| 221 | |
| 222 | v=0.22 |
| 223 | nb=10 |
| 224 | a=np.full((nb,),v) |
| 225 | print(a) |
| 226 | |
| 227 | a=dsp.arm_fill_f32(v,nb) |
| 228 | print(a) |
| 229 | |
| 230 | a=f.Q31toF32(dsp.arm_fill_q31(f.toQ31(v),nb)) |
| 231 | print(a) |
| 232 | |
| 233 | a=f.Q15toF32(dsp.arm_fill_q15(f.toQ15(v),nb)) |
| 234 | print(a) |
| 235 | |
| 236 | a=f.Q7toF32(dsp.arm_fill_q7(f.toQ7(v),nb)) |
| 237 | print(a) |
| 238 | |
| 239 | ################# COMPLEX MAT TRANSPOSE ################# |
| 240 | |
| 241 | printTitle("Complex Transposition") |
| 242 | a=np.array([[1. + 0.0j ,2 + 1.0j,3 + 0.0j,4 + 2.0j], |
| 243 | [5 + 1.0j,6 + 2.0j,7 + 3.0j,8 + 1.0j], |
| 244 | [9 - 2.0j,10 + 1.0j,11 - 4.0j,12 + 1.0j]]) |
| 245 | normalizationFactor=np.max(np.abs(c[1])) |
| 246 | a = a / normalizationFactor |
| 247 | |
| 248 | print(np.transpose(a)) |
| 249 | print("") |
| 250 | r=dsp.arm_mat_cmplx_trans_f32(imToReal2D(a)) |
| 251 | print(realToIm2D(r[1])) |
| 252 | print("") |
| 253 | |
| 254 | r=dsp.arm_mat_cmplx_trans_q31(f.toQ31(imToReal2D(a))) |
| 255 | print(realToIm2D(f.Q31toF32(r[1]))) |
| 256 | print("") |
| 257 | |
| 258 | r=dsp.arm_mat_cmplx_trans_q15(f.toQ15(imToReal2D(a))) |
| 259 | print(realToIm2D(f.Q15toF32(r[1]))) |
| 260 | print("") |
| 261 | |
| 262 | ################ Levinson ################## |
| 263 | |
| 264 | printTitle("Levinson Durbin") |
| 265 | na=5 |
| 266 | s = np.random.randn(na+1) |
| 267 | s = normalize(s) |
| 268 | phi = autocorr(s) |
| 269 | phi = normalize(phi) |
| 270 | |
| 271 | sigmav,arcoef,pacf,sigma,phi1=statsmodels.tsa.stattools.levinson_durbin(phi,nlags=na,isacov=True) |
| 272 | |
| 273 | print(arcoef) |
| 274 | print(sigmav) |
| 275 | |
| 276 | (a,err)=dsp.arm_levinson_durbin_f32(phi,na) |
| 277 | print(a) |
| 278 | print(err) |
| 279 | |
| 280 | phiQ31 = f.toQ31(phi) |
| 281 | (aQ31,errQ31)=dsp.arm_levinson_durbin_q31(phiQ31,na) |
| 282 | print(f.Q31toF32(aQ31)) |
| 283 | print(f.Q31toF32(errQ31)) |
| 284 | |
| 285 | ################## Bitwise operations ################# |
| 286 | |
| 287 | printTitle("Bitwise operations") |
| 288 | def genBitvectors(nb,format): |
| 289 | if format == 31: |
| 290 | maxVal = 0x7fffffff |
| 291 | if format == 15: |
| 292 | maxVal = 0x7fff |
| 293 | if format == 7: |
| 294 | maxVal = 0x7f |
| 295 | |
| 296 | minVal = -maxVal-1 |
| 297 | |
| 298 | return(np.random.randint(minVal, maxVal, size=nb)) |
| 299 | |
| 300 | NBSAMPLES=10 |
| 301 | |
| 302 | |
| 303 | |
| 304 | printSubTitle("u32") |
| 305 | su32A=genBitvectors(NBSAMPLES,31) |
| 306 | su32B=genBitvectors(NBSAMPLES,31) |
| 307 | ffff = (np.ones(NBSAMPLES)*(-1)).astype(np.int) |
| 308 | |
| 309 | |
| 310 | ref=np.bitwise_and(su32A, su32B) |
| 311 | #print(ref) |
| 312 | result=dsp.arm_and_u32(su32A, su32B).astype(int) |
| 313 | print(result-ref) |
| 314 | |
| 315 | ref=np.bitwise_or(su32A, su32B) |
| 316 | #print(ref) |
| 317 | result=dsp.arm_or_u32(su32A, su32B).astype(int) |
| 318 | print(result-ref) |
| 319 | |
| 320 | ref=np.bitwise_xor(su32A, su32B) |
| 321 | #print(ref) |
| 322 | result=dsp.arm_xor_u32(su32A, su32B).astype(int) |
| 323 | print(result-ref) |
| 324 | |
| 325 | ref=np.bitwise_xor(ffff, su32A) |
| 326 | #print(ref) |
| 327 | result=dsp.arm_not_u32(su32A).astype(int) |
| 328 | print(result-ref) |
| 329 | |
| 330 | printSubTitle("u16") |
| 331 | su16A=genBitvectors(NBSAMPLES,15) |
| 332 | su16B=genBitvectors(NBSAMPLES,15) |
| 333 | |
| 334 | ffff = (np.ones(NBSAMPLES)*(-1)).astype(np.int) |
| 335 | |
| 336 | |
| 337 | ref=np.bitwise_and(su16A, su16B) |
| 338 | #print(ref) |
| 339 | result=dsp.arm_and_u16(su16A, su16B).astype(np.short) |
| 340 | print(result-ref) |
| 341 | |
| 342 | ref=np.bitwise_or(su16A, su16B) |
| 343 | #print(ref) |
| 344 | result=dsp.arm_or_u16(su16A, su16B).astype(np.short) |
| 345 | print(result-ref) |
| 346 | |
| 347 | ref=np.bitwise_xor(su16A, su16B) |
| 348 | #print(ref) |
| 349 | result=dsp.arm_xor_u16(su16A, su16B).astype(np.short) |
| 350 | print(result-ref) |
| 351 | |
| 352 | ref=np.bitwise_xor(ffff, su16A) |
| 353 | #print(ref) |
| 354 | result=dsp.arm_not_u16(su16A).astype(np.short) |
| 355 | print(result-ref) |
| 356 | |
| 357 | printSubTitle("u8") |
| 358 | |
| 359 | su8A=genBitvectors(NBSAMPLES,7) |
| 360 | su8B=genBitvectors(NBSAMPLES,7) |
| 361 | |
| 362 | ref=np.bitwise_and(su8A, su8B) |
| 363 | #print(ref) |
| 364 | result=dsp.arm_and_u8(su8A, su8B).astype(np.byte) |
| 365 | print(result-ref) |
| 366 | |
| 367 | ref=np.bitwise_or(su8A, su8B) |
| 368 | #print(ref) |
| 369 | result=dsp.arm_or_u8(su8A, su8B).astype(np.byte) |
| 370 | print(result-ref) |
| 371 | |
| 372 | ref=np.bitwise_xor(su8A, su8B) |
| 373 | #print(ref) |
| 374 | result=dsp.arm_xor_u8(su8A, su8B).astype(np.byte) |
| 375 | print(result-ref) |
| 376 | |
| 377 | ref=np.bitwise_xor(ffff, su8A) |
| 378 | #print(ref) |
| 379 | result=dsp.arm_not_u8(su8A).astype(np.byte) |
| 380 | print(result-ref) |
| 381 | |
| 382 | #################### Quaternion tests ################## |
| 383 | NBSAMPLES=3 |
| 384 | |
| 385 | def flattenQuat(l): |
| 386 | return(np.array([list(x) for x in l]).reshape(4*len(l))) |
| 387 | |
| 388 | def flattenRot(l): |
| 389 | return(np.array([list(x) for x in l]).reshape(9*len(l))) |
| 390 | |
| 391 | # q and -q are representing the same rotation. |
| 392 | # So there is an ambiguity for the tests. |
| 393 | # We force the real part of be positive. |
| 394 | def mkQuaternion(mat): |
| 395 | q=Quaternion(matrix=mat) |
| 396 | if q.scalar < 0: |
| 397 | return(-q) |
| 398 | else: |
| 399 | return(q) |
| 400 | |
| 401 | a=[2.0*Quaternion.random() for x in range(NBSAMPLES)] |
| 402 | src=flattenQuat(a) |
| 403 | |
| 404 | |
| 405 | res=flattenQuat([x.normalised for x in a]) |
| 406 | print(res) |
| 407 | output=dsp.arm_quaternion_normalize_f32(src) |
| 408 | print(output) |
| 409 | print("") |
| 410 | |
| 411 | res=flattenQuat([x.conjugate for x in a]) |
| 412 | print(res) |
| 413 | output=dsp.arm_quaternion_conjugate_f32(src) |
| 414 | print(output) |
| 415 | print("") |
| 416 | |
| 417 | res=flattenQuat([x.inverse for x in a]) |
| 418 | print(res) |
| 419 | output=dsp.arm_quaternion_inverse_f32(src) |
| 420 | print(output) |
| 421 | print("") |
| 422 | |
| 423 | res=[x.norm for x in a] |
| 424 | print(res) |
| 425 | output=dsp.arm_quaternion_norm_f32(src) |
| 426 | print(output) |
| 427 | print("") |
| 428 | |
| 429 | a=[x.normalised for x in a] |
| 430 | ra=[x.rotation_matrix for x in a] |
| 431 | rb=[mkQuaternion(x) for x in ra] |
| 432 | |
| 433 | srca=flattenQuat(a) |
| 434 | resa=dsp.arm_quaternion2rotation_f32(srca) |
| 435 | resb=dsp.arm_rotation2quaternion_f32(resa) |
| 436 | |
| 437 | |
| 438 | print(ra) |
| 439 | print(resa) |
| 440 | print("") |
| 441 | print(rb) |
| 442 | print(resb)# |
| 443 | |
| 444 | a=[2.0*Quaternion.random() for x in range(NBSAMPLES)] |
| 445 | b=[2.0*Quaternion.random() for x in range(NBSAMPLES)] |
| 446 | |
| 447 | c = np.array(a) * np.array(b) |
| 448 | print(c) |
| 449 | |
| 450 | srca=flattenQuat(a) |
| 451 | srcb=flattenQuat(b) |
| 452 | resc=dsp.arm_quaternion_product_f32(srca,srcb) |
| 453 | |
| 454 | print(resc) |
| 455 | |
| 456 | print(a[0]*b[0]) |
| 457 | res=dsp.arm_quaternion_product_single_f32(srca[0:4],srcb[0:4]) |
| 458 | print(res) |
| 459 | |