excit.c 36 KB
Newer Older
1
#include <stdlib.h>
2 3
#include <excit.h>

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#define CASE(val) case val: return #val; break;

const char * excit_type_name(enum excit_type_e type)
{
	switch(type) {
		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)
{
	switch(err) {
		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
struct slice_it_s {
42 43
	excit_t src;
	excit_t indexer;
44 45
};

46
static int slice_it_alloc(excit_t data)
47
{
48
	data->data = malloc(sizeof(struct slice_it_s));
49
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
50
		return -EXCIT_ENOMEM;
51
	struct slice_it_s *it = (struct slice_it_s *) data->data;
52

53 54
	it->src = NULL;
	it->indexer = NULL;
Brice Videau's avatar
Brice Videau committed
55
	return EXCIT_SUCCESS;
56 57
}

58
static void slice_it_free(excit_t data)
59
{
60
	struct slice_it_s *it = (struct slice_it_s *) data->data;
61

62 63
	excit_free(it->src);
	excit_free(it->indexer);
64 65 66
	free(data->data);
}

67
static int slice_it_copy(excit_t dst, const excit_t src)
68
{
69 70
	const struct slice_it_s *it = (const struct slice_it_s *) src->data;
	struct slice_it_s *result = (struct slice_it_s *) dst->data;
71

72
	result->src = excit_dup(it->src);
73
	if (!result->src)
Brice Videau's avatar
Brice Videau committed
74
		return -EXCIT_ENOMEM;
75
	result->indexer = excit_dup(it->indexer);
76
	if (!result->indexer) {
77
		excit_free(it->src);
Brice Videau's avatar
Brice Videau committed
78
		return -EXCIT_ENOMEM;
79
	}
Brice Videau's avatar
Brice Videau committed
80
	return EXCIT_SUCCESS;
81 82
}

83
static int slice_it_next(excit_t data, ssize_t *indexes)
84
{
85 86 87
	struct slice_it_s *it = (struct slice_it_s *) data->data;
	ssize_t n;
	int err = excit_next(it->indexer, &n);
88 89 90

	if (err)
		return err;
91
	return excit_nth(it->src, n, indexes);
92 93
}

94
static int slice_it_peek(const excit_t data, ssize_t *indexes)
95
{
96 97 98
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t n;
	int err = excit_peek(it->indexer, &n);
99 100 101

	if (err)
		return err;
102
	return excit_nth(it->src, n, indexes);
103 104
}

105
static int slice_it_size(const excit_t data, ssize_t *size)
106
{
107
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
108

109
	return excit_size(it->indexer, size);
110 111
}

112
static int slice_it_rewind(excit_t data)
113
{
114
	struct slice_it_s *it = (struct slice_it_s *) data->data;
115

116
	return excit_rewind(it->indexer);
117 118
}

119
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
120
{
121 122 123
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t p;
	int err = excit_nth(it->indexer, n, &p);
124 125 126

	if (err)
		return err;
127
	return excit_nth(it->src, p, indexes);
128 129
}

130
static int slice_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
131
{
132 133 134
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t inner_n;
	int err = excit_n(it->src, indexes, &inner_n);
135 136 137

	if (err)
		return err;
138
	return excit_n(it->indexer, &inner_n, n);
139 140
}

141
static int slice_it_pos(const excit_t data, ssize_t *n)
142
{
143
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
144

145
	return excit_pos(it->indexer, n);
146 147
}

148
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
149
{
150 151
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	int err = excit_split(it->indexer, n, results);
152 153 154 155

	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
156
		return EXCIT_SUCCESS;
157
	for (int i = 0; i < n; i++) {
158 159
		excit_t tmp;
		excit_t tmp2;
160 161

		tmp = results[i];
162
		results[i] = excit_alloc(EXCIT_SLICE);
163
		if (!results[i]) {
164
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
165
			err = -EXCIT_ENOMEM;
166 167
			goto error;
		}
168
		tmp2 = excit_dup(it->src);
169
		if (!tmp2) {
170
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
171
			err = -EXCIT_ENOMEM;
172 173
			goto error;
		}
174
		err = excit_slice_init(results[i], tmp, tmp2);
175
		if (err) {
176 177
			excit_free(tmp);
			excit_free(tmp2);
178 179 180
			goto error;
		}
	}
Brice Videau's avatar
Brice Videau committed
181
	return EXCIT_SUCCESS;
182 183
error:
	for (int i = 0; i < n; i++)
184
		excit_free(results[i]);
185 186 187
	return err;
}

188
static const struct excit_func_table_s excit_slice_func_table = {
189 190 191 192 193 194 195 196 197 198 199
	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,
	slice_it_n,
	slice_it_pos
200 201
};

202
int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
203
{
204 205
	if (!it || it->type != EXCIT_SLICE || !src || !indexer
		|| indexer->dimension != 1)
Brice Videau's avatar
Brice Videau committed
206
		return -EXCIT_EINVAL;
207 208 209
	struct slice_it_s *slice_it = (struct slice_it_s *) it->data;
	ssize_t size_src;
	ssize_t size_indexer;
210
	int err = excit_size(src, &size_src);
211 212 213

	if (err)
		return err;
214
	err = excit_size(indexer, &size_indexer);
215 216 217
	if (err)
		return err;
	if (size_indexer > size_src)
Brice Videau's avatar
Brice Videau committed
218
		return -EXCIT_EDOM;
219 220 221
	slice_it->src = src;
	slice_it->indexer = indexer;
	it->dimension = src->dimension;
Brice Videau's avatar
Brice Videau committed
222
	return EXCIT_SUCCESS;
223 224 225 226
}

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

227 228 229
struct prod_it_s {
	ssize_t count;
	excit_t *its;
230 231
};

232
static int prod_it_alloc(excit_t data)
233
{
234
	data->data = malloc(sizeof(struct prod_it_s));
235
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
236
		return -EXCIT_ENOMEM;
237
	struct prod_it_s *it = (struct prod_it_s *) data->data;
238

239 240
	it->count = 0;
	it->its = NULL;
Brice Videau's avatar
Brice Videau committed
241
	return EXCIT_SUCCESS;
242 243
}

244
static void prod_it_free(excit_t data)
245
{
246 247 248 249 250
	struct prod_it_s *it = (struct prod_it_s *) data->data;
	if (it->its) {
		for (ssize_t i = 0; i < it->count; i++)
			excit_free(it->its[i]);
		free(it->its);
251 252 253 254
	}
	free(data->data);
}

255
static int prod_it_copy(excit_t dst, const excit_t src)
256
{
257 258
	const struct prod_it_s *it = (const struct prod_it_s *)src->data;
	struct prod_it_s *result = (struct prod_it_s *) dst->data;
259

260 261
	result->its = (excit_t *) malloc(it->count * sizeof(excit_t));
	if (!result->its)
Brice Videau's avatar
Brice Videau committed
262
		return -EXCIT_ENOMEM;
263
	ssize_t i;
264

265 266 267
	for (i = 0; i < it->count; i++) {
		result->its[i] = excit_dup(it->its[i]);
		if (!result->its[i]) {
268 269 270 271
			i--;
			goto error;
		}
	}
272
	result->count = it->count;
Brice Videau's avatar
Brice Videau committed
273
	return EXCIT_SUCCESS;
274 275
error:
	while (i >= 0) {
276
		free(result->its[i]);
277 278
		i--;
	}
279
	free(result->its);
Brice Videau's avatar
Brice Videau committed
280
	return -EXCIT_ENOMEM;
281 282
}

283
static int prod_it_rewind(excit_t data)
284
{
285
	struct prod_it_s *it = (struct prod_it_s *) data->data;
286

287 288
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_rewind(it->its[i]);
289 290 291 292

		if (err)
			return err;
	}
Brice Videau's avatar
Brice Videau committed
293
	return EXCIT_SUCCESS;
294 295
}

296
static int prod_it_size(const excit_t data, ssize_t *size)
297
{
298 299
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
	ssize_t tmp_size = 0;
300 301

	if (!size)
Brice Videau's avatar
Brice Videau committed
302
		return -EXCIT_EINVAL;
303
	if (it->count == 0)
304 305 306
		*size = 0;
	else {
		*size = 1;
307 308
		for (ssize_t i = 0; i < it->count; i++) {
			int err = excit_size(it->its[i], &tmp_size);
309 310 311 312 313 314 315 316

			if (err) {
				*size = 0;
				return err;
			}
			*size *= tmp_size;
		}
	}
Brice Videau's avatar
Brice Videau committed
317
	return EXCIT_SUCCESS;
318 319
}

320
static int prod_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
321
{
322 323
	ssize_t size;
	int err = prod_it_size(data, &size);
324 325 326 327

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
328
		return -EXCIT_EDOM;
329
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
330 331

	if (indexes) {
332 333
		ssize_t subsize = 0;
		ssize_t offset = data->dimension;
334

335 336 337
		for (ssize_t i = it->count - 1; i >= 0; i--) {
			offset -= it->its[i]->dimension;
			err = excit_size(it->its[i], &subsize);
338 339
			if (err)
				return err;
340 341
			err = excit_nth(it->its[i], n % subsize,
					indexes + offset);
342 343 344 345 346
			if (err)
				return err;
			n /= subsize;
		}
	}
Brice Videau's avatar
Brice Videau committed
347
	return EXCIT_SUCCESS;
348 349
}

350
static int prod_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
351
{
352
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
353

354
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
355
		return -EXCIT_EINVAL;
356 357 358 359 360 361 362
	ssize_t offset = 0;
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;

	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_n(it->its[i], indexes + offset, &inner_n);
363 364
		if (err)
			return err;
365
		err = excit_size(it->its[i], &subsize);
366 367 368 369
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
370
		offset += it->its[i]->dimension;
371 372 373
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
374
	return EXCIT_SUCCESS;
375 376
}

377
static int prod_it_pos(const excit_t data, ssize_t *n)
378
{
379
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
380

381
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
382
		return -EXCIT_EINVAL;
383 384 385
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;
386

387 388
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_pos(it->its[i], &inner_n);
389 390 391

		if (err)
			return err;
392
		err = excit_size(it->its[i], &subsize);
393 394 395 396 397 398 399
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
400
	return EXCIT_SUCCESS;
401 402
}

403 404
static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
					  int next)
405
{
406
	struct prod_it_s *it = (struct prod_it_s *) data->data;
407 408
	int err;
	int looped;
409 410 411
	ssize_t i;
	ssize_t *next_indexes;
	ssize_t offset = data->dimension;
412

413
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
414
		return -EXCIT_EINVAL;
415
	looped = next;
416
	for (i = it->count - 1; i > 0; i--) {
417
		if (indexes) {
418
			offset -= it->its[i]->dimension;
419 420 421 422
			next_indexes = indexes + offset;
		} else
			next_indexes = NULL;
		if (looped)
423 424
			err = excit_cyclic_next(it->its[i], next_indexes,
						&looped);
425
		else
426
			err = excit_peek(it->its[i], next_indexes);
427 428 429 430
		if (err)
			return err;
	}
	if (indexes) {
431
		offset -= it->its[i]->dimension;
432 433 434 435
		next_indexes = indexes + offset;
	} else
		next_indexes = NULL;
	if (looped)
436
		err = excit_next(it->its[0], next_indexes);
437
	else
438
		err = excit_peek(it->its[0], next_indexes);
439 440
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
441
	return EXCIT_SUCCESS;
442 443
}

444
static int prod_it_peek(const excit_t data, ssize_t *indexes)
445
{
446
	return prod_it_peeknext_helper(data, indexes, 0);
447 448
}

449
static int prod_it_next(excit_t data, ssize_t *indexes)
450
{
451
	return prod_it_peeknext_helper(data, indexes, 1);
452 453
}

454
static int prod_it_split(const excit_t data, ssize_t n, excit_t *results)
455
{
456 457
	ssize_t size;
	int err = prod_it_size(data, &size);
458 459 460 461

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
462
		return -EXCIT_EDOM;
463
	if (!results)
Brice Videau's avatar
Brice Videau committed
464
		return EXCIT_SUCCESS;
465
	excit_t range = excit_alloc(EXCIT_RANGE);
466 467

	if (!range)
Brice Videau's avatar
Brice Videau committed
468
		return -EXCIT_ENOMEM;
469
	err = excit_range_init(range, 0, size - 1, 1);
470 471
	if (err)
		goto error1;
472
	err = excit_split(range, n, results);
473 474 475
	if (err)
		goto error1;
	for (int i = 0; i < n; i++) {
476
		excit_t tmp, tmp2;
477

478
		tmp = excit_dup(data);
479 480 481
		if (!tmp)
			goto error2;
		tmp2 = results[i];
482
		results[i] = excit_alloc(EXCIT_SLICE);
483
		if (!results[i]) {
484
			excit_free(tmp2);
485 486
			goto error2;
		}
487
		err = excit_slice_init(results[i], tmp, tmp2);
488
		if (err) {
489
			excit_free(tmp2);
490 491 492
			goto error2;
		}
	}
493
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
494
	return EXCIT_SUCCESS;
495 496
error2:
	for (int i = 0; i < n; i++)
497
		excit_free(results[i]);
498
error1:
499
	excit_free(range);
500 501 502
	return err;
}

503
int excit_product_count(const excit_t it, ssize_t *count)
504
{
505
	if (!it || it->type != EXCIT_PRODUCT || !count)
Brice Videau's avatar
Brice Videau committed
506
		return -EXCIT_EINVAL;
507
	*count = ((struct prod_it_s *) it->data)->count;
Brice Videau's avatar
Brice Videau committed
508
	return EXCIT_SUCCESS;
509 510
}

511 512
int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n,
			    excit_t *results)
