excit.c 36.5 KB
Newer Older
1
#include <stdlib.h>
Brice Videau's avatar
Brice Videau committed
2 3
#include <excit.h>

4 5 6 7
#define CASE(val) case val: return #val; break;

const char * excit_type_name(enum excit_type_e type)
{
8
	switch (type) {
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
		CASE(EXCIT_RANGE)
		CASE(EXCIT_CONS)
		CASE(EXCIT_REPEAT)
		CASE(EXCIT_HILBERT2D)
		CASE(EXCIT_PRODUCT)
		CASE(EXCIT_SLICE)
		CASE(EXCIT_USER)
		CASE(EXCIT_TYPE_MAX)
	default:
		return NULL;
	}
}

const char * excit_error_name(enum excit_error_e err)
{
24
	switch (err) {
25 26 27 28 29 30 31 32 33 34 35 36 37 38
		CASE(EXCIT_SUCCESS)
		CASE(EXCIT_STOPIT)
		CASE(EXCIT_ENOMEM)
		CASE(EXCIT_EINVAL)
		CASE(EXCIT_EDOM)
		CASE(EXCIT_ENOTSUP)
		CASE(EXCIT_ERROR_MAX)
	default:
		return NULL;
	}
}

#undef CASE

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
struct excit_s {
	struct excit_func_table_s *func_table;
	ssize_t dimension;
	enum excit_type_e type;
	void *data;
};

int excit_set_dimension(excit_t it, ssize_t dimension)
{
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	it->dimension = dimension;
	return EXCIT_SUCCESS;
}

int excit_get_data(excit_t it, void **data)
{
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	*data = it->data;
	return EXCIT_SUCCESS;
}

int excit_set_func_table(excit_t it, struct excit_func_table_s *func_table)
{
	if (!it)
		return -EXCIT_EINVAL;
	it->func_table = func_table;
	return EXCIT_SUCCESS;
}

int excit_get_func_table(excit_t it, struct excit_func_table_s **func_table)
{
	if (!it)
		return -EXCIT_EINVAL;
	*func_table = it->func_table;
	return EXCIT_SUCCESS;
}

82 83
/*--------------------------------------------------------------------*/

84
struct slice_it_s {
Brice Videau's avatar
Brice Videau committed
85 86
	excit_t src;
	excit_t indexer;
87 88
};

89
static int slice_it_alloc(excit_t data)
90
{
91
	struct slice_it_s *it = (struct slice_it_s *) data->data;
92

93 94
	it->src = NULL;
	it->indexer = NULL;
Brice Videau's avatar
Brice Videau committed
95
	return EXCIT_SUCCESS;
96 97
}

98
static void slice_it_free(excit_t data)
99
{
100
	struct slice_it_s *it = (struct slice_it_s *) data->data;
101

102 103
	excit_free(it->src);
	excit_free(it->indexer);
104 105
}

106
static int slice_it_copy(excit_t dst, const excit_t src)
107
{
108 109
	const struct slice_it_s *it = (const struct slice_it_s *) src->data;
	struct slice_it_s *result = (struct slice_it_s *) dst->data;
110

111
	result->src = excit_dup(it->src);
112
	if (!result->src)
Brice Videau's avatar
Brice Videau committed
113
		return -EXCIT_ENOMEM;
114
	result->indexer = excit_dup(it->indexer);
115
	if (!result->indexer) {
116
		excit_free(it->src);
Brice Videau's avatar
Brice Videau committed
117
		return -EXCIT_ENOMEM;
118
	}
Brice Videau's avatar
Brice Videau committed
119
	return EXCIT_SUCCESS;
120 121
}

122
static int slice_it_next(excit_t data, ssize_t *indexes)
123
{
124 125 126
	struct slice_it_s *it = (struct slice_it_s *) data->data;
	ssize_t n;
	int err = excit_next(it->indexer, &n);
127 128 129

	if (err)
		return err;
130
	return excit_nth(it->src, n, indexes);
131 132
}

133
static int slice_it_peek(const excit_t data, ssize_t *indexes)
134
{
135 136 137
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t n;
	int err = excit_peek(it->indexer, &n);
138 139 140

	if (err)
		return err;
141
	return excit_nth(it->src, n, indexes);
142 143
}

