A vector is defined as having three dimensions as being represented by an ordered collection of three numbers:   (X, Y, Z).

If you imagine a graph with the   x   and   y   axis being at right angles to each other and having a third,   z   axis coming out of the page, then a triplet of numbers,   (X, Y, Z)   would represent a point in the region,   and a vector from the origin to the point.

Given the vectors:

        A = (a1,  a2,  a3) 
        B = (b1,  b2,  b3) 
        C = (c1,  c2,  c3) 

then the following common vector products are defined:

 The dot product       (a scalar quantity)
  A • B = a1b1   +   a2b2   +   a3b3  
 The cross product       (a vector quantity)
  A x B = (a2b3  -   a3b2,     a3b1   -   a1b3,     a1b2   -   a2b1)  
 The scalar triple product       (a scalar quantity)
  A • (B x C) 
 The vector triple product       (a vector quantity)
  A x (B x C) 


Task

Given the three vectors:

        a = ( 3,    4,    5)
        b = ( 4,    3,    5)
        c = (-5,  -12,  -13)

 Create a named function/subroutine/method to compute the dot product of two vectors.
 Create a function to compute the cross product of two vectors.
 Optionally create a function to compute the scalar triple product of three vectors.
 Optionally create a function to compute the vector triple product of three vectors.
 Compute and display: a • b
 Compute and display: a x b
 Compute and display: a • (b x c), the scalar triple product.
 Compute and display: a x (b x c), the vector triple product.


References

   A starting page on Wolfram MathWorld is   Vector Multiplication .
   Wikipedia   dot product. 
   Wikipedia   cross product. 
   Wikipedia   triple product.


Related tasks

   Dot product
   Quaternion type


include "cowgol.coh";
 
record Vector is
    x: int32;   # Cowgol does not have floating point types,
    y: int32;   # but for the examples it does not matter.
    z: int32;
end record;
 
sub print_signed(n: int32) is
    if n < 0 then
        print_char('-');
        n := -n;
    end if;
    print_i32(n as uint32);
end sub;
 
sub print_vector(v: [Vector]) is
    print_char('(');
    print_signed(v.x);
    print(", ");
    print_signed(v.y);
    print(", ");
    print_signed(v.z);
    print_char(')');
    print_nl();
end sub;
 
sub dot(a: [Vector], b: [Vector]): (r: int32) is
    r := a.x * b.x + a.y * b.y + a.z * b.z;
end sub;
 
# Unfortunately it is impossible to return a complex type
# from a function. We have to have the caller pass in a pointer
# and have this function set its fields. 
sub cross(a: [Vector], b: [Vector], r: [Vector]) is
    r.x := a.y * b.z - a.z * b.y;
    r.y := a.z * b.x - a.x * b.z;
    r.z := a.x * b.y - a.y * b.x;
end sub;
 
sub scalarTriple(a: [Vector], b: [Vector], c: [Vector]): (r: int32) is
    var v: Vector;
    cross(b, c, &v);
    r := dot(a, &v);
end sub;
 
sub vectorTriple(a: [Vector], b: [Vector], c: [Vector], r: [Vector]) is
    var v: Vector;
    cross(b, c, &v);
    cross(a, &v, r);
end sub;
 
var a: Vector := {3, 4, 5};
var b: Vector := {4, 3, 5};
var c: Vector := {-5, -12, -13};
var scratch: Vector;
 
print("        a = "); print_vector(&a);
print("        b = "); print_vector(&b);
print("        c = "); print_vector(&c);
print("    a . b = "); print_signed(dot(&a, &b)); print_nl();
print("    a x b = "); cross(&a, &b, &scratch); print_vector(&scratch);
print("a . b x c = "); print_signed(scalarTriple(&a, &b, &c)); print_nl();
print("a x b x c = "); vectorTriple(&a, &b, &c, &scratch);
                       print_vector(&scratch);