gfio: Add mini library to draw bar graphs and line graphs
[fio.git] / tickmarks.c
CommitLineData
af58ef32
SC
1#include <stdio.h>
2#include <math.h>
3#include <malloc.h>
4
5/*
6 * adapted from Paul Heckbert's algorithm on p 657-659 of
7 * Andrew S. Glassner's book, "Graphics Gems"
8 * ISBN 0-12-286166-3
9 *
10 */
11
12#include "tickmarks.h"
13
14#define MAX(a, b) (((a) < (b)) ? (b) : (a))
15
16static double nicenum(double x, int round)
17{
18 int exp; /* exponent of x */
19 double f; /* fractional part of x */
20
21 exp = floor(log10(x));
22 f = x / pow(10.0, exp);
23 if (round) {
24 if (f < 1.5)
25 return 1.0 * pow(10.0, exp);
26 if (f < 3.0)
27 return 2.0 * pow(10.0, exp);
28 if (f < 7.0)
29 return 5.0 * pow(10.0, exp);
30 return 10.0 * pow(10.0, exp);
31 }
32 if (f <= 1.0)
33 return 1.0 * pow(10.0, exp);
34 if (f <= 2.0)
35 return 2.0 * pow(10.0, exp);
36 if (f <= 5.0)
37 return 5.0 * pow(10.0, exp);
38 return 10.0 * pow(10.0, exp);
39}
40
41int calc_tickmarks(double min, double max, int nticks, struct tickmark **tm)
42{
43 char str[100];
44 int nfrac;
45 double d; /* tick mark spacing */
46 double graphmin, graphmax; /* graph range min and max */
47 double range, x;
48 int count, i;
49
50 /* we expect min != max */
51 range = nicenum(max - min, 0);
52 d = nicenum(range / (nticks - 1), 1);
53 graphmin = floor(min / d) * d;
54 graphmax = ceil(max / d) * d;
55 nfrac = MAX(-floor(log10(d)), 0);
56 snprintf(str, sizeof(str)-1, "%%.%df", nfrac);
57
58 count = ((graphmax + 0.5 * d) - graphmin) / d + 1;
59 *tm = malloc(sizeof(**tm) * count);
60
61 i = 0;
62 for (x = graphmin; x < graphmax + 0.5 * d; x += d) {
63 (*tm)[i].value = x;
64 sprintf((*tm)[i].string, str, x);
65 i++;
66 }
67 return i;
68}
69
70#if 0
71
72static void test_range(double x, double y)
73{
74 int nticks, i;
75
76 struct tickmark *tm = NULL;
77 printf("Testing range %g - %g\n", x, y);
78 nticks = calc_tickmarks(x, y, 10, &tm);
79
80 for (i = 0; i < nticks; i++) {
81 printf(" (%s) %g\n", tm[i].string, tm[i].value);
82 }
83 printf("\n\n");
84 free(tm);
85}
86
87int main(int argc, char *argv[])
88{
89 test_range(0.0005, 0.008);
90 test_range(0.5, 0.8);
91 test_range(5.5, 8.8);
92 test_range(50.5, 80.8);
93 test_range(-20, 20.8);
94 test_range(-30, 700.8);
95}
96#endif