excit.c 7.28 KB
Newer Older
1
2
3
4
5
6
7
8
9
/*******************************************************************************
 * Copyright 2019 UChicago Argonne, LLC.
 * (c.f. AUTHORS, LICENSE)
 *
 * This file is part of the EXCIT project.
 * For more info, see https://xgitlab.cels.anl.gov/argo/excit
 *
 * SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
10
#include <stdlib.h>
11
#include "excit.h"
12
#include "dev/excit.h"
13
#include "composition.h"
14
15
#include "prod.h"
#include "cons.h"
16
#include "repeat.h"
17
#include "hilbert2d.h"
18
#include "range.h"
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
19
#include "index.h"
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
20
#include "tleaf.h"
Brice Videau's avatar
Brice Videau committed
21

Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
22
#define CASE(val) case val: return #val; break
23

24
const char *excit_type_name(enum excit_type_e type)
25
{
26
	switch (type) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
27
		CASE(EXCIT_INDEX);
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
28
29
30
31
32
		CASE(EXCIT_RANGE);
		CASE(EXCIT_CONS);
		CASE(EXCIT_REPEAT);
		CASE(EXCIT_HILBERT2D);
		CASE(EXCIT_PRODUCT);
33
		CASE(EXCIT_COMPOSITION);
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
34
35
		CASE(EXCIT_USER);
		CASE(EXCIT_TYPE_MAX);
36
37
38
39
40
	default:
		return NULL;
	}
}

41
const char *excit_error_name(enum excit_error_e err)
42
{
43
	switch (err) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
44
45
46
47
48
49
50
		CASE(EXCIT_SUCCESS);
		CASE(EXCIT_STOPIT);
		CASE(EXCIT_ENOMEM);
		CASE(EXCIT_EINVAL);
		CASE(EXCIT_EDOM);
		CASE(EXCIT_ENOTSUP);
		CASE(EXCIT_ERROR_MAX);
51
52
53
54
55
56
57
	default:
		return NULL;
	}
}

#undef CASE

58
59
int excit_set_dimension(excit_t it, ssize_t dimension)
{
60
61
62
63
64
65
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	it->dimension = dimension;
	return EXCIT_SUCCESS;
66
67
}

68
int excit_get_data(excit_t it, void **data)
69
{
70
71
72
73
74
75
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	*data = it->data;
	return EXCIT_SUCCESS;
76
77
}

78
int excit_set_func_table(excit_t it, struct excit_func_table_s *func_table)
79
{
80
81
82
83
	if (!it)
		return -EXCIT_EINVAL;
	it->func_table = func_table;
	return EXCIT_SUCCESS;
84
85
}

86
int excit_get_func_table(excit_t it, struct excit_func_table_s **func_table)
87
{
88
89
90
91
	if (!it)
		return -EXCIT_EINVAL;
	*func_table = it->func_table;
	return EXCIT_SUCCESS;
92
93
}

94
95
/*--------------------------------------------------------------------*/

Brice Videau's avatar
Brice Videau committed
96
97
98
99
100
101
102
103
104
105
106
#define ALLOC_EXCIT(op) { \
	it = malloc(sizeof(struct excit_s) + sizeof(struct op## _it_s)); \
	if (!it) \
		return NULL; \
	it->data = (void *)((char *)it + sizeof(struct excit_s)); \
	if (!excit_ ##op## _func_table.alloc) \
		goto error; \
	it->func_table = &excit_ ##op## _func_table; \
	it->dimension = 0; \
	if (excit_ ##op## _func_table.alloc(it)) \
		goto error; \
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
107
}
108

Brice Videau's avatar
Brice Videau committed
109
excit_t excit_alloc(enum excit_type_e type)
110
{
111
112
113
	excit_t it = NULL;

	switch (type) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
114
115
116
	case EXCIT_INDEX:
		ALLOC_EXCIT(index);
		break;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	case EXCIT_RANGE:
		ALLOC_EXCIT(range);
		break;
	case EXCIT_CONS:
		ALLOC_EXCIT(cons);
		break;
	case EXCIT_REPEAT:
		ALLOC_EXCIT(repeat);
		break;
	case EXCIT_HILBERT2D:
		ALLOC_EXCIT(hilbert2d);
		break;
	case EXCIT_PRODUCT:
		ALLOC_EXCIT(prod);
		break;
132
133
	case EXCIT_COMPOSITION:
		ALLOC_EXCIT(composition);
134
135
136
137
138
139
140
141
142
		break;
	case EXCIT_TLEAF:
		ALLOC_EXCIT(tleaf);
		break;
	default:
		goto error;
	}
	it->type = type;
	return it;
143
error:
144
145
	free(it);
	return NULL;
146
147
}

148
149
excit_t excit_alloc_user(struct excit_func_table_s *func_table,
			 size_t data_size)
150
{
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
	excit_t it;

	if (!func_table || !data_size)
		return NULL;
	it = malloc(sizeof(struct excit_s) + data_size);
	if (!it)
		return NULL;
	it->data = (void *)((char *)it + sizeof(struct excit_s));
	if (!func_table->alloc)
		goto error;
	it->func_table = func_table;
	it->dimension = 0;
	it->type = EXCIT_USER;
	if (func_table->alloc(it))
		goto error;
	return it;
167
error:
168
169
	free(it);
	return NULL;
170
171
}

172
excit_t excit_dup(excit_t it)
173
{
Brice Videau's avatar
Brice Videau committed
174
	excit_t result = NULL;
175

176
	if (!it || !it->data || !it->func_table || !it->func_table->copy)
177
		return NULL;
178
	result = excit_alloc(it->type);
179
180
	if (!result)
		return NULL;
181
	result->dimension = it->dimension;
182
	if (it->func_table->copy(result, it))
183
184
185
		goto error;
	return result;
error:
186
187
	excit_free(result);
	return NULL;
188
189
}

190
void excit_free(excit_t it)
191
{
192
193
194
195
196
197
	if (!it)
		return;
	if (!it->func_table)
		goto error;
	if (it->func_table->free)
		it->func_table->free(it);
198
error:
199
	free(it);
200
201
}

202
int excit_dimension(excit_t it, ssize_t *dimension)
203
{
204
205
206
207
	if (!it || !dimension)
		return -EXCIT_EINVAL;
	*dimension = it->dimension;
	return EXCIT_SUCCESS;
208
209
}

210
int excit_type(excit_t it, enum excit_type_e *type)
211
{
212
213
214
215
216
217
	if (!it || !type)
		return -EXCIT_EINVAL;
	*type = it->type;
	return EXCIT_SUCCESS;
}

218
int excit_next(excit_t it, ssize_t *indexes)
219
{
220
221
222
223
224
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->next)
		return -EXCIT_ENOTSUP;
	return it->func_table->next(it, indexes);
225
226
}

227
int excit_peek(const excit_t it, ssize_t *indexes)
228
{
229
230
231
232
233
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->peek)
		return -EXCIT_ENOTSUP;
	return it->func_table->peek(it, indexes);
234
235
}

