Example #1
0
void analyse_part(gsl_vector * v, unsigned int left, unsigned int right,
                  unsigned long nvalues, double * median, double * leftquartile,
                  double * rightquartile, double * percentage) {
    unsigned long n = right - left + 1;
    unsigned long c = 0;
    unsigned int i;
    dump_ul("number of values in this part", n);
    *percentage = 1.0 * n / nvalues;
    dump_d("equal to percentage of", *percentage);
    for (i = left; i <= right; i++) {
        c++;
        if (c <= n * 1 / 4) {
            *leftquartile = gsl_vector_get(v, i);
        }
        if (c <= n * 2 / 4) {
            *median = gsl_vector_get(v, i);
        }
        if (c <= n * 3 / 4) {
            *rightquartile = gsl_vector_get(v, i);
        }
    }
    dump_d("leftquartile", *leftquartile);
    dump_d("median", *median);
    dump_d("rightquartile", *rightquartile);
}
Example #2
0
gsl_histogram * calc_hist(const gsl_vector * v, int nbins) {
	double max;
	double min;
	unsigned int i;
	double binwidth;
	double sum = 0;
	double val;
	gsl_histogram * h;

	gsl_vector_minmax(v, &min, &max);
	binwidth = (max - min) / nbins;
	dump_d("min", min);
	dump_d("max", max);

	debug("allocating the histogram");
	h = gsl_histogram_alloc(v->size);
	debug("setting range");
	require(gsl_histogram_set_ranges_uniform (h, min, max));

	/* with out the following, the max element doesn't fall in the last bin */
	h->range[h->n] += 1;

	debug("summing up");
	for (i = 0; i < v->size; i++) {
		val = gsl_vector_get(v, i);
		sum += val;
		require(gsl_histogram_increment (h, val));
	}
	debug("scaling");
	/* double gsl_histogram_sum (const gsl_histogram * h) */
	require(gsl_histogram_scale (h, 1/sum));
	debug("done");
	return h;
}
Example #3
0
static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
{
	if (!channel_en(ctrl, c) 
	    || channel_stopped(ctrl, c)
	    || ctrl->channels[c].state != RUNNING
	    /* Only reload the current data descriptor if it has eol set.  */
	    || !ctrl->channels[c].current_d.eol) {
		D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n", 
			 c, ctrl->channels[c].state,
			 channel_stopped(ctrl, c),
			 channel_en(ctrl,c),
			 ctrl->channels[c].eol));
		D(dump_d(c, &ctrl->channels[c].current_d));
		return;
	}

	/* Reload the current descriptor.  */
	channel_load_d(ctrl, c);

	/* If the current descriptor cleared the eol flag and we had already
	   reached eol state, do the continue.  */
	if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
		D(printf("continue %d ok %x\n", c,
			 ctrl->channels[c].current_d.next));
		ctrl->channels[c].regs[RW_SAVED_DATA] =
			(uint32_t) ctrl->channels[c].current_d.next;
		channel_load_d(ctrl, c);
		channel_start(ctrl, c);
	}
}
Example #4
0
static void channel_store_c(struct fs_dma_ctrl *ctrl, int c)
{
	hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN);

	/* Encode and store. FIXME: handle endianness.  */
	D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
	D(dump_d(c, &ctrl->channels[c].current_d));
	cpu_physical_memory_write (addr,
				  (void *) &ctrl->channels[c].current_c,
				  sizeof ctrl->channels[c].current_c);
}
Example #5
0
static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
{
	hwaddr addr = channel_reg(ctrl, c, RW_SAVED_DATA);

	/* Load and decode. FIXME: handle endianness.  */
	D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
	cpu_physical_memory_read (addr,
				  (void *) &ctrl->channels[c].current_d, 
				  sizeof ctrl->channels[c].current_d);

	D(dump_d(c, &ctrl->channels[c].current_d));
	ctrl->channels[c].regs[RW_DATA] = addr;
}
Example #6
0
static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
{
	target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);

	/* Load and decode. FIXME: handle endianness.  */
	D(printf("%s addr=%x\n", __func__, addr));
	cpu_physical_memory_read (addr,
				  (void *) &ctrl->channels[c].current_d, 
				  sizeof ctrl->channels[c].current_d);

	D(dump_d(c, &ctrl->channels[c].current_d));
	ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
		(uint32_t)ctrl->channels[c].current_d.buf;
}
Example #7
0
/**
 * returns 0 on success.
 */
