/* fwritef : convert double type data to float type and write */ int fwritef(double *ptr, const size_t size, const int nitems, FILE * fp) { int i; if (items < nitems) { if (f != NULL) free(f); items = nitems; f = fgetmem(items); } for (i = 0; i < nitems; i++) f[i] = ptr[i]; #if defined(WIN32) _setmode(_fileno(fp), _O_BINARY); #endif return fwrite(f, sizeof(float), nitems, fp); }
/* freadf : read float type data and convert to double type */ int freadf(double *ptr, const size_t size, const int nitems, FILE * fp) { int i, n; if (items < nitems) { if (f != NULL) free(f); items = nitems; f = fgetmem(items); } #if defined(WIN32) _setmode(_fileno(fp), _O_BINARY); #endif n = fread(f, sizeof(float), nitems, fp); for (i = 0; i < n; i++) ptr[i] = f[i]; return n; }
double *read_input(FILE * fp, size_t dim, size_t * length) { size_t i, j; double *x = NULL, *input = NULL; float_list *top = NULL, *prev = NULL, *cur = NULL, *next = NULL, *tmp = NULL; input = dgetmem(dim); top = prev = (float_list *) getmem(1, sizeof(float_list)); *length = 0; prev->next = NULL; while (freadf(input, sizeof(*input), dim, fp) == (int) dim) { cur = (float_list *) getmem(1, sizeof(float_list)); cur->f = fgetmem(dim); for (i = 0; i < dim; i++) { cur->f[i] = (float) input[i]; } (*length)++; prev->next = cur; cur->next = NULL; prev = cur; } x = dgetmem(*length * dim); for (i = 0, tmp = top->next; tmp != NULL; i++, tmp = tmp->next) { for (j = 0; j < dim; j++) { x[i * dim + j] = tmp->f[j]; } } for (tmp = top->next; tmp != NULL; tmp = next) { cur = tmp; next = tmp->next; free(cur->f); free(cur); } free(top); free(input); return (x); }
int main(int argc, char *argv[]) { FILE *fp = stdin, *fp_eigen = NULL; int i, j, k, n = PRICOMP_ORDER, leng = LENG, total = -1; BOOL out_evecFlg = FALSE, out_evalFlg = FALSE; double sum; double *buf = NULL; double *mean = NULL, **var = NULL; double eps = EPS; int itemax = ITEMAX; double **e_vec = NULL, *e_val = NULL; /* eigenvector and eigenvalue */ double *cont_rate = NULL; /* contribution rate */ double jacobi_conv; float_list *top, *cur, *prev, *tmpf, *tmpff; if ((cmnd = strrchr(argv[0], '/')) == NULL) cmnd = argv[0]; else cmnd++; while (--argc) if ((**++argv) == '-') { switch (*(*argv + 1)) { case 'l': leng = atoi(*++argv); --argc; break; case 'n': n = atoi(*++argv); --argc; break; case 'e': eps = atof(*++argv); --argc; break; case 'i': itemax = atoi(*++argv); --argc; break; case 'v': out_evecFlg = TRUE; break; case 'V': out_evalFlg = TRUE; fp_eigen = getfp(*++argv, "wb"); --argc; break; case 'h': usage(EXIT_SUCCESS); default: fprintf(stderr, "%s : Invalid option '%s'!\n", cmnd, *argv); usage(EXIT_FAILURE); } } else fp = getfp(*argv, "rb"); if (n > leng) { fprintf(stderr, "\n %s (Error) output number of pricipal component" " must be less than length of vector.\n", cmnd); usage(EXIT_FAILURE); } /* -- Count number of input vectors and read -- */ buf = dgetmem(leng); top = prev = (float_list *) malloc(sizeof(float_list)); top->f = fgetmem(leng); total = 0; prev->next = NULL; while (freadf(buf, sizeof(*buf), leng, fp) == leng) { cur = (float_list *) malloc(sizeof(float_list)); cur->f = fgetmem(leng); for (i = 0; i < leng; i++) { cur->f[i] = (float) buf[i]; } total++; prev->next = cur; cur->next = NULL; prev = cur; } free(buf); buf = dgetmem(total * leng); for (i = 0, tmpf = top->next; tmpf != NULL; i++, tmpf = tmpff) { for (j = 0; j < leng; j++) { buf[i * leng + j] = tmpf->f[j]; } tmpff = tmpf->next; free(tmpf->f); free(tmpf); } free(top); /* PCA */ /* allocate memory for mean vectors and covariance matrix */ mean = dgetmem(leng); var = malloc_matrix(leng); /* calculate mean vector */ for (i = 0; i < leng; i++) { for (j = 0, sum = 0.0; j < total; j++) sum += buf[i + j * leng]; mean[i] = sum / total; } /* calculate cov. mat. */ for (i = 0; i < leng; i++) { for (j = 0; j < leng; j++) { sum = 0.0; for (k = 0; k < total; k++) sum += (buf[i + k * leng] - mean[i]) * (buf[j + k * leng] - mean[j]); var[i][j] = sum / total; } } /* allocate memory for eigenvector and eigenvalue */ e_vec = malloc_matrix(leng); e_val = dgetmem(leng); /* calculate eig.vec. and eig.val. with jacobi method */ if ((jacobi_conv = jacobi(var, leng, eps, e_val, e_vec, itemax)) == -1) { fprintf(stderr, "Error : matrix is not symmetric.\n"); exit(EXIT_FAILURE); } else if (jacobi_conv == -2) { fprintf(stderr, "Error : loop in jacobi method reached %d times.\n", itemax); exit(EXIT_FAILURE); } /* allocate memory for contribution rate of each eigenvalue */ cont_rate = dgetmem(leng); /* calculate contribution rate of each eigenvalue */ for (j = 0; j < leng; j++) { sum = 0.0; for (i = 0; i < leng; i++) sum += e_val[i]; cont_rate[j] = e_val[j] / sum; } /* end of PCA */ /* output mean vector and eigen vectors */ if (out_evecFlg == TRUE) { fwritef(mean, sizeof(*mean), leng, stdout); for (i = 0; i < n; i++) fwritef(e_vec[i], sizeof(*(e_vec[i])), leng, stdout); } /* output eigen values and contribution ratio */ if (out_evalFlg == TRUE) { for (i = 0; i < n; i++) { fwritef(e_val + i, sizeof(*e_val), 1, fp_eigen); fwritef(cont_rate + i, sizeof(*cont_rate), 1, fp_eigen); } fclose(fp_eigen); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { FILE *fp = stdin; double *x, *mean, *med = NULL, **mtmp = NULL, **cov = NULL, **invcov = NULL, *var = NULL, conf = CONFLEV, *upper = NULL, *lower = NULL, t, err; int leng = LENG, nv = -1, i, j, k = 0, lp = 0, m, outtype = 0, count = 0; Boolean outmean = OUTMEAN, outcov = OUTCOV, outconf = OUTCONF, outmed = OUTMED, diagc = DIAGC, inv = INV, corr = CORR; if ((cmnd = strrchr(argv[0], '/')) == NULL) cmnd = argv[0]; else cmnd++; while (--argc) if (**++argv == '-') { switch (*(*argv + 1)) { case 'l': leng = atoi(*++argv); --argc; break; case 'n': leng = atoi(*++argv) + 1; --argc; break; case 't': nv = atoi(*++argv); --argc; break; case 'o': outtype = atoi(*++argv); --argc; break; case 'c': conf = atof(*++argv); --argc; break; case 'd': diagc = 1 - diagc; break; case 'i': inv = 1 - inv; break; case 'r': corr = 1 - corr; break; case 'h': usage(0); default: fprintf(stderr, "%s : Invalid option '%c'!\n", cmnd, *(*argv + 1)); usage(1); } } else fp = getfp(*argv, "rb"); if (conf < 0 || conf > 100) { fprintf(stderr, "%s : Confidence level must be greater than 0 and less than 1.0!\n", cmnd); } switch (outtype) { case 1: outcov = FA; break; case 2: outmean = FA; break; case 3: outcov = FA; outconf = TR; break; case 4: outcov = FA; outmean = FA; outmed = TR; break; } if (diagc && corr) diagc = FA; if (diagc && inv) diagc = FA; if (corr && inv) corr = FA; mean = dgetmem(leng + leng); x = mean + leng; if (outmed) { if (nv == -1) { typedef struct _float_list { float *f; struct _float_list *next; } float_list; float_list *top = NULL, *prev = NULL, *cur = NULL; top = prev = (float_list *) getmem(1, sizeof(float_list)); prev->next = NULL; while (freadf(x, sizeof(*x), leng, fp) == leng) { cur = (float_list *) getmem(1, sizeof(float_list)); cur->f = fgetmem(leng); for (i = 0; i < leng; i++) { cur->f[i] = (float) x[i]; } count++; prev->next = cur; cur->next = NULL; prev = cur; } k = count; mtmp = (double **) getmem(leng, sizeof(*mtmp)); mtmp[0] = dgetmem(leng * k); for (i = 1; i < leng; i++) mtmp[i] = mtmp[i - 1] + k; med = dgetmem(leng); for (j = 0, cur = top->next; j < k; j++, cur = cur->next) { for (i = 0; i < leng; i++) { mtmp[i][j] = (double) cur->f[i]; } } } else { k = nv; mtmp = (double **) getmem(leng, sizeof(*mtmp)); mtmp[0] = dgetmem(leng * k); for (i = 1; i < leng; i++) mtmp[i] = mtmp[i - 1] + k; med = dgetmem(leng); for (j = 0; j < k; j++) { for (i = 0; i < leng; i++) { freadf(&mtmp[i][j], sizeof(**mtmp), 1, fp); } } } if (k % 2 == 0) { fprintf(stderr, "%s : warning: the number of vectors is even!\n", cmnd); } for (i = 0; i < leng; i++) { quicksort(mtmp[i], 0, k - 1); if (k % 2 == 1) { med[i] = mtmp[i][k / 2]; } else { med[i] = ((mtmp[i][k / 2] + mtmp[i][k / 2 - 1]) / 2); } } fwritef(med, sizeof(*med), leng, stdout); return (0); } if (outcov) { if (!diagc) { cov = (double **) getmem(leng, sizeof(*cov)); cov[0] = dgetmem(leng * leng); for (i = 1; i < leng; i++) cov[i] = cov[i - 1] + leng; if (inv) { invcov = (double **) getmem(leng, sizeof(*invcov)); invcov[0] = dgetmem(leng * leng); for (i = 1; i < leng; i++) invcov[i] = invcov[i - 1] + leng; } } else var = dgetmem(leng); } if (outconf) { var = dgetmem(leng); upper = dgetmem(leng); lower = dgetmem(leng); } while (!feof(fp)) { for (i = 0; i < leng; i++) { mean[i] = 0.0; if (outcov) { if (!diagc) for (j = 0; j < leng; j++) cov[i][j] = 0.0; else var[i] = 0.0; } if (outconf) { var[i] = 0.0; } } for (lp = nv; lp;) { if (freadf(x, sizeof(*x), leng, fp) != leng) break; for (i = 0; i < leng; i++) { mean[i] += x[i]; if (outcov) { if (!diagc) for (j = i; j < leng; j++) cov[i][j] += x[i] * x[j]; else var[i] += x[i] * x[i]; } if (outconf) { var[i] += x[i] * x[i]; } } --lp; } if (lp == 0 || nv == -1) { if (nv > 0) k = nv; else k = -lp - 1; for (i = 0; i < leng; i++) mean[i] /= k; if (outcov) { if (!diagc) for (i = 0; i < leng; i++) for (j = i; j < leng; j++) cov[j][i] = cov[i][j] = cov[i][j] / k - mean[i] * mean[j]; else for (i = 0; i < leng; i++) var[i] = var[i] / k - mean[i] * mean[i]; } if (outconf) { for (i = 0; i < leng; i++) { var[i] = (var[i] - k * mean[i] * mean[i]) / (k - 1); } t = t_percent(conf / 100, k - 1); for (i = 0; i < leng; i++) { err = t * sqrt(var[i] / k); upper[i] = mean[i] + err; lower[i] = mean[i] - err; } } if (corr) { for (i = 0; i < leng; i++) for (j = i + 1; j < leng; j++) cov[j][i] = cov[i][j] = cov[i][j] / sqrt(cov[i][i] * cov[j][j]); for (i = 0; i < leng; i++) cov[i][i] = 1.0; } if (outmean) fwritef(mean, sizeof(*mean), leng, stdout); if (outcov) { if (!diagc) { if (inv) { for (i = 0; i < leng; i++) { for (j = i + 1; j < leng; j++) { cov[j][i] /= cov[i][i]; for (m = i + 1; m < leng; m++) cov[j][m] -= cov[i][m] * cov[j][i]; } } for (m = 0; m < leng; m++) { for (i = 0; i < leng; i++) { if (i == m) invcov[i][m] = 1.0; else invcov[i][m] = 0.0; } for (i = 0; i < leng; i++) { for (j = i + 1; j < leng; j++) invcov[j][m] -= invcov[i][m] * cov[j][i]; } for (i = leng - 1; i >= 0; i--) { for (j = i + 1; j < leng; j++) invcov[i][m] -= cov[i][j] * invcov[j][m]; invcov[i][m] /= cov[i][i]; } } fwritef(invcov[0], sizeof(*invcov[0]), leng * leng, stdout); } else fwritef(cov[0], sizeof(*cov[0]), leng * leng, stdout); } else fwritef(var, sizeof(*var), leng, stdout); } if (outconf) { fwritef(upper, sizeof(*upper), leng, stdout); fwritef(lower, sizeof(*lower), leng, stdout); } } } return (0); }