Task: Quaternion type
C: #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

typedef struct quaternion
{
  double q[4];
} quaternion_t;


quaternion_t *quaternion_new(void)
{
  return malloc(sizeof(quaternion_t));
}

quaternion_t *quaternion_new_set(double q1,
				 double q2,
				 double q3,
				 double q4)
{
  quaternion_t *q = malloc(sizeof(quaternion_t));
  if (q != NULL) {
    q->q[0] = q1; q->q[1] = q2; q->q[2] = q3; q->q[3] = q4;
  }
  return q;
}


void quaternion_copy(quaternion_t *r, quaternion_t *q)
{
  size_t i;

  if (r == NULL || q == NULL) return;
  for(i = 0; i < 4; i++) r->q[i] = q->q[i];
}


double quaternion_norm(quaternion_t *q)
{
  size_t i;
  double r = 0.0;
  
  if (q == NULL) {
    fprintf(stderr, "NULL quaternion in norm\n");
    return 0.0;
  }

  for(i = 0; i < 4; i++) r += q->q[i] * q->q[i];
  return sqrt(r);
}


void quaternion_neg(quaternion_t *r, quaternion_t *q)
{
  size_t i;

  if (q == NULL || r == NULL) return;
  for(i = 0; i < 4; i++) r->q[i] = -q->q[i];
}


void quaternion_conj(quaternion_t *r, quaternion_t *q)
{
  size_t i;

  if (q == NULL || r == NULL) return;
  r->q[0] = q->q[0];
  for(i = 1; i < 4; i++) r->q[i] = -q->q[i];
}


void quaternion_add_d(quaternion_t *r, quaternion_t *q, double d)
{
  if (q == NULL || r == NULL) return;
  quaternion_copy(r, q);
  r->q[0] += d;
}


void quaternion_add(quaternion_t *r, quaternion_t *a, quaternion_t *b)
{
  size_t i;

  if (r == NULL || a == NULL || b == NULL) return;
  for(i = 0; i < 4; i++) r->q[i] = a->q[i] + b->q[i];
}


void quaternion_mul_d(quaternion_t *r, quaternion_t *q, double d)
{
  size_t i;

  if (r == NULL || q == NULL) return;
  for(i = 0; i < 4; i++) r->q[i] = q->q[i] * d;
}

bool quaternion_equal(quaternion_t *a, quaternion_t *b)
{
  size_t i;
  
  for(i = 0; i < 4; i++) if (a->q[i] != b->q[i]) return false;
  return true;
}


#define A(N) (a->q[(N)])
#define B(N) (b->q[(N)])
#define R(N) (r->q[(N)])
void quaternion_mul(quaternion_t *r, quaternion_t *a, quaternion_t *b)
{
  size_t i;
  double ri = 0.0;

  if (r == NULL || a == NULL || b == NULL) return;
  R(0) = A(0)*B(0) - A(1)*B(1) - A(2)*B(2) - A(3)*B(3);
  R(1) = A(0)*B(1) + A(1)*B(0) + A(2)*B(3) - A(3)*B(2);
  R(2) = A(0)*B(2) - A(1)*B(3) + A(2)*B(0) + A(3)*B(1);
  R(3) = A(0)*B(3) + A(1)*B(2) - A(2)*B(1) + A(3)*B(0);
}
#undef A
#undef B
#undef R


void quaternion_print(quaternion_t *q)
{
  if (q == NULL) return;
  printf("(%lf, %lf, %lf, %lf)\n", 
	 q->q[0], q->q[1], q->q[2], q->q[3]);
}

VB: Option Base 1
Private Function norm(q As Variant) As Double
    norm = Sqr(WorksheetFunction.SumSq(q))
End Function

Private Function negative(q) As Variant
    Dim res(4) As Double
    For i = 1 To 4
        res(i) = -q(i)
    Next i
    negative = res
End Function

Private Function conj(q As Variant) As Variant
    Dim res(4) As Double
    res(1) = q(1)
    For i = 2 To 4
        res(i) = -q(i)
    Next i
    conj = res
End Function

Private Function addr(r As Double, q As Variant) As Variant
    Dim res As Variant
    res = q
    res(1) = r + q(1)
    addr = res
End Function

Private Function add(q1 As Variant, q2 As Variant) As Variant
    add = WorksheetFunction.MMult(Array(1, 1), Array(q1, q2))
End Function

Private Function multr(r As Double, q As Variant) As Variant
    multr = WorksheetFunction.MMult(r, q)
End Function

Private Function mult(q1 As Variant, q2 As Variant)
    Dim res(4) As Double
    res(1) = q1(1) * q2(1) - q1(2) * q2(2) - q1(3) * q2(3) - q1(4) * q2(4)
    res(2) = q1(1) * q2(2) + q1(2) * q2(1) + q1(3) * q2(4) - q1(4) * q2(3)
    res(3) = q1(1) * q2(3) - q1(2) * q2(4) + q1(3) * q2(1) + q1(4) * q2(2)
    res(4) = q1(1) * q2(4) + q1(2) * q2(3) - q1(3) * q2(2) + q1(4) * q2(1)
    mult = res
End Function

Private Sub quats(q As Variant)
    Debug.Print q(1); IIf(q(2) < 0, " - " & Abs(q(2)), " + " & q(2));
    Debug.Print IIf(q(3) < 0, "i - " & Abs(q(3)), "i + " & q(3));
    Debug.Print IIf(q(4) < 0, "j - " & Abs(q(4)), "j + " & q(4)); "k"
End Sub

Public Sub quaternions()
    q = [{ 1, 2, 3, 4}]
    q1 = [{2, 3, 4, 5}]
    q2 = [{3, 4, 5, 6}]
    Dim r_ As Double
    r_ = 7#
    Debug.Print "q            = ";: quats q
    Debug.Print "q1           = ";: quats q1
    Debug.Print "q2           = ";: quats q2
    Debug.Print "r            = "; r_
    Debug.Print "norm(q)      = "; norm(q)
    Debug.Print "negative(q)  = ";: quats negative(q)
    Debug.Print "conjugate(q) = ";: quats conj(q)
    Debug.Print "r + q        = ";: quats addr(r_, q)
    Debug.Print "q1 + q2      = ";: quats add(q1, q2)
    Debug.Print "q * r        = ";: quats multr(r_, q)
    Debug.Print "q1 * q2      = ";: quats mult(q1, q2)
    Debug.Print "q2 * q1      = ";: quats mult(q2, q1)
End Sub