static int load_parameter(mcmc * m, FILE * input, int i) {
	int col = 0;
	double start;
	double min;
	double max;
	double step;
	char * descr = (char*) mem_calloc(MAX_LINE_LENGTH, sizeof(char));
	IFDEBUGPARSER
	dump_i("parsing line", i);

	col = fscanf(input, "%lf\t%lf\t%lf\t%s\t%lf\n", &start, &min, &max, descr,
			&step);
	if (col != 5) {
		fprintf(stderr, "only %d fields matched.\n", col);
		return 1;
	}
	if (!(descr != NULL && mystrnlen(descr, MAX_LINE_LENGTH) > 0 && mystrnlen(
			descr, MAX_LINE_LENGTH) < MAX_LINE_LENGTH)) {
		fprintf(stderr, "description invalid: %s\n", descr);
		return 1;
	}
	IFDEBUGPARSER
	debug("setting values");
	gsl_vector_set(m->params, i, start);
	gsl_vector_set(m->params_best, i, start);
	if (min > max) {
		fprintf(stderr, "min(%f) < max(%f)\n", min, max);
		return 1;
	}
	if (start > max) {
		fprintf(stderr, "start(%f) > max(%f)\n", start, max);
		return 1;
	}
	if (start < min) {
		fprintf(stderr, "start(%f) < min(%f)\n", start, min);
		return 1;
	}
	if (step < 0) {
		step = (max - min) * 0.1;
		dump_d("using auto step size, 10% of parameter space", step);
	}
	gsl_vector_set(m->params_min, i, min);
	gsl_vector_set(m->params_max, i, max);
	m->params_descr[i] = descr;
	gsl_vector_set(m->params_step, i, step /* * (max - min) */);
	IFDEBUGPARSER
	debug("setting values done.");
	return 0;
}
Example #8
0
static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, 
			      unsigned char *buf, int buflen, int eop)
{
	uint32_t len;
	uint32_t saved_data_buf;

	if (ctrl->channels[c].eol == 1)
		return 0;

	saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
	len = (uint32_t) ctrl->channels[c].current_d.after;
	len -= saved_data_buf;
	
	if (len > buflen)
		len = buflen;

	cpu_physical_memory_write (saved_data_buf, buf, len);
	saved_data_buf += len;

	if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after
	    || eop) {
		uint32_t r_intr = ctrl->channels[c].regs[R_INTR];

		D(printf("in dscr end len=%d\n", 
			 ctrl->channels[c].current_d.after
			 - ctrl->channels[c].current_d.buf));
		ctrl->channels[c].current_d.after = 
			(void *) saved_data_buf;

		/* Done. Step to next.  */
		if (ctrl->channels[c].current_d.intr) {
			/* TODO: signal eop to the client.  */
			/* data intr.  */
			ctrl->channels[c].regs[R_INTR] |= 3;
		}
		if (eop) {
			ctrl->channels[c].current_d.in_eop = 1;
			ctrl->channels[c].regs[R_INTR] |= 8;
		}
		if (r_intr != ctrl->channels[c].regs[R_INTR])
			channel_update_irq(ctrl, c);

		channel_store_d(ctrl, c);
		D(dump_d(c, &ctrl->channels[c].current_d));

		if (ctrl->channels[c].current_d.eol) {
			D(printf("channel %d EOL\n", c));
			ctrl->channels[c].eol = 1;
			channel_stop(ctrl, c);
		} else {
			ctrl->channels[c].regs[RW_SAVED_DATA] =
				(uint32_t) ctrl->channels[c].current_d.next;
			/* Load new descriptor.  */
			channel_load_d(ctrl, c);
			saved_data_buf =
				ctrl->channels[c].regs[RW_SAVED_DATA_BUF];
		}
	}

	ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
	return len;
}
Example #9
0
static void channel_out_run(struct fs_dma_ctrl *ctrl, int c)
{
	uint32_t len;
	uint32_t saved_data_buf;
	unsigned char buf[2 * 1024];

	if (ctrl->channels[c].eol == 1)
		return;

	saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);

	D(printf("buf=%x after=%x saved_data_buf=%x\n",
		 (uint32_t)ctrl->channels[c].current_d.buf,
		 (uint32_t)ctrl->channels[c].current_d.after,
		 saved_data_buf));

	if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) {
		/* Done. Step to next.  */
		if (ctrl->channels[c].current_d.out_eop) {
			/* TODO: signal eop to the client.  */
			D(printf("signal eop\n"));
		}
		if (ctrl->channels[c].current_d.intr) {
			/* TODO: signal eop to the client.  */
			/* data intr.  */
			D(printf("signal intr\n"));
			ctrl->channels[c].regs[R_INTR] |= (1 << 2);
			channel_update_irq(ctrl, c);
		}
		if (ctrl->channels[c].current_d.eol) {
			D(printf("channel %d EOL\n", c));
			ctrl->channels[c].eol = 1;
			channel_stop(ctrl, c);
		} else {
			ctrl->channels[c].regs[RW_SAVED_DATA] =
				(uint32_t) ctrl->channels[c].current_d.next;
			/* Load new descriptor.  */
			channel_load_d(ctrl, c);
		}

		channel_store_d(ctrl, c);
		D(dump_d(c, &ctrl->channels[c].current_d));
		return;
	}

	len = (uint32_t) ctrl->channels[c].current_d.after;
	len -= saved_data_buf;

	if (len > sizeof buf)
		len = sizeof buf;
	cpu_physical_memory_read (saved_data_buf, buf, len);

	D(printf("channel %d pushes %x %u bytes\n", c, 
		 saved_data_buf, len));
	/* TODO: Push content.  */
	if (ctrl->channels[c].client->client.push)
		ctrl->channels[c].client->client.push(
			ctrl->channels[c].client->client.opaque, buf, len);
	else
		printf("WARNING: DMA ch%d dataloss, no attached client.\n", c);

	ctrl->channels[c].regs[RW_SAVED_DATA_BUF] += len;
}
Example #10
0
static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
{
	uint32_t len;
	uint32_t saved_data_buf;
	unsigned char buf[2 * 1024];

	struct dma_context_metadata meta;
	bool send_context = true;

	if (ctrl->channels[c].eol)
		return 0;

	do {
		bool out_eop;
		D(printf("ch=%d buf=%x after=%x\n",
			 c,
			 (uint32_t)ctrl->channels[c].current_d.buf,
			 (uint32_t)ctrl->channels[c].current_d.after));

		if (send_context) {
			if (ctrl->channels[c].client->client.metadata_push) {
				meta.metadata = ctrl->channels[c].current_d.md;
				ctrl->channels[c].client->client.metadata_push(
					ctrl->channels[c].client->client.opaque,
					&meta);
			}
			send_context = false;
		}

		channel_load_d(ctrl, c);
		saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
		len = (uint32_t)(unsigned long)
			ctrl->channels[c].current_d.after;
		len -= saved_data_buf;

		if (len > sizeof buf)
			len = sizeof buf;
		cpu_physical_memory_read (saved_data_buf, buf, len);

		out_eop = ((saved_data_buf + len) ==
		           ctrl->channels[c].current_d.after) &&
			ctrl->channels[c].current_d.out_eop;

		D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
		         saved_data_buf, len, out_eop));

		if (ctrl->channels[c].client->client.push)
			ctrl->channels[c].client->client.push(
				ctrl->channels[c].client->client.opaque,
				buf, len, out_eop);
		else
			printf("WARNING: DMA ch%d dataloss,"
			       " no attached client.\n", c);

		saved_data_buf += len;

		if (saved_data_buf == (uint32_t)(unsigned long)
				ctrl->channels[c].current_d.after) {
			/* Done. Step to next.  */
			if (ctrl->channels[c].current_d.out_eop) {
				send_context = true;
			}
			if (ctrl->channels[c].current_d.intr) {
				/* data intr.  */
				D(printf("signal intr %d eol=%d\n",
					len, ctrl->channels[c].current_d.eol));
				ctrl->channels[c].regs[R_INTR] |= (1 << 2);
				channel_update_irq(ctrl, c);
			}
			channel_store_d(ctrl, c);
			if (ctrl->channels[c].current_d.eol) {
				D(printf("channel %d EOL\n", c));
				ctrl->channels[c].eol = 1;

				/* Mark the context as disabled.  */
				ctrl->channels[c].current_c.dis = 1;
				channel_store_c(ctrl, c);

				channel_stop(ctrl, c);
			} else {
				ctrl->channels[c].regs[RW_SAVED_DATA] =
					(uint32_t)(unsigned long)ctrl->
						channels[c].current_d.next;
				/* Load new descriptor.  */
				channel_load_d(ctrl, c);
				saved_data_buf = (uint32_t)(unsigned long)
					ctrl->channels[c].current_d.buf;
			}

			ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
							saved_data_buf;
			D(dump_d(c, &ctrl->channels[c].current_d));
		}
		ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
	} while (!ctrl->channels[c].eol);
	return 1;
}
/* find a local maximum (climb the hill)
 * one probe at a time */