144
static int slice_it_size(const excit_t data, ssize_t *size)
145
{
146
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
147

148
	return excit_size(it->indexer, size);
149 150
}

151
static int slice_it_rewind(excit_t data)
152
{
153
	struct slice_it_s *it = (struct slice_it_s *) data->data;
154

155
	return excit_rewind(it->indexer);
156 157
}

158
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
159
{
160 161 162
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t p;
	int err = excit_nth(it->indexer, n, &p);
163 164 165

	if (err)
		return err;
166
	return excit_nth(it->src, p, indexes);
167 168
}

169
static int slice_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n)
170
{
171 172
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t inner_n;
173
	int err = excit_rank(it->src, indexes, &inner_n);
174 175 176

	if (err)
		return err;
177
	return excit_rank(it->indexer, &inner_n, n);
178 179
}

180
static int slice_it_pos(const excit_t data, ssize_t *n)
181
{
182
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
183

184
	return excit_pos(it->indexer, n);
185 186
}

187
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
188
{
189 190
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	int err = excit_split(it->indexer, n, results);
191 192 193 194

	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
195
		return EXCIT_SUCCESS;
196
	for (int i = 0; i < n; i++) {
Brice Videau's avatar
Brice Videau committed
197 198
		excit_t tmp;
		excit_t tmp2;
199 200

		tmp = results[i];
Brice Videau's avatar
Brice Videau committed
201
		results[i] = excit_alloc(EXCIT_SLICE);
202
		if (!results[i]) {
Brice Videau's avatar
Brice Videau committed
203
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
204
			err = -EXCIT_ENOMEM;
205 206
			goto error;
		}
207
		tmp2 = excit_dup(it->src);
208
		if (!tmp2) {
Brice Videau's avatar
Brice Videau committed
209
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
210
			err = -EXCIT_ENOMEM;
211 212
			goto error;
		}
Brice Videau's avatar
Brice Videau committed
213
		err = excit_slice_init(results[i], tmp, tmp2);
214
		if (err) {
Brice Videau's avatar
Brice Videau committed
215 216
			excit_free(tmp);
			excit_free(tmp2);
217 218 219
			goto error;
		}
	}
Brice Videau's avatar
Brice Videau committed
220
	return EXCIT_SUCCESS;
221 222
error:
	for (int i = 0; i < n; i++)
Brice Videau's avatar
Brice Videau committed
223
		excit_free(results[i]);
224 225 226
	return err;
}

227
static struct excit_func_table_s excit_slice_func_table = {
228 229 230 231 232 233 234 235 236
	slice_it_alloc,
	slice_it_free,
	slice_it_copy,
	slice_it_next,
	slice_it_peek,
	slice_it_size,
	slice_it_rewind,
	slice_it_split,
	slice_it_nth,
237
	slice_it_rank,
238
	slice_it_pos
239 240
};

241
int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
242
{
243 244
	if (!it || it->type != EXCIT_SLICE || !src || !indexer
		|| indexer->dimension != 1)
Brice Videau's avatar
Brice Videau committed
245
		return -EXCIT_EINVAL;
246 247 248
	struct slice_it_s *slice_it = (struct slice_it_s *) it->data;
	ssize_t size_src;
	ssize_t size_indexer;
Brice Videau's avatar
Brice Videau committed
249
	int err = excit_size(src, &size_src);
250 251 252

	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
253
	err = excit_size(indexer, &size_indexer);
254 255 256
	if (err)
		return err;
	if (size_indexer > size_src)
Brice Videau's avatar
Brice Videau committed
257
		return -EXCIT_EDOM;
258 259 260
	slice_it->src = src;
	slice_it->indexer = indexer;
	it->dimension = src->dimension;
Brice Videau's avatar
Brice Videau committed
261
	return EXCIT_SUCCESS;
262 263 264 265
}

/*--------------------------------------------------------------------*/

266 267 268
struct prod_it_s {
	ssize_t count;
	excit_t *its;
269 270
};

271
static int prod_it_alloc(excit_t data)
272
{
273
	struct prod_it_s *it = (struct prod_it_s *) data->data;
274

275 276
	it->count = 0;
	it->its = NULL;
Brice Videau's avatar
Brice Videau committed
277
	return EXCIT_SUCCESS;
278 279
}

