component histobins
"""histogram bins utility for scripts/hal-histogram
Usage:
Read availablebins pin for the number of bins available.
Set the minvalue, binsize, and nbins pins.
Ensure nbins <= availablebins
For nbins = N, the bins are numbered: 0 ... N\-1
Iterate:
Set index pin to a bin number: 0 <= index < nbins.
Read check pin and verify that check pin == index pin.
Read outputs: binvalue, pextra, nextra pins.
(binvalue is count for the indexed bin)
(pextra is count for all inputs > maxvalue)
(nextra is count for all bins < minvalue)
If index is out of range (index < 0 or index > maxbinnumber)
then binvalue == \-1.
The input-error pin is set when input rules are violated
and updates cease.
The reset pin may be used to restart.
The input used is selected based on pintype:
pintype inputpin
------- -----------
0 input
1 input-s32
2 input-u32
3 input-bit
Additional output statistics pins:
input-min
input-max
nsamples
variance
mean
The method input pin selects an alternate variance calculation.
Maintainers note: hardcoded for MAXBINNUMBER==200
""";
pin in u32 pintype;
pin in float input;
pin in s32 input_s32;
pin in u32 input_u32;
pin in bit input_bit;
pin in u32 nbins = 20; // must be < MAXBINNUMBER
pin in float binsize = 1;
pin in float minvalue = 0;
pin in s32 index; // use s32 to avoid 0x hex display in hal
pin out s32 check; // use s32 to avoid 0x hex display in hal
pin in bit reset;
pin in bit method;
pin out bit input_error;
pin out float binvalue;
pin out float pextra;
pin out float nextra;
pin out float input_min;
pin out float input_max;
pin out u32 nsamples;
pin out float variance;
pin out float mean;
// user may interrogate availablebins to determine this compiled-in limit
pin out s32 availablebins = 200; //MAXBINNUMBER
function _ fp;
variable int bin[200]; // MAXBINNUMBER
variable int first = 1;
variable int last_nbins = 0;
variable hal_float_t maxvalue;
variable hal_float_t last_binsize = 0;
variable hal_float_t last_minvalue = 0;
variable hal_float_t sum;
variable hal_float_t sq_sum;
variable hal_float_t m2;
license "GPL";
;;
hal_float_t invalue;
int i;
int idx;
check = index;
if ( (nbins > availablebins)
|| (nbins < 1)
) {
input_error = 1;
check = index; // allow continue with no updates
return;
}
input_error = 0;
if (reset) {first = 1;}
//pintype "0:float, 1:s32, 2:u32 3:bit";
switch (pintype) {
case 0: invalue = input; break;
case 1: invalue = input_s32; break;
case 2: invalue = input_u32; break;
case 3: invalue = input_bit; break;
default: invalue = input; break;
}
if ( first
|| nbins != last_nbins
|| binsize != last_binsize
|| minvalue != last_minvalue
) {
maxvalue = minvalue + nbins * binsize;
first = 0;
pextra = 0; nextra = 0;
for (i = 0; i < nbins; i++) {
bin[i] = 0;
}
nsamples = 0;
mean = 0;
sum = 0;
sq_sum = 0;
variance = 0;
input_min = 1e99; //dng
input_max = -1e99; //dng
m2 = 0;
} else {
if (invalue < minvalue) {
nextra++;
} else if (invalue > maxvalue) {
pextra++;
} else {
idx = (invalue - minvalue)/binsize;
bin[idx]++;
}
}
check = index; // user should verify check==index for reading values
// -1 value indicates illegal index
if (index < 0) {
binvalue = -1;
} else if (index < nbins) {
binvalue = bin[index];
} else {
binvalue = -1;
}
if (invalue < input_min) input_min = invalue;
if (invalue > input_max) input_max = invalue;
nsamples++;
if (nsamples >= 2) {
if (method == 0 ) {
hal_float_t delta;
delta = invalue - mean;
mean = mean + delta / nsamples;
m2 = m2 + delta * (invalue - mean);
variance = m2/(nsamples - 1);
} else {
sum += invalue;
sq_sum += invalue * invalue;
variance = (sq_sum - (sum * sum)/nsamples)/(nsamples -1);
mean = sum/nsamples;
}
}
last_nbins = nbins;
last_binsize = binsize;
last_minvalue = minvalue;