int find_local_maximum_naive(unsigned int ndim, double exactness,
		gsl_vector * current_x) {
	unsigned int i = 0;
	unsigned int last_i = 0;
	unsigned int j = 0;
	unsigned int count = 0;
	double current_val;
	gsl_vector * current_probe = gsl_vector_alloc(ndim);
	gsl_vector * next_probe = gsl_vector_alloc(ndim);
	gsl_vector * scales = gsl_vector_alloc(ndim);
	/* did we switch direction in the last move? */
	int flaps = 0;
	double probe_value;
	gsl_vector_set_all(scales, START_SCALE);

	current_val = f(current_x);
	count++;

	dump_v("currently at", current_x)
	dump_d("current value", current_val);
	while (1) {
		for (j = 0; j < ndim; j++) {
			i = (last_i + j) % ndim;
			gsl_vector_memcpy(current_probe, current_x);
			gsl_vector_set(current_probe, i, gsl_vector_get(current_probe, i)
					+ gsl_vector_get(scales, i));
			limit(current_probe);
			if (calc_same(current_probe, current_x) == 1) {
				dump_i("we clashed a wall in", i);
				gsl_vector_set(scales, i, gsl_vector_get(scales, i) * -1);
				continue;
			}
			dump_v("will probe at", current_probe);
			probe_value = f(current_probe);
			count++;
			if (probe_value > current_val) {
				dump_i("we jump forward in", i);
				current_val = probe_value;
				gsl_vector_memcpy(current_x, current_probe);
				dump_v("currently at", current_x)
				dump_d("current value", current_val);
				break;
			} else {
				dump_i("we turn back in", i);
				gsl_vector_set(scales, i, gsl_vector_get(scales, i) * -1);
			}
		}
#ifndef NO_ROUNDROBIN
		last_i = i;
#else
		last_i = 0;
#endif
		if (j == ndim) {
			if (flaps == 1) {
				debug("all dimensions are ready, lets refine");
				dump_v("currently at", current_x)
				dump_d("exactness (min)", gsl_vector_min(scales));
				dump_d("exactness (max)", gsl_vector_max(scales));
				dump_d("exactness (desired)", exactness);
				if (gsl_vector_max(scales) < exactness
						&& gsl_vector_min(scales) > -exactness) {
					for (i = 0; i < ndim; i++) {
						gsl_vector_memcpy(current_probe, current_x);
						gsl_vector_set(current_probe, i, gsl_vector_get(
								current_probe, i) + abs(gsl_vector_get(scales,
								i)));
						assert(f(current_probe) >= current_val);
						gsl_vector_set(current_probe, i, gsl_vector_get(
								current_probe, i) - 2* abs (gsl_vector_get(
								scales, i)));
						assert(f(current_probe) >= current_val);
					}
					gsl_vector_free(scales);
					gsl_vector_free(current_probe);
					gsl_vector_free(next_probe);
					return count;
				}
				gsl_vector_scale(scales, ZOOM_IN_FACTOR);
				flaps = 0;
				dump_d("new exactness (min)", gsl_vector_min(scales));
				dump_d("new exactness (max)", gsl_vector_max(scales));
			} else {
				flaps = 1;
			}
		} else {
			flaps = 0;
		}
	}
	return count;
}
/* find a local maximum (climb the hill)
 * diagonals */
