use tab_t for storage
[calc.git] / tabular.c
1 #include <malloc.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "debug.h"
7 #include "alloc.h"
8
9 #include "tabular.h"
10
11 /* management function */
12
13 /* allocate a tab of N elements */
14
15 tab_t *alloc_tab (int nb)
16 {
17 tab_t *tab = (tab_t *) callocordie (1, sizeof (tab_t));
18 if (nb > 0) {
19 tab->data = (double *) callocordie (nb, sizeof (double));
20 tab->size = nb;
21 }
22 return (tab);
23 }
24
25 /* resize a tab to size N */
26
27 tab_t *resize_tab (tab_t *tab, int nb)
28 {
29 double *tmp = NULL;
30 tab = (tab) ? tab : (tab_t *) callocordie (1, sizeof (tab_t));
31 nb = (nb > 0) ? nb : 0;
32 if (nb > 0) {
33 tmp = (double *) callocordie (nb, sizeof (double));
34 memcpy (tmp, tab->data, ((tab->size < nb) ? tab->size : nb) * sizeof (double));
35 }
36 free (tab->data);
37 tab->data = tmp;
38 tab->size = nb;
39 return tab;
40 }
41
42 /* copy a tab */
43
44 tab_t *copy_tab (tab_t *tab)
45 {
46 tab_t *new = alloc_tab (tab->size);
47 memcpy (new->data, tab->data, tab->size * sizeof (double));
48 return new;
49 }
50
51 /* free a tab */
52
53 void free_tab (tab_t *tab)
54 {
55 if (tab) {
56 if (tab->data) {
57 free (tab->data);
58 }
59 free (tab);
60 }
61 }
62
63 /* get table size */
64
65 int size_tab (tab_t *tab)
66 {
67 int ret = 0;
68 if (tab) {
69 ret = tab->size;
70 }
71 return ret;
72 }
73
74 /* set an element into a tab at position id [1..N] */
75
76 double set_tab (tab_t *tab, int id, double val)
77 {
78 double ret = NAN;
79 if ((!tab) || (id < 1) || (id > tab->size)) {
80 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
81 } else {
82 ret = tab->data[id - 1] = val;
83 }
84 return ret;
85 }
86
87 /* get an element from a tab at position id [1..N] */
88
89 double get_tab (tab_t *tab, int id)
90 {
91 double ret = NAN;
92 if ((!tab) || (id < 1) || (id > tab->size)) {
93 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
94 } else {
95 ret = tab->data[id - 1];
96 }
97 return ret;
98 }
99
100 /* push an element into a tab at position id [1.. N](-1 means end) resulting to a tab of N+1 elements */
101
102 double push_tab (tab_t *tab, int id, double val)
103 {
104 double ret = NAN;
105 if ((!tab) || (((id < 1) || (id > tab->size + 1)) && (id != -1))) {
106 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
107 } else {
108
109 /* special case for inserting an element at the end */
110 id = (id == -1) ? tab->size + 1 : id;
111
112 /* create larger tab */
113 double *tmp = (double *) callocordie (tab->size + 1, sizeof (double));
114 memcpy (tmp, tab->data, (id - 1) * sizeof (double));
115 ret = tmp[id - 1] = val;
116 memcpy (tmp + id , tab->data + id - 1, (tab->size - id + 1) * sizeof (double));
117
118 /* update structure */
119 free (tab->data);
120 tab->data = tmp;
121 tab->size++;
122 }
123 return ret;
124 }
125
126 /* pop an element from a tab at position id [1.. N](-1 means last) resulting to a tab of N-1 elements */
127
128 double pop_tab (tab_t *tab, int id)
129 {
130 double ret = NAN;
131 if ((!tab) || (((id < 1) || (id > tab->size)) && (id != -1))) {
132 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
133 } else {
134 ret = tab->data[id - 1];
135
136 /* special case for inserting an element at the end */
137 id = (id == -1) ? tab->size : id;
138
139 /* create larger tab */
140 double *tmp = (double *) callocordie (tab->size - 1, sizeof (double));
141 memcpy (tmp, tab->data, (id - 1) * sizeof (double));
142 memcpy (tmp + id - 1, tab->data + id, (tab->size - id) * sizeof (double));
143
144 /* update structure */
145 free (tab->data);
146 tab->data = tmp;
147 tab->size--;
148 }
149 return ret;
150 }
151
152 /* sort tab */
153
154 void order_tab (tab_t *tab)
155 {
156 int i, j;
157 if ((!tab) || (tab->size < 3)) {
158 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", tab->size));
159 return;
160 }
161
162 /* buble sort */
163 for (i = 0; i < tab->size - 1; i++) {
164 int done = 0;
165 for (j = 0; j < tab->size - 1; j++) {
166 double tab_j = tab->data[j];
167 double tab_jp1 = tab->data[j + 1];
168 if (tab_j > tab_jp1) {
169 tab->data[j] = tab_jp1;
170 tab->data[j + 1] = tab_j;
171 done = 1;
172 }
173 }
174 if (done == 0) {
175 break;
176 }
177 }
178 }
179
180 /* vim: set ts=4 sw=4 et: */