Quick actions

cmd+k|ctrl+k

Navigation

Languages

N-th dimensional arithmetic vector

Snippet info

Language

C

Visibility

public

Author

mrsimb

Created

2017-04-24T16:34:54Z

Updated

2017-05-31T14:53:22Z

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

#define TRUE 1
#define FALSE 0
#define BUFFER_LENGTH 80


typedef struct {
  int size;
  double* data;
} Vector;


Vector v_create(int size, double* source);
Vector v_input();
Vector v_load(char* path);
void v_destroy(Vector v);

void v_save(Vector v, char* path);
void v_print(Vector v);

int v_equal(Vector a, Vector b);

void v_add(Vector v1, Vector v2);
void v_sub(Vector v1, Vector v2);

double v_dot(Vector v1, Vector v2);
Vector va_cross(Vector* vectors, int count);
int v_collinear(Vector v1, Vector v2);
int va_collinear(Vector* vectors, int count);
int va_complanar(Vector* vectors, int count);


Vector v_create(int size, double* source) {
  if (size < 0) size = 0;

  Vector v;
  v.size = size;
  v.data = malloc(size * sizeof(double));

  for (int i = 0; i < v.size; i++) {
    v.data[i] = 0;
  }

  if (source) {
    for (int i = 0; i < v.size; i++) {
      v.data[i] = source[i];
    }
  }

  return v;
}

Vector v_input() {
  char buffer[BUFFER_LENGTH];
  int size;

  printf("Input Vector size (int): ");

  while (1) {
    fgets(buffer, BUFFER_LENGTH, stdin);

    if (sscanf(buffer, "%i", &size) == 1) break;

    printf(
      "Error while reading input.\n"
      "Try again with correct number (int): "
    );
  }

  Vector v = v_create(size, NULL);

  printf("Input %i values separated by new line (double): \n", size);

  for (int i = 0; i < size; i++) {
    fgets(buffer, BUFFER_LENGTH, stdin);

    if (sscanf(buffer, "%lf", &v.data[i]) != 1) {
      printf(
        "Error while reading input.\n"
        "Starting over from #[%i] (double): ",
        i
      );

      i--;
    }
  }

  return v;
}

void v_print(Vector v) {
  printf("{ ");

  for (int i = 0; i < v.size; i++) {
    printf("%lf ", v.data[i]);
  }

  printf("}");
}

Vector v_load(char* path) {
  char buffer[BUFFER_LENGTH];
  int size;
  Vector v;

  FILE* file = fopen(path, "r");

  if (!file) {
    printf("Error while opening file [%s]. Returning empty vector...\n", path);
    return v_create(0, NULL);
  }

  fgets(buffer, BUFFER_LENGTH, file);

  if (sscanf(buffer, "%i", &size) != 1) {
    printf("Error while reading vector size [%s]. Setting size to 0...\n", path);
    size = 0;
  }

  v = v_create(size, NULL);

  for (int i = 0; i < size; i++) {
    fgets(buffer, BUFFER_LENGTH, file);

    if (sscanf(buffer, "%lf", &v.data[i]) != 1) {
      printf("Error while reading vector data [%s]. Returning empty vector...\n", path);

      v_destroy(v);
    }
  }

  return v;
}

void v_save(Vector v, char* path) {
  FILE* file = fopen(path, "w");

  if (file == NULL) {
    printf("Error while saving vector to file [%s]\n", path);
    return;
  }

  fprintf(file, "%i\n", v.size);

  for (int i = 0; i < v.size; i++) {
    fprintf(file, "%lf\n", v.data[i]);
  }

  printf("Vector saved [%s]\n", path);
}

void v_destroy(Vector v) {
  v.size = 0;
  free(v.data);
}

int v_equal(Vector v1, Vector v2) {
  if (v1.size == v2.size) {
    for (int i = 0; i < v1.size; i++) {
      if (v1.data[i] != v2.data[i]) return FALSE;
    }

    return TRUE;
  }

  return FALSE;
}

void v_add(Vector v1, Vector v2) {
  if (v2.size > v1.size) {
    v1.data = realloc(v1.data, v2.size * sizeof(double));

    for (int i = v1.size; i < v2.size; i++) {
      v1.data[i] = 0;
    }

    v1.size = v2.size;
  }

  for (int i = 0; i < v1.size; i++) {
    v1.data[i] += v2.data[i];
  }
}

void v_sub(Vector v1, Vector v2) {
  if (v2.size > v1.size) {
    v1.data = realloc(v1.data, v2.size * sizeof(double));

    for (int i = v1.size; i < v2.size; i++) {
      v1.data[i] = 0;
    }

    v1.size = v2.size;
  }

  for (int i = 0; i < v1.size; i++) {
    v1.data[i] -= v2.data[i];
  }
}

void v_mul(Vector v, double k) {
  for (int i = 0; i < v.size; i++) {
    v.data[i] *= k;
  }
}

int v_collinear(Vector v1, Vector v2) {
  Vector vectors[2] = {v1, v2};

  Vector cross = va_cross(vectors, 2);

  for (int i = 0; i < cross.size; i++) {
    if (cross.data[i] != 0) return FALSE;
  }

  return TRUE;
}

int va_collinear(Vector* vectors, int count) {
  for (int i = 1; i < count; i++) {
    if (!v_collinear(vectors[i], vectors[0])) return FALSE;
  }

  return TRUE;
}

int va_complanar(Vector* vectors, int count) {
  return FALSE;
}

double v_dot(Vector v1, Vector v2) {
  int min_size = v1.size;

  if (v2.size < v1.size) min_size = v2.size;

  double sum = 0;

  for (int i = 0; i < min_size; i++) {
    sum += v1.data[i] * v2.data[i];
  }

  return sum;
}

Vector va_cross(Vector* vectors, int count) {
  int size = count + 1;

  for (int i = 0; i < count; i++) {
    if (vectors[i].size != size) return v_create(0, NULL);
  }

  Vector result = v_create(size, NULL);

  if (size == 2) {
    result.data[0] = vectors[0].data[1];
    result.data[1] = -vectors[0].data[0];
    return result;
  }

  for (int r = 0; r < size; r++) {
    double sub_det = 0;

    for (int offset = 0; offset < count; offset++) {
      double positive_mul = 1;
      double negative_mul = 1;

      for (int w = 0; w < count; w++) {
        int index = (r + w + offset + 1) % size;

        if (index == r) index = (index + 2) % size;

        positive_mul *= vectors[w].data[index];
        negative_mul *= vectors[count - 1 - w].data[index];
      }

      sub_det += positive_mul;
      sub_det -= negative_mul;
    }

    result.data[r] = sub_det;
  }

  return result;
}

/*
  main
*/
int main() {
  Vector a = v_create(3, (double[]) {
    1, 2, 3
  });

  Vector b = v_create(3, (double[]) {
    4, 5, 6
  });

  Vector vectors[] = {a, b};

  Vector cross = va_cross(vectors, 2);
  printf("\nCross result:\n");
  v_print(cross);

  return 0;
}
INFO