int find_local_maximum_multi(unsigned int ndim, double exactness,
		gsl_vector * start) {
	unsigned int i;
	unsigned int count = 0;
	int possibly_circle_jump;
	double current_val;
	gsl_vector * current_probe = gsl_vector_alloc(ndim);
	gsl_vector * next_probe = gsl_vector_alloc(ndim);
	gsl_vector * current_x = dup_vector(start);
	gsl_vector * scales = gsl_vector_alloc(ndim);
	/* did we switch direction in the last move? */
	gsl_vector * flaps = gsl_vector_alloc(ndim);
	gsl_vector * probe_values = gsl_vector_alloc(ndim);
	gsl_vector_set_all(scales, START_SCALE);
	gsl_vector_set_all(flaps, 0);
	assert(exactness < 1);

	while (1) {
		dump_v("currently at", current_x)
		current_val = f(current_x);
		count++;
		dump_d("current value", current_val);

		gsl_vector_memcpy(next_probe, current_x);
		gsl_vector_add(next_probe, scales);
		limit(next_probe);
		dump_v("will probe at", next_probe);

		for (i = 0; i < ndim; i++) {
			gsl_vector_memcpy(current_probe, current_x);
			gsl_vector_set(current_probe, i, gsl_vector_get(next_probe, i));

			gsl_vector_set(probe_values, i, f(current_probe) - current_val);
			if (gsl_vector_get(probe_values, i) < 0)
				gsl_vector_set(probe_values, i, 0);
			count++;
		}
		if(gsl_vector_max(probe_values) != 0)
			gsl_vector_scale(probe_values, 1 / gsl_vector_max(probe_values));
		dump_v("probe results", probe_values);
		gsl_vector_memcpy(start, current_x);

		possibly_circle_jump = detect_circle_jump(flaps, probe_values);

		for (i = 0; i < ndim; i++) {
			if (gsl_vector_get(probe_values, i) > 0) {
				dump_i("we jump forward in", i);
				gsl_vector_set(
						current_x,
						i,
						gsl_vector_get(current_x, i)
								+ gsl_vector_get(scales, i) * JUMP_SCALE
										*
#ifdef ADAPTIVE
										gsl_vector_get(probe_values, i) *
#endif
										(1
												+ (gsl_rng_uniform(
														get_rng_instance())
														- 0.5) * 2
														* (RANDOM_SCALE
																+ possibly_circle_jump
																		* RANDOM_SCALE_CIRCLE_JUMP)));
				limit(current_x);
				if (gsl_vector_get(current_x, i) == gsl_vector_get(start, i)) {
					/* we clashed against a wall. That means we are ready to
					 * refine */
					gsl_vector_set(flaps, i, 2);
				} else {
					gsl_vector_set(flaps, i, 0);
				}
			} else {
				if (gsl_vector_get(flaps, i) == 0) {
					dump_i("we turn back in", i);
					gsl_vector_set(flaps, i, 1);
					/* TODO: should we step back a little?
					 * no we can't, otherwise our double-turnback is tainted */
					gsl_vector_set(scales, i, gsl_vector_get(scales, i) * -1);
				} else {
					dump_i("we turned back twice in", i);
					gsl_vector_set(flaps, i, 2);
				}
			}
		}
		if (gsl_vector_min(flaps) == 2) {
			debug("all dimensions are ready, lets refine");
			dump_d("exactness (min)", gsl_vector_min(scales));
			dump_d("exactness (max)", gsl_vector_max(scales));
			dump_d("exactness (desired)", exactness);
			if (gsl_vector_max(scales) < exactness && gsl_vector_min(scales)
					> -exactness) {
				for (i = 0; i < ndim; i++) {
					gsl_vector_memcpy(current_probe, start);
					gsl_vector_set(current_probe, i, gsl_vector_get(
							current_probe, i) + abs(gsl_vector_get(scales, i)));
					assert(f(current_probe) >= current_val);
					gsl_vector_set(current_probe, i, gsl_vector_get(
							current_probe, i) - 2* abs (gsl_vector_get(scales,
							i)));
					assert(f(current_probe) >= current_val);
				}
				gsl_vector_free(scales);
				gsl_vector_free(flaps);
				gsl_vector_free(probe_values);
				gsl_vector_free(current_probe);
				gsl_vector_free(next_probe);
				gsl_vector_free(current_x);
				return count;
			}
			gsl_vector_scale(scales, ZOOM_IN_FACTOR);
			gsl_vector_set_all(flaps, 0);
			dump_d("new exactness (min)", gsl_vector_min(scales));
			dump_d("new exactness (max)", gsl_vector_max(scales));
		}
	}
}
Example #13
0
void run(char * filename, unsigned long nmaxvalues, double min, double max) {
    unsigned int i;
    unsigned int nvalues;
    double empty_space_needed;
    unsigned int left;
    unsigned int right;
    double median = 0, leftquartile = 0, rightquartile = 0, percentage = 0;
    gsl_vector * values = gsl_vector_alloc(nmaxvalues);
    gsl_vector * medians = gsl_vector_alloc(100);
    gsl_vector * leftquartiles = gsl_vector_alloc(100);
    gsl_vector * rightquartiles = gsl_vector_alloc(100);
    gsl_vector * percentages = gsl_vector_alloc(100);
    gsl_vector * vectors[4];
    unsigned int npeaks = 0;
    vectors[0] = percentages;
    vectors[1] = medians;
    vectors[2] = leftquartiles;
    vectors[3] = rightquartiles;

    dump_ul("nmaxvalues", nmaxvalues);
    nvalues = fill_vector(values, filename, min, max);
    dump_ul("nvalues", nmaxvalues);
    debug("data ready!");
    qsort(values->data, nvalues, sizeof(double), double_comp);
    debug("data sorted!");

    /* 0.1% of parameter space */
    empty_space_needed = (max - min) / 100;
    dump_d("empty_space_needed", empty_space_needed);
    dump_d("min", min);
    dump_d("max", max);

    assert(gsl_vector_get(values, 0) >= min);
    assert(gsl_vector_get(values, 0) <= max);
    assert(gsl_vector_get(values, nvalues - 1) >= min);
    assert(gsl_vector_get(values, nvalues - 1) <= max);

    left = 0;
    while (1) {
        dump_ui("found left side", left);
        dump_d("left side", gsl_vector_get(values, left));
        right = left + 1;
        for (; right < nvalues; right++) {
            if (gsl_vector_get(values, right) - gsl_vector_get(values, right
                    - 1) > empty_space_needed) {
                dump_d("gap till next", gsl_vector_get(values, right) - gsl_vector_get(values, right
                        - 1));
                break;
            }
        }
        right--;
        dump_ui("found right side", right);
        dump_d("right side", gsl_vector_get(values, right));
        analyse_part(values, left, right, nvalues, &median, &leftquartile,
                     &rightquartile, &percentage);
        gsl_vector_set(medians, npeaks, median);
        gsl_vector_set(leftquartiles, npeaks, leftquartile);
        gsl_vector_set(rightquartiles, npeaks, rightquartile);
        gsl_vector_set(percentages, npeaks, percentage);
        npeaks++;
        assert(npeaks < 100);

        if (right == nvalues - 1)
            break;
        left = right + 1;
    }

#ifndef NOSORT
    sort(vectors, 4, npeaks);
#endif
    printf("median\t-\t+\tpercent\n");
    fflush(NULL);
    for (i = 0; i < npeaks; i++) {
        printf("%f\t%f\t%f\t%f\n", gsl_vector_get(medians, i), gsl_vector_get(
                   medians, i) - gsl_vector_get(leftquartiles, i), gsl_vector_get(
                   rightquartiles, i) - gsl_vector_get(medians, i),
               gsl_vector_get(percentages, i));
    }

    gsl_vector_free(values);
    gsl_vector_free(medians);
    gsl_vector_free(leftquartiles);
    gsl_vector_free(rightquartiles);
    gsl_vector_free(percentages);
}