RMUL2025/lib/cmsis_5/CMSIS/DSP/Testing/PatternGeneration/Stats.py

567 lines
15 KiB
Python
Executable File

import os.path
import itertools
import Tools
import random
import numpy as np
import scipy
import scipy.stats
import math
NBTESTS = 10
VECDIM = [12,14,20]
def entropyTest(config,nb):
DIMS = [3,8,9,12]
inputs = []
outputs = []
dims=[NBTESTS]
for i in range(0,NBTESTS):
vecDim = DIMS[i % len(DIMS)]
dims.append(vecDim)
v = np.random.rand(vecDim)
v = v / np.sum(v)
e = scipy.stats.entropy(v)
inputs += list(v)
outputs.append(e)
inputs = np.array(inputs)
outputs = np.array(outputs)
dims = np.array(dims)
config.writeInput(nb, inputs,"Input")
config.writeInputS16(nb, dims,"Dims")
config.writeReference(nb, outputs,"RefEntropy")
def logsumexpTest(config,nb):
DIMS = [3,8,9,12]
inputs = []
outputs = []
dims=[NBTESTS]
for i in range(0,NBTESTS):
vecDim = DIMS[i % len(DIMS)]
dims.append(vecDim)
v = np.random.rand(vecDim)
v = v / np.sum(v)
e = scipy.special.logsumexp(v)
inputs += list(v)
outputs.append(e)
inputs = np.array(inputs)
outputs = np.array(outputs)
dims = np.array(dims)
config.writeInput(nb, inputs,"Input")
config.writeInputS16(nb, dims,"Dims")
config.writeReference(nb, outputs,"RefLogSumExp")
def klTest(config,nb):
DIMS = [3,8,9,12]
inputsA = []
inputsB = []
outputs = []
vecDim = VECDIM[nb % len(VECDIM)]
dims=[NBTESTS]
for i in range(0,NBTESTS):
vecDim = DIMS[i % len(DIMS)]
dims.append(vecDim)
va = np.random.rand(vecDim)
va = va / np.sum(va)
vb = np.random.rand(vecDim)
vb = vb / np.sum(vb)
e = scipy.stats.entropy(va,vb)
inputsA += list(va)
inputsB += list(vb)
outputs.append(e)
inputsA = np.array(inputsA)
inputsB = np.array(inputsB)
outputs = np.array(outputs)
dims = np.array(dims)
config.writeInput(nb, inputsA,"InputA")
config.writeInput(nb, inputsB,"InputB")
config.writeInputS16(nb, dims,"Dims")
config.writeReference(nb, outputs,"RefKL")
def logSumExpDotTest(config,nb):
DIMS = [3,8,9,12]
inputsA = []
inputsB = []
outputs = []
vecDim = VECDIM[nb % len(VECDIM)]
dims=[NBTESTS]
for i in range(0,NBTESTS):
vecDim = DIMS[i % len(DIMS)]
dims.append(vecDim)
va = np.random.rand(vecDim)
va = va / np.sum(va)
vb = np.random.rand(vecDim)
vb = vb / np.sum(vb)
d = 0.001
# It is a proba so must be in [0,1]
# But restricted to ]d,1] so that the log exists
va = (1-d)*va + d
vb = (1-d)*vb + d
e = np.log(np.dot(va,vb))
va = np.log(va)
vb = np.log(vb)
inputsA += list(va)
inputsB += list(vb)
outputs.append(e)
inputsA = np.array(inputsA)
inputsB = np.array(inputsB)
outputs = np.array(outputs)
dims = np.array(dims)
config.writeInput(nb, inputsA,"InputA")
config.writeInput(nb, inputsB,"InputB")
config.writeInputS16(nb, dims,"Dims")
config.writeReference(nb, outputs,"RefLogSumExpDot")
def writeF16OnlyTests(config,nb):
entropyTest(config,nb)
logsumexpTest(config,nb+1)
klTest(config,nb+2)
logSumExpDotTest(config,nb+3)
return(nb+4)
def writeF32OnlyTests(config,nb):
entropyTest(config,nb)
logsumexpTest(config,nb+1)
klTest(config,nb+2)
logSumExpDotTest(config,nb+3)
return(nb+4)
def writeF64OnlyTests(config,nb):
entropyTest(config,nb)
logsumexpTest(config,nb+1)
klTest(config,nb+2)
logSumExpDotTest(config,nb+3)
return(nb+4)
# For index in min and max we need to ensure that the difference between values
# of the input is big enough to be representable on q31, q15 or q7.
# Otherwise python will compute an index different from the one
# computed by CMSIS which is normal but then the CMSIS test will fail.
#vfunc = np.vectorize(squarer)
def floatRound(x,f):
return(np.round(x * 2**f)/2**f)
# Min / Max tests
def generateMaxTests(config,nb,format,data):
indexes=[]
maxvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
if format == 7:
# Force max at position 280
nbiters = 280
data = np.zeros(nbiters)
data[nbiters-1] = 0.9
data[nbiters-2] = 0.8
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
config.writeInput(nb, data,"InputMaxIndexMax")
config.writeReference(nb, maxvals,"MaxVals")
config.writeInputS16(nb, indexes,"MaxIndexes")
return(nb+1)
def generateMinTests(config,nb,format,data):
indexes=[]
maxvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
if format == 7:
# Force max at position 280
nbiters = 280
data = 0.9*np.ones(nbiters)
data[nbiters-1] = 0.0
data[nbiters-2] = 0.1
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
config.writeInput(nb, data,"InputMinIndexMax")
config.writeReference(nb, maxvals,"MinVals")
config.writeInputS16(nb, indexes,"MinIndexes")
return(nb+1)
# Min/Max Abs Tests
def generateMaxAbsTests(config,nb,format,data):
data = np.abs(data)
indexes=[]
maxvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
if format == 7:
# Force max at position 280
nbiters = 280
data = np.zeros(nbiters)
data[nbiters-1] = 0.9
data[nbiters-2] = 0.8
index=np.argmax(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
config.writeInput(nb, data,"InputAbsMaxIndexMax")
config.writeReference(nb, maxvals,"AbsMaxVals")
config.writeInputS16(nb, indexes,"AbsMaxIndexes")
return(nb+1)
def generateMinAbsTests(config,nb,format,data):
data = np.abs(data)
indexes=[]
maxvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
if format == 7:
# Force max at position 280
nbiters = 280
data = 0.9*np.ones(nbiters)
data[nbiters-1] = 0.0
data[nbiters-2] = 0.1
index=np.argmin(data[0:nbiters])
maxvalue=data[index]
indexes.append(index)
maxvals.append(maxvalue)
config.writeInput(nb, data,"InputAbsMinIndexMax")
config.writeReference(nb, maxvals,"AbsMinVals")
config.writeInputS16(nb, indexes,"AbsMinIndexes")
return(nb+1)
def averageTest(format,data):
return(np.average(data))
def powerTest(format,data):
if format == 31:
return(np.dot(data,data) / 2**15) # CMSIS is 2.28 format
elif format == 15:
return(np.dot(data,data) / 2**33) # CMSIS is 34.30 format
elif format == 7:
return(np.dot(data,data) / 2**17) # CMSIS is 18.14 format
else:
return(np.dot(data,data))
def mseTest(format,data1,data2):
nb = len(data1)
err = data1 - data2
return(np.dot(err,err) / nb)
def rmsTest(format,data):
return(math.sqrt(np.dot(data,data)/data.size))
def stdTest(format,data):
return(np.std(data,ddof=1))
def varTest(format,data):
return(np.var(data,ddof=1))
def generateFuncTests(config,nb,format,data,func,name):
funcvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
funcvalue=func(format,data[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
funcvalue=func(format,data[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
funcvalue=func(format,data[0:nbiters])
funcvals.append(funcvalue)
nbiters = 100
funcvalue=func(format,data[0:nbiters])
funcvals.append(funcvalue)
config.writeReference(nb, funcvals,name)
return(nb+1)
def generateOperatorTests(config,nb,format,data1,data2,func,name):
funcvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
funcvals.append(funcvalue)
nbiters = 100
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
funcvals.append(funcvalue)
config.writeReference(nb, funcvals,name)
return(nb+1)
def generatePowerTests(config,nb,format,data):
funcvals=[]
nbiters = Tools.loopnb(format,Tools.TAILONLY)
funcvalue=powerTest(format,data[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYONLY)
funcvalue=powerTest(format,data[0:nbiters])
funcvals.append(funcvalue)
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
funcvalue=powerTest(format,data[0:nbiters])
funcvals.append(funcvalue)
if format==31 or format==15:
config.writeReferenceQ63(nb, funcvals,"PowerVals")
elif format==7:
config.writeReferenceQ31(nb, funcvals,"PowerVals")
else:
config.writeReference(nb, funcvals,"PowerVals")
return(nb+1)
def writeTests(config,nb,format):
NBSAMPLES = 300
data1=np.random.randn(NBSAMPLES)
data2=np.random.randn(NBSAMPLES)
data1 = Tools.normalize(data1)
data2 = np.abs(data1)
# Force quantization so that computation of indexes
# in min/max is coherent between Python and CMSIS.
# Otherwise there will be normal differences and the test
# will be displayed as failed.
if format==31:
data1=floatRound(data1,31)
if format==15:
data1=floatRound(data1,15)
if format==7:
data1=floatRound(data1,7)
config.writeInput(1, data1,"Input")
config.writeInput(2, data2,"Input")
nb=generateMaxTests(config,nb,format,data1)
nb=generateFuncTests(config,nb,format,data2,averageTest,"MeanVals")
nb=generateMinTests(config,nb,format,data1)
nb=generatePowerTests(config,nb,format,data1)
nb=generateFuncTests(config,nb,format,data1,rmsTest,"RmsVals")
nb=generateFuncTests(config,nb,format,data1,stdTest,"StdVals")
nb=generateFuncTests(config,nb,format,data1,varTest,"VarVals")
return(nb)
# We don't want to change ID number of existing tests.
# So new tests have to be added after existing ones
def writeNewsTests(config,nb,format):
NBSAMPLES = 300
if format==Tools.F16:
config.setOverwrite(True)
data1=np.random.randn(NBSAMPLES)
data1 = Tools.normalize(data1)
data2=np.random.randn(NBSAMPLES)
data2 = Tools.normalize(data2)
config.writeInput(1, data1,"InputNew")
nb=generateMaxAbsTests(config,nb,format,data1)
nb=generateMinAbsTests(config,nb,format,data1)
config.writeInput(2, data2,"InputNew")
nb=generateOperatorTests(config,nb,format,data1,data2,mseTest,"MSEVals")
config.setOverwrite(False)
def generateBenchmark(config,format):
NBSAMPLES = 256
data1=np.random.randn(NBSAMPLES)
data2=np.random.randn(NBSAMPLES)
data1 = Tools.normalize(data1)
data2 = np.abs(data1)
if format==31:
data1=floatRound(data1,31)
if format==15:
data1=floatRound(data1,15)
if format==7:
data1=floatRound(data1,7)
config.writeInput(1, data1,"InputBench")
config.writeInput(2, data2,"InputBench")
def generatePatterns():
PATTERNDIR = os.path.join("Patterns","DSP","Stats","Stats")
PARAMDIR = os.path.join("Parameters","DSP","Stats","Stats")
configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")
configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
configq7 =Tools.Config(PATTERNDIR,PARAMDIR,"q7")
configf64.setOverwrite(False)
configf32.setOverwrite(False)
configf16.setOverwrite(False)
configq31.setOverwrite(False)
configq15.setOverwrite(False)
configq7.setOverwrite(False)
nb=writeTests(configf32,1,0)
nb=writeF32OnlyTests(configf32,22)
writeNewsTests(configf32,nb,Tools.F32)
nb=writeTests(configf64,1,Tools.F64)
nb=writeF64OnlyTests(configf64,22)
writeNewsTests(configf64,nb,Tools.F64)
nb=writeTests(configq31,1,31)
writeNewsTests(configq31,nb,Tools.Q31)
nb=writeTests(configq15,1,15)
writeNewsTests(configq15,nb,Tools.Q15)
nb=writeTests(configq7,1,7)
writeNewsTests(configq7,nb,Tools.Q7)
nb=writeTests(configf16,1,16)
nb=writeF16OnlyTests(configf16,22)
writeNewsTests(configf16,nb,Tools.F16)
generateBenchmark(configf64, Tools.F64)
generateBenchmark(configf32, Tools.F32)
generateBenchmark(configf16, Tools.F16)
generateBenchmark(configq31, Tools.Q31)
generateBenchmark(configq15, Tools.Q15)
generateBenchmark(configq7, Tools.Q7)
if __name__ == '__main__':
generatePatterns()