Task: Geometric algebra


C++: #include <algorithm>
#include <iostream>
#include <random>
#include <vector>

double uniform01() {
    static std::default_random_engine generator;
    static std::uniform_real_distribution<double> distribution(0.0, 1.0);
    return distribution(generator);
}

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;
}

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

struct MyVector {
public:
    MyVector(const std::vector<double> &da) : dims(da) {
        
    }

    double &operator[](size_t i) {
        return dims[i];
    }

    const double &operator[](size_t i) const {
        return dims[i];
    }

    MyVector operator+(const MyVector &rhs) const {
        std::vector<double> temp(dims);
        for (size_t i = 0; i < rhs.dims.size(); ++i) {
            temp[i] += rhs[i];
        }
        return MyVector(temp);
    }

    MyVector operator*(const MyVector &rhs) const {
        std::vector<double> temp(dims.size(), 0.0);
        for (size_t i = 0; i < dims.size(); i++) {
            if (dims[i] != 0.0) {
                for (size_t j = 0; j < dims.size(); j++) {
                    if (rhs[j] != 0.0) {
                        auto s = reorderingSign(i, j) * dims[i] * rhs[j];
                        auto k = i ^ j;
                        temp[k] += s;
                    }
                }
            }
        }
        return MyVector(temp);
    }

    MyVector operator*(double scale) const {
        std::vector<double> temp(dims);
        std::for_each(temp.begin(), temp.end(), [scale](double a) { return a * scale; });
        return MyVector(temp);
    }

    MyVector operator-() const {
        return *this * -1.0;
    }

    MyVector dot(const MyVector &rhs) const {
        return (*this * rhs + rhs * *this) * 0.5;
    }

    friend std::ostream &operator<<(std::ostream &, const MyVector &);

private:
    std::vector<double> dims;
};

std::ostream &operator<<(std::ostream &os, const MyVector &v) {
    auto it = v.dims.cbegin();
    auto end = v.dims.cend();

    os << '[';
    if (it != end) {
        os << *it;
        it = std::next(it);
    }
    while (it != end) {
        os << ", " << *it;
        it = std::next(it);
    }
    return os << ']';
}

MyVector e(int n) {
    if (n > 4) {
        throw new std::runtime_error("n must be less than 5");
    }

    auto result = MyVector(std::vector<double>(32, 0.0));
    result[1 << n] = 1.0;
    return result;
}

MyVector randomVector() {
    auto result = MyVector(std::vector<double>(32, 0.0));
    for (int i = 0; i < 5; i++) {
        result = result + MyVector(std::vector<double>(1, uniform01())) * e(i);
    }
    return result;
}

MyVector randomMultiVector() {
    auto result = MyVector(std::vector<double>(32, 0.0));
    for (int i = 0; i < 32; i++) {
        result[i] = uniform01();
    }
    return result;
}

int 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) {
                    std::cout << "Unexpected non-null scalar product.";
                    return 1;
                } else if (i == j) {
                    if (e(i).dot(e(j))[0] == 0.0) {
                        std::cout << "Unexpected null scalar product.";
                    }
                }
            }
        }
    }

    auto a = randomMultiVector();
    auto b = randomMultiVector();
    auto c = randomMultiVector();
    auto x = randomVector();

    
    std::cout << ((a * b) * c) << '\n';
    std::cout << (a * (b * c)) << "\n\n";

    
    std::cout << (a * (b + c)) << '\n';
    std::cout << (a * b + a * c) << "\n\n";

    
    std::cout << ((a + b) * c) << '\n';
    std::cout << (a * c + b * c) << "\n\n";

    
    std::cout << (x * x) << '\n';

    return 0;
}



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))
}