// Operaciones sobre arreglos de int. Qué se hace con cada elemento lo decide un callback.
#ifndef ARRAY_OPS_H
#define ARRAY_OPS_H

typedef int (*IntMap)(int value);
typedef int (*IntPredicate)(int value);
typedef int (*IntCombine)(int accumulated, int value);
typedef int (*ContextPredicate)(int value, void *context);

// Guarda en out[i] el resultado de transform(in[i]), para i de 0 a n - 1.
// out tiene espacio para n valores y puede ser el mismo arreglo que in.
void array_map(const int *in, int n, IntMap transform, int *out);

// Copia en out, en el mismo orden, los elementos de in para los que keep devuelve algo
// distinto de 0. Devuelve cuántos copió. out tiene espacio para n valores y puede ser el
// mismo arreglo que in.
int array_filter(const int *in, int n, IntPredicate keep, int *out);

// Empieza con initial, y combina el acumulado con cada elemento, de izquierda a derecha.
// Con n igual a 0 devuelve initial.
int array_fold(const int *values, int n, IntCombine combine, int initial);

// Cuenta los elementos para los que accept(valor, context) devuelve algo distinto de 0.
// No toca context: solo se lo pasa a accept, sin mirarlo.
int array_count_if(const int *values, int n, ContextPredicate accept, void *context);

// Cuenta los elementos mayores que threshold. Usa array_count_if, sin variables globales.
int count_above(const int *values, int n, int threshold);

#endif