280
static void prod_it_free(excit_t data)
281
{
282
	struct prod_it_s *it = (struct prod_it_s *) data->data;
283

284 285 286 287
	if (it->its) {
		for (ssize_t i = 0; i < it->count; i++)
			excit_free(it->its[i]);
		free(it->its);
288 289 290
	}
}

291
static int prod_it_copy(excit_t dst, const excit_t src)
292
{
293 294
	const struct prod_it_s *it = (const struct prod_it_s *)src->data;
	struct prod_it_s *result = (struct prod_it_s *) dst->data;
295

296 297
	result->its = (excit_t *) malloc(it->count * sizeof(excit_t));
	if (!result->its)
Brice Videau's avatar
Brice Videau committed
298
		return -EXCIT_ENOMEM;
299
	ssize_t i;
300

301 302 303
	for (i = 0; i < it->count; i++) {
		result->its[i] = excit_dup(it->its[i]);
		if (!result->its[i]) {
304 305 306 307
			i--;
			goto error;
		}
	}
308
	result->count = it->count;
Brice Videau's avatar
Brice Videau committed
309
	return EXCIT_SUCCESS;
310 311
error:
	while (i >= 0) {
312
		free(result->its[i]);
313 314
		i--;
	}
315
	free(result->its);
Brice Videau's avatar
Brice Videau committed
316
	return -EXCIT_ENOMEM;
317 318
}

319
static int prod_it_rewind(excit_t data)
320
{
321
	struct prod_it_s *it = (struct prod_it_s *) data->data;
322

323 324
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_rewind(it->its[i]);
325 326 327 328

		if (err)
			return err;
	}
Brice Videau's avatar
Brice Videau committed
329
	return EXCIT_SUCCESS;
330 331
}

332
static int prod_it_size(const excit_t data, ssize_t *size)
333
{
334 335
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
	ssize_t tmp_size = 0;
336 337

	if (!size)
Brice Videau's avatar
Brice Videau committed
338
		return -EXCIT_EINVAL;
339
	if (it->count == 0)
340 341 342
		*size = 0;
	else {
		*size = 1;
343 344
		for (ssize_t i = 0; i < it->count; i++) {
			int err = excit_size(it->its[i], &tmp_size);
345 346 347 348 349 350 351 352

			if (err) {
				*size = 0;
				return err;
			}
			*size *= tmp_size;
		}
	}
Brice Videau's avatar
Brice Videau committed
353
	return EXCIT_SUCCESS;
354 355
}

356
static int prod_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
357
{
358 359
	ssize_t size;
	int err = prod_it_size(data, &size);
360 361 362 363

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
364
		return -EXCIT_EDOM;
365
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
366 367

	if (indexes) {
368 369
		ssize_t subsize = 0;
		ssize_t offset = data->dimension;
370

371 372 373
		for (ssize_t i = it->count - 1; i >= 0; i--) {
			offset -= it->its[i]->dimension;
			err = excit_size(it->its[i], &subsize);
374 375
			if (err)
				return err;
376 377
			err = excit_nth(it->its[i], n % subsize,
					indexes + offset);
378 379 380 381 382
			if (err)
				return err;
			n /= subsize;
		}
	}
Brice Videau's avatar
Brice Videau committed
383
	return EXCIT_SUCCESS;
384 385
}

386
static int prod_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n)
387
{
388
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
389

390
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
391
		return -EXCIT_EINVAL;
392 393 394 395 396 397
	ssize_t offset = 0;
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;

	for (ssize_t i = 0; i < it->count; i++) {
398
		int err = excit_rank(it->its[i], indexes + offset, &inner_n);
399 400
		if (err)
			return err;
401
		err = excit_size(it->its[i], &subsize);
402 403 404 405
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
406
		offset += it->its[i]->dimension;
407 408 409
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
410
	return EXCIT_SUCCESS;
411 412
}

413
static int prod_it_pos(const excit_t data, ssize_t *n)
414
{
415
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
416

417
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
418
		return -EXCIT_EINVAL;
419 420 421
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;
422

423 424
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_pos(it->its[i], &inner_n);
425 426 427

		if (err)
			return err;
428
		err = excit_size(it->its[i], &subsize);
429 430 431 432 433 434 435
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
436
	return EXCIT_SUCCESS;
437 438
}

439 440
static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
					  int next)
