Stats.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. import os.path
  2. import itertools
  3. import Tools
  4. import random
  5. import numpy as np
  6. import scipy
  7. import scipy.stats
  8. import math
  9. NBTESTS = 10
  10. VECDIM = [12,14,20]
  11. def entropyTest(config,nb):
  12. DIMS = [3,8,9,12]
  13. inputs = []
  14. outputs = []
  15. dims=[NBTESTS]
  16. for i in range(0,NBTESTS):
  17. vecDim = DIMS[i % len(DIMS)]
  18. dims.append(vecDim)
  19. v = np.random.rand(vecDim)
  20. v = v / np.sum(v)
  21. e = scipy.stats.entropy(v)
  22. inputs += list(v)
  23. outputs.append(e)
  24. inputs = np.array(inputs)
  25. outputs = np.array(outputs)
  26. dims = np.array(dims)
  27. config.writeInput(nb, inputs,"Input")
  28. config.writeInputS16(nb, dims,"Dims")
  29. config.writeReference(nb, outputs,"RefEntropy")
  30. def logsumexpTest(config,nb):
  31. DIMS = [3,8,9,12]
  32. inputs = []
  33. outputs = []
  34. dims=[NBTESTS]
  35. for i in range(0,NBTESTS):
  36. vecDim = DIMS[i % len(DIMS)]
  37. dims.append(vecDim)
  38. v = np.random.rand(vecDim)
  39. v = v / np.sum(v)
  40. e = scipy.special.logsumexp(v)
  41. inputs += list(v)
  42. outputs.append(e)
  43. inputs = np.array(inputs)
  44. outputs = np.array(outputs)
  45. dims = np.array(dims)
  46. config.writeInput(nb, inputs,"Input")
  47. config.writeInputS16(nb, dims,"Dims")
  48. config.writeReference(nb, outputs,"RefLogSumExp")
  49. def klTest(config,nb):
  50. DIMS = [3,8,9,12]
  51. inputsA = []
  52. inputsB = []
  53. outputs = []
  54. vecDim = VECDIM[nb % len(VECDIM)]
  55. dims=[NBTESTS]
  56. for i in range(0,NBTESTS):
  57. vecDim = DIMS[i % len(DIMS)]
  58. dims.append(vecDim)
  59. va = np.random.rand(vecDim)
  60. va = va / np.sum(va)
  61. vb = np.random.rand(vecDim)
  62. vb = vb / np.sum(vb)
  63. e = scipy.stats.entropy(va,vb)
  64. inputsA += list(va)
  65. inputsB += list(vb)
  66. outputs.append(e)
  67. inputsA = np.array(inputsA)
  68. inputsB = np.array(inputsB)
  69. outputs = np.array(outputs)
  70. dims = np.array(dims)
  71. config.writeInput(nb, inputsA,"InputA")
  72. config.writeInput(nb, inputsB,"InputB")
  73. config.writeInputS16(nb, dims,"Dims")
  74. config.writeReference(nb, outputs,"RefKL")
  75. def logSumExpDotTest(config,nb):
  76. DIMS = [3,8,9,12]
  77. inputsA = []
  78. inputsB = []
  79. outputs = []
  80. vecDim = VECDIM[nb % len(VECDIM)]
  81. dims=[NBTESTS]
  82. for i in range(0,NBTESTS):
  83. vecDim = DIMS[i % len(DIMS)]
  84. dims.append(vecDim)
  85. va = np.random.rand(vecDim)
  86. va = va / np.sum(va)
  87. vb = np.random.rand(vecDim)
  88. vb = vb / np.sum(vb)
  89. d = 0.001
  90. # It is a proba so must be in [0,1]
  91. # But restricted to ]d,1] so that the log exists
  92. va = (1-d)*va + d
  93. vb = (1-d)*vb + d
  94. e = np.log(np.dot(va,vb))
  95. va = np.log(va)
  96. vb = np.log(vb)
  97. inputsA += list(va)
  98. inputsB += list(vb)
  99. outputs.append(e)
  100. inputsA = np.array(inputsA)
  101. inputsB = np.array(inputsB)
  102. outputs = np.array(outputs)
  103. dims = np.array(dims)
  104. config.writeInput(nb, inputsA,"InputA")
  105. config.writeInput(nb, inputsB,"InputB")
  106. config.writeInputS16(nb, dims,"Dims")
  107. config.writeReference(nb, outputs,"RefLogSumExpDot")
  108. def writeF16OnlyTests(config,nb):
  109. entropyTest(config,nb)
  110. logsumexpTest(config,nb+1)
  111. klTest(config,nb+2)
  112. logSumExpDotTest(config,nb+3)
  113. return(nb+4)
  114. def writeF32OnlyTests(config,nb):
  115. entropyTest(config,nb)
  116. logsumexpTest(config,nb+1)
  117. klTest(config,nb+2)
  118. logSumExpDotTest(config,nb+3)
  119. return(nb+4)
  120. def writeF64OnlyTests(config,nb):
  121. entropyTest(config,nb)
  122. logsumexpTest(config,nb+1)
  123. klTest(config,nb+2)
  124. logSumExpDotTest(config,nb+3)
  125. return(nb+4)
  126. # For index in min and max we need to ensure that the difference between values
  127. # of the input is big enough to be representable on q31, q15 or q7.
  128. # Otherwise python will compute an index different from the one
  129. # computed by CMSIS which is normal but then the CMSIS test will fail.
  130. #vfunc = np.vectorize(squarer)
  131. def floatRound(x,f):
  132. return(np.round(x * 2**f)/2**f)
  133. # Min / Max tests
  134. def generateMaxTests(config,nb,format,data):
  135. indexes=[]
  136. maxvals=[]
  137. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  138. index=np.argmax(data[0:nbiters])
  139. maxvalue=data[index]
  140. indexes.append(index)
  141. maxvals.append(maxvalue)
  142. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  143. index=np.argmax(data[0:nbiters])
  144. maxvalue=data[index]
  145. indexes.append(index)
  146. maxvals.append(maxvalue)
  147. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  148. index=np.argmax(data[0:nbiters])
  149. maxvalue=data[index]
  150. indexes.append(index)
  151. maxvals.append(maxvalue)
  152. if format == 7:
  153. # Force max at position 280
  154. nbiters = 280
  155. data = np.zeros(nbiters)
  156. data[nbiters-1] = 0.9
  157. data[nbiters-2] = 0.8
  158. index=np.argmax(data[0:nbiters])
  159. maxvalue=data[index]
  160. indexes.append(index)
  161. maxvals.append(maxvalue)
  162. config.writeInput(nb, data,"InputMaxIndexMax")
  163. config.writeReference(nb, maxvals,"MaxVals")
  164. config.writeInputS16(nb, indexes,"MaxIndexes")
  165. return(nb+1)
  166. def generateMinTests(config,nb,format,data):
  167. indexes=[]
  168. maxvals=[]
  169. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  170. index=np.argmin(data[0:nbiters])
  171. maxvalue=data[index]
  172. indexes.append(index)
  173. maxvals.append(maxvalue)
  174. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  175. index=np.argmin(data[0:nbiters])
  176. maxvalue=data[index]
  177. indexes.append(index)
  178. maxvals.append(maxvalue)
  179. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  180. index=np.argmin(data[0:nbiters])
  181. maxvalue=data[index]
  182. indexes.append(index)
  183. maxvals.append(maxvalue)
  184. if format == 7:
  185. # Force max at position 280
  186. nbiters = 280
  187. data = 0.9*np.ones(nbiters)
  188. data[nbiters-1] = 0.0
  189. data[nbiters-2] = 0.1
  190. index=np.argmin(data[0:nbiters])
  191. maxvalue=data[index]
  192. indexes.append(index)
  193. maxvals.append(maxvalue)
  194. config.writeInput(nb, data,"InputMinIndexMax")
  195. config.writeReference(nb, maxvals,"MinVals")
  196. config.writeInputS16(nb, indexes,"MinIndexes")
  197. return(nb+1)
  198. # Min/Max Abs Tests
  199. def generateMaxAbsTests(config,nb,format,data):
  200. data = np.abs(data)
  201. indexes=[]
  202. maxvals=[]
  203. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  204. index=np.argmax(data[0:nbiters])
  205. maxvalue=data[index]
  206. indexes.append(index)
  207. maxvals.append(maxvalue)
  208. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  209. index=np.argmax(data[0:nbiters])
  210. maxvalue=data[index]
  211. indexes.append(index)
  212. maxvals.append(maxvalue)
  213. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  214. index=np.argmax(data[0:nbiters])
  215. maxvalue=data[index]
  216. indexes.append(index)
  217. maxvals.append(maxvalue)
  218. if format == Tools.Q7 or format == Tools.Q15 or format == Tools.Q31:
  219. index=np.argmax(data)
  220. maxvalue=data[index]
  221. indexes.append(index)
  222. maxvals.append(maxvalue)
  223. if format == 7:
  224. # Force max at position 280 with a new test
  225. nbiters = 280
  226. data = np.zeros(nbiters)
  227. data[nbiters-1] = 0.9
  228. data[nbiters-2] = 0.8
  229. index=np.argmax(data[0:nbiters])
  230. maxvalue=data[index]
  231. indexes.append(index)
  232. maxvals.append(maxvalue)
  233. config.writeInput(nb, data,"InputAbsMaxIndexMax")
  234. config.writeReference(nb, maxvals,"AbsMaxVals")
  235. config.writeInputS16(nb, indexes,"AbsMaxIndexes")
  236. return(nb+1)
  237. def generateMinAbsTests(config,nb,format,data):
  238. data = np.abs(data)
  239. indexes=[]
  240. maxvals=[]
  241. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  242. index=np.argmin(data[0:nbiters])
  243. maxvalue=data[index]
  244. indexes.append(index)
  245. maxvals.append(maxvalue)
  246. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  247. index=np.argmin(data[0:nbiters])
  248. maxvalue=data[index]
  249. indexes.append(index)
  250. maxvals.append(maxvalue)
  251. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  252. index=np.argmin(data[0:nbiters])
  253. maxvalue=data[index]
  254. indexes.append(index)
  255. maxvals.append(maxvalue)
  256. if format == 7:
  257. # Force max at position 280
  258. nbiters = 280
  259. data = 0.9*np.ones(nbiters)
  260. data[nbiters-1] = 0.0
  261. data[nbiters-2] = 0.1
  262. index=np.argmin(data[0:nbiters])
  263. maxvalue=data[index]
  264. indexes.append(index)
  265. maxvals.append(maxvalue)
  266. config.writeInput(nb, data,"InputAbsMinIndexMax")
  267. config.writeReference(nb, maxvals,"AbsMinVals")
  268. config.writeInputS16(nb, indexes,"AbsMinIndexes")
  269. return(nb+1)
  270. def averageTest(format,data):
  271. return(np.average(data))
  272. def powerTest(format,data):
  273. if format == 31:
  274. return(np.dot(data,data) / 2**15) # CMSIS is 2.28 format
  275. elif format == 15:
  276. return(np.dot(data,data) / 2**33) # CMSIS is 34.30 format
  277. elif format == 7:
  278. return(np.dot(data,data) / 2**17) # CMSIS is 18.14 format
  279. else:
  280. return(np.dot(data,data))
  281. def mseTest(format,data1,data2):
  282. nb = len(data1)
  283. err = data1 - data2
  284. return(np.dot(err,err) / nb)
  285. def rmsTest(format,data):
  286. return(math.sqrt(np.dot(data,data)/data.size))
  287. def stdTest(format,data):
  288. return(np.std(data,ddof=1))
  289. def varTest(format,data):
  290. return(np.var(data,ddof=1))
  291. def generateFuncTests(config,nb,format,data,func,name):
  292. funcvals=[]
  293. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  294. funcvalue=func(format,data[0:nbiters])
  295. funcvals.append(funcvalue)
  296. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  297. funcvalue=func(format,data[0:nbiters])
  298. funcvals.append(funcvalue)
  299. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  300. funcvalue=func(format,data[0:nbiters])
  301. funcvals.append(funcvalue)
  302. nbiters = 100
  303. funcvalue=func(format,data[0:nbiters])
  304. funcvals.append(funcvalue)
  305. config.writeReference(nb, funcvals,name)
  306. return(nb+1)
  307. def generateOperatorTests(config,nb,format,data1,data2,func,name):
  308. funcvals=[]
  309. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  310. funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
  311. funcvals.append(funcvalue)
  312. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  313. funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
  314. funcvals.append(funcvalue)
  315. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  316. funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
  317. funcvals.append(funcvalue)
  318. nbiters = 100
  319. funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
  320. funcvals.append(funcvalue)
  321. config.writeReference(nb, funcvals,name)
  322. return(nb+1)
  323. def generatePowerTests(config,nb,format,data):
  324. funcvals=[]
  325. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  326. funcvalue=powerTest(format,data[0:nbiters])
  327. funcvals.append(funcvalue)
  328. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  329. funcvalue=powerTest(format,data[0:nbiters])
  330. funcvals.append(funcvalue)
  331. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  332. funcvalue=powerTest(format,data[0:nbiters])
  333. funcvals.append(funcvalue)
  334. if format==31 or format==15:
  335. config.writeReferenceQ63(nb, funcvals,"PowerVals")
  336. elif format==7:
  337. config.writeReferenceQ31(nb, funcvals,"PowerVals")
  338. else:
  339. config.writeReference(nb, funcvals,"PowerVals")
  340. return(nb+1)
  341. def writeTests(config,nb,format):
  342. NBSAMPLES = 300
  343. data1=np.random.randn(NBSAMPLES)
  344. data2=np.random.randn(NBSAMPLES)
  345. data1 = Tools.normalize(data1)
  346. data2 = np.abs(data1)
  347. # Force quantization so that computation of indexes
  348. # in min/max is coherent between Python and CMSIS.
  349. # Otherwise there will be normal differences and the test
  350. # will be displayed as failed.
  351. if format==31:
  352. data1=floatRound(data1,31)
  353. if format==15:
  354. data1=floatRound(data1,15)
  355. if format==7:
  356. data1=floatRound(data1,7)
  357. config.writeInput(1, data1,"Input")
  358. config.writeInput(2, data2,"Input")
  359. nb=generateMaxTests(config,nb,format,data1)
  360. nb=generateFuncTests(config,nb,format,data2,averageTest,"MeanVals")
  361. nb=generateMinTests(config,nb,format,data1)
  362. nb=generatePowerTests(config,nb,format,data1)
  363. nb=generateFuncTests(config,nb,format,data1,rmsTest,"RmsVals")
  364. nb=generateFuncTests(config,nb,format,data1,stdTest,"StdVals")
  365. nb=generateFuncTests(config,nb,format,data1,varTest,"VarVals")
  366. return(nb)
  367. # We don't want to change ID number of existing tests.
  368. # So new tests have to be added after existing ones
  369. def writeNewsTests(config,nb,format):
  370. NBSAMPLES = 300
  371. data1=np.random.randn(NBSAMPLES)
  372. data1 = Tools.normalize(data1)
  373. data2=np.random.randn(NBSAMPLES)
  374. data2 = Tools.normalize(data2)
  375. # Add max negative value
  376. # to test saturation
  377. if format == Tools.Q7:
  378. data1 = np.hstack((data1,np.array([-1.0])))
  379. if format == Tools.Q15:
  380. data1 = np.hstack((data1,np.array([-1.0])))
  381. if format == Tools.Q31:
  382. data1 = np.hstack((data1,np.array([-1.0])))
  383. config.writeInput(1, data1,"InputNew")
  384. nb=generateMaxAbsTests(config,nb,format,data1)
  385. nb=generateMinAbsTests(config,nb,format,data1)
  386. config.writeInput(2, data2,"InputNew")
  387. nb=generateOperatorTests(config,nb,format,data1,data2,mseTest,"MSEVals")
  388. return(nb)
  389. def writeAccumulateTests(config,nb,format):
  390. NBSAMPLES = 300
  391. data1=np.random.randn(NBSAMPLES)
  392. # First value is the number of tests
  393. # Other values are the number of samples in each test
  394. nbsamples = [4]
  395. nbiters = Tools.loopnb(format,Tools.TAILONLY)
  396. nbsamples.append(nbiters)
  397. nbiters = Tools.loopnb(format,Tools.BODYONLY)
  398. nbsamples.append(nbiters)
  399. nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
  400. nbsamples.append(nbiters)
  401. nbsamples.append(NBSAMPLES)
  402. ref=[]
  403. for nb in nbsamples[1:]:
  404. t = np.sum(data1[:nb])
  405. ref.append(t)
  406. config.writeInput(1, data1,"InputAccumulate")
  407. config.writeInputS16(1, nbsamples,"InputAccumulateConfig")
  408. config.writeReference(1, ref,"RefAccumulate")
  409. return(nb+1)
  410. def generateBenchmark(config,format):
  411. NBSAMPLES = 256
  412. data1=np.random.randn(NBSAMPLES)
  413. data2=np.random.randn(NBSAMPLES)
  414. data1 = Tools.normalize(data1)
  415. data2 = np.abs(data1)
  416. if format==31:
  417. data1=floatRound(data1,31)
  418. if format==15:
  419. data1=floatRound(data1,15)
  420. if format==7:
  421. data1=floatRound(data1,7)
  422. config.writeInput(1, data1,"InputBench")
  423. config.writeInput(2, data2,"InputBench")
  424. def generatePatterns():
  425. PATTERNDIR = os.path.join("Patterns","DSP","Stats","Stats")
  426. PARAMDIR = os.path.join("Parameters","DSP","Stats","Stats")
  427. configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
  428. configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
  429. configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")
  430. configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
  431. configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
  432. configq7 =Tools.Config(PATTERNDIR,PARAMDIR,"q7")
  433. configf64.setOverwrite(False)
  434. configf32.setOverwrite(False)
  435. configf16.setOverwrite(False)
  436. configq31.setOverwrite(False)
  437. configq15.setOverwrite(False)
  438. configq7.setOverwrite(False)
  439. nb=writeTests(configf32,1,0)
  440. nb=writeF32OnlyTests(configf32,22)
  441. nb=writeNewsTests(configf32,nb,Tools.F32)
  442. nb=writeAccumulateTests(configf32,nb,Tools.F32)
  443. nb=writeTests(configf64,1,Tools.F64)
  444. nb=writeF64OnlyTests(configf64,22)
  445. nb=writeNewsTests(configf64,nb,Tools.F64)
  446. nb=writeAccumulateTests(configf64,nb,Tools.F64)
  447. nb=writeTests(configq31,1,31)
  448. nb=writeNewsTests(configq31,nb,Tools.Q31)
  449. nb=writeTests(configq15,1,15)
  450. nb=writeNewsTests(configq15,nb,Tools.Q15)
  451. nb=writeTests(configq7,1,7)
  452. nb=writeNewsTests(configq7,nb,Tools.Q7)
  453. nb=writeTests(configf16,1,16)
  454. nb=writeF16OnlyTests(configf16,22)
  455. nb=writeNewsTests(configf16,nb,Tools.F16)
  456. nb=writeAccumulateTests(configf16,nb,Tools.F16)
  457. generateBenchmark(configf64, Tools.F64)
  458. generateBenchmark(configf32, Tools.F32)
  459. generateBenchmark(configf16, Tools.F16)
  460. generateBenchmark(configq31, Tools.Q31)
  461. generateBenchmark(configq15, Tools.Q15)
  462. generateBenchmark(configq7, Tools.Q7)
  463. if __name__ == '__main__':
  464. generatePatterns()