513
{
514
	if (!it || it->type != EXCIT_PRODUCT)
Brice Videau's avatar
Brice Videau committed
515
		return -EXCIT_EINVAL;
516
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
517
		return -EXCIT_EDOM;
518 519
	ssize_t count;
	int err = excit_product_count(it, &count);
520 521 522 523

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

527
	err = excit_split(prod_it->its[dim], n, results);
528 529 530
	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
531
		return EXCIT_SUCCESS;
532
	for (int i = 0; i < n; i++) {
533
		excit_t tmp = results[i];
534

535
		results[i] = excit_dup(it);
536
		if (!tmp) {
537
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
538
			err = -EXCIT_ENOMEM;
539 540
			goto error;
		}
541 542 543 544
		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;
545
	}
Brice Videau's avatar
Brice Videau committed
546
	return EXCIT_SUCCESS;
547 548
error:
	for (int i = 0; i < n; i++)
549
		excit_free(results[i]);
550 551 552
	return err;
}

553
int excit_product_add_copy(excit_t it, excit_t added_it)
554 555
{
	int err = 0;
556
	excit_t copy = excit_dup(added_it);
557 558

	if (!copy)
Brice Videau's avatar
Brice Videau committed
559
		return -EXCIT_EINVAL;
560
	err = excit_product_add(it, copy);
561
	if (err) {
562
		excit_free(added_it);
563 564
		return err;
	}
Brice Videau's avatar
Brice Videau committed
565
	return EXCIT_SUCCESS;
566 567
}

