John Miles wrote:
If you'd like to make the C source available, I'll look at building an
incremental version...?
If you can accept the current quick-hack state of the code (yes, I am
not too proud of the cleanness, so no comments about coding style or the
general uglyness), find it attached. The main goal of this code is
correctness. Find it attached.
I'll hacking away further.
An incremental version is a trivial extention for MTOTDEV as the outer
loop steps the 3*m sample window over the data-samples. So you need to
keep a 3*m big backlog of samples for the largest m you need. For
simplicity I made the expantion into the 9*m series explicit and with a
3*m offset from the index of the original data only for clarity while
debugging the code. Some of that debugging was not in the core
algorithm, but in the missing 0.73 factor, which is the bias factor for
white FM noise. A good quality measure would adjust the bias factor
based on the dominant noise-source, but that comes as later refinement.
Anyway, hope you find the code usefull. Will hack away to make more
values calculated. Currently the Hadamard Total Deviation is not
correct, as a quick-check with SP1065 page 118 would tell you. But that
was a quick-hack anyway.
Oh, yes... among the particular uglyness issues is that the routines
know just how many samples the time or frequency sample series contains.
Ugly as hell, but for the intended purpose (known test-series) that is ok.
Cheers,
Magnus
#include <math.h>
#include <stdio.h>
double td_f[1000];
double td_t[1001];
double td_mtot_t[1601];
// Expected series of l is
// l0 = 1234567890
// l1 = 395529916
// l2 = 1209410747
// l3 = 633705974
void ts_gen()
{
int i;
long long l;
l = 1234567890;
td_t[0] = 0;
//printf("%12.10f\n", td_t[0]);
for (i = 0; i < 1000; i++)
{
//printf("%i %li\n", i, l);
td_f[i] = (double)l / 2147483647;
td_t[i+1] = td_t[i] + td_f[i];
//printf("%14.10f\n", td_t[i+1]);
l = (16807 * l) % 2147483647;
}
}
void ts_gen_drift(double D, double tau0)
{
int i;
td_t[0] = 0;
for (i = 0; i < 1000; i++)
{
td_f[i] = D*i*tau0;
td_t[i+1] = td_t[i] + td_f[i];
}
}
double get_avg(int i, int m)
{
int j;
double a;
a = 0;
for (j = 0; j < m; j++)
a += td_f[i+j];
return a / m;
}
double calc_max(int m)
{
int i;
double n,o;
for (i = 0; i < 1000; i+=m)
{
n = get_avg(i,m);
if (i == 0)
o = n;
else if (n > o)
o = n;
}
return o;
}
double calc_min(int m)
{
int i;
double n,o;
for (i = 0; i < 1000; i+=m)
{
n = get_avg(i,m);
if (i == 0)
o = n;
else if (n < o)
o = n;
}
return o;
}
double calc_avg(int m)
{
int i;
double a;
a = 0;
for (i = 0; i < 1000; i+=m)
a += get_avg(i,m);
return a / (1000/m);
}
double calc_sdev(int m)
{
int i;
double a,d;
a = calc_avg(m);
d = 0;
for (i = 0; i < 1000; i+=m)
d += pow(get_avg(i,m) - a, 2);
return sqrt(d / (1000/m - 1));
}
double calc_nadev(int m)
{
int i;
double d;
d = 0;
for (i = 0; i + m < 1000; i+=m)
d += pow(get_avg(i+m,m) - get_avg(i,m), 2);
return sqrt(d / (2 * (1000/m - 1)));
}
double calc_osadev(int m)
{
int j,i,c;
double d,e;
d = 0;
c = 1000;
for (i = 0; i < c -2*m+1; i++)
{
e = 0;
for (j = 0; j < m; j++)
e += td_f[i+j+m] - td_f[i+j];
d += pow(e,2);
}
return sqrt(d / (2 *m*m * (c - 2*m+1)));
}
double calc_oadev(int m)
{
int i,c;
double d,e;
d = 0;
c = 1000;
for (i = 0; i < c -2*m+1; i++)
{
e = td_t[i+2*m] - 2 * td_t[i+m] + td_t[i];
d += pow(e,2);
}
return sqrt(d / (2 *m*m * (c - 2*m+1)));
}
double calc_madev(int m)
{
int j,i,k,c;
double d,e,md;
d = 0;
c = 1000;
for (j = 1; j <= c -3*m+2; j++)
{
e = 0;
for (i = j; i <= j+m-1; i++)
for (k = i; k <= i+m-1; k++)
e += td_f[k+m-1] - td_f[k-1];
d += e*e;
}
md = m;
return sqrt(d / (2 *md*md*md*md * (c - 3*md+2)));
}
double calc_tdev(int m)
{
int j,i,k,c;
double d,e,md;
d = 0;
c = 1000;
for (j = 1; j <= c -3*m+2; j++)
{
e = 0;
for (i = j; i <= j+m-1; i++)
for (k = i; k <= i+m-1; k++)
e += td_f[k+m-1] - td_f[k-1];
d += e*e;
}
md = m;
return sqrt(d / (6 *md*md * (c - 3*md+2)));
}
double calc_hdev(int m)
{
int i;
double d;
d = 0;
for (i = 0; i + 2*m < 1000; i+=m)
d += pow(get_avg(i+2*m,m) - 2*get_avg(i+m,m) + get_avg(i,m), 2);
return sqrt(d / (6 * (1000/m - 2)));
}
double calc_ohdev(int m)
{
int i,c;
double d,e,md;
d = 0;
c = 1001;
for (i = 0; i < c -3*m; i++)
{
e = td_t[i+3*m] - 3 * td_t[i+2*m] + 3 * td_t[i+m] - td_t[i];
d += e*e;
}
md = m;
return sqrt(d / (6 *md*md * (c - 3*md)));
}
double calc_mhdev(int m)
{
int i,j,c;
double d,e,md;
d = 0;
c = 1001;
for (j = 0; j < c -4*m; j++)
{
e = 0;
for (i=j; i <= j+m-1; i++)
e -= td_t[i+3*m] - 3 * td_t[i+2*m] + 3 * td_t[i+m] - td_t[i];
d += e*e;
}
md = m;
return sqrt(d / (6 *md*md*md*md * (c - 4*md+1)));
}
double get_wt(int i, int N)
{
i = i - 1;
if (i < 0)
{
i = -i;
return 2*td_t[0] - td_t[i];
}
else if (i > N - 1)
{
i = 2*(N-1) - i;
return 2*td_t[N-1] - td_t[i];
}
return td_t[i];
}
double calc_totdev(int m)
{
int c,i;
double d,e,md;
d = 0;
c = 1001;
for (i = 2; i <= c-1; i++)
{
e = get_wt(i-m,c) -2*get_wt(i,c) + get_wt(i+m,c);
d += e*e;
}
md = m;
return sqrt(d / (2 *md*md* (c - 2)));
}
/**
* 1 <= n <= N
* 1 <= l <= 3m
* i = l - 1
* x0(n+o) = td_mtot_t(o)
* x0#(n-l) = x0(n+l-1) = td_mtot_t(l-1) = td_mtot_t(i)
* x0#(n+l) = x0(n+l) = td_mtot_t(l); = td_mtot_t(i+1)
* x0#(n+3m+l-1) = x0(n+3m-l) = td_mtot_t(3m-l) = td_mtot_t(3m-i+1)
*
* i = n-l => l = n-i
* i = n+3m+l-1 => l = i - n - 3m +1
*/
double get_mtot_wt(int i, int n, int m)
{
int l;
if (i < n+1)
{
l = n-i;
i = n+l-1;
return td_mtot_t[i-(n-1)];
}
else if (i > n + 3*m)
{
l = i - n - 3*m + 1;
i = n+3*m - l;
return td_mtot_t[i-(n-1)];
}
return td_mtot_t[i-(n-1)];
}
double get_mtot_wtavg(int i, int n, int m)
{
int j;
double a,md;
a = 0;
for (j = 0; j < m; j++)
a+=get_mtot_wt(i+j,n,m);
md = m;
return a/md;
}
double get_mtot_wtavg2(int i, int m)
{
int j;
double a,md;
a = 0;
for (j = 0; j < m; j++)
a+=td_mtot_t[i+j];
md = m;
return a/md;
}
double calc_mtotdev(int m)
{
int n,i,c,j,x;
double d,e,x1,x2,f,md;
d = 0;
c = 1001;
md = m;
for (n = 0; n < c -3*m+1; n++)
{
// Calculate average frequency
x = (3*m+1)/2;
for (x1 = 0, i = 0, j = 0; i < 3*m/2; i++, j++)
x1 += (td_t[n+i+x]-td_t[n+i])/x;
f = x1/j;
// Compensate for average frequency
for (i = 0; i <= 3*m-1; i++)
{
int l;
l = i + 1;
e = td_t[n+i] - f*i;
//td_mtot_t[3*m-1-i] = e;
//td_mtot_t[3*m +i] = e;
//td_mtot_t[9*m-1-i] = e;
td_mtot_t[300+n-l] = e;
td_mtot_t[300+n+l-1] = e;
// i = 3*m - h => h = 3*m - i
// n + 3*m + h - 1 = n + 6*m - i - 1 = n + 6*m - l
td_mtot_t[300+n-l+6*m] = e;
}
//printf("%e\n", (td_mtot_t[3*m-1]-td_mtot_t[0])/(3*m-1));
e = 0;
//for (i = 0; i <= 6*m-1; i++)
for (i = n-3*m; i <= n+3*m-1; i++)
{
//f = get_mtot_wtavg2(i,m) -2.0*get_mtot_wtavg2(i+m,m) + get_mtot_wtavg2(i+2*m,m);
f = get_mtot_wtavg2(300+i,m) -2.0*get_mtot_wtavg2(300+i+m,m) + get_mtot_wtavg2(300+i+2*m,m);
e += f*f;
}
d += e/(6*md);
}
return sqrt(d / (0.73 * 2 *md*md * (c - 3*md+1)));
}
double calc_ttotdev(int m)
{
double md;
md = m;
return calc_mtotdev(m)*sqrt(md*md/3);
}
double calc_htotdev(int m)
{
int n,i,c,j,x;
double d,e,x1,x2,f,md;
d = 0;
c = 1000;
md = m;
for (n = 0; n < c -3*m+1; n++)
{
// Calculate average frequency
x = (3*m+1)/2;
for (x1 = 0, i = 0, j = 0; i < 3*m/2; i++, j++)
x1 += (td_f[n+i+x]-td_f[n+i])/x;
f = x1/j;
//printf("m %i n %i x1 %e x2 %e x2-x1 %e f %e ", m, n, x1, x2, x2-x1, f);
// Compensate for average frequency
for (i = 0; i <= 3*m-1; i++)
{
int l;
l = i + 1;
e = td_f[n+i] - f*i;
//td_mtot_t[3*m-1-i] = e;
//td_mtot_t[3*m +i] = e;
//td_mtot_t[9*m-1-i] = e;
td_mtot_t[300+n-l] = e;
td_mtot_t[300+n+l-1] = e;
// i = 3*m - h => h = 3*m - i
// n + 3*m + h - 1 = n + 6*m - i - 1 = n + 6*m - l
td_mtot_t[300+n-l+6*m] = e;
}
//printf("%e\n", (td_mtot_t[3*m-1]-td_mtot_t[0])/(3*m-1));
e = 0;
//for (i = 0; i <= 6*m-1; i++)
for (i = n-3*m; i <= n+3*m-1; i++)
{
//f = get_mtot_wtavg2(i,m) -2.0*get_mtot_wtavg2(i+m,m) + get_mtot_wtavg2(i+2*m,m);
f = get_mtot_wtavg2(300+i,m) -2.0*get_mtot_wtavg2(300+i+m,m) + get_mtot_wtavg2(300+i+2*m,m);
e += f*f;
}
d += e/(6*md);
}
return sqrt(d / (6.0 * (c - 3*md+1)));
}
int main()
{
ts_gen();
//ts_gen_drift(1.0E-4, 1.0);
printf(" m = 1 m = 10 m = 100\n");
printf("Max %12.10f %12.10f %12.10f\n", calc_max(1), calc_max(10), calc_max(100));
printf("Min %12.10f %12.10f %12.10f\n", calc_min(1), calc_min(10), calc_min(100));
printf("Avg %12.10f %12.10f %12.10f\n", calc_avg(1), calc_avg(10), calc_avg(100));
printf("Sdev %12.10f %12.10f %12.10f\n", calc_sdev(1), calc_sdev(10), calc_sdev(100));
printf("NAdev %12.10f %12.10f %12.10f\n", calc_nadev(1), calc_nadev(10), calc_nadev(100));
printf("OSAdev %12.10f %12.10f %12.10f\n", calc_osadev(1), calc_osadev(10), calc_osadev(100));
printf("OAdev %12.10f %12.10f %12.10f\n", calc_oadev(1), calc_oadev(10), calc_oadev(100));
printf("MAdev %12.10f %12.10f %12.10f\n", calc_madev(1), calc_madev(10), calc_madev(100));
printf("Tdev %12.10f %12.10f %12.10f\n", calc_tdev(1), calc_tdev(10), calc_tdev(100));
printf("Hdev %12.10f %12.10f %12.10f\n", calc_hdev(1), calc_hdev(10), calc_hdev(100));
printf("OHdev %12.10f %12.10f %12.10f\n", calc_ohdev(1), calc_ohdev(10), calc_ohdev(100));
printf("MHdev %12.10f %12.10f %12.10f\n", calc_mhdev(1), calc_mhdev(10), calc_mhdev(100));
printf("HTOTdev %12.10f %12.10f %12.10f\n", calc_htotdev(1), calc_htotdev(10), calc_htotdev(100));
printf("TOTdev %12.10f %12.10f %12.10f\n", calc_totdev(1), calc_totdev(10), calc_totdev(100));
printf("MTOTdev %12.10f %12.10f %12.10f\n", calc_mtotdev(1), calc_mtotdev(10), calc_mtotdev(100));
printf("TTOTdev %12.10f %12.10f %12.10f\n", calc_ttotdev(1), calc_ttotdev(10), calc_ttotdev(100));
return -1;
}
_______________________________________________
time-nuts mailing list -- [email protected]
To unsubscribe, go to https://www.febo.com/cgi-bin/mailman/listinfo/time-nuts
and follow the instructions there.