_f_log8 _IEEE_FINITE_L8( _f_real8 x) { /* Union defined to work with IEEE 64-bit floating point. */ union _ieee_double { _f_real8 dword; unsigned long long ui[1]; }; union _ieee_double x_val; x_val.dword = x; /* if x is finite, return TRUE */ return ((_f_log8) isfinite64(x_val.ui[0])); }
int geomap( const size_t ninput, const coord_t* const input, const size_t nref, const coord_t* const ref, const bbox_t* const bbox, const geomap_fit_e fit_geometry, const surface_type_e function, const size_t xxorder, const size_t xyorder, const size_t yxorder, const size_t yyorder, const xterms_e xxterms, const xterms_e yxterms, const size_t maxiter, const double reject, /* Input/Output */ size_t* const noutput, /* Output */ geomap_output_t* const output, /* [MAX(ninput, nref)] */ geomap_result_t* const result, stimage_error_t* const error) { geomap_fit_t fit; bbox_t tbbox; size_t ninput_in_bbox = ninput; size_t nref_in_bbox = nref; coord_t* input_in_bbox = NULL; coord_t* ref_in_bbox = NULL; double* xfit = NULL; double* yfit = NULL; double* weights = NULL; double* tweights = NULL; geomap_output_t* outi = NULL; surface_t sx1, sy1, sx2, sy2; int has_sx2 = 0; int has_sy2 = 0; size_t i = 0; double my_nan = fmod(1.0, 0.0); int status = 1; assert(input); assert(ref); assert(error); if (ninput != nref) { stimage_error_set_message( error, "Must have the same number of input and reference coordinates."); goto exit; } surface_new(&sx1); surface_new(&sy1); surface_new(&sx2); surface_new(&sy2); geomap_fit_init( &fit, geomap_proj_none, fit_geometry, function, xxorder, xyorder, xxterms, yxorder, yyorder, yxterms, maxiter, reject); /* If bbox is NULL, provide a dummy one full of NaNs */ if (bbox == NULL) { bbox_init(&tbbox); } else { bbox_copy(bbox, &tbbox); } /* If the bbox is all NaNs, we don't need to reduce the data, saving an alloc and copy */ if (bbox == NULL || (!isfinite64(tbbox.min.x) && !isfinite64(tbbox.min.y) && !isfinite64(tbbox.max.x) && !isfinite64(tbbox.max.y))) { /* If we have no bbox, we don't need to allocate and copy */ input_in_bbox = (coord_t*)input; ref_in_bbox = (coord_t*)ref; ninput_in_bbox = ninput; nref_in_bbox = nref; } else { input_in_bbox = malloc_with_error( ninput * sizeof(coord_t), error); if (input_in_bbox == NULL) goto exit; ref_in_bbox = malloc_with_error( nref * sizeof(coord_t), error); if (ref_in_bbox == NULL) goto exit; /* Reduce data to only those in the bbox */ ninput_in_bbox = nref_in_bbox = limit_to_bbox( ninput, input, ref, &tbbox, input_in_bbox, ref_in_bbox); } /* Compute the mean of the reference and input coordinates */ compute_mean_coord(nref_in_bbox, ref_in_bbox, &fit.oref); compute_mean_coord(ninput_in_bbox, input_in_bbox, &fit.oin); /* Set the reference point for the projections to undefined */ fit.refpt.x = my_nan; fit.refpt.y = my_nan; /* Allocate some memory */ xfit = malloc_with_error(ninput_in_bbox * sizeof(double), error); if (xfit == NULL) goto exit; yfit = malloc_with_error(ninput_in_bbox * sizeof(double), error); if (yfit == NULL) goto exit; /* Compute the weights */ weights = malloc_with_error(ninput_in_bbox * sizeof(double), error); if (weights == NULL) goto exit; for (i = 0; i < ninput_in_bbox; ++i) { weights[i] = 1.0; } /* Determine the actual max and min of the coordinates */ determine_bbox(nref_in_bbox, ref_in_bbox, &tbbox); bbox_copy(&tbbox, &fit.bbox); if (geofit( &fit, &sx1, &sy1, &sx2, &sy2, &has_sx2, &has_sy2, ninput_in_bbox, input_in_bbox, ref_in_bbox, weights, error)) goto exit; /* Compute the fitted x and y values */ if (geoeval( &sx1, &sy1, &sx2, &sy2, has_sx2, has_sy2, ninput_in_bbox, ref_in_bbox, xfit, yfit, error)) goto exit; if (geo_get_results( &fit, &sx1, &sy1, &sx2, &sy2, has_sx2, has_sy2, result, error)) goto exit; /* DIFF: This section is from geo_plistd */ /* Copy the results to the output buffer */ tweights = malloc_with_error(ninput_in_bbox * sizeof(double), error); if (tweights == NULL) goto exit; for (i = 0; i < ninput_in_bbox; ++i) { tweights[i] = weights[i]; } for (i = 0; i < fit.nreject; ++i) { assert(fit.rej); assert(fit.rej[i] < ninput_in_bbox); if (weights[fit.rej[i]] > 0.0) { tweights[fit.rej[i]] = 0.0; } } outi = output; for (i = 0; i < ninput_in_bbox; ++i, ++outi) { outi->ref.x = ref_in_bbox[i].x; outi->ref.y = ref_in_bbox[i].y; outi->input.x = input_in_bbox[i].x; outi->input.y = input_in_bbox[i].y; if (tweights[i] > 0.0) { outi->fit.x = xfit[i]; outi->fit.y = yfit[i]; outi->residual.x = input_in_bbox[i].x - xfit[i]; outi->residual.y = input_in_bbox[i].y - yfit[i]; } else { outi->fit.x = my_nan; outi->fit.y = my_nan; outi->residual.x = my_nan; outi->residual.y = my_nan; } } *noutput = ninput_in_bbox; status = 0; exit: if (input_in_bbox != input) { free(input_in_bbox); } if (ref_in_bbox != ref) { free(ref_in_bbox); } free(weights); free(xfit); free(yfit); free(tweights); surface_free(&sx1); surface_free(&sy1); surface_free(&sx2); surface_free(&sy2); return status; }
/* DIFF: was geo_fitd */ static int geofit( geomap_fit_t* const fit, surface_t* const sx1, surface_t* const sy1, surface_t* const sx2, surface_t* const sy2, int* const has_sx2, int* const has_sy2, const size_t ncoord, const coord_t* const input, const coord_t* const ref, double* const weights, stimage_error_t* error) { double* residual_x = NULL; double* residual_y = NULL; int status = 1; assert(fit); assert(sx1); assert(sy1); assert(sx2); assert(sy2); assert(input); assert(ref); assert(weights); assert(has_sx2); assert(has_sy2); assert(error); *has_sx2 = 0; *has_sy2 = 0; residual_x = malloc_with_error(ncoord * sizeof(double), error); if (residual_x == NULL) goto exit; residual_y = malloc_with_error(ncoord * sizeof(double), error); if (residual_y == NULL) goto exit; switch(fit->fit_geometry) { case geomap_fit_rotate: if (geo_fit_theta( fit, sx1, sy1, ncoord, input, ref, weights, residual_x, residual_y, error)) goto exit; break; case geomap_fit_rscale: if (geo_fit_magnify( fit, sx1, sy1, ncoord, input, ref, weights, residual_x, residual_y, error)) goto exit; break; case geomap_fit_rxyscale: if (geo_fit_linear( fit, sx1, sy1, ncoord, input, ref, weights, residual_x, residual_y, error)) goto exit; break; default: if (geo_fit_xy( fit, sx1, sx2, ncoord, 0, input, ref, has_sx2, weights, residual_x, error) || geo_fit_xy( fit, sy1, sy2, ncoord, 1, input, ref, has_sy2, weights, residual_y, error)) goto exit; break; } if (fit->maxiter <= 0 || !isfinite64(fit->reject)) { fit->nreject = 0; } else { if (geo_fit_reject( fit, sx1, sy1, sx2, sy2, has_sx2, has_sy2, ncoord, input, ref, weights, residual_x, residual_y, error)) goto exit; } status = 0; exit: free(residual_x); free(residual_y); return status; }