568
int excit_product_add(excit_t it, excit_t added_it)
569
{
570 571
	if (!it || it->type != EXCIT_PRODUCT || !it->data
	    || !added_it)
Brice Videau's avatar
Brice Videau committed
572
		return -EXCIT_EINVAL;
573

574 575
	struct prod_it_s *prod_it = (struct prod_it_s *) it->data;
	ssize_t mew_count = prod_it->count + 1;
576

577
	excit_t *new_its =
578
	    (excit_t *) realloc(prod_it->its, mew_count * sizeof(excit_t));
579
	if (!new_its)
Brice Videau's avatar
Brice Videau committed
580
		return -EXCIT_ENOMEM;
581 582 583 584
	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
585
	return EXCIT_SUCCESS;
586 587
}

588
static const struct excit_func_table_s excit_product_func_table = {
589 590 591 592 593 594 595 596 597 598 599
	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,
	prod_it_n,
	prod_it_pos
600 601 602 603 604
};

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

struct circular_fifo_s {
605 606 607 608 609
	ssize_t length;
	ssize_t start;
	ssize_t end;
	ssize_t size;
	ssize_t *buffer;
610 611
};

612
static void circular_fifo_add(struct circular_fifo_s *fifo, ssize_t elem)
613 614 615 616 617 618 619 620 621 622 623
{
	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;
}

