#include <stdio.h>
#include <stdlib.h>

#include "vector.h"

double_vector_t *init_vector(uint_t N)
{
    double_vector_t *vec = malloc(sizeof(double_vector_t));
    vec->components = malloc(N * sizeof(double));
    vec->N = N;
    if (vec == NULL)
    {
        perror("Can't allocate memory");
        exit(EXIT_FAILURE);
    }
    return vec;
}
double_vector_t *iota(uint_t N)
{
    double_vector_t *vec = init_vector(N);
    for (uint_t i = 0; i < N; i++)
    {
        vec->components[i] = i;
    }
    return vec;
}
double_vector_t *apply_function(double_vector_t *vec, double_function_t f)
{
    double_vector_t *res = init_vector(vec->N);
    for (uint_t i = 0; i < vec->N; i++)
    {
        res->components[i] = f(vec->components[i]);
    }
    return res;
}
void fill_vector(double_vector_t *vec, double value)
{
    for (uint_t i = 0; i < vec->N; i++)
    {
        vec->components[i] = value;
    }
}
void export_vector(const char *filename, double_vector_t *vec)
{
    FILE *output = fopen(filename, "w");

    uint_t endianness = 0x01020304;
    vector_metadata_t metadata;
    // Return the endianness by accessing the first byte in memory
    // which should be 1 if big-endian and 4 if little-endian
    metadata.endianness = *((byte_t *)(&endianness)) == 4;
    metadata.size_of_a_component = sizeof(double);
    metadata.number_of_component = vec->N;

    fwrite(&metadata, sizeof(vector_metadata_t), 1, output);
    fwrite(vec->components,
           metadata.size_of_a_component,
           metadata.number_of_component,
           output);

    fclose(output);
}

void destroy_vector(double_vector_t **vec)
{
    free((*vec)->components);
    free(*vec);
    *vec = NULL;
}