void analyze_method(std::string method_name, double initial_step, int iterations_count, std::function<double(double, double, double)> calc_next) {
    std::cout << method_name << std::endl;
    print_hline();

    double step = initial_step;
    for (int i = 0; i < iterations_count; ++i, step /= 2) {
        std::cout << "Step: " << step << std::endl;
        double cur_value = LEFT_END_VALUE;
        for (double x = SEGMENT_LEFT_END; x < SEGMENT_RIGHT_END - EPS; x += step) {
            std::cout << std::fixed << std::setprecision(10) << cur_value << std::endl;
            cur_value = calc_next(step, x, cur_value);
        }
        std::cout << std::fixed << std::setprecision(10) << cur_value << std::endl;
    }

    print_hline();
}
/** 
 * Get list of supported cameras, walk through it and create some output.
 */
int
main (int argc, char *argv[])
{
	CameraAbilitiesList *al;
	int i;
	int count;
	const char *fmt_str = NULL;

	parse_command_line (argc, argv);

	if (do_debug) {
		gettimeofday (&glob_tv_zero, NULL);
		CHECK (gp_log_add_func (GP_LOG_ALL, debug_func, NULL));
		
		gp_log (GP_LOG_DEBUG, "main", "test-camera-list start");
	}


	CHECK (gp_abilities_list_new (&al));
	CHECK (gp_abilities_list_load (al, NULL));

	count = gp_abilities_list_count (al);
	if (count < 0) {
		printf("gp_abilities_list_count error: %d\n", count);
		return(1);
	} else if (count == 0) {
		/* Copied from gphoto2-abilities-list.c gp_abilities_list_load() */
		const char *camlib_env = getenv(CAMLIBDIR_ENV);
		const char *camlibs = (camlib_env != NULL)?camlib_env:CAMLIBS;

		printf("no camera drivers (camlibs) found in camlib dir:\n"
		       "    CAMLIBS='%s', default='%s', used=%s\n",
		       camlib_env?camlib_env:"(null)", CAMLIBS,
		       (camlib_env!=NULL)?"CAMLIBS":"default");
		return(1);
	}


	/* Set output format for file body, 
	 * and print opening part of output file. */
	switch (format) {
	case FMT_CSV:
		fmt_str = "%d,%s,%s,%s\n";
		break;
	case FMT_FLAT_TEXT:
		fmt_str = "%3d|%-20s|%-20s|%s\n";
		break;
	case FMT_HEADED_TEXT:
		fmt_str = "%3d|%-20s|%-20s|%s\n";
		break;
	case FMT_XML:
		fmt_str = "  <camera name=\"%4$s\" entry_number=\"%1$d\">\n"
			"    <camlib-name value=\"%2$s\"/>\n"
			"    <driver-name value=\"%3$s\"/>\n"
			"  </camera>\n";
		printf("<?xml version=\"%s\" encoding=\"%s\"?>\n"
		       "<camera-list camera-count=\"%d\">\n", 
		       "1.0", "us-ascii", count);
		break;
	case FMT_FLAT_CAMLIBS:
		fmt_str = "%2$-28s  %3$s\n";
		break;
	case FMT_COUNT:
		printf("%d\n", count);
		return(0);
		break;
	}

	/* For each camera in the list, add a text snippet to the 
	 * output file. */
	for (i = 0; i < count; i++) {
		CameraAbilities abilities;
		const char *camlib_basename;
		CHECK (gp_abilities_list_get_abilities (al, i, &abilities));
		camlib_basename = path_basename(abilities.library);

		switch (format) {
		case FMT_HEADED_TEXT:
			if ( ((i%25)== 0) && 
			     ( (i==0) || ((count-i) > 5) ) ) {
				print_hline();
				print_headline();
				print_hline();
			}
			break;
		case FMT_FLAT_CAMLIBS:
			break;
		case FMT_XML:
			break;
		case FMT_CSV:
			break;
		case FMT_FLAT_TEXT:
			break;
		case FMT_COUNT:
			break;
		}

		printf(fmt_str,
		       i+1, 
		       camlib_basename,
		       abilities.id,
		       abilities.model);
	}

	/* Print closing part of output file. */
	switch (format) {
	case FMT_HEADED_TEXT:
		print_hline();
		print_headline();
		print_hline();
		break;
	case FMT_FLAT_CAMLIBS:
		break;
	case FMT_XML:
		printf("</camera-list>\n");
		break;
	case FMT_CSV:
		break;
	case FMT_FLAT_TEXT:
		break;
	case FMT_COUNT:
		break;
	}
	
	CHECK (gp_abilities_list_free (al));
	return (0);
}