624 625
static void circular_fifo_dump(const struct circular_fifo_s *fifo, 
			       ssize_t *vals)
626
{
627 628
	ssize_t i;
	ssize_t j;
629 630 631 632 633 634 635

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

636 637 638
struct cons_it_s {
	excit_t it;
	ssize_t n;
639 640 641
	struct circular_fifo_s fifo;
};

642
static int cons_it_alloc(excit_t data)
643
{
644
	data->data = malloc(sizeof(struct cons_it_s));
645
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
646
		return -EXCIT_ENOMEM;
647 648 649 650 651 652 653 654 655
	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
656
	return EXCIT_SUCCESS;
657 658
}

659
static void cons_it_free(excit_t data)
660
{
661
	struct cons_it_s *it = (struct cons_it_s *) data->data;
662

663 664
	excit_free(it->it);
	free(it->fifo.buffer);
665 666 667
	free(data->data);
}

668
static int cons_it_copy(excit_t ddst, const excit_t dsrc)
669
{
670 671 672
	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);
673 674

	if (!copy)
Brice Videau's avatar
Brice Videau committed
675
		return -EXCIT_EINVAL;
676
	dst->it = copy;
677 678 679 680 681 682
	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 =
683
	    (ssize_t *) malloc(src->fifo.length * sizeof(ssize_t));
684
	if (!dst->fifo.buffer) {
685
		excit_free(copy);
Brice Videau's avatar
Brice Videau committed
686
		return -EXCIT_ENOMEM;
687 688 689
	}
	for (int i = 0; i < dst->fifo.length; i++)
		dst->fifo.buffer[i] = src->fifo.buffer[i];
Brice Videau's avatar
Brice Videau committed
690
	return EXCIT_SUCCESS;
691 692
}

