int harp_import_netcdf(const char *filename, harp_product **product) { harp_product *new_product; netcdf_dimensions dimensions; int ncid; int result; if (filename == NULL) { harp_set_error(HARP_ERROR_INVALID_ARGUMENT, "filename is NULL (%s:%u)", __FILE__, __LINE__); return -1; } result = nc_open(filename, 0, &ncid); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); return -1; } if (verify_product(ncid) != 0) { nc_close(ncid); return -1; } if (harp_product_new(&new_product) != 0) { nc_close(ncid); return -1; } dimensions_init(&dimensions); if (read_product(ncid, new_product, &dimensions) != 0) { dimensions_done(&dimensions); harp_product_delete(new_product); nc_close(ncid); return -1; } dimensions_done(&dimensions); result = nc_close(ncid); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); harp_product_delete(new_product); return -1; } *product = new_product; return 0; }
int harp_import_global_attributes_netcdf(const char *filename, double *datetime_start, double *datetime_stop, long dimension[], char **source_product) { char *attr_source_product = NULL; harp_scalar attr_datetime_start; harp_scalar attr_datetime_stop; harp_data_type attr_data_type; long attr_dimension[HARP_NUM_DIM_TYPES]; int result; int ncid; int i; if (datetime_start == NULL && datetime_stop == NULL) { return 0; } if (filename == NULL) { harp_set_error(HARP_ERROR_INVALID_ARGUMENT, "filename is NULL (%s:%u)", __FILE__, __LINE__); return -1; } result = nc_open(filename, 0, &ncid); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); return -1; } if (verify_product(ncid) != 0) { nc_close(ncid); return -1; } if (datetime_start != NULL) { if (nc_inq_att(ncid, NC_GLOBAL, "datetime_start", NULL, NULL) == NC_NOERR) { if (read_numeric_attribute(ncid, NC_GLOBAL, "datetime_start", &attr_data_type, &attr_datetime_start) != 0) { nc_close(ncid); return -1; } if (attr_data_type != harp_type_double) { harp_set_error(HARP_ERROR_IMPORT, "attribute 'datetime_start' has invalid type"); nc_close(ncid); return -1; } } else { attr_datetime_start.double_data = harp_mininf(); } } if (datetime_stop != NULL) { if (nc_inq_att(ncid, NC_GLOBAL, "datetime_stop", NULL, NULL) == NC_NOERR) { if (read_numeric_attribute(ncid, NC_GLOBAL, "datetime_stop", &attr_data_type, &attr_datetime_stop) != 0) { nc_close(ncid); return -1; } if (attr_data_type != harp_type_double) { harp_set_error(HARP_ERROR_IMPORT, "attribute 'datetime_stop' has invalid type"); nc_close(ncid); return -1; } } else { attr_datetime_stop.double_data = harp_plusinf(); } } if (source_product != NULL) { if (read_string_attribute(ncid, NC_GLOBAL, "source_product", &attr_source_product) != 0) { nc_close(ncid); return -1; } } if (dimension != NULL) { int num_dimensions; int num_variables; int num_attributes; int unlim_dim; int result; for (i = 0; i < HARP_NUM_DIM_TYPES; i++) { attr_dimension[i] = -1; } result = nc_inq(ncid, &num_dimensions, &num_variables, &num_attributes, &unlim_dim); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); return -1; } for (i = 0; i < num_dimensions; i++) { netcdf_dimension_type netcdf_dim_type; harp_dimension_type harp_dim_type; char name[NC_MAX_NAME + 1]; size_t length; result = nc_inq_dim(ncid, i, name, &length); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); return -1; } if (parse_dimension_type(name, &netcdf_dim_type) != 0) { return -1; } if (netcdf_dim_type != netcdf_dimension_independent && netcdf_dim_type != netcdf_dimension_string) { if (get_harp_dimension_type(netcdf_dim_type, &harp_dim_type) != 0) { return -1; } attr_dimension[harp_dim_type] = length; } } } result = nc_close(ncid); if (result != NC_NOERR) { harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result)); free(attr_source_product); return -1; } if (datetime_start != NULL) { *datetime_start = attr_datetime_start.double_data; } if (datetime_stop != NULL) { *datetime_stop = attr_datetime_stop.double_data; } if (source_product != NULL) { *source_product = attr_source_product; } if (dimension != NULL) { for (i = 0; i < HARP_NUM_DIM_TYPES; i++) { dimension[i] = attr_dimension[i]; } } return 0; }
/*-------------------------------------------------------------------*/ void alg_square_root(msieve_obj *obj, mp_poly_t *mp_alg_poly, mp_t *n, mp_t *c, signed_mp_t *m1, signed_mp_t *m0, abpair_t *rlist, uint32 num_relations, uint32 check_q, mp_t *sqrt_a) { /* external interface for computing the algebraic square root */ uint32 i; gmp_poly_t alg_poly; gmp_poly_t d_alg_poly; gmp_poly_t prod; gmp_poly_t alg_sqrt; relation_prod_t prodinfo; double log2_prodsize; mpz_t q; /* initialize */ mpz_init(q); gmp_poly_init(&alg_poly); gmp_poly_init(&d_alg_poly); gmp_poly_init(&prod); gmp_poly_init(&alg_sqrt); /* convert the algebraic poly to arbitrary precision */ for (i = 0; i < mp_alg_poly->degree; i++) { signed_mp_t *coeff = mp_alg_poly->coeff + i; mp2gmp(&coeff->num, alg_poly.coeff[i]); if (coeff->sign == NEGATIVE) mpz_neg(alg_poly.coeff[i], alg_poly.coeff[i]); } alg_poly.degree = mp_alg_poly->degree - 1; /* multiply all the relations together */ prodinfo.monic_poly = &alg_poly; prodinfo.rlist = rlist; prodinfo.c = c; logprintf(obj, "multiplying %u relations\n", num_relations); multiply_relations(&prodinfo, 0, num_relations - 1, &prod); logprintf(obj, "multiply complete, coefficients have about " "%3.2lf million bits\n", (double)mpz_sizeinbase(prod.coeff[0], 2) / 1e6); /* perform a sanity check on the result */ i = verify_product(&prod, rlist, num_relations, check_q, c, mp_alg_poly); free(rlist); if (i == 0) { logprintf(obj, "error: relation product is incorrect\n"); goto finished; } /* multiply by the square of the derivative of alg_poly; this will guarantee that the square root of prod actually is an element of the number field defined by alg_poly. If we didn't do this, we run the risk of the main Newton iteration not converging */ gmp_poly_monic_derivative(&alg_poly, &d_alg_poly); gmp_poly_mul(&d_alg_poly, &d_alg_poly, &alg_poly, 0); gmp_poly_mul(&prod, &d_alg_poly, &alg_poly, 1); /* pick the initial small prime to start the Newton iteration. To save both time and memory, choose an initial prime such that squaring it a large number of times will produce a value just a little larger than we need to calculate the square root. Note that contrary to what some authors write, pretty much any starting prime is okay. The Newton iteration has a division by 2, so that 2 must be invertible mod the prime (this is guaranteed for odd primes). Also, the Newton iteration will fail if both square roots have the same value mod the prime; however, even a 16-bit prime makes this very unlikely */ i = mpz_size(prod.coeff[0]); log2_prodsize = (double)GMP_LIMB_BITS * (i - 2) + log(mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-1)) * pow(2.0, (double)GMP_LIMB_BITS) + mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-2))) / M_LN2 + 10000; while (log2_prodsize > 31.5) log2_prodsize *= 0.5; mpz_set_d(q, (uint32)pow(2.0, log2_prodsize) + 1); /* get the initial inverse square root */ if (!get_initial_inv_sqrt(obj, mp_alg_poly, &prod, &alg_sqrt, q)) { goto finished; } /* compute the actual square root */ if (get_final_sqrt(obj, &alg_poly, &prod, &alg_sqrt, q)) convert_to_integer(&alg_sqrt, n, c, m1, m0, sqrt_a); finished: gmp_poly_clear(&prod); gmp_poly_clear(&alg_sqrt); gmp_poly_clear(&alg_poly); gmp_poly_clear(&d_alg_poly); mpz_clear(q); }