441
{
442
	struct prod_it_s *it = (struct prod_it_s *) data->data;
443 444
	int err;
	int looped;
445 446 447
	ssize_t i;
	ssize_t *next_indexes;
	ssize_t offset = data->dimension;
448

449
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
450
		return -EXCIT_EINVAL;
451
	looped = next;
452
	for (i = it->count - 1; i > 0; i--) {
453
		if (indexes) {
454
			offset -= it->its[i]->dimension;
455 456 457 458
			next_indexes = indexes + offset;
		} else
			next_indexes = NULL;
		if (looped)
459 460
			err = excit_cyclic_next(it->its[i], next_indexes,
						&looped);
461
		else
462
			err = excit_peek(it->its[i], next_indexes);
463 464 465 466
		if (err)
			return err;
	}
	if (indexes) {
467
		offset -= it->its[i]->dimension;
468 469 470 471
		next_indexes = indexes + offset;
	} else
		next_indexes = NULL;
	if (looped)
472
		err = excit_next(it->its[0], next_indexes);
473
	else
474
		err = excit_peek(it->its[0], next_indexes);
475 476
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
477
	return EXCIT_SUCCESS;
478 479
}

480
static int prod_it_peek(const excit_t data, ssize_t *indexes)
481
{
482
	return prod_it_peeknext_helper(data, indexes, 0);
483 484
}

485
static int prod_it_next(excit_t data, ssize_t *indexes)
486
{
487
	return prod_it_peeknext_helper(data, indexes, 1);
488 489
}

490
static int prod_it_split(const excit_t data, ssize_t n, excit_t *results)
491
{
492 493
	ssize_t size;
	int err = prod_it_size(data, &size);
494 495 496 497

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
498
		return -EXCIT_EDOM;
499
	if (!results)
Brice Videau's avatar
Brice Videau committed
500
		return EXCIT_SUCCESS;
Brice Videau's avatar
Brice Videau committed
501
	excit_t range = excit_alloc(EXCIT_RANGE);
502 503

	if (!range)
Brice Videau's avatar
Brice Videau committed
504
		return -EXCIT_ENOMEM;
Brice Videau's avatar
Brice Videau committed
505
	err = excit_range_init(range, 0, size - 1, 1);
506 507
	if (err)
		goto error1;
Brice Videau's avatar
Brice Videau committed
508
	err = excit_split(range, n, results);
509 510 511
	if (err)
		goto error1;
	for (int i = 0; i < n; i++) {
Brice Videau's avatar
Brice Videau committed
512
		excit_t tmp, tmp2;
513

Brice Videau's avatar
Brice Videau committed
514
		tmp = excit_dup(data);
515 516 517
		if (!tmp)
			goto error2;
		tmp2 = results[i];
Brice Videau's avatar
Brice Videau committed
518
		results[i] = excit_alloc(EXCIT_SLICE);
519
		if (!results[i]) {
Brice Videau's avatar
Brice Videau committed
520
			excit_free(tmp2);
521 522
			goto error2;
		}
Brice Videau's avatar
Brice Videau committed
523
		err = excit_slice_init(results[i], tmp, tmp2);
524
		if (err) {
Brice Videau's avatar
Brice Videau committed
525
			excit_free(tmp2);
526 527 528
			goto error2;
		}
	}
Brice Videau's avatar
Brice Videau committed
529
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
530
	return EXCIT_SUCCESS;
531 532
error2:
	for (int i = 0; i < n; i++)
Brice Videau's avatar
Brice Videau committed
533
		excit_free(results[i]);
534
error1:
Brice Videau's avatar
Brice Videau committed
535
	excit_free(range);
536 537 538
	return err;
}

539
int excit_product_count(const excit_t it, ssize_t *count)
540
{
541
	if (!it || it->type != EXCIT_PRODUCT || !count)
Brice Videau's avatar
Brice Videau committed
542
		return -EXCIT_EINVAL;
543
	*count = ((struct prod_it_s *) it->data)->count;
Brice Videau's avatar
Brice Videau committed
544
	return EXCIT_SUCCESS;
545 546
}

547 548
int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n,
			    excit_t *results)
