/*============================================================================== * find minimum within array y[] *==============================================================================*/ void find_min(double *x, double *y, int nbins, int ismooth, double *x_min, double *y_min) { int ibin, ibin_min[2]; double ymax; smooth3(y, nbins, ismooth); ymax = -10.0; /* approach from left */ ibin_min[0] = nbins-1; for(ibin=0; ibin<nbins-1; ibin++) { if(y[ibin] < ymax) { ymax = y[ibin]; ibin_min[0] = ibin; } } /* approch from right */ ibin_min[1] = ibin_min[0]; for(ibin=(nbins-1+ibin_min[0])/2; ibin>ibin_min[0]; ibin--) { if(y[ibin] < ymax) { ymax = y[ibin]; ibin_min[1] = ibin; } } *x_min = ( x[ibin_min[0]] + x[ibin_min[1]] )/2; *y_min = ( y[ibin_min[0]] + y[ibin_min[1]] )/2; }
/** * \brief Finds the minimum in a given array. * * \param *x An array containing the x-values. * \param *y An array containing the y-values. * \param num The length of the both arrays. * \param steps Total number of interpolation steps. * \param smooth Total number of smoothing steps. * \param *maxx A pointer to a variable that will hold the position of * the maximum. * \param *maxy A pointer to a variable that will hold the value of * the function at the found maximum. * * \return Returns nothing. */ void find_min_spline(double *x, double *y, int num, int smooth, double *minx, double *miny, int steps) { double *y2, xi, yi, incr; /* Smooth the data */ smooth3(y, num, smooth); /* obtain second derivatives to be used with splint(), i.e. "spline interpolation" */ y2 = (double *) calloc(num, sizeof(double)); spline(x-1, y-1, num, 2E33, 2E33, y2-1); /* scan the spline interpolation using splint() */ *miny = 1e10; incr = (x[num-1] - x[0])/(double)(steps-1); xi = x[0]; while (xi <= x[num-1]) { splint(x-1, y-1, y2-1, num, xi, &yi); if (yi < *miny) { *minx = xi; *miny = yi; } xi += incr; } free(y2); return; }
__attribute__((noinline)) static void smooth3(float* v) { #if 0 for(int64_t k=0; (size_t)k < dims[2]; ++k) { for(int64_t j=0; (size_t)j < dims[1]; ++j) { for(int64_t i=0; (size_t)i < dims[0]; ++i) { #else for(uint64_t k=0; k < dims[2]; ++k) { for(uint64_t j=0; j < dims[1]; ++j) { for(uint64_t i=0; i < dims[0]; ++i) { #endif const size_t idx = (size_t)k*dims[0]*dims[1] + (size_t)j*dims[0] + i; /* technically 1D, but whatever... */ v[idx] = (IDX3(i-1,j,k) + IDX3(i,j,k) + IDX3(i+1,j,k)) / 3.0f; } } } } int main(int argc, char* argv[]) { if(argc < 2) { fprintf(stderr, "need arg: which computation to run.\n"); return EXIT_FAILURE; } if(argc == 42) { dims[0] = 12398; } for(size_t i=1; i < (size_t)argc; ++i) { if(atoi(argv[i]) == 0) { scalarvar(); } else if(atoi(argv[i]) == 1) { varr = calloc(dims[0], sizeof(float)); smooth1(); free(varr); } else if(atoi(argv[i]) == 2) { v2darr = calloc(dims[0]*dims[1], sizeof(float)); smooth2(v2darr); free(v2darr); } else if(atoi(argv[i]) == 3) { v3darr = calloc(dims[0]*dims[1]*dims[2], sizeof(float)); smooth3(v3darr); free(v3darr); } else { fprintf(stderr, "unknown computational id '%s'\n", argv[i]); return EXIT_FAILURE; } } printf("%s finished.\n", argv[0]); return 0; }
/*============================================================================== * find maximum within array y[] *==============================================================================*/ void find_max(double *x, double *y_raw, int nbins, int ismooth, double *x_max, double *y_max) { int ibin, ibin_max[2]; double ymax; double *y; /* do not smooth the actual array as this will obscure the peak value! */ y = calloc(nbins,sizeof(double)); for(ibin=0; ibin<nbins; ibin++) y[ibin]=y_raw[ibin]; smooth3(y, nbins, ismooth); ymax = -10.0; /* approach from left */ ibin_max[0] = nbins-1; for(ibin=0; ibin<nbins-1; ibin++) { if(y[ibin] > ymax) { ymax = y[ibin]; ibin_max[0] = ibin; } } /* approch from right */ ibin_max[1] = ibin_max[0]; for(ibin=(nbins-1+ibin_max[0])/2; ibin>ibin_max[0]; ibin--) { if(y[ibin] > ymax) { ymax = y[ibin]; ibin_max[1] = ibin; } } *x_max = ( x[ibin_max[0]] + x[ibin_max[1]] )/2; *y_max = ( y_raw[ibin_max[0]] + y_raw[ibin_max[1]] )/2; /* be nice */ free(y); }