void well_rate_sample_shift( well_rate_type * well_rate ) { int size = time_t_vector_size( well_rate->time_vector ); double * R = util_malloc( size * sizeof * R , __func__); int i; rand_stdnormal_vector( size , R ); for (i=0; i < size; i++) R[i] = R[i] * double_vector_iget( well_rate->std_shift , i ) + double_vector_iget( well_rate->mean_shift , i ); double_vector_iset( well_rate->shift , 0 , R[0]); for (i=1; i < size; i++) { double dt = 1.0 * (time_t_vector_iget( well_rate->time_vector , i ) - time_t_vector_iget( well_rate->time_vector , i - 1)) / (24 * 3600); /* Days */ double a = exp(-dt / well_rate->corr_length ); double shift = a * double_vector_iget( well_rate->shift , i - 1 ) + (1 - a) * R[i]; double base_rate = double_vector_safe_iget( well_rate->base_value , i); /* The time series is sampled - irrespective of whether the well is open or not. */ if ((shift + base_rate) < 0) shift = -base_rate; if (sched_history_well_open( well_rate->sched_history , well_rate->name , i)) double_vector_iset( well_rate->shift , i , shift ); else double_vector_iset( well_rate->shift , i , 0); } free( R ); }
static void text_fprintf2(plot_driver_type * driver , const char * label , const double_vector_type * d1 , const double_vector_type * d2) { FILE * stream = text_fopen( driver , label ); for (int i=0; i < double_vector_size( d1 ); i++) fprintf(stream , "%12.7f %12.7f \n",double_vector_iget(d1 , i) , double_vector_iget(d2 , i)); fclose( stream ); }
void test_insert_double() { double_vector_type * vec = double_vector_alloc(0,0); double_vector_append( vec , 1 ); double_vector_insert( vec , 0 , 0 ); test_assert_double_equal( 0 , double_vector_iget( vec , 0 )); test_assert_double_equal( 1 , double_vector_iget( vec , 1 )); double_vector_free( vec ); }
bool geo_polygon_segment_intersects(const geo_polygon_type * polygon , double x1 , double y1 , double x2 , double y2) { bool intersects = false; double ** points = (double**)util_malloc( 4 * sizeof * points); { int i; for (i = 0; i < 4; i++) points[i] = (double*)util_malloc( 2 * sizeof * points[i]); } points[0][0] = x1; points[1][0] = x2; points[0][1] = y1; points[1][1] = y2; { int index = 0; while (true) { if (index >= (geo_polygon_get_size( polygon ) - 1)) break; { double xc,yc; points[2][0] = double_vector_iget( polygon->xcoord , index ); points[3][0] = double_vector_iget( polygon->xcoord , index + 1); points[2][1] = double_vector_iget( polygon->ycoord , index ); points[3][1] = double_vector_iget( polygon->ycoord , index + 1); { geo_util_xlines_status_enum xline_status = geo_util_xsegments(( const double **) points , &xc , &yc); if ((xline_status == GEO_UTIL_LINES_CROSSING) || (xline_status == GEO_UTIL_LINES_OVERLAPPING)) intersects = true; } if (intersects) break; } index++; } } { int i; for (i = 0; i < 4; i++) free(points[i]); free( points ); } return intersects; }
void test_trace_edge( const ecl_grid_type * grid) { const int k = 1; fault_block_layer_type * layer = fault_block_layer_alloc( grid , k ); double_vector_type * x_list = double_vector_alloc( 0,0); double_vector_type * y_list = double_vector_alloc( 0,0); fault_block_type * block = fault_block_layer_safe_get_block( layer , 99); int_vector_type * cell_list = int_vector_alloc(0,0); test_assert_false( fault_block_trace_edge( block , x_list , y_list , cell_list)); fault_block_add_cell( block , 0,0); test_assert_true( fault_block_trace_edge( block , x_list , y_list , cell_list)); test_assert_int_equal( 4 , double_vector_size( x_list )); test_assert_int_equal( 4 , double_vector_size( y_list )); test_assert_double_equal( 0 , double_vector_iget( x_list , 0 )); test_assert_double_equal( 1 , double_vector_iget( x_list , 1 )); test_assert_double_equal( 1 , double_vector_iget( x_list , 2 )); test_assert_double_equal( 0 , double_vector_iget( x_list , 3 )); test_assert_double_equal( 0 , double_vector_iget( y_list , 0 )); test_assert_double_equal( 0 , double_vector_iget( y_list , 1 )); test_assert_double_equal( 1 , double_vector_iget( y_list , 2 )); test_assert_double_equal( 1 , double_vector_iget( y_list , 3 )); test_assert_int_equal( 1 , int_vector_size( cell_list )); test_assert_int_equal( 0 , int_vector_iget( cell_list , 0)); int_vector_free( cell_list ); double_vector_free( x_list ); double_vector_free( y_list ); }
void group_rate_sample( group_rate_type * group_rate ) { int length = time_t_vector_size( group_rate->time_vector ); double * group_shift = util_malloc( length * sizeof * group_shift , __func__); int * well_count = util_malloc( length * sizeof * well_count , __func__); int num_wells = vector_get_size( group_rate->well_rates ); int i,well_nr; for (i = 0; i < length; i++) { group_shift[i] = 0; well_count[i] = 0; } for (well_nr=0; well_nr < num_wells; well_nr++) { well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); well_rate_sample_shift( well_rate ); { const double * well_shift = double_vector_get_ptr( well_rate_get_shift( well_rate )); for (i = 0; i < length; i++) { group_shift[i] += well_shift[i]; if (well_rate_well_open( well_rate , i )) well_count[i] += 1; } } } { for (i = 0; i < length; i++) { if (group_shift[i] > double_vector_iget( group_rate->max_shift , i)) { double adjustment = -(group_shift[i] - double_vector_iget(group_rate->max_shift , i)) / well_count[i]; for (well_nr = 0; well_nr < num_wells; well_nr++) { well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); well_rate_ishift( well_rate , i , adjustment ); } } else if (group_shift[i] < double_vector_iget( group_rate->min_shift , i )) { double adjustment = -(group_shift[i] - double_vector_iget(group_rate->min_shift , i)) / well_count[i]; for (well_nr = 0; well_nr < num_wells; well_nr++) { well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); well_rate_ishift( well_rate , i , adjustment ); } } } } free( well_count ); free( group_shift ); }
static double SUMMARY_GET_VALUE( const summary_type * summary , node_id_type node_id) { if (summary->vector_storage) { double_vector_type * storage_vector = SELECT_VECTOR( summary , node_id.state ); return double_vector_iget( storage_vector , node_id.report_step ); } else return summary->data[0]; }
void test_content() { rng_type * rng = rng_alloc(MZRAN , INIT_DEFAULT); matrix_type * PC = matrix_alloc( 3 , 10); matrix_type * PC_obs = matrix_alloc( 3 , 1 ); double_vector_type * singular_values = double_vector_alloc(3 , 1); matrix_random_init( PC , rng ); matrix_random_init( PC_obs , rng ); { pca_plot_data_type * data = pca_plot_data_alloc("KEY" , PC , PC_obs, singular_values); for (int i=0; i < matrix_get_rows( PC ); i++) { const pca_plot_vector_type * vector = pca_plot_data_iget_vector( data , i ); test_assert_double_equal( matrix_iget( PC_obs , i , 0) , pca_plot_vector_get_obs_value( vector ) ); test_assert_double_equal( double_vector_iget( singular_values , i), pca_plot_vector_get_singular_value( vector ) ); for (int j=0; j < matrix_get_columns( PC ); j++) test_assert_double_equal( matrix_iget( PC , i , j ) , pca_plot_vector_iget_sim_value( vector , j )); test_assert_int_equal( matrix_get_columns( PC ) , pca_plot_vector_get_size( vector )); } pca_plot_data_free( data ); } double_vector_free( singular_values ); matrix_free( PC ); matrix_free( PC_obs ); }
bool double_vector_approx_equal( const double_vector_type * v1 , const double_vector_type * v2 , double epsilon) { bool equal = true; if (double_vector_size( v1 ) == double_vector_size( v2 )) { int i; for (i=0; i < double_vector_size( v1 ); i++) { double d1 = double_vector_iget( v1 , i ); double d2 = double_vector_iget( v2 , i ); if (!util_double_approx_equal__(d1 , d2 , epsilon)) equal = false; } } else equal = false; return equal; }
/** Step2 is inclusive - what a f*****g mess. */ double misfit_ts_eval( const misfit_ts_type * vector , int step1 , int step2 ) { double misfit_sum = 0; int step; for (step = step1; step <= step2; step++) misfit_sum += double_vector_iget(vector->data , step ); return misfit_sum; }
void misfit_ranking_fprintf( const misfit_ranking_type * misfit_ranking , const char * filename) { FILE * stream = util_mkdir_fopen( filename , "w"); const int ens_size = misfit_ranking->ens_size; const int * permutations = misfit_ranking->sort_permutation; double summed_up = 0.0; { // All this whitespace is finely tuned and highly significant .... const char * key_fmt = " %18s "; const char * value_fmt = " %10.3f %8.3f"; const char * start_fmt = " %2d %3d %7.3f %8.3f"; hash_type * obs_hash = vector_iget( misfit_ranking->ensemble , 0); stringlist_type * obs_keys = hash_alloc_stringlist( obs_hash ); int num_obs = stringlist_get_size( obs_keys ); int iobs; int num_obs_total = num_obs * ens_size; stringlist_sort( obs_keys , enkf_util_compare_keys__ ); fprintf(stream , " Overall "); for (iobs =0; iobs < num_obs; iobs++) fprintf(stream , key_fmt , stringlist_iget( obs_keys , iobs )); fprintf(stream , "\n"); fprintf(stream , " # Realization Norm Total"); for (iobs =0; iobs < num_obs; iobs++) fprintf(stream , " Norm Total"); fprintf(stream , "\n"); for (int i = 0; i < ens_size; i++) { int iens = permutations[i]; hash_type * obs_hash = vector_iget( misfit_ranking->ensemble , iens ); double total_value = double_vector_iget( misfit_ranking->total , iens ); double normalized_misfit = sqrt(total_value / num_obs_total); summed_up = summed_up+total_value; fprintf(stream , start_fmt , i , iens , normalized_misfit , total_value); for (iobs =0; iobs < num_obs; iobs++){ double single_value = hash_get_double( obs_hash , stringlist_iget( obs_keys , iobs )); double single_value_normalized = sqrt(single_value / (num_obs_total)); fprintf(stream , value_fmt , single_value_normalized , single_value); } fprintf(stream , "\n"); } double summed_up_normalized = sqrt(summed_up / (num_obs_total * ens_size)); fprintf(stream , " All %7.3f %8.3f" , summed_up_normalized , summed_up); for (iobs = 0; iobs < num_obs; iobs++){ double single_value_summed_up = 0.0; for (int i = 0; i < ens_size; i++) { single_value_summed_up = single_value_summed_up + hash_get_double( obs_hash , stringlist_iget( obs_keys , iobs )); } double single_value_summed_up_normalized=sqrt(single_value_summed_up / (num_obs_total * ens_size)); fprintf(stream , value_fmt , single_value_summed_up_normalized , single_value_summed_up); } fprintf(stream , "\n"); } fclose( stream ); }
double geo_polygon_get_length( geo_polygon_type * polygon ) { if (double_vector_size( polygon->xcoord) == 1) return 0; else { double length = 0; double x0 = double_vector_iget( polygon->xcoord , 0 ); double y0 = double_vector_iget( polygon->ycoord , 0 ); int i; for (i = 1; i < double_vector_size( polygon->xcoord ); i++) { double x1 = double_vector_iget( polygon->xcoord , i ); double y1 = double_vector_iget( polygon->ycoord , i ); length += sqrt( (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)); x0 = x1; y0 = y1; } return length; } }
time_t_vector_type * ecl_sum_alloc_time_solution( const ecl_sum_type * ecl_sum , const char * gen_key , double cmp_value , bool rates_clamp_lower) { time_t_vector_type * solution = time_t_vector_alloc( 0 , 0); { double_vector_type * seconds = ecl_sum_alloc_seconds_solution( ecl_sum , gen_key , cmp_value , rates_clamp_lower ); time_t start_time = ecl_sum_get_start_time(ecl_sum); for (int i=0; i < double_vector_size( seconds ); i++) { time_t t = start_time; util_inplace_forward_seconds( &t , double_vector_iget( seconds , i )); time_t_vector_append( solution , t ); } double_vector_free( seconds ); } return solution; }
void well_rate_update_wconhist( well_rate_type * well_rate , sched_kw_wconhist_type * kw, int restart_nr ) { double shift = double_vector_iget( well_rate->shift , restart_nr ); switch (well_rate->phase) { case(OIL): sched_kw_wconhist_shift_orat( kw , well_rate->name , shift); break; case(GAS): sched_kw_wconhist_shift_grat( kw , well_rate->name , shift); break; case(WATER): sched_kw_wconhist_shift_wrat( kw , well_rate->name , shift); break; } }
void plplot_plot_hist( plot_driver_type * driver, const char * label , double_vector_type * x , line_attribute_type line_attr) { int size = double_vector_size( x ); plplot_setup_linestyle( line_attr ); { int bins = (int) sqrt( size ); double xmin = double_vector_get_min( x ); double xmax = double_vector_get_max( x ); { /* Could for some fuxxxing reason not get the plhist() function to work, and had to resort to the low level plbin function. */ double * limits = util_calloc(bins + 1 , sizeof * limits ); double * x_ = util_calloc(bins , sizeof * x_ ); double * y_ = util_calloc(bins , sizeof * y_ ); int i; double delta = (xmax - xmin) / bins; for (i= 0; i <= bins; i++) limits[i] = xmin + i*delta; for (i=0; i < bins; i++) { y_[i] = 0; x_[i] = 0.50 * (limits[i] + limits[i + 1]); } for (i=0; i < size; i++) { double value = double_vector_iget(x , i); int j; for (j = 1; j <= bins; j++) if (value < limits[j]) { y_[j-1]++; break; } } /* for (i = 0; i < bins; i++) printf("x[%d] = %g y[%d] = %g\n",i,x_[i],i,y_[i]); */ plbin(bins , x_ , y_ , PL_BIN_CENTRED + PL_BIN_NOEXPAND); free(x_); free(y_); free(limits); } //plhist(size , double_vector_get_ptr(d->x) , xmin , xmax , bins , 0 /* PL_HIST_DEFAULT */); } }
void test_range_fill_double() { double_vector_type * double_vector = double_vector_alloc(0,0); double_vector_range_fill( double_vector , 1,2,10 ); /* 1 , 3 , 5 , 7 , 9 */ test_assert_double_equal( double_vector_size( double_vector ), 5); test_assert_double_equal( double_vector_iget( double_vector , 0 ) , 1 ); test_assert_double_equal( double_vector_iget( double_vector , 1 ) , 3 ); test_assert_double_equal( double_vector_iget( double_vector , 2 ) , 5 ); test_assert_double_equal( double_vector_iget( double_vector , 3 ) , 7 ); test_assert_double_equal( double_vector_iget( double_vector , 4 ) , 9 ); double_vector_range_fill( double_vector , 3,3,9 ); /* 3,6,9 */ test_assert_double_equal( double_vector_size( double_vector ), 3); test_assert_double_equal( double_vector_iget( double_vector , 0 ) , 3 ); test_assert_double_equal( double_vector_iget( double_vector , 1 ) , 6 ); test_assert_double_equal( double_vector_iget( double_vector , 2 ) , 9 ); double_vector_free( double_vector ); }
void data_ranking_display( const data_ranking_type * data_ranking , FILE * stream) { const int ens_size = data_ranking->ens_size; const int * permutations = data_ranking->sort_permutation; { int i; fprintf(stream,"\n\n"); fprintf(stream," # Realization %12s\n" , data_ranking->user_key); fprintf(stream,"----------------------------------\n"); for (i = 0; i < ens_size; i++) { if (bool_vector_iget( data_ranking->valid , permutations[i])) { int iens = permutations[i]; fprintf(stream,"%3d %3d %14.3f\n",i,iens,double_vector_iget(data_ranking->data_ensemble , iens)); } } fprintf(stream,"----------------------------------\n"); } }
void misfit_ranking_display( const misfit_ranking_type * misfit_ranking , FILE * stream) { const int ens_size = double_vector_size( misfit_ranking->total ); const int * permutations = misfit_ranking->sort_permutation; hash_type * obs_hash = NULL; { // The ensemble vector can contain invalid nodes with NULL. int index = 0; while ((obs_hash == NULL) && (index < vector_get_size( misfit_ranking->ensemble))) { obs_hash = vector_iget( misfit_ranking->ensemble , index ); index++; } if (obs_hash == NULL) { fprintf(stderr,"Sorry: no valid results loaded for this misfit_ranking - returning\n"); return; } } { int i; double summed_up = 0.0; stringlist_type * obs_keys = hash_alloc_stringlist( obs_hash ); int num_obs = stringlist_get_size( obs_keys ); int num_obs_total = num_obs * ens_size; // SHould not count failed/missing members ... fprintf(stream,"\n\n"); fprintf(stream," # Realization Normalized misfit Total misfit\n"); fprintf(stream,"-------------------------------------------------------\n"); for (i = 0; i < ens_size; i++) { int iens = permutations[i]; double total_misfit = double_vector_iget( misfit_ranking->total , iens ); double normalized_misfit = sqrt(total_misfit / num_obs_total); summed_up = summed_up+total_misfit; fprintf(stream,"%3d %3d %10.3f %10.3f \n",i,iens,normalized_misfit,total_misfit); } { double normalized_summed_up = sqrt(summed_up / (num_obs_total * ens_size)); fprintf(stream," All %10.3f %10.3f \n",normalized_summed_up,summed_up); } fprintf(stream,"-------------------------------------------------------\n"); } }
bool obs_vector_load_from_HISTORY_OBSERVATION(obs_vector_type * obs_vector , const conf_instance_type * conf_instance , const history_type * history , ensemble_config_type * ensemble_config, double std_cutoff ) { if(!conf_instance_is_of_class(conf_instance, "HISTORY_OBSERVATION")) util_abort("%s: internal error. expected \"HISTORY_OBSERVATION\" instance, got \"%s\".\n",__func__, conf_instance_get_class_name_ref(conf_instance) ); { bool initOK = false; int size , restart_nr; double_vector_type * value = double_vector_alloc(0,0); double_vector_type * std = double_vector_alloc(0,0); bool_vector_type * valid = bool_vector_alloc(0 , false); /* The auto_corrf parameters can not be "segmentized" */ double auto_corrf_param = -1; const char * auto_corrf_name = NULL; double error = conf_instance_get_item_value_double(conf_instance, "ERROR" ); double error_min = conf_instance_get_item_value_double(conf_instance, "ERROR_MIN" ); const char * error_mode = conf_instance_get_item_value_ref( conf_instance, "ERROR_MODE"); const char * sum_key = conf_instance_get_name_ref( conf_instance ); if(conf_instance_has_item(conf_instance, "AUTO_CORRF")) { auto_corrf_name = conf_instance_get_item_value_ref( conf_instance , "AUTO_CORRF"); auto_corrf_param = conf_instance_get_item_value_double(conf_instance, "AUTO_CORRF_PARAM"); if(conf_instance_has_item(conf_instance, "AUTO_CORRF_PARAM")) auto_corrf_param = conf_instance_get_item_value_double(conf_instance, "AUTO_CORRF_PARAM"); else util_abort("%s: When specifying AUTO_CORRF you must also give a vlaue for AUTO_CORRF_PARAM",__func__); } // Get time series data from history object and allocate size = history_get_last_restart(history); if (history_init_ts( history , sum_key , value , valid )) { // Create the standard deviation vector if(strcmp(error_mode, "ABS") == 0) { for( restart_nr = 0; restart_nr < size; restart_nr++) double_vector_iset( std , restart_nr , error ); } else if(strcmp(error_mode, "REL") == 0) { for( restart_nr = 0; restart_nr < size; restart_nr++) double_vector_iset( std , restart_nr , error * abs( double_vector_iget( value , restart_nr ))); } else if(strcmp(error_mode, "RELMIN") == 0) { for(restart_nr = 0; restart_nr < size; restart_nr++) { double tmp_std = util_double_max( error_min , error * abs( double_vector_iget( value , restart_nr ))); double_vector_iset( std , restart_nr , tmp_std); } } else util_abort("%s: Internal error. Unknown error mode \"%s\"\n", __func__, error_mode); // Handle SEGMENTs which can be used to customize the observation error. */ { stringlist_type * segment_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(conf_instance, "SEGMENT"); stringlist_sort( segment_keys , NULL ); int num_segments = stringlist_get_size(segment_keys); for(int segment_nr = 0; segment_nr < num_segments; segment_nr++) { const char * segment_name = stringlist_iget(segment_keys, segment_nr); const conf_instance_type * segment_conf = conf_instance_get_sub_instance_ref(conf_instance, segment_name); int start = conf_instance_get_item_value_int( segment_conf, "START" ); int stop = conf_instance_get_item_value_int( segment_conf, "STOP" ); double error_segment = conf_instance_get_item_value_double(segment_conf, "ERROR" ); double error_min_segment = conf_instance_get_item_value_double(segment_conf, "ERROR_MIN" ); const char * error_mode_segment = conf_instance_get_item_value_ref( segment_conf, "ERROR_MODE"); if(start < 0) { printf("%s: WARNING - Segment out of bounds. Truncating start of segment to 0.\n", __func__); start = 0; } if(stop >= size) { printf("%s: WARNING - Segment out of bounds. Truncating end of segment to %d.\n", __func__, size - 1); stop = size -1; } if(start > stop) { printf("%s: WARNING - Segment start after stop. Truncating end of segment to %d.\n", __func__, start ); stop = start; } // Create the standard deviation vector if(strcmp(error_mode_segment, "ABS") == 0) { for( restart_nr = start; restart_nr <= stop; restart_nr++) double_vector_iset( std , restart_nr , error_segment) ; } else if(strcmp(error_mode_segment, "REL") == 0) { for( restart_nr = start; restart_nr <= stop; restart_nr++) double_vector_iset( std , restart_nr , error_segment * abs(double_vector_iget( value , restart_nr))); } else if(strcmp(error_mode_segment, "RELMIN") == 0) { for(restart_nr = start; restart_nr <= stop ; restart_nr++) { double tmp_std = util_double_max( error_min_segment , error_segment * abs( double_vector_iget( value , restart_nr ))); double_vector_iset( std , restart_nr , tmp_std); } } else util_abort("%s: Internal error. Unknown error mode \"%s\"\n", __func__, error_mode); } stringlist_free(segment_keys); } /* This is where the summary observations are finally added. */ for (restart_nr = 0; restart_nr < size; restart_nr++) { if (bool_vector_safe_iget( valid , restart_nr)) { if (double_vector_iget( std , restart_nr) > std_cutoff) { obs_vector_add_summary_obs( obs_vector , restart_nr , sum_key , sum_key , double_vector_iget( value ,restart_nr) , double_vector_iget( std , restart_nr ) , auto_corrf_name , auto_corrf_param); } else fprintf(stderr,"** Warning: to small observation error in observation %s:%d - ignored. \n", sum_key , restart_nr); } } initOK = true; } double_vector_free(std); double_vector_free(value); bool_vector_free(valid); return initOK; } }
void ecl_sum_resample_from_sim_days( const ecl_sum_type * ecl_sum , const double_vector_type * sim_days , double_vector_type * value , const char * gen_key) { const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); double_vector_reset( value ); { int i; for (i=0; i < double_vector_size( sim_days ); i++) double_vector_iset( value , i , ecl_sum_data_get_from_sim_days( ecl_sum->data , double_vector_iget( sim_days , i ) , node)); } }
void well_rate_update_wconinje( well_rate_type * well_rate , sched_kw_wconinje_type * kw, int restart_nr ) { sched_kw_wconinje_shift_surface_flow( kw , well_rate->name , double_vector_iget( well_rate->shift , restart_nr )); return; }
void geo_polygon_iget_xy(const geo_polygon_type * polygon , int index , double *x , double *y) { *x = double_vector_iget( polygon->xcoord , index ); *y = double_vector_iget( polygon->ycoord , index ); }
void geo_polygon_fprintf(const geo_polygon_type * polygon , FILE * stream) { int i; for (i=0; i < double_vector_size( polygon->xcoord ); i++) fprintf(stream , "%10.3f %10.3f \n", double_vector_iget( polygon->xcoord , i ) , double_vector_iget( polygon->ycoord , i)); }
double statistics_empirical_quantile__( const double_vector_type * data , double quantile ) { if ((quantile < 0) || (quantile > 1.0)) util_abort("%s: quantile must be in [0,1] \n",__func__); { const int size = (double_vector_size( data ) - 1); if (double_vector_iget( data , 0) == double_vector_iget( data , size)) /* All elements are equal - and it is impossible to find a meaingful quantile, we just return "the value". */ return double_vector_iget( data, 0 ); else { double value; double lower_value; double upper_value; double real_index; double upper_quantile; double lower_quantile; int lower_index; int upper_index; real_index = quantile * size; lower_index = floor( real_index ); upper_index = ceil( real_index ); upper_value = double_vector_iget( data , upper_index ); lower_value = double_vector_iget( data , lower_index ); /* Will iterate in this loop until we have found upper_value != lower_value. As long as we know that now all elements are equal (the first test), this is guaranteed to succeed, but of course the estimate will not be very meaningful if the sample consist of a significant number of equal values. */ while (true) { /*1: Try to shift the upper index up. */ if (upper_value == lower_value) { upper_index = util_int_min( size , upper_index + 1); upper_value = double_vector_iget( data , upper_index ); } else break; /*2: Try to shift the lower index down. */ if (upper_value == lower_value) { lower_index = util_int_max( 0 , lower_index - 1); lower_value = double_vector_iget( data , lower_index ); } else break; } upper_quantile = upper_index * 1.0 / size; lower_quantile = lower_index * 1.0 / size; /* Linear interpolation: */ { double a = (upper_value - lower_value) / (upper_quantile - lower_quantile); value = lower_value + a*(quantile - lower_quantile); return value; } } } }