549
{
550
	if (!it || it->type != EXCIT_PRODUCT)
Brice Videau's avatar
Brice Videau committed
551
		return -EXCIT_EINVAL;
552
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
553
		return -EXCIT_EDOM;
554 555
	ssize_t count;
	int err = excit_product_count(it, &count);
556 557 558 559

	if (err)
		return err;
	if (dim >= count)
Brice Videau's avatar
Brice Videau committed
560
		return -EXCIT_EDOM;
561
	struct prod_it_s *prod_it = (struct prod_it_s *) it->data;
562

563
	err = excit_split(prod_it->its[dim], n, results);
564 565 566
	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
567
		return EXCIT_SUCCESS;
568
	for (int i = 0; i < n; i++) {
Brice Videau's avatar
Brice Videau committed
569
		excit_t tmp = results[i];
570

571
		results[i] = excit_dup(it);
572
		if (!tmp) {
Brice Videau's avatar
Brice Videau committed
573
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
574
			err = -EXCIT_ENOMEM;
575 576
			goto error;
		}
577 578 579 580
		struct prod_it_s *new_prod_it =
		    (struct prod_it_s *) results[i]->data;
		excit_free(new_prod_it->its[dim]);
		new_prod_it->its[dim] = tmp;
581
	}
Brice Videau's avatar
Brice Videau committed
582
	return EXCIT_SUCCESS;
583 584
error:
	for (int i = 0; i < n; i++)
Brice Videau's avatar
Brice Videau committed
585
		excit_free(results[i]);
586 587 588
	return err;
}

589
int excit_product_add_copy(excit_t it, excit_t added_it)
590 591
{
	int err = 0;
592
	excit_t copy = excit_dup(added_it);
593 594

	if (!copy)
Brice Videau's avatar
Brice Videau committed
595
		return -EXCIT_EINVAL;
596
	err = excit_product_add(it, copy);
597
	if (err) {
598
		excit_free(added_it);
599 600
		return err;
	}
Brice Videau's avatar
Brice Videau committed
601
	return EXCIT_SUCCESS;
602 603
}

604
int excit_product_add(excit_t it, excit_t added_it)
605
{
606 607
	if (!it || it->type != EXCIT_PRODUCT || !it->data
	    || !added_it)
Brice Videau's avatar
Brice Videau committed
608
		return -EXCIT_EINVAL;
609

610 611
	struct prod_it_s *prod_it = (struct prod_it_s *) it->data;
	ssize_t mew_count = prod_it->count + 1;
612

Brice Videau's avatar
Brice Videau committed
613
	excit_t *new_its =
614
	    (excit_t *) realloc(prod_it->its, mew_count * sizeof(excit_t));
615
	if (!new_its)
Brice Videau's avatar
Brice Videau committed
616
		return -EXCIT_ENOMEM;
617 618 619 620
	prod_it->its = new_its;
	prod_it->its[prod_it->count] = added_it;
	prod_it->count = mew_count;
	it->dimension += added_it->dimension;
Brice Videau's avatar
Brice Videau committed
621
	return EXCIT_SUCCESS;
622 623
}

624
static struct excit_func_table_s excit_prod_func_table = {
625 626 627 628 629 630 631 632 633
	prod_it_alloc,
	prod_it_free,
	prod_it_copy,
	prod_it_next,
	prod_it_peek,
	prod_it_size,
	prod_it_rewind,
	prod_it_split,
	prod_it_nth,
634
	prod_it_rank,
635
	prod_it_pos
636 637 638 639 640
};

/*--------------------------------------------------------------------*/

struct circular_fifo_s {
641 642 643 644 645
	ssize_t length;
	ssize_t start;
	ssize_t end;
	ssize_t size;
	ssize_t *buffer;
646 647
};

648
static void circular_fifo_add(struct circular_fifo_s *fifo, ssize_t elem)
649 650 651 652 653 654 655 656 657 658 659
{
	if (fifo->size == fifo->length) {
		fifo->start = (fifo->start + 1) % fifo->length;
		fifo->end = (fifo->end + 1) % fifo->length;
	} else {
		fifo->end = (fifo->end + 1) % fifo->length;
		fifo->size++;
	}
	fifo->buffer[fifo->end] = elem;
}