236
int excit_size(const excit_t it, ssize_t *size)
237
{
238
239
240
241
242
	if (!it || !it->func_table || !size)
		return -EXCIT_EINVAL;
	if (!it->func_table->size)
		return -EXCIT_ENOTSUP;
	return it->func_table->size(it, size);
243
244
}

245
int excit_rewind(excit_t it)
246
{
247
248
249
250
251
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->rewind)
		return -EXCIT_ENOTSUP;
	return it->func_table->rewind(it);
252
253
}

254
int excit_split(const excit_t it, ssize_t n, excit_t *results)
255
{
256
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
257
		return -EXCIT_EINVAL;
258
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
259
		return -EXCIT_EDOM;
Brice Videau's avatar
Brice Videau committed
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
	if (!it->func_table->split) {
		ssize_t size;
		int err = excit_size(it, &size);

		if (err)
			return err;
		if (size < n)
			return -EXCIT_EDOM;
		if (!results)
			return EXCIT_SUCCESS;
		excit_t range = excit_alloc(EXCIT_RANGE);

		if (!range)
			return -EXCIT_ENOMEM;
		err = excit_range_init(range, 0, size - 1, 1);
		if (err)
			goto error1;
		err = excit_split(range, n, results);
		if (err)
			goto error1;
		for (int i = 0; i < n; i++) {
			excit_t tmp, tmp2;

			tmp = excit_dup(it);
			if (!tmp)
				goto error2;
			tmp2 = results[i];
287
			results[i] = excit_alloc(EXCIT_COMPOSITION);
Brice Videau's avatar
Brice Videau committed
288
289
290
291
			if (!results[i]) {
				excit_free(tmp2);
				goto error2;
			}
292
			err = excit_composition_init(results[i], tmp, tmp2);
Brice Videau's avatar
Brice Videau committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
			if (err) {
				excit_free(tmp2);
				goto error2;
			}
		}
		excit_free(range);
		return EXCIT_SUCCESS;
error2:
		for (int i = 0; i < n; i++)
			excit_free(results[i]);
error1:
		excit_free(range);
		return err;
	} else
		return it->func_table->split(it, n, results);
308
309
}

310
int excit_nth(const excit_t it, ssize_t n, ssize_t *indexes)
311
{
312
313
314
315
316
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->nth)
		return -EXCIT_ENOTSUP;
	return it->func_table->nth(it, n, indexes);
317
318
}

Brice Videau's avatar
Brice Videau committed
319
int excit_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
320
{
321
322
323
324
325
	if (!it || !it->func_table || !indexes)
		return -EXCIT_EINVAL;
	if (!it->func_table->rank)
		return -EXCIT_ENOTSUP;
	return it->func_table->rank(it, indexes, n);
326
327
}

328
int excit_pos(const excit_t it, ssize_t *n)
329
{
330
331
332
333
334
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->pos)
		return -EXCIT_ENOTSUP;
	return it->func_table->pos(it, n);
335
336
}

337
int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped)
338
{
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	int err;

	if (!it)
		return -EXCIT_EINVAL;
	*looped = 0;
	err = excit_next(it, indexes);
	switch (err) {
	case EXCIT_SUCCESS:
		break;
	case EXCIT_STOPIT:
		err = excit_rewind(it);
		if (err)
			return err;
		*looped = 1;
		err = excit_next(it, indexes);
		if (err)
			return err;
		break;
	default:
		return err;
	}
	if (excit_peek(it, NULL) == EXCIT_STOPIT) {
		err = excit_rewind(it);
		if (err)
			return err;
		*looped = 1;
	}
	return EXCIT_SUCCESS;
367
368
}

369
int excit_skip(excit_t it)
370
{
371
	return excit_next(it, NULL);
372
}
373