add worspace type
[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 if (tab == NULL) {
47 return NULL;
48 }
49 tab_t *new = alloc_tab (tab->size);
50 memcpy (new->data, tab->data, tab->size * sizeof (double));
51 return new;
52 }
53
54 /* free a tab */
55
56 void free_tab (tab_t *tab)
57 {
58 if (tab) {
59 if (tab->data) {
60 free (tab->data);
61 }
62 free (tab);
63 }
64 }
65
66 /* get table size */
67
68 int size_tab (tab_t *tab)
69 {
70 int ret = 0;
71 if (tab) {
72 ret = tab->size;
73 }
74 return ret;
75 }
76
77 /* set an element into a tab at position id [1..N] */
78
79 double set_tab (tab_t *tab, int id, double val)
80 {
81 double ret = NAN;
82 if ((!tab) || (id < 1) || (id > tab->size)) {
83 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
84 } else {
85 ret = tab->data[id - 1] = val;
86 }
87 return ret;
88 }
89
90 /* get an element from a tab at position id [1..N] */
91
92 double get_tab (tab_t *tab, int id)
93 {
94 double ret = NAN;
95 if ((!tab) || (id < 1) || (id > tab->size)) {
96 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
97 } else {
98 ret = tab->data[id - 1];
99 }
100 return ret;
101 }
102
103 /* push an element into a tab at position id [1.. N](-1 means end) resulting to a tab of N+1 elements */
104
105 double push_tab (tab_t *tab, int id, double val)
106 {
107 double ret = NAN;
108 if ((!tab) || (((id < 1) || (id > tab->size + 1)) && (id != -1))) {
109 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
110 } else {
111
112 /* special case for inserting an element at the end */
113 id = (id == -1) ? tab->size + 1 : id;
114
115 /* create larger tab */
116 double *tmp = (double *) callocordie (tab->size + 1, sizeof (double));
117 memcpy (tmp, tab->data, (id - 1) * sizeof (double));
118 ret = tmp[id - 1] = val;
119 memcpy (tmp + id , tab->data + id - 1, (tab->size - id + 1) * sizeof (double));
120
121 /* update structure */
122 free (tab->data);
123 tab->data = tmp;
124 tab->size++;
125 }
126 return ret;
127 }
128
129 /* pop an element from a tab at position id [1.. N](-1 means last) resulting to a tab of N-1 elements */
130
131 double pop_tab (tab_t *tab, int id)
132 {
133 double ret = NAN;
134 if ((!tab) || (((id < 1) || (id > tab->size)) && (id != -1))) {
135 VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0));
136 } else {
137 ret = tab->data[id - 1];
138
139 /* special case for inserting an element at the end */
140 id = (id == -1) ? tab->size : id;
141
142 /* create larger tab */
143 double *tmp = (double *) callocordie (tab->size - 1, sizeof (double));
144 memcpy (tmp, tab->data, (id - 1) * sizeof (double));
145 memcpy (tmp + id - 1, tab->data + id, (tab->size - id) * sizeof (double));
146
147 /* update structure */
148 free (tab->data);
149 tab->data = tmp;
150 tab->size--;
151 }
152 return ret;
153 }
154
155 /* sort tab */
156
157 void order_tab (tab_t *tab)
158 {
159 int i, j;
160 if ((!tab) || (tab->size < 3)) {
161 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", tab->size));
162 return;
163 }
164
165 /* buble sort */
166 for (i = 0; i < tab->size - 1; i++) {
167 int done = 0;
168 for (j = 0; j < tab->size - 1; j++) {
169 double tab_j = tab->data[j];
170 double tab_jp1 = tab->data[j + 1];
171 if (tab_j > tab_jp1) {
172 tab->data[j] = tab_jp1;
173 tab->data[j + 1] = tab_j;
174 done = 1;
175 }
176 }
177 if (done == 0) {
178 break;
179 }
180 }
181 }
182
183 /* vim: set ts=4 sw=4 et: */