660 661
static void circular_fifo_dump(const struct circular_fifo_s *fifo, 
			       ssize_t *vals)
662
{
663 664
	ssize_t i;
	ssize_t j;
665 666 667 668 669 670 671

	for (i = 0, j = fifo->start; i < fifo->size; i++) {
		vals[i] = fifo->buffer[j];
		j = (j + 1) % fifo->length;
	}
}

672 673 674
struct cons_it_s {
	excit_t it;
	ssize_t n;
675 676 677
	struct circular_fifo_s fifo;
};

678
static int cons_it_alloc(excit_t data)
679
{
680 681 682 683 684 685 686 687 688
	struct cons_it_s *it = (struct cons_it_s *) data->data;

	it->it = NULL;
	it->n = 0;
	it->fifo.length = 0;
	it->fifo.start = 0;
	it->fifo.end = -1;
	it->fifo.size = 0;
	it->fifo.buffer = NULL;
Brice Videau's avatar
Brice Videau committed
689
	return EXCIT_SUCCESS;
690 691
}

692
static void cons_it_free(excit_t data)
693
{
694
	struct cons_it_s *it = (struct cons_it_s *) data->data;
695

696 697
	excit_free(it->it);
	free(it->fifo.buffer);
698 699
}

700
static int cons_it_copy(excit_t ddst, const excit_t dsrc)
701
{
702 703 704
	struct cons_it_s *dst = (struct cons_it_s *) ddst->data;
	const struct cons_it_s *src = (const struct cons_it_s *)dsrc->data;
	excit_t copy = excit_dup(src->it);
705 706

	if (!copy)
Brice Videau's avatar
Brice Videau committed
707
		return -EXCIT_EINVAL;
708
	dst->it = copy;
709 710 711 712 713 714
	dst->n = src->n;
	dst->fifo.length = src->fifo.length;
	dst->fifo.start = src->fifo.start;
	dst->fifo.end = src->fifo.end;
	dst->fifo.size = src->fifo.size;
	dst->fifo.buffer =
715
	    (ssize_t *) malloc(src->fifo.length * sizeof(ssize_t));
716
	if (!dst->fifo.buffer) {
Brice Videau's avatar
Brice Videau committed
717
		excit_free(copy);
Brice Videau's avatar
Brice Videau committed
718
		return -EXCIT_ENOMEM;
719 720 721
	}
	for (int i = 0; i < dst->fifo.length; i++)
		dst->fifo.buffer[i] = src->fifo.buffer[i];
Brice Videau's avatar
Brice Videau committed
722
	return EXCIT_SUCCESS;
723 724
}

725
static int cons_it_size(const excit_t data, ssize_t *size)
726
{
727 728 729
	const struct cons_it_s *it = (const struct cons_it_s *)data->data;
	ssize_t tmp_size = 0;
	int err = excit_size(it->it, &tmp_size);
730 731 732

	if (err)
		return err;
733
	*size = tmp_size - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
734
	return EXCIT_SUCCESS;
735 736
}

737
static int cons_it_split(const excit_t data, ssize_t n, excit_t *results)
738
{
739 740
	ssize_t size;
	int err = cons_it_size(data, &size);
741 742 743 744

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
745
		return -EXCIT_EDOM;
746
	if (!results)
Brice Videau's avatar
Brice Videau committed
747
		return EXCIT_SUCCESS;
Brice Videau's avatar
Brice Videau committed
748
	excit_t range = excit_alloc(EXCIT_RANGE);
749 750

	if (!range)
Brice Videau's avatar
Brice Videau committed
751
		return -EXCIT_ENOMEM;
Brice Videau's avatar
Brice Videau committed
752
	err = excit_range_init(range, 0, size - 1, 1);
753 754
	if (err)
		goto error1;
Brice Videau's avatar
Brice Videau committed
755
	err = excit_split(range, n, results);
756 757 758 759 760
	if (err)
		goto error1;
	int i;

	for (i = 0; i < n; i++) {
Brice Videau's avatar
Brice Videau committed
761
		excit_t tmp, tmp2;
762

Brice Videau's avatar
Brice Videau committed
763
		tmp = excit_dup(data);
764 765 766
		if (!tmp)
			goto error2;
		tmp2 = results[i];
Brice Videau's avatar
Brice Videau committed
767
		results[i] = excit_alloc(EXCIT_SLICE);
768
		if (!results[i]) {
Brice Videau's avatar
Brice Videau committed
769
			excit_free(tmp2);
770 771
			goto error2;
		}
Brice Videau's avatar
Brice Videau committed
772
		err = excit_slice_init(results[i], tmp, tmp2);
773
		if (err) {
Brice Videau's avatar
Brice Videau committed
774
			excit_free(tmp2);
775 776 777
			goto error2;
		}
	}
Brice Videau's avatar
Brice Videau committed
778
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
779
	return EXCIT_SUCCESS;
780 781
error2:
	for (; i >= 0; i--)
Brice Videau's avatar
Brice Videau committed
782
		excit_free(results[i]);
783
error1:
Brice Videau's avatar
Brice Videau committed
784
	excit_free(range);
785 786 787
	return err;
}

