/* Copyright (c) 2018, Rafat Hussain */ #include "wtmath.h" void dwt_per_stride(double *inp, int N, double *lpd,double*hpd,int lpd_len,double *cA, int len_cA, double *cD, int istride, int ostride) { int l, l2, isodd, i, t, len_avg,is,os; len_avg = lpd_len; l2 = len_avg / 2; isodd = N % 2; for (i = 0; i < len_cA; ++i) { t = 2 * i + l2; os = i *ostride; cA[os] = 0.0; cD[os] = 0.0; for (l = 0; l < len_avg; ++l) { if ((t - l) >= l2 && (t - l) < N) { is = (t - l) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) < l2 && (t - l) >= 0) { is = (t - l) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) < 0 && isodd == 0) { is = (t - l + N) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) < 0 && isodd == 1) { if ((t - l) != -1) { is = (t - l + N + 1) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else { is = (N - 1) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } } else if ((t - l) >= N && isodd == 0) { is = (t - l - N) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) >= N && isodd == 1) { is = (t - l - (N + 1)) * istride; if (t - l != N) { cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else { is = (N - 1) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } } } } } void dwt_sym_stride(double *inp, int N, double *lpd, double*hpd, int lpd_len, double *cA, int len_cA, double *cD, int istride, int ostride) { int i, l, t, len_avg; int is, os; len_avg = lpd_len; for (i = 0; i < len_cA; ++i) { t = 2 * i + 1; os = i *ostride; cA[os] = 0.0; cD[os] = 0.0; for (l = 0; l < len_avg; ++l) { if ((t - l) >= 0 && (t - l) < N) { is = (t - l) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) < 0) { is = (-t + l - 1) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - l) >= N) { is = (2 * N - t + l - 1) * istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } } } } void modwt_per_stride(int M, double *inp, int N, double *filt, int lpd_len, double *cA, int len_cA, double *cD, int istride, int ostride) { int l, i, t, len_avg; int is, os; len_avg = lpd_len; for (i = 0; i < len_cA; ++i) { t = i; os = i *ostride; is = t *istride; cA[os] = filt[0] * inp[is]; cD[os] = filt[len_avg] * inp[is]; for (l = 1; l < len_avg; l++) { t -= M; while (t >= len_cA) { t -= len_cA; } while (t < 0) { t += len_cA; } os = i * ostride; is = t * istride; cA[os] += filt[l] * inp[is]; cD[os] += filt[len_avg + l] * inp[is]; } } } void swt_per_stride(int M, double *inp, int N, double *lpd, double*hpd, int lpd_len, double *cA, int len_cA, double *cD, int istride, int ostride) { int l, l2, isodd, i, t, len_avg, j; int is, os; len_avg = M * lpd_len; l2 = len_avg / 2; isodd = N % 2; for (i = 0; i < len_cA; ++i) { t = i + l2; os = i *ostride; cA[os] = 0.0; cD[os] = 0.0; l = -1; for (j = 0; j < len_avg; j += M) { l++; while (j >= len_cA) { j -= len_cA; } if ((t - j) >= l2 && (t - j) < N) { is = (t - j)*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - j) < l2 && (t - j) >= 0) { is = (t - j)*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - j) < 0) { is = (t - j + N)*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - j) >= N && isodd == 0) { is = (t - j - N)*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else if ((t - j) >= N && isodd == 1) { if (t - l != N) { is = (t - j - (N + 1))*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[is]; } else { is = (N - 1)*istride; cA[os] += lpd[l] * inp[is]; cD[os] += hpd[l] * inp[N - 1]; } } } } } void idwt_per_stride(double *cA, int len_cA, double *cD, double *lpr, double *hpr, int lpr_len, double *X, int istride, int ostride) { int len_avg, i, l, m, n, t, l2; int is, ms, ns; len_avg = lpr_len; l2 = len_avg / 2; m = -2; n = -1; for (i = 0; i < len_cA + l2 - 1; ++i) { m += 2; n += 2; ms = m * ostride; ns = n * ostride; X[ms] = 0.0; X[ns] = 0.0; for (l = 0; l < l2; ++l) { t = 2 * l; if ((i - l) >= 0 && (i - l) < len_cA) { is = (i - l) * istride; X[ms] += lpr[t] * cA[is] + hpr[t] * cD[is]; X[ns] += lpr[t + 1] * cA[is] + hpr[t + 1] * cD[is]; } else if ((i - l) >= len_cA && (i - l) < len_cA + len_avg - 1) { is = (i - l - len_cA) * istride; X[ms] += lpr[t] * cA[is] + hpr[t] * cD[is]; X[ns] += lpr[t + 1] * cA[is] + hpr[t + 1] * cD[is]; } else if ((i - l) < 0 && (i - l) > -l2) { is = (len_cA + i - l) * istride; X[ms] += lpr[t] * cA[is] + hpr[t] * cD[is]; X[ns] += lpr[t + 1] * cA[is] + hpr[t + 1] * cD[is]; } } } } void idwt_sym_stride(double *cA, int len_cA, double *cD, double *lpr, double *hpr, int lpr_len, double *X, int istride, int ostride) { int len_avg, i, l, m, n, t, v; int ms, ns, is; len_avg = lpr_len; m = -2; n = -1; for (v = 0; v < len_cA; ++v) { i = v; m += 2; n += 2; ms = m * ostride; ns = n * ostride; X[ms] = 0.0; X[ns] = 0.0; for (l = 0; l < len_avg / 2; ++l) { t = 2 * l; if ((i - l) >= 0 && (i - l) < len_cA) { is = (i - l) * istride; X[ms] += lpr[t] * cA[is] + hpr[t] * cD[is]; X[ns] += lpr[t + 1] * cA[is] + hpr[t + 1] * cD[is]; } } } } void imodwt_per_stride(int M, double *cA, int len_cA, double *cD, double *filt,int lf,double *X,int istride, int ostride) { int len_avg, i, l, t; int is, os; len_avg = lf; for (i = 0; i < len_cA; ++i) { t = i; os = i * ostride; is = t *istride; X[os] = (filt[0] * cA[is]) + (filt[len_avg] * cD[is]); for (l = 1; l < len_avg; l++) { t += M; while (t >= len_cA) { t -= len_cA; } while (t < 0) { t += len_cA; } is = t *istride; X[os] += (filt[l] * cA[is]) + (filt[len_avg + l] * cD[is]); } } } void idwt2_shift(int shift, int rows, int cols, double *lpr, double *hpr, int lf, double *A,double *H, double *V,double *D, double *oup) { int i, k, N, ir, ic, J, dim1, dim2; int istride, ostride; double *cL, *cH, *X_lp; N = rows > cols ? 2 * rows : 2 * cols; J = 1; dim1 = 2 * rows; dim2 = 2 * cols; X_lp = (double*)malloc(sizeof(double)* (N + 2 * lf - 1)); cL = (double*)calloc(dim1*dim2, sizeof(double)); cH = (double*)calloc(dim1*dim2, sizeof(double)); ir = rows; ic = cols; istride = ic; ostride = 1; for (i = 0; i < ic; ++i) { idwt_per_stride(A+i, ir, H+i, lpr, hpr, lf, X_lp, istride, ostride); for (k = lf / 2 - 1; k < 2 * ir + lf / 2 - 1; ++k) { cL[(k - lf / 2 + 1)*ic + i] = X_lp[k]; } idwt_per_stride(V+i, ir, D+i, lpr, hpr, lf, X_lp, istride, ostride); for (k = lf / 2 - 1; k < 2 * ir + lf / 2 - 1; ++k) { cH[(k - lf / 2 + 1)*ic + i] = X_lp[k]; } } ir *= 2; istride = 1; ostride = 1; for (i = 0; i < ir; ++i) { idwt_per_stride(cL + i*ic, ic, cH + i*ic, lpr, hpr, lf, X_lp, istride, ostride); for (k = lf / 2 - 1; k < 2 * ic + lf / 2 - 1; ++k) { oup[(k - lf / 2 + 1) + i*ic * 2] = X_lp[k]; } } ic *= 2; if (shift == -1) { //Save the last column for (i = 0; i < ir; ++i) { cL[i] = oup[(i + 1)*ic - 1]; } // Save the last row memcpy(cH, oup + (ir - 1)*ic, sizeof(double)*ic); for (i = ir - 1; i > 0; --i) { memcpy(oup + i*ic + 1, oup + (i - 1)*ic, sizeof(double)*(ic - 1)); } oup[0] = cL[ir - 1]; for (i = 1; i < ir; ++i) { oup[i*ic] = cL[i - 1]; } for (i = 1; i < ic; ++i) { oup[i] = cH[i - 1]; } } free(X_lp); free(cL); free(cH); } int upsamp(double *x, int lenx, int M, double *y) { int N, i, j, k; if (M < 0) { return -1; } if (M == 0) { for (i = 0; i < lenx; ++i) { y[i] = x[i]; } return lenx; } N = M * (lenx - 1) + 1; j = 1; k = 0; for (i = 0; i < N; ++i) { j--; y[i] = 0.0; if (j == 0) { y[i] = x[k]; k++; j = M; } } return N; } int upsamp2(double *x, int lenx, int M, double *y) { int N, i, j, k; // upsamp2 returns even numbered output. Last value is set to zero if (M < 0) { return -1; } if (M == 0) { for (i = 0; i < lenx; ++i) { y[i] = x[i]; } return lenx; } N = M * lenx; j = 1; k = 0; for (i = 0; i < N; ++i) { j--; y[i] = 0.0; if (j == 0) { y[i] = x[k]; k++; j = M; } } return N; } int downsamp(double *x, int lenx, int M, double *y) { int N, i; if (M < 0) { return -1; } if (M == 0) { for (i = 0; i < lenx; ++i) { y[i] = x[i]; } return lenx; } N = (lenx - 1) / M + 1; for (i = 0; i < N; ++i) { y[i] = x[i*M]; } return N; } /* int per_ext(double *sig, int len, int a,double *oup) { int i,len2; // oup is of length len + (len%2) + 2 * a for (i = 0; i < len; ++i) { oup[a + i] = sig[i]; } len2 = len; if ((len % 2) != 0) { len2 = len + 1; oup[a + len] = sig[len - 1]; } for (i = 0; i < a; ++i) { oup[a-1-i] = sig[len - 1 - i]; oup[len2 + a + i] = sig[i]; } return len2; } */ int per_ext(double *sig, int len, int a, double *oup) { int i, len2; double temp1; double temp2; for (i = 0; i < len; ++i) { oup[a + i] = sig[i]; } len2 = len; if ((len % 2) != 0) { len2 = len + 1; oup[a + len] = sig[len - 1]; } for (i = 0; i < a; ++i) { temp1 = oup[a + i]; temp2 = oup[a + len2 - 1 - i]; oup[a - 1 - i] = temp2; oup[len2 + a + i] = temp1; } return len2; } /* int symm_ext(double *sig, int len, int a, double *oup) { int i, len2; // oup is of length len + 2 * a for (i = 0; i < len; ++i) { oup[a + i] = sig[i]; } len2 = len; for (i = 0; i < a; ++i) { oup[a - 1 - i] = sig[i]; oup[len2 + a + i] = sig[len - 1 - i]; } return len2; } */ int symm_ext(double *sig, int len, int a, double *oup) { int i, len2; double temp1; double temp2; // oup is of length len + 2 * a for (i = 0; i < len; ++i) { oup[a + i] = sig[i]; } len2 = len; for (i = 0; i < a; ++i) { temp1 = oup[a + i]; temp2 = oup[a + len2 - 1 - i]; oup[a - 1 - i] = temp1; oup[len2 + a + i] = temp2; } return len2; } static int isign(int N) { int M; if (N >= 0) { M = 1; } else { M = -1; } return M; } static int iabs(int N) { if (N >= 0) { return N; } else { return -N; } } void circshift(double *array, int N, int L) { int i; double *temp; if (iabs(L) > N) { L = isign(L) * (iabs(L) % N); } if (L < 0) { L = (N + L) % N; } temp = (double*)malloc(sizeof(double) * L); for (i = 0; i < L; ++i) { temp[i] = array[i]; } for (i = 0; i < N - L; ++i) { array[i] = array[i + L]; } for (i = 0; i < L; ++i) { array[N - L + i] = temp[i]; } free(temp); } int testSWTlength(int N, int J) { int ret,div,i; ret = 1; div = 1; for (i = 0; i < J; ++i) { div *= 2; } if (N % div) { ret = 0; } return ret; } int wmaxiter(int sig_len, int filt_len) { int lev; double temp; temp = log((double)sig_len / ((double)filt_len - 1.0)) / log(2.0); lev = (int)temp; return lev; } static double entropy_s(double *x,int N) { int i; double val,x2; val = 0.0; for(i = 0; i < N; ++i) { if (x[i] != 0) { x2 = x[i] * x[i]; val -= x2 * log(x2); } } return val; } static double entropy_t(double *x,int N, double t) { int i; double val,x2; if (t < 0) { printf("Threshold value must be >= 0"); exit(1); } val = 0.0; for(i = 0; i < N; ++i) { x2 = fabs(x[i]); if (x2 > t) { val += 1; } } return val; } static double entropy_n(double *x,int N,double p) { int i; double val,x2; if (p < 1) { printf("Norm power value must be >= 1"); exit(1); } val = 0.0; for(i = 0; i < N; ++i) { x2 = fabs(x[i]); val += pow(x2,(double)p); } return val; } static double entropy_l(double *x,int N) { int i; double val,x2; val = 0.0; for(i = 0; i < N; ++i) { if (x[i] != 0) { x2 = x[i] * x[i]; val += log(x2); } } return val; } double costfunc(double *x, int N ,char *entropy,double p) { double val; if (!strcmp(entropy, "shannon")) { val = entropy_s(x, N); } else if (!strcmp(entropy, "threshold")) { val = entropy_t(x, N,p); } else if (!strcmp(entropy, "norm")) { val = entropy_n(x, N,p); } else if (!strcmp(entropy, "logenergy") || !strcmp(entropy, "log energy") || !strcmp(entropy, "energy")) { val = entropy_l(x, N); } else { printf("Entropy must be one of shannon, threshold, norm or energy"); exit(-1); } return val; }