[utils] cartesian product iterator for grid search during model selection
This commit is contained in:
91
src/cartesian_product.c
Normal file
91
src/cartesian_product.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
23
src/cartesian_product.h
Normal file
23
src/cartesian_product.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef CARTESIAN_PRODUCT_H
|
||||||
|
#define CARTESIAN_PRODUCT_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "collections.h"
|
||||||
|
|
||||||
|
typedef struct cartesian_product_iterator {
|
||||||
|
size_t remaining;
|
||||||
|
uint32_array *lengths;
|
||||||
|
uint32_array *state;
|
||||||
|
} cartesian_product_iterator_t;
|
||||||
|
|
||||||
|
cartesian_product_iterator_t *cartesian_product_iterator_new(size_t n, ...);
|
||||||
|
cartesian_product_iterator_t *cartesian_product_iterator_new_vargs(size_t n, va_list args);
|
||||||
|
uint32_t *cartesian_product_iterator_start(cartesian_product_iterator_t *self);
|
||||||
|
uint32_t *cartesian_product_iterator_next(cartesian_product_iterator_t *self);
|
||||||
|
bool cartesian_product_iterator_done(cartesian_product_iterator_t *self);
|
||||||
|
|
||||||
|
void cartesian_product_iterator_destroy(cartesian_product_iterator_t *self);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user