788
static int cons_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
789
{
790 791
	ssize_t size;
	int err = cons_it_size(data, &size);
792 793 794 795

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
796
		return -EXCIT_EDOM;
797 798
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	int dim = it->it->dimension;
799 800

	if (indexes) {
801 802
		for (int i = 0; i < it->n; i++) {
			err = excit_nth(it->it, n + i, indexes + dim * i);
803 804 805 806
			if (err)
				return err;
		}
	}
Brice Videau's avatar
Brice Videau committed
807
	return EXCIT_SUCCESS;
808 809
}

810
static int cons_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n)
811
{
812 813
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	ssize_t inner_n, inner_n_tmp;
814
	int err = excit_rank(it->it, indexes, &inner_n);
815 816 817

	if (err)
		return err;
818
	int dim = it->it->dimension;
819

820
	for (int i = 1; i < it->n; i++) {
821
		err = excit_rank(it->it, indexes + dim * i, &inner_n_tmp);
822 823 824
		if (err)
			return err;
		if (inner_n_tmp != inner_n + 1)
Brice Videau's avatar
Brice Videau committed
825
			return -EXCIT_EINVAL;
826 827 828
		inner_n = inner_n_tmp;
	}
	if (n)
829
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
830
	return EXCIT_SUCCESS;
831 832
}

833
static int cons_it_pos(const excit_t data, ssize_t *n)
834
{
835 836 837
	ssize_t inner_n;
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	int err = excit_pos(it->it, &inner_n);
838 839 840 841

	if (err)
		return err;
	if (n)
842
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
843
	return EXCIT_SUCCESS;
844 845
}

846
static int cons_it_peek(const excit_t data, ssize_t *indexes)
847
{
848
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
849
	int err;
850 851
	int dim = it->it->dimension;
	int n = it->n;
852 853

	if (indexes) {
854 855
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_peek(it->it, indexes + dim * (n - 1));
856
	} else
857
		err = excit_peek(it->it, NULL);
858 859
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
860
	return EXCIT_SUCCESS;
861 862
}

863
static int cons_it_next(excit_t data, ssize_t *indexes)
864
{
865
	struct cons_it_s *it = (struct cons_it_s *) data->data;
866
	int err;
867 868
	int dim = it->it->dimension;
	int n = it->n;
869 870

	if (indexes) {
871 872
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_next(it->it, indexes + dim * (n - 1));
873
	} else
874
		err = excit_next(it->it, NULL);
875 876 877 878
	if (err)
		return err;
	if (indexes)
		for (int i = dim * (n - 1); i < dim * n; i++)
879
			circular_fifo_add(&it->fifo, indexes[i]);
Brice Videau's avatar
Brice Videau committed
880
	return EXCIT_SUCCESS;
881 882
}

883
static int cons_it_rewind(excit_t data)
884
{
885 886
	struct cons_it_s *it = (struct cons_it_s *) data->data;
	int err = excit_rewind(it->it);
887 888 889

	if (err)
		return err;
890 891 892
	it->fifo.start = 0;
	it->fifo.end = -1;
	it->fifo.size = 0;
893

894
	for (int i = 0; i < it->n - 1; i++) {
895 896 897
		int err;

		err =
898
		    excit_next(it->it, it->fifo.buffer + it->it->dimension * i);
899 900
		if (err)
			return err;