693
static int cons_it_size(const excit_t data, ssize_t *size)
694
{
695 696 697
	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);
698 699 700

	if (err)
		return err;
701
	*size = tmp_size - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
702
	return EXCIT_SUCCESS;
703 704
}

705
static int cons_it_split(const excit_t data, ssize_t n, excit_t *results)
706
{
707 708
	ssize_t size;
	int err = cons_it_size(data, &size);
709 710 711 712

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
713
		return -EXCIT_EDOM;
714
	if (!results)
Brice Videau's avatar
Brice Videau committed
715
		return EXCIT_SUCCESS;
716
	excit_t range = excit_alloc(EXCIT_RANGE);
717 718

	if (!range)
Brice Videau's avatar
Brice Videau committed
719
		return -EXCIT_ENOMEM;
720
	err = excit_range_init(range, 0, size - 1, 1);
721 722
	if (err)
		goto error1;
723
	err = excit_split(range, n, results);
724 725 726 727 728
	if (err)
		goto error1;
	int i;

	for (i = 0; i < n; i++) {
729
		excit_t tmp, tmp2;
730

731
		tmp = excit_dup(data);
732 733 734
		if (!tmp)
			goto error2;
		tmp2 = results[i];
735
		results[i] = excit_alloc(EXCIT_SLICE);
736
		if (!results[i]) {
737
			excit_free(tmp2);
738 739
			goto error2;
		}
740
		err = excit_slice_init(results[i], tmp, tmp2);
741
		if (err) {
742
			excit_free(tmp2);
743 744 745
			goto error2;
		}
	}
746
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
747
	return EXCIT_SUCCESS;
748 749
error2:
	for (; i >= 0; i--)
750
		excit_free(results[i]);
751
error1:
752
	excit_free(range);
753 754 755
	return err;
}

