Task: Geometric algebra



C#: using System;
using System.Text;

namespace GeometricAlgebra {
    struct Vector {
        private readonly double[] dims;

        public Vector(double[] da) {
            dims = da;
        }

        public static Vector operator -(Vector v) {
            return v * -1.0;
        }

        public static Vector operator +(Vector lhs, Vector rhs) {
            var result = new double[32];
            Array.Copy(lhs.dims, 0, result, 0, lhs.Length);
            for (int i = 0; i < result.Length; i++) {
                result[i] = lhs[i] + rhs[i];
            }
            return new Vector(result);
        }

        public static Vector operator *(Vector lhs, Vector rhs) {
            var result = new double[32];
            for (int i = 0; i < lhs.Length; i++) {
                if (lhs[i] != 0.0) {
                    for (int j = 0; j < lhs.Length; j++) {
                        if (rhs[j] != 0.0) {
                            var s = ReorderingSign(i, j) * lhs[i] * rhs[j];
                            var k = i ^ j;
                            result[k] += s;
                        }
                    }
                }
            }
            return new Vector(result);
        }

        public static Vector operator *(Vector v, double scale) {
            var result = (double[])v.dims.Clone();
            for (int i = 0; i < result.Length; i++) {
                result[i] *= scale;
            }
            return new Vector(result);
        }

        public double this[int key] {
            get {
                return dims[key];
            }

            set {
                dims[key] = value;
            }
        }

        public int Length {
            get {
                return dims.Length;
            }
        }

        public Vector Dot(Vector rhs) {
            return (this * rhs + rhs * this) * 0.5;
        }

        private static int BitCount(int i) {
            i -= ((i >> 1) & 0x55555555);
            i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
            i = (i + (i >> 4)) & 0x0F0F0F0F;
            i += (i >> 8);
            i += (i >> 16);
            return i & 0x0000003F;
        }

        private static double ReorderingSign(int i, int j) {
            int k = i >> 1;
            int sum = 0;
            while (k != 0) {
                sum += BitCount(k & j);
                k >>= 1;
            }
            return ((sum & 1) == 0) ? 1.0 : -1.0;
        }

        public override string ToString() {
            var it = dims.GetEnumerator();

            StringBuilder sb = new StringBuilder("[");
            if (it.MoveNext()) {
                sb.Append(it.Current);
            }
            while (it.MoveNext()) {
                sb.Append(", ");
                sb.Append(it.Current);
            }

            sb.Append(']');
            return sb.ToString();
        }
    }

    class Program {
        static double[] DoubleArray(uint size) {
            double[] result = new double[size];
            for (int i = 0; i < size; i++) {
                result[i] = 0.0;
            }
            return result;
        }

        static Vector E(int n) {
            if (n > 4) {
                throw new ArgumentException("n must be less than 5");
            }

            var result = new Vector(DoubleArray(32));
            result[1 << n] = 1.0;
            return result;
        }

        static readonly Random r = new Random();

        static Vector RandomVector() {
            var result = new Vector(DoubleArray(32));
            for (int i = 0; i < 5; i++) {
                var singleton = new double[] { r.NextDouble() };
                result += new Vector(singleton) * E(i);
            }
            return result;
        }

        static Vector RandomMultiVector() {
            var result = new Vector(DoubleArray(32));
            for (int i = 0; i < result.Length; i++) {
                result[i] = r.NextDouble();
            }
            return result;
        }

        static void Main() {
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    if (i < j) {
                        if (E(i).Dot(E(j))[0] != 0.0) {
                            Console.WriteLine("Unexpected non-null sclar product.");
                            return;
                        }
                    } else if (i == j) {
                        if ((E(i).Dot(E(j)))[0] == 0.0) {
                            Console.WriteLine("Unexpected null sclar product.");
                        }
                    }
                }
            }

            var a = RandomMultiVector();
            var b = RandomMultiVector();
            var c = RandomMultiVector();
            var x = RandomVector();

            
            Console.WriteLine((a * b) * c);
            Console.WriteLine(a * (b * c));
            Console.WriteLine();

            
            Console.WriteLine(a * (b + c));
            Console.WriteLine(a * b + a * c);
            Console.WriteLine();

            
            Console.WriteLine((a + b) * c);
            Console.WriteLine(a * c + b * c);
            Console.WriteLine();

            
            Console.WriteLine(x * x);
        }
    }
}


Go: package main

import (
    "fmt"
    "math/rand"
    "time"
)

type vector []float64

func e(n uint) vector {
    if n > 4 {
        panic("n must be less than 5")
    }
    result := make(vector, 32)
    result[1<<n] = 1.0
    return result
}

func cdot(a, b vector) vector {
    return mul(vector{0.5}, add(mul(a, b), mul(b, a)))
}

func neg(x vector) vector {
    return mul(vector{-1}, x)
}

func bitCount(i int) int {
    i = i - ((i >> 1) & 0x55555555)
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
    i = (i + (i >> 4)) & 0x0F0F0F0F
    i = i + (i >> 8)
    i = i + (i >> 16)
    return i & 0x0000003F
}

func reorderingSign(i, j int) float64 {
    i >>= 1
    sum := 0
    for i != 0 {
        sum += bitCount(i & j)
        i >>= 1
    }
    cond := (sum & 1) == 0
    if cond {
        return 1.0
    }
    return -1.0
}

func add(a, b vector) vector {
    result := make(vector, 32)
    copy(result, a)
    for i, _ := range b {
        result[i] += b[i]
    }
    return result
}

func mul(a, b vector) vector {
    result := make(vector, 32)
    for i, _ := range a {
        if a[i] != 0 {
            for j, _ := range b {
                if b[j] != 0 {
                    s := reorderingSign(i, j) * a[i] * b[j]
                    k := i ^ j
                    result[k] += s
                }
            }
        }
    }
    return result
}

func randomVector() vector {
    result := make(vector, 32)
    for i := uint(0); i < 5; i++ {
        result = add(result, mul(vector{rand.Float64()}, e(i)))
    }
    return result
}

func randomMultiVector() vector {
    result := make(vector, 32)
    for i := 0; i < 32; i++ {
        result[i] = rand.Float64()
    }
    return result
}

func main() {
    rand.Seed(time.Now().UnixNano())
    for i := uint(0); i < 5; i++ {
        for j := uint(0); j < 5; j++ {
            if i < j {
                if cdot(e(i), e(j))[0] != 0 {
                    fmt.Println("Unexpected non-null scalar product.")
                    return
                }
            } else if i == j {
                if cdot(e(i), e(j))[0] == 0 {
                    fmt.Println("Unexpected null scalar product.")
                }
            }
        }
    }

    a := randomMultiVector()
    b := randomMultiVector()
    c := randomMultiVector()
    x := randomVector()

    
    fmt.Println(mul(mul(a, b), c))
    fmt.Println(mul(a, mul(b, c)))

    
    fmt.Println(mul(a, add(b, c)))
    fmt.Println(add(mul(a, b), mul(a, c)))

    
    fmt.Println(mul(add(a, b), c))
    fmt.Println(add(mul(a, c), mul(b, c)))

    
    fmt.Println(mul(x, x))
}