Files
libpostal/src/cartesian_product.c

92 lines
2.2 KiB
C

#include "cartesian_product.h"
#include <stdarg.h>
cartesian_product_iterator_t *cartesian_product_iterator_new_vargs(size_t n, va_list args) {
cartesian_product_iterator_t *iter = malloc(sizeof(cartesian_product_iterator_t));
if (iter == NULL) return NULL;
iter->lengths = uint32_array_new_size(n);
if (iter->lengths == NULL) {
goto exit_iter_created;
}
size_t remaining = 1;
for (size_t i = 0; i < n; i++) {
uint32_t arg = va_arg(args, uint32_t);
uint32_array_push(iter->lengths, arg);
if (arg > 0) {
remaining *= arg;
}
}
iter->remaining = remaining;
iter->state = uint32_array_new_zeros(n);
if (iter->state == NULL) {
goto exit_iter_created;
}
return iter;
exit_iter_created:
cartesian_product_iterator_destroy(iter);
return NULL;
}
cartesian_product_iterator_t *cartesian_product_iterator_new(size_t n, ...) {
va_list args;
va_start(args, n);
cartesian_product_iterator_t *iter = cartesian_product_iterator_new_vargs(n, args);
va_end(args);
return iter;
}
uint32_t *cartesian_product_iterator_start(cartesian_product_iterator_t *self) {
return self->state->a;
}
bool cartesian_product_iterator_done(cartesian_product_iterator_t *self) {
return self->remaining == 0;
}
uint32_t *cartesian_product_iterator_next(cartesian_product_iterator_t *self) {
if (self == NULL) return NULL;
uint32_t *lengths = self->lengths->a;
uint32_t *state = self->state->a;
if (self->remaining > 0) {
ssize_t i;
ssize_t n = self->lengths->n;
for (i = n - 1; i >= 0; i--) {
state[i]++;
if (state[i] == lengths[i]) {
state[i] = 0;
} else {
self->remaining--;
break;
}
}
if (i < 0) {
self->remaining = 0;
}
} else {
return NULL;
}
return state;
}
void cartesian_product_iterator_destroy(cartesian_product_iterator_t *self) {
if (self == NULL) return;
if (self->lengths != NULL) {
uint32_array_destroy(self->lengths);
}
if (self->state != NULL) {
uint32_array_destroy(self->state);
}
free(self);
}