756
static int cons_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
757
{
758 759
	ssize_t size;
	int err = cons_it_size(data, &size);
760 761 762 763

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
764
		return -EXCIT_EDOM;
765 766
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	int dim = it->it->dimension;
767 768

	if (indexes) {
769 770
		for (int i = 0; i < it->n; i++) {
			err = excit_nth(it->it, n + i, indexes + dim * i);
771 772 773 774
			if (err)
				return err;
		}
	}
Brice Videau's avatar
Brice Videau committed
775
	return EXCIT_SUCCESS;
776 777
}

778
static int cons_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
779
{
780 781 782
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	ssize_t inner_n, inner_n_tmp;
	int err = excit_n(it->it, indexes, &inner_n);
783 784 785

	if (err)
		return err;
786
	int dim = it->it->dimension;
787

788 789
	for (int i = 1; i < it->n; i++) {
		err = excit_n(it->it, indexes + dim * i, &inner_n_tmp);
790 791 792
		if (err)
			return err;
		if (inner_n_tmp != inner_n + 1)
Brice Videau's avatar
Brice Videau committed
793
			return -EXCIT_EINVAL;
794 795 796
		inner_n = inner_n_tmp;
	}
	if (n)
797
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
798
	return EXCIT_SUCCESS;
799 800
}

801
static int cons_it_pos(const excit_t data, ssize_t *n)
802
{
803 804 805
	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);
806 807 808 809

	if (err)
		return err;
	if (n)
810
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
811
	return EXCIT_SUCCESS;
812 813
}

814
static int cons_it_peek(const excit_t data, ssize_t *indexes)
815
{
816
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
817
	int err;
818 819
	int dim = it->it->dimension;
	int n = it->n;
820 821

	if (indexes) {
822 823
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_peek(it->it, indexes + dim * (n - 1));
824
	} else
825
		err = excit_peek(it->it, NULL);
826 827
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
828
	return EXCIT_SUCCESS;
829 830
}

831
static int cons_it_next(excit_t data, ssize_t *indexes)
832
{
833
	struct cons_it_s *it = (struct cons_it_s *) data->data;
834
	int err;
835 836
	int dim = it->it->dimension;
	int n = it->n;
837 838

	if (indexes) {
839 840
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_next(it->it, indexes + dim * (n - 1));
841
	} else
842
		err = excit_next(it->it, NULL);
843 844 845 846
	if (err)
		return err;
	if (indexes)
		for (int i = dim * (n - 1); i < dim * n; i++)
847
			circular_fifo_add(&it->fifo, indexes[i]);
Brice Videau's avatar
Brice Videau committed
848
	return EXCIT_SUCCESS;
849 850
}

851
static int cons_it_rewind(excit_t data)
852
{
853 854
	struct cons_it_s *it = (struct cons_it_s *) data->data;
	int err = excit_rewind(it->it);
855 856 857

	if (err)
		return err;
858 859 860
	it->fifo.start = 0;
	it->fifo.end = -1;
	it->fifo.size = 0;
861

862
	for (int i = 0; i < it->n - 1; i++) {
863 864 865
		int err;

		err =
866
		    excit_next(it->it, it->fifo.buffer + it->it->dimension * i);
867 868
		if (err)
			return err;
869 870
		it->fifo.size += it->it->dimension;
		it->fifo.end += it->it->dimension;
871
	}
Brice Videau's avatar
Brice Videau committed
872
	return EXCIT_SUCCESS;
873 874
}

875
int excit_cons_init(excit_t it, excit_t src, ssize_t n)
876
{
877
	ssize_t src_size;
878 879
	int err;

880
	if (!it || it->type != EXCIT_CONS || !src || n <= 0)
Brice Videau's avatar
Brice Videau committed
881
		return -EXCIT_EINVAL;
882
	err = excit_size(src, &src_size);
883 884 885
	if (err)
		return err;
	if (src_size < n)
Brice Videau's avatar
Brice Videau committed
886
		return -EXCIT_EINVAL;
887 888 889 890 891 892 893 894 895 896 897
	struct cons_it_s *cons_it = (struct cons_it_s *) it->data;

	free(cons_it->fifo.buffer);
	excit_free(cons_it->it);
	it->dimension = n * src->dimension;
	cons_it->it = src;
	cons_it->n = n;
	cons_it->fifo.length = src->dimension * (n - 1);
	cons_it->fifo.buffer =
	    (ssize_t *) malloc(cons_it->fifo.length * sizeof(ssize_t));
	if (!cons_it->fifo.buffer)
Brice Videau's avatar
Brice Videau committed
898
		return -EXCIT_ENOMEM;
899
	err = cons_it_rewind(it);
900
	if (err) {
901
		free(cons_it->fifo.buffer);
902 903
		return err;
	}
Brice Videau's avatar
Brice Videau committed
904
	return EXCIT_SUCCESS;
905 906
}

