#include <math.h>
#include <stdlib.h>
#include <string.h>

#include "vector.h"

void vec_init(vec_t *vector, int capacity)
{
   vector->x = NULL;
   vector->y = NULL;

   if(capacity > 0) {
      vec_reserve(vector, capacity);
   }
}

void vec_reserve(vec_t *vector, int capacity)
{
   vector->x = realloc(vector->x, capacity * sizeof(double));
   vector->y = realloc(vector->y, capacity * sizeof(double));
}

void vec_free(vec_t *vector)
{
   vec_reserve(vector, 0);
}

void vec_copy(vec_t *dst, int dst_start, const vec_t *src, int src_start, int count)
{
   memmove(&dst->x[dst_start], &src->x[src_start], count * sizeof(double));
   memmove(&dst->y[dst_start], &src->y[src_start], count * sizeof(double));
}

void vec_set_zero(vec_t *vector, int count)
{
   memset(vector->x, 0, count * sizeof(double));
   memset(vector->y, 0, count * sizeof(double));
}

void vec_add(vec_t *accumulator, const vec_t *operand, int count)
{
   vec_add_scaled(accumulator, operand, 1., count);
}

void vec_add_scaled(vec_t *accumulator, const vec_t* operand, double factor, int count)
{
   int i;
   double *a, *o;

   a = accumulator->x;
   o = operand->x;
   for(i = 0; i < count; i++) {
      a[i] += o[i] * factor;
   }
   a = accumulator->y;
   o = operand->y;
   for(i = 0; i < count; i++) {
      a[i] += o[i] * factor;
   }
}

void vec_add_scaled_mod(vec_t *accumulator, const vec_t* operand, double factor, double modx, double mody, int count)
{
   int i;
   double *a, *o;

   a = accumulator->x;
   o = operand->x;
   for(i = 0; i < count; i++) {
      a[i] = fmod(modx + fmod(a[i] + o[i] * factor, modx), modx);
   }
   a = accumulator->y;
   o = operand->y;
   for(i = 0; i < count; i++) {
      a[i] = fmod(mody + fmod(a[i] + o[i] * factor, mody), mody);
   }
}

void vec_scale(vec_t *vector, double factor, int count)
{
   int i;
   double *v;

   v = vector->x;
   for(i = 0; i < count; i++) {
      v[i] *= factor;
   }
   v = vector->y;
   for(i = 0; i < count; i++) {
      v[i] *= factor;
   }
}

void vec_arr_divide(vec_t *result, const vec_t *operand, const double *divisor, int count)
{
   int i;
   double *a;
   const double *b;

   a = result->x;
   b = operand->x;
   for(i = 0; i < count; i++) {
      a[i] = b[i] / divisor[i];
   }
   a = result->y;
   b = operand->y;
   for(i = 0; i < count; i++) {
      a[i] = b[i] / divisor[i];
   }
}