907
static const struct excit_func_table_s excit_cons_func_table = {
908 909 910 911 912 913 914 915 916 917 918
	cons_it_alloc,
	cons_it_free,
	cons_it_copy,
	cons_it_next,
	cons_it_peek,
	cons_it_size,
	cons_it_rewind,
	cons_it_split,
	cons_it_nth,
	cons_it_n,
	cons_it_pos
919 920 921 922
};

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

923 924 925 926
struct repeat_it_s {
	excit_t it;
	ssize_t n;
	ssize_t counter;
927 928
};

929
static int repeat_it_alloc(excit_t data)
930
{
931
	data->data = malloc(sizeof(struct repeat_it_s));
932
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
933
		return -EXCIT_ENOMEM;
934
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
935

936 937 938
	it->it = NULL;
	it->n = 0;
	it->counter = 0;
Brice Videau's avatar
Brice Videau committed
939
	return EXCIT_SUCCESS;
940 941
}

942
static void repeat_it_free(excit_t data)
943
{
944
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
945

946
	excit_free(it->it);
947 948 949
	free(data->data);
}

950
static int repeat_it_copy(excit_t ddst, const excit_t dsrc)
951
{
952 953 954
	struct repeat_it_s *dst = (struct repeat_it_s *) ddst->data;
	const struct repeat_it_s *src = (const struct repeat_it_s *)dsrc->data;
	excit_t copy = excit_dup(src->it);
955 956

	if (!copy)
Brice Videau's avatar
Brice Videau committed
957
		return -EXCIT_EINVAL;
958
	dst->it = copy;
959 960
	dst->n = src->n;
	dst->counter = src->counter;
Brice Videau's avatar
Brice Videau committed
961
	return EXCIT_SUCCESS;
962 963
}

964
static int repeat_it_peek(const excit_t data, ssize_t *indexes)
965
{
966
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
967

968
	return excit_peek(it->it, indexes);
969 970
}

971
static int repeat_it_next(excit_t data, ssize_t *indexes)
972
{
973
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
974

975 976 977 978 979
	it->counter++;
	if (it->counter < it->n)
		return excit_peek(it->it, indexes);
	it->counter = 0;
	return excit_next(it->it, indexes);
980 981
}

982
static int repeat_it_size(const excit_t data, ssize_t *size)
983
{
984 985
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_size(it->it, size);
986 987 988

	if (err)
		return err;
989
	*size *= it->n;
Brice Videau's avatar
Brice Videau committed
990
	return EXCIT_SUCCESS;
991 992
}

993
static int repeat_it_rewind(excit_t data)
994
{
995
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
996

997 998
	it->counter = 0;
	return excit_rewind(it->it);
999 1000
}

1001
static int repeat_it_nth(const excit_t data, ssize_t n, ssize_t *val)
1002
{
1003 1004
	ssize_t size;
	int err = repeat_it_size(data, &size);
1005 1006 1007 1008

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
1009
		return -EXCIT_EDOM;
1010
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
1011

1012
	return excit_nth(it->it, n / it->n, val);
1013 1014
}

1015
static int repeat_it_pos(const excit_t data, ssize_t *n)
1016
{
1017 1018 1019
	ssize_t inner_n;
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_pos(it->it, &inner_n);
1020 1021 1022 1023

	if (err)
		return err;
	if (n)
1024
		*n = inner_n * it->n + it->counter;
Brice Videau's avatar
Brice Videau committed
1025
	return EXCIT_SUCCESS;
1026 1027
}

1028
static int repeat_it_split(const excit_t data, ssize_t n, excit_t *results)
1029
{
1030 1031
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_split(it->it, n, results);
1032