Geometric algebra: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(41 intermediate revisions by 12 users not shown)
Line 1:
{{draft task}}
 
'''Geometric algebra''' is an otheranother name for [[wp:Clifford algebra|Clifford algebra]]s and it's basically an algebra containing a vector space <math>\mathcal{V}</math> and obeying the following axioms:
 
:<math>\begin{array}{c}
Line 11:
</math>
 
The product operation in thissuch algebra is called the ''geometric product''. The elementsElements are called ''multivectors''., while Multivectorsmultivectors in <math>\mathcal{V}</math> are just called ''vectors''. If the dimension of <math>\mathcal{V}</math> is <math>n</math>, then the dimension of the algebra is <math>2^n</math>.
 
There are a few simple examples of geometric algebras. A trivial one for instance is simply <math>\R</math>, where <math>\mathcal{V} = \R</math>. The complex numbers also form a geometric algebra, where the vector space is the one-dimensional space of all purely imaginary numbers. Another example is the space of [[Quaternion type|quaternions]], where the vector space is the three-dimensional space of all linear combinations of <math>(i, j, k)</math>.
The purpose of this task is to implement such an algebra for an arbitrary large dimension <math>n</math>, but just take <math>n = 5</math> if that's easier to implement in your language (for instance if support of large integers is not easy). For this task we will also focus on simple versions of this algebra where <math>\forall\mathbf{x}\in\mathcal{V},\,\mathbf{x}\neq 0 \implies \mathbf{x}^2>0</math>, but you can also implement a general version for extra credit.
 
The purpose of this task is to implement a geometric algebra with a vector space <math>\mathcal{V}</math> of dimension ''n'' of at least five, but for extra-credit you can implement a version with ''n'' arbitrary large. Using a dimension five is useful as it is the dimension required for the so-called ''conformal model'' which will be the subject of a derived task.
To demonstrate your solution, you will use it to implement [[Quaternion type|quaternions]]:
 
* define the inner product of two vectors : <math>\mathbf{a}\cdot\mathbf{b} = (\mathbf{ab} + \mathbf{ba})/2</math>.
To ensure the unicity of the solution (that is, up to some isomorphism), we will also restrict ourselves to the so-called euclidean case, where the square of a non-zero vector is positive:
Since <math>\mathbf{ab} + \mathbf{ba} = (\mathbf{a} + \mathbf{b})^2 - \mathbf{a}^2 - \mathbf{b}^2</math>, the fourth axiom tells us that the inner product is a real number, and since it is also clearly symmetric and bilinear, it defines a [[wp:scalar product|scalar product]] on <math>\mathcal{V}</math>.
 
* define a function <math>n\mapsto e(n)</math> which allows for creation of an orthonormal basis of <math>\mathcal{V}</math>
<math>(\forall\mathbf{ex}_0,\mathbfin\mathcal{eV}_1,\, \mathbf{ex}_2,\ldots)neq 0 \implies\mathbf{x}^2 > 0</math>,.
 
* verify that the square of an arbitrary vector is real. Use this example: <math>(\mathbf{e}_0 - \mathbf{e}_1 + 2\mathbf{e}_2 + 3\mathbf{e}_3 - 2\mathbf{e}_4)^2 = 19</math>
You can of course, for extra credit, implement the general case. This would require the definition of a parameter for the ''signature'' of the metric.
* verify the orthonormality <math>\mathbf{e}_i\cdot\mathbf{e}_j = \delta_{i,j}</math> for i, j in <math>\{0, 1, 2, 3\}</math>.
 
* define the following three constants:
In order to show that your solution uses a vector space of dimension at least five, you will create a function <tt>n -> e(n)</tt> such that the vectors <tt>e(0), e(1), e(2), e(3), e(4)</tt> are linearly independent. To do so you will make them orthonormal with the following [[wp:scalar product|scalar product]]:
:<math>\begin{array}{c}
 
i = \mathbf{e}_0\mathbf{e}_1\\
j<math>\mathbf{x}\cdot\mathbf{y} = (\mathbf{ex}_1\mathbf{ey}_2 + \mathbf{y}\mathbf{x})/2</math>
 
k = \mathbf{e}_0\mathbf{e}_2
The fact that this so-called ''inner product'' defines a scalar product is a consequence of the fourth axiom. To see it one just needs to notice the relation:
\end{array}</math>
 
* verify that <math>i^2 = j^2 = k^2 = ijk = -1</math>
<math>\mathbf{x}\mathbf{y} + \mathbf{y}\mathbf{x} = (\mathbf{x} + \mathbf{y})^2 - \mathbf{x}^2 - \mathbf{y}^2</math>
* to verify that your implementation does not just reuse an ad-hoc implementation of quaternions, also define the following three constants:
 
:<math>\begin{array}{c}
Once you'll have shown that your vector space is at least of dimension five, you will show that the axioms are satisfied. For this purpose you will pick three random multivectors ''a'', ''b'' and ''c'', along with a random vector <math>\mathbf{x}</math>.
I = \mathbf{e}_1\mathbf{e}_2\\
 
J = \mathbf{e}_2\mathbf{e}_3\\
Producing a random vector is easy. Just use a pseudo-random generation function <tt>rand</tt> and create a vector:
K = \mathbf{e}_1\mathbf{e}_3
 
\end{array}</math>
* verify that <math>I^2\mathrm{randomVector}() = J^2 \sum_{i= K0}^24 = IJK =\mathrm{rand}() -1\mathbf{e}_i</math>
 
* verify that <math>(K-J) = I(J+K)</math>
Producing a random multivector is slightly more involved. It is known that when the dimension of <math>\mathcal{V}</math> is ''n'', then the dimension of the algebra (seen as a vector space with its natural scalar multiplication) is 2<sup>n</sup>. This means that for n=5 there is a basis of 2<sup>5</sup> = 32 basis multivectors from which any multivector can be written as a linear combination. Create such a basis <math>m_0, m_1,\ldots,m_{31}</math> along with a function producting a random multivector:
 
<math>\mathrm{randomMultivector}() = \sum_{i=0}^{31} \mathrm{rand}() m_i</math>
 
To summarize, to solve this task you will:
* define the inner product of two vectors : <math>\mathbf{x}\cdot\mathbf{y} = (\mathbf{xy} + \mathbf{yx})/2</math>.
* define the function <tt>e</tt>
* verify the orthonormality <math>\mathbf{e}_i\cdot\mathbf{e}_j = \delta_{i,j}</math> for i, j in <math>\{0, 1, 2, 3, 4\}</math>.
* create a function returning a random multivector
* create a function returning a random vector
* verify the axioms for three rarndom multivectors ''a'', ''b'', ''c'' and a random vector '''x'''.
 
<br>
Optionally, you will repeat the last step a large number of times, in order to increase confidence in the result.
<br><br>
 
=={{header|C sharp|C#}}==
{{trans|D}}
<syntaxhighlight lang="csharp">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;//there is an index out of bounds here
}
}
}
}
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();
 
// (ab)c == a(bc)
Console.WriteLine((a * b) * c);
Console.WriteLine(a * (b * c));
Console.WriteLine();
 
// a(b+c) == ab + ac
Console.WriteLine(a * (b + c));
Console.WriteLine(a * b + a * c);
Console.WriteLine();
 
// (a+b)c == ac + bc
Console.WriteLine((a + b) * c);
Console.WriteLine(a * c + b * c);
Console.WriteLine();
 
// x^2 is real
Console.WriteLine(x * x);
}
}
}</syntaxhighlight>
{{out}}
<pre>[-2.7059639813936, -2.65443237395364, -1.03355975191747, 5.431067101183, 9.57183741787636, 7.41390675997241, -8.09043009371666, -7.30180304927878, -1.50642825479215, -4.14594595273162, -1.78857280373918, -0.484382016930444, -7.42401696794793, -4.78491995868705, -8.43252648860165, -4.47485336471182, -2.3458119817208, 3.6184495826099, -7.50802924695147, -2.10106278080463, 7.15782745037037, 7.60049996423655, -10.6945339837475, -6.9874232887485, -4.85603010723139, -9.8225346377117, 3.50534384939214, 3.08239272713895, -9.92019737517891, -10.1065306142574, -8.79795495448311, -4.01442257971653]
[-2.70596398139361, -2.65443237395364, -1.03355975191747, 5.43106710118299, 9.57183741787636, 7.41390675997241, -8.09043009371666, -7.30180304927878, -1.50642825479215, -4.14594595273162, -1.78857280373917, -0.484382016930444, -7.42401696794793, -4.78491995868705, -8.43252648860165, -4.47485336471182, -2.3458119817208, 3.6184495826099, -7.50802924695147, -2.10106278080463, 7.15782745037036, 7.60049996423655, -10.6945339837475, -6.9874232887485, -4.85603010723139, -9.8225346377117, 3.50534384939214, 3.08239272713894, -9.9201973751789, -10.1065306142574, -8.79795495448311, -4.01442257971653]
 
[-5.35792362178344, -2.83992055857095, -0.00435065203934659, 0.548701864561436, 7.31905167177133, 2.98280880755406, 2.54042778638867, -1.82513292511705, -4.07944497473881, -3.87206774796269, 2.05320674506366, 1.00599045579458, -3.72912260067605, -3.4226426940923, 1.62806109332525, 3.26554642532303, -2.2232872618717, -2.06401927877361, 3.31046340349916, 3.21397515180161, 4.84963949791875, 1.98923326842668, 2.28775873178049, -0.927084258496161, -3.99100687576943, -1.67065148926557, 2.70438629346319, 0.400654313359669, -0.74522009023782, 0.737528754412463, 4.53246775536051, 5.82111882775243]
[-5.35792362178344, -2.83992055857095, -0.0043506520393467, 0.548701864561437, 7.31905167177133, 2.98280880755406, 2.54042778638867, -1.82513292511705, -4.0794449747388, -3.87206774796269, 2.05320674506366, 1.00599045579458, -3.72912260067605, -3.4226426940923, 1.62806109332525, 3.26554642532303, -2.2232872618717, -2.06401927877361, 3.31046340349916, 3.21397515180161, 4.84963949791875, 1.98923326842668, 2.28775873178049, -0.92708425849616, -3.99100687576943, -1.67065148926557, 2.70438629346319, 0.40065431335967, -0.745220090237821, 0.737528754412463, 4.53246775536051, 5.82111882775243]
 
[-6.85152530876464, -2.6466613868296, -0.814269203555543, -2.63807771948643, 6.89540453623166, 4.70804372948965, 2.78512631505336, 2.03877626337364, -1.77047482836463, 1.52836763170898, 0.71565745873906, 0.886707645932111, -2.25661460785133, -1.08891196061849, 3.44949857952115, 5.8645384965889, -3.09249704978979, -1.41518183096078, 1.87603297737169, 2.45042504250642, 3.66908389117503, 1.85358883025892, 1.23206155683761, -0.216105143607701, -1.88866851071821, -0.131570581491294, 5.7355274883507, 4.22029797577044, -0.212906215521922, -0.323884694190184, 4.41630150883192, 5.94513377054442]
[-6.85152530876464, -2.6466613868296, -0.814269203555542, -2.63807771948643, 6.89540453623166, 4.70804372948965, 2.78512631505335, 2.03877626337364, -1.77047482836463, 1.52836763170898, 0.715657458739061, 0.886707645932111, -2.25661460785133, -1.08891196061849, 3.44949857952115, 5.8645384965889, -3.09249704978979, -1.41518183096078, 1.87603297737169, 2.45042504250642, 3.66908389117503, 1.85358883025892, 1.23206155683761, -0.216105143607701, -1.88866851071821, -0.131570581491294, 5.7355274883507, 4.22029797577044, -0.212906215521922, -0.323884694190183, 4.41630150883192, 5.94513377054442]
 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</pre>
 
=={{header|C++}}==
{{trans|D}}
<syntaxhighlight lang="cpp">#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) {
// empty
}
 
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();
 
// (ab)c == a(bc)
std::cout << ((a * b) * c) << '\n';
std::cout << (a * (b * c)) << "\n\n";
 
// a(b+c) == ab + ac
std::cout << (a * (b + c)) << '\n';
std::cout << (a * b + a * c) << "\n\n";
 
// (a+b)c == ac + bc
std::cout << ((a + b) * c) << '\n';
std::cout << (a * c + b * c) << "\n\n";
 
// x^2 is real
std::cout << (x * x) << '\n';
 
return 0;
}</syntaxhighlight>
{{out}}
<pre>[-5.63542, -6.59107, -10.2043, -5.21095, 8.68946, 0.579114, -4.67295, -6.72461, 1.55005, -2.63952, -1.83855, 2.4967, -4.3396, -9.9157, -4.6942, -3.23625, -2.3767, -4.55607, -14.3135, -14.2001, 9.84839, 3.69933, -3.38306, -7.60063, -0.236772, 0.988399, -0.549176, 6.61959, 4.69712, -5.34606, -12.2294, -12.6537]
[-5.63542, -6.59107, -10.2043, -5.21095, 8.68946, 0.579114, -4.67295, -6.72461, 1.55005, -2.63952, -1.83855, 2.4967, -4.3396, -9.9157, -4.6942, -3.23625, -2.3767, -4.55607, -14.3135, -14.2001, 9.84839, 3.69933, -3.38306, -7.60063, -0.236772, 0.988399, -0.549176, 6.61959, 4.69712, -5.34606, -12.2294, -12.6537]
 
[-6.27324, -6.7904, 3.10486, -1.14265, 6.38677, 3.57612, -3.90542, -4.17752, -1.36656, -0.0780159, 6.77775, 6.39118, 1.5939, 1.04175, 8.18152, 2.72047, -3.59085, -5.1028, 2.62711, -1.41586, 5.84934, 4.25817, 1.1197, 0.123976, -2.04301, -1.81806, 4.87518, 6.67182, 2.91358, 0.252558, 6.15595, 1.1159]
[-6.27324, -6.7904, 3.10486, -1.14265, 6.38677, 3.57612, -3.90542, -4.17752, -1.36656, -0.0780159, 6.77775, 6.39118, 1.5939, 1.04175, 8.18152, 2.72047, -3.59085, -5.1028, 2.62711, -1.41586, 5.84934, 4.25817, 1.1197, 0.123976, -2.04301, -1.81806, 4.87518, 6.67182, 2.91358, 0.252558, 6.15595, 1.1159]
 
[-7.29133, -8.2555, 0.985588, -1.48171, 2.4995, 4.5152, -1.1938, -2.29702, -2.34025, -2.16526, 10.2208, 7.0629, 0.552639, -0.437582, 7.18962, 2.63274, -3.25348, -4.07006, -0.883786, -3.09677, 1.1018, 2.91198, -0.0095405, 0.0123323, -2.69156, -1.30815, 3.36179, 3.26852, 3.09518, -0.166247, 6.74016, 3.20827]
[-7.29133, -8.2555, 0.985588, -1.48171, 2.4995, 4.5152, -1.1938, -2.29702, -2.34025, -2.16526, 10.2208, 7.0629, 0.552639, -0.437582, 7.18962, 2.63274, -3.25348, -4.07006, -0.883786, -3.09677, 1.1018, 2.91198, -0.0095405, 0.0123323, -2.69156, -1.30815, 3.36179, 3.26852, 3.09518, -0.166247, 6.74016, 3.20827]
 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</pre>
 
=={{header|D}}==
{{trans|Kotlin}}
<syntaxhighlight lang="d">import std.exception;
import std.random;
import std.stdio;
 
auto doubleArray(size_t size) {
double[] result;
result.length = size;
result[] = 0.0;
return result;
}
 
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 Vector {
private double[] dims;
 
this(double[] da) {
dims = da;
}
 
Vector dot(Vector rhs) {
return (this * rhs + rhs * this) * 0.5;
}
 
Vector opUnary(string op : "-")() {
return this * -1.0;
}
 
Vector opBinary(string op)(Vector rhs) {
import std.algorithm.mutation : copy;
static if (op == "+") {
auto result = doubleArray(32);
copy(dims, result);
foreach (i; 0..rhs.dims.length) {
result[i] += rhs[i];
}
return Vector(result);
} else if (op == "*") {
auto result = doubleArray(32);
foreach (i; 0..dims.length) {
if (dims[i] != 0.0) {
foreach (j; 0..dims.length) {
if (rhs[j] != 0.0) {
auto s = reorderingSign(i, j) * dims[i] * rhs[j];
auto k = i ^ j;
result[k] += s;
}
}
}
}
return Vector(result);
} else {
assert(false);
}
}
 
Vector opBinary(string op : "*")(double scale) {
auto result = dims.dup;
foreach (i; 0..5) {
dims[i] = dims[i] * scale;
}
return Vector(result);
}
 
double opIndex(size_t i) {
return dims[i];
}
 
void opIndexAssign(double value, size_t i) {
dims[i] = value;
}
}
 
Vector e(int n) {
enforce(n <= 4, "n must be less than 5");
 
auto result = Vector(doubleArray(32));
result[1 << n] = 1.0;
return result;
}
 
Vector randomVector() {
auto result = Vector(doubleArray(32));
foreach (i; 0..5) {
result = result + Vector([uniform01()]) * e(i);
}
return result;
}
 
Vector randomMultiVector() {
auto result = Vector(doubleArray(32));
foreach (i; 0..32) {
result[i] = uniform01();
}
return result;
}
 
void main() {
foreach (i; 0..5) {
foreach (j; 0..5) {
if (i < j) {
if ((e(i).dot(e(j)))[0] != 0.0) {
writeln("Unexpected non-null scalar product.");
return;
} else if (i == j) {
if ((e(i).dot(e(j)))[0] == 0.0) {
writeln("Unexpected null scalar product.");
}
}
}
}
}
 
auto a = randomMultiVector();
auto b = randomMultiVector();
auto c = randomMultiVector();
auto x = randomVector();
 
// (ab)c == a(bc)
writeln((a * b) * c);
writeln(a * (b * c));
writeln;
 
// a(b+c) == ab + ac
writeln(a * (b + c));
writeln(a * b + a * c);
writeln;
 
// (a+b)c == ac + bc
writeln((a + b) * c);
writeln(a * c + b * c);
writeln;
 
// x^2 is real
writeln(x * x);
}</syntaxhighlight>
{{out}}
<pre>Vector([-4.60357, -1.66951, 0.230125, -4.36372, 11.0032, 7.21226, -1.5373, -6.44947, -5.07115, -1.63098, 2.90828, 7.1582, -15.5565, -1.31705, 1.3186, -1.07552, -4.04055, -2.16556, -4.41229, 0.323326, 5.03127, -1.36494, -0.915379, -6.86147, -5.87756, -4.31528, 12.4005, 15.6349, -9.54983, -1.08376, 3.60886, 4.17844])
Vector([-4.60357, -1.66951, 0.230125, -4.36372, 11.0032, 7.21226, -1.5373, -6.44947, -5.07115, -1.63098, 2.90828, 7.1582, -15.5565, -1.31705, 1.3186, -1.07552, -4.04055, -2.16556, -4.41229, 0.323326, 5.03127, -1.36494, -0.915379, -6.86147, -5.87756, -4.31528, 12.4005, 15.6349, -9.54983, -1.08376, 3.60886, 4.17844])
 
Vector([-3.70178, 0.430038, -3.1952, -0.878759, 2.91374, 4.86224, 3.52303, 1.66396, -0.847575, -2.11591, 1.3121, 4.42268, -3.80298, -0.773252, 5.63781, 4.70647, -2.50968, 0.196386, -1.51296, 1.92306, 2.38331, 3.00232, 4.1991, -0.254381, 0.112317, 1.53895, 2.74983, 7.70699, 0.00697711, 0.785638, 7.04352, 3.94291])
Vector([-3.70178, 0.430038, -3.1952, -0.878759, 2.91374, 4.86224, 3.52303, 1.66396, -0.847575, -2.11591, 1.3121, 4.42268, -3.80298, -0.773252, 5.63781, 4.70647, -2.50968, 0.196386, -1.51296, 1.92306, 2.38331, 3.00232, 4.1991, -0.254381, 0.112317, 1.53895, 2.74983, 7.70699, 0.00697711, 0.785638, 7.04352, 3.94291])
 
Vector([-4.49501, 0.40722, -3.84594, -0.429832, 6.94562, 7.06166, 1.99871, 2.27987, 0.153668, 0.16586, 1.44596, 3.74806, -3.1458, -2.35553, 3.87377, 7.18143, -2.17737, 0.987571, -1.47633, 3.38, 2.24917, 2.68417, 1.81881, 0.886526, 1.28089, 1.63795, 7.06364, 8.61935, 2.78735, -0.226174, 3.83569, 2.1715])
Vector([-4.49501, 0.40722, -3.84594, -0.429832, 6.94562, 7.06166, 1.99871, 2.27987, 0.153668, 0.16586, 1.44596, 3.74806, -3.1458, -2.35553, 3.87377, 7.18143, -2.17737, 0.987571, -1.47633, 3.38, 2.24917, 2.68417, 1.81881, 0.886526, 1.28089, 1.63795, 7.06364, 8.61935, 2.78735, -0.226174, 3.83569, 2.1715])
 
Vector([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])</pre>
 
=={{header|EchoLisp}}==
We build a CGA based upon a generationggenerating quadratic form in R^n. The implementation is general enough, that is ei*ei = +/- 1 , and not restricted to 1. The 5 dimension limit comes from the use of 32 bits numbers to generate all permutations 101... , but this could be improved. The multi-vector multiplication is based on a multiplication table 2^n * 2^n , generated once for all.
 
<langsyntaxhighlight lang="scheme">
(define e-bits (build-vector 32 (lambda(i) (arithmetic-shift 1 i)))) ;; 1,2,4,..
(define (e-index i) ;; index of ei in native vector
Line 155 ⟶ 715:
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
;; we use indices (1 ... n) in conformity with the Wikipedia reference
 
Line 207 ⟶ 767:
(• II J K) → -1*1
 
</syntaxhighlight>
</lang>
Multiplication table for A(3 0)
 
Line 259 ⟶ 819:
<br> <b>e</b>1<b>e</b>2<b>e</b>3 * <b>e</b>1<b>e</b>3 = <b>e</b>2
<br> <b>e</b>1<b>e</b>2<b>e</b>3 * <b>e</b>2<b>e</b>3 = - <b>e</b>1
<br> <b>e</b>1<b>e</b>2<b>e</b>3 * <b>e</b>1<b>e</b>2<b>e</b>3 = - <b>1</b>
 
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">Type Vector
dims(31) As Single
End Type
 
Function bitCount(i As Integer) As Integer
i = i - ((i Shr 1) And &h55555555)
i = (i And &h33333333) + ((i Shr 2) And &h33333333)
i = (i + (i Shr 4)) And &h0f0f0f0f
i = i + (i Shr 8)
i = i + (i Shr 16)
Return i And &h0000003F
End Function
 
Function ReorderingSign(i As Integer, j As Integer) As Integer
Dim As Integer k = i Shr 1
Dim As Integer sum = 0
While (k <> 0)
sum += bitCount(k And j)
k Shr= 1
Wend
Return Iif((sum And 1) = 0, 1, -1)
End Function
 
Function dot(lhs As Vector, rhs As Vector) As Vector
Dim result As Vector
For i As Integer = 0 To 31
result.dims(i) = 0.5 * (lhs.dims(i) * rhs.dims(i) + rhs.dims(i) * lhs.dims(i))
Next i
Return result
End Function
 
Function addition(lhs As Vector, rhs As Vector) As Vector
Dim result As Vector
For i As Integer = 0 To 31
result.dims(i) = lhs.dims(i) + rhs.dims(i)
Next i
Return result
End Function
 
Function multiply(lhs As Vector, rhs As Vector) As Vector
Dim result As Vector
Dim As Single s
Dim As Integer i, j, k
For i = 0 To 31
If lhs.dims(i) <> 0 Then
For j = 0 To 31
If rhs.dims(j) <> 0 Then
s = ReorderingSign(i, j) * lhs.dims(i) * rhs.dims(j)
k = i Xor j
result.dims(k) += s
End If
Next j
End If
Next i
Return result
End Function
 
Function multiplyScalar(lhs As Vector, rhs As Single) As Vector
Dim result As Vector
For i As Integer = 0 To 31
result.dims(i) = lhs.dims(i) * rhs
Next i
Return result
End Function
 
Function e(n As Integer) As Vector
If n > 4 Then Print "n must be less than 5": End
Dim result As Vector
result.dims(1 Shl n) = 1
Return result
End Function
 
Function randomVector() As Vector
Dim result As Vector
For i As Integer = 0 To 4
result = addition(result, multiplyScalar(e(i), Rnd))
Next i
Return result
End Function
 
Function randomMultiVector() As Vector
Dim result As Vector
For i As Integer = 0 To 31
result.dims(i) = Rnd
Next i
Return result
End Function
 
Randomize Timer
Dim a As Vector = randomMultiVector()
Dim b As Vector = randomMultiVector()
Dim c As Vector = randomMultiVector()
Dim x As Vector = randomVector()
 
' (ab)c == a(bc)
Print (multiply(multiply(a, b), c).dims(0))
Print (multiply(a, multiply(b, c)).dims(0))
Print
 
' a(b+c) == ab + ac
Print (multiply(a, addition(b, c)).dims(0))
Print (addition(multiply(a, b), multiply(a, c)).dims(0))
Print
 
' (a+b)c == ac + bc
Print (multiply(addition(a, b), c).dims(0))
Print (addition(multiply(a, c), multiply(b, c)).dims(0))
Print
 
' x^2 is real
Print (multiply(x, x).dims(0))
 
Sleep</syntaxhighlight>
 
=={{header|Go}}==
{{trans|JavaScript}}
<syntaxhighlight lang="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()
 
// (ab)c == a(bc)
fmt.Println(mul(mul(a, b), c))
fmt.Println(mul(a, mul(b, c)))
 
// a(b + c) == ab + ac
fmt.Println(mul(a, add(b, c)))
fmt.Println(add(mul(a, b), mul(a, c)))
 
// (a + b)c == ac + bc
fmt.Println(mul(add(a, b), c))
fmt.Println(add(mul(a, c), mul(b, c)))
 
// x² is real
fmt.Println(mul(x, x))
}</syntaxhighlight>
 
{{out}}
Sample output:
<pre>
[1.6282881498413662 0.2490818261523896 -0.8936755921478269 -1.555477163901491 6.47589688756284 8.705633181089887 -1.28416798750558 -3.0984267307080446 -14.384954438859133 -13.511137120485879 6.071767421804147 1.099627765550034 -0.40641746354718655 -3.3593459129408076 -2.8089033176352967 -3.003641914720827 4.223517526463662 5.7807271315990185 -4.921271185053852 -5.698203073886508 -0.5449956221104395 3.2199941835007997 -0.4168598688210261 -1.6164380014352773 -13.447900615475964 -11.892642419707807 5.484071302025009 2.781324432176212 5.237445180167182 0.4643791234551212 -7.986755945938485 -2.9272187129576714]
[1.628288149841367 0.24908182615239083 -0.8936755921478254 -1.5554771639014895 6.475896887562836 8.705633181089889 -1.2841679875055805 -3.0984267307080433 -14.384954438859129 -13.51113712048588 6.071767421804145 1.099627765550032 -0.40641746354718755 -3.359345912940806 -2.8089033176352958 -3.003641914720825 4.223517526463663 5.7807271315990185 -4.921271185053855 -5.698203073886506 -0.5449956221104393 3.2199941835008032 -0.4168598688210253 -1.6164380014352775 -13.44790061547596 -11.89264241970781 5.484071302025003 2.781324432176209 5.237445180167183 0.464379123455121 -7.986755945938484 -2.9272187129576706]
[-4.652496095413123 -6.651741805769786 -0.18044192849719706 -1.118756694503706 -1.4545868044605725 0.10199724090664991 0.5018587820915257 2.3004721822960024 -1.813996268087529 0.38357415506855985 7.882236705126414 4.377167004918281 0.338317137066833 1.0631923204534859 5.08861779773926 4.611434580371178 -5.277764644396049 -7.961720991272197 -1.27063408303169 -1.2002120748969933 -0.3251154212726659 2.005000622005424 1.0505371909084391 1.9822320823801767 -2.271503682913346 -0.2403902213900877 6.6269980604812275 4.006018365857085 -0.15074367863748028 -0.48557428903338595 5.291057793190274 2.7751733146879394]
[-4.652496095413124 -6.651741805769786 -0.18044192849719662 -1.1187566945037064 -1.454586804460573 0.10199724090665008 0.5018587820915265 2.3004721822960037 -1.8139962680875295 0.38357415506856163 7.882236705126415 4.377167004918281 0.338317137066834 1.0631923204534859 5.088617797739261 4.611434580371178 -5.277764644396049 -7.9617209912721965 -1.2706340830316898 -1.200212074896994 -0.3251154212726654 2.0050006220054257 1.050537190908438 1.9822320823801762 -2.2715036829133437 -0.24039022139008648 6.626998060481226 4.006018365857084 -0.15074367863747984 -0.4855742890333855 5.291057793190275 2.7751733146879403]
[-4.682894668443622 -7.686899263290272 -0.2500585680601418 -0.8779897639638435 2.579501108403806 2.901924320921563 -0.4542430696469483 1.0374201754917136 -2.588607371991848 -3.229485794697976 7.444924967244714 4.93089687101153 -2.0124785310408284 0.46939350205418884 6.568153651157447 5.710192967946121 -1.41530169954937 -4.536345225213684 0.5240731948596796 1.5123734256564463 1.767786974613905 2.9960861930917018 0.969306657461082 1.036924529835111 -1.456640437477983 -1.3085896429723467 2.9678738261068895 1.3051596528834055 -3.8197616441989037 -1.3030506523824616 4.7818448875243895 4.122121121578954]
[-4.682894668443622 -7.686899263290271 -0.2500585680601421 -0.877989763963844 2.5795011084038055 2.9019243209215633 -0.4542430696469487 1.0374201754917127 -2.5886073719918494 -3.2294857946979736 7.444924967244715 4.93089687101153 -2.0124785310408275 0.46939350205418884 6.568153651157447 5.710192967946121 -1.415301699549369 -4.536345225213685 0.5240731948596802 1.512373425656447 1.7677869746139057 2.9960861930917013 0.9693066574610807 1.036924529835109 -1.456640437477983 -1.3085896429723465 2.9678738261068895 1.305159652883405 -3.819761644198904 -1.3030506523824616 4.781844887524388 4.122121121578957]
[2.1206022437357284 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
</pre>
 
=={{header|J}}==
Line 267 ⟶ 1,086:
Implementation:
 
<langsyntaxhighlight Jlang="j">NB. indices are signed machine integers
vzero=: 1 $.2^31+IF64*32
odim=. 2^.#vzero
Line 300 ⟶ 1,119:
 
obasis=:1 (2^i.odim)ndx01 vzero
e=: {&obasis</langsyntaxhighlight>
 
Explanation:
Line 321 ⟶ 1,140:
 
Where we have more than one non-zero value pair contributing to the same product index we sum those values. (Of course, this would apply to value pairs whose result is zero, but since typically there's something approaching 85070591730234615847396907784232501249 of those, we don't actually compute all those zeros...)
 
[It's unclear whether there are other ways of satisfying all of the task requirements. No other approach seems simpler, at least...]
 
Task examples:
 
<langsyntaxhighlight Jlang="j"> NB. test arbitrary vector being real (and having the specified result)
clean gmul~ +/ (e 0 1 2 3 4) gmul 1 _1 2 3 _2 (0 ndx01) vzero
0 │ 19
Line 369 ⟶ 1,186:
I gmul J+K
10 │ 1
12 │ _1</langsyntaxhighlight>
 
Note that sparse arrays display as <code>indices | value</code> for elements which are not the default element (0).
 
So, for example in the part where we check for orthogonality, we are forming a 5 by 5 by 9223372036854775807 array. The first two dimensions correspond to arguments to <code>e</code> and the final dimension is the multivector dimension. A <code>0</code> in the multivector dimension means that that's the "real" or "scalar" part of the multivector. And, since the pair of dimensions for the <code>e</code> arguments whose "dot" product are <code>1</code> are identical, we know we have an [[wp:Identity_matrix|identity matrix]].
 
=={{header|Java}}==
{{trans|Kotlin}}
<syntaxhighlight lang="java">import java.util.Arrays;
import java.util.Random;
 
public class GeometricAlgebra {
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 = k >> 1;
}
return ((sum & 1) == 0) ? 1.0 : -1.0;
}
 
static class Vector {
private double[] dims;
 
public Vector(double[] dims) {
this.dims = dims;
}
 
public Vector dot(Vector rhs) {
return times(rhs).plus(rhs.times(this)).times(0.5);
}
 
public Vector unaryMinus() {
return times(-1.0);
}
 
public Vector plus(Vector rhs) {
double[] result = Arrays.copyOf(dims, 32);
for (int i = 0; i < rhs.dims.length; ++i) {
result[i] += rhs.get(i);
}
return new Vector(result);
}
 
public Vector times(Vector rhs) {
double[] result = new double[32];
for (int i = 0; i < dims.length; ++i) {
if (dims[i] != 0.0) {
for (int j = 0; j < rhs.dims.length; ++j) {
if (rhs.get(j) != 0.0) {
double s = reorderingSign(i, j) * dims[i] * rhs.dims[j];
int k = i ^ j;
result[k] += s;
}
}
}
}
return new Vector(result);
}
 
public Vector times(double scale) {
double[] result = dims.clone();
for (int i = 0; i < 5; ++i) {
dims[i] *= scale;
}
return new Vector(result);
}
 
double get(int index) {
return dims[index];
}
 
void set(int index, double value) {
dims[index] = value;
}
 
@Override
public String toString() {
StringBuilder sb = new StringBuilder("(");
boolean first = true;
for (double value : dims) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(value);
}
return sb.append(")").toString();
}
}
 
private static Vector e(int n) {
if (n > 4) {
throw new IllegalArgumentException("n must be less than 5");
}
Vector result = new Vector(new double[32]);
result.set(1 << n, 1.0);
return result;
}
 
private static final Random rand = new Random();
 
private static Vector randomVector() {
Vector result = new Vector(new double[32]);
for (int i = 0; i < 5; ++i) {
Vector temp = new Vector(new double[]{rand.nextDouble()});
result = result.plus(temp.times(e(i)));
}
return result;
}
 
private static Vector randomMultiVector() {
Vector result = new Vector(new double[32]);
for (int i = 0; i < 32; ++i) {
result.set(i, rand.nextDouble());
}
return result;
}
 
public static void main(String[] args) {
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (i < j) {
if (e(i).dot(e(j)).get(0) != 0.0) {
System.out.println("Unexpected non-null scalar product.");
return;
}
}
}
}
 
Vector a = randomMultiVector();
Vector b = randomMultiVector();
Vector c = randomMultiVector();
Vector x = randomVector();
 
// (ab)c == a(bc)
System.out.println(a.times(b).times(c));
System.out.println(a.times(b.times(c)));
System.out.println();
 
// a(b+c) == ab + ac
System.out.println(a.times(b.plus(c)));
System.out.println(a.times(b).plus(a.times(c)));
System.out.println();
 
// (a+b)c == ac + bc
System.out.println(a.plus(b).times(c));
System.out.println(a.times(c).plus(b.times(c)));
System.out.println();
 
// x^2 is real
System.out.println(x.times(x));
}
}</syntaxhighlight>
{{out}}
<pre>(-14.826385115483191, -10.223187918212313, -15.02996653452487, -14.46670632198489, 9.367877413249497, 16.476783705852135, -15.946557036515442, -6.398255774639048, 1.5560496352407314, -7.135570742872677, -3.926278194944716, 4.7948511296793646, -8.132546330778185, -6.8139397609050025, -4.203632573891533, -0.5216302370612196, -11.240590807272154, -4.724378457579242, -16.477497153082254, -16.781194046381223, 3.715894934067395, 14.220125782905383, -12.846081825616357, -2.8313637859206557, 3.149468439469149, -5.163082715280577, -7.174869565605504, -3.34527279512389, -11.232806169860876, -9.975821980348016, -3.7795503524017735, -1.0610782061627755)
(-14.826385115483196, -10.223187918212307, -15.029966534524872, -14.46670632198489, 9.367877413249495, 16.476783705852135, -15.946557036515443, -6.398255774639046, 1.5560496352407327, -7.135570742872677, -3.92627819494472, 4.794851129679368, -8.132546330778192, -6.813939760904995, -4.203632573891537, -0.5216302370612151, -11.240590807272161, -4.724378457579236, -16.477497153082247, -16.781194046381223, 3.7158949340673937, 14.220125782905386, -12.846081825616348, -2.831363785920656, 3.1494684394691537, -5.163082715280574, -7.174869565605505, -3.3452727951238828, -11.232806169860877, -9.975821980348009, -3.7795503524017757, -1.0610782061627715)
 
(-6.53148126676475, -3.686197874035778, -0.7257324996849555, 4.278415831115293, 6.812402569345597, 1.3919745454991994, -2.3737314163466, -2.534117136854738, -0.02773680252709232, -2.959894343894277, 9.079951306324414, 3.5445539013571175, 4.855317638943012, 2.7949884209613094, 3.4702307051832215, 5.9614310877021195, -6.273887650229915, -3.3318300067614355, 2.5996846757588705, 5.753030636602611, 8.66307309332676, 4.103168227184037, -2.0758275707527396, -0.7429391125916148, -1.7949737037366886, -2.709591610956401, 10.9623759848287, 5.951981557918796, 5.367767313008209, 1.288037481749198, 4.141675073009981, 7.643531800306178)
(-6.5314812667647475, -3.686197874035778, -0.7257324996849563, 4.278415831115293, 6.812402569345599, 1.3919745454991996, -2.3737314163465992, -2.5341171368547366, -0.02773680252709232, -2.9598943438942764, 9.079951306324414, 3.54455390135712, 4.8553176389430135, 2.7949884209613103, 3.470230705183222, 5.96143108770212, -6.273887650229915, -3.3318300067614346, 2.5996846757588723, 5.753030636602611, 8.66307309332676, 4.103168227184039, -2.075827570752741, -0.742939112591615, -1.7949737037366884, -2.7095916109564, 10.9623759848287, 5.951981557918795, 5.367767313008202, 1.2880374817491977, 4.141675073009981, 7.64353180030618)
 
(-7.736834353560962, -2.502599400656683, -1.3572044140931654, 0.08823728154205668, 6.035469456565145, -0.12760675585521175, 1.6863493427502443, 0.3572366658217211, -0.5993428822081044, -1.9667973240788488, 9.136744013591118, 5.590676320343252, 5.026876608331699, 2.930873432370117, 3.3588635932299327, 7.0096288327820115, -9.169529600001841, -2.648288994190627, 1.0293696456484516, 1.403189013821808, 6.487492648530549, 2.70613886829337, -0.1101834481621051, 0.9130516717900701, -1.5135624840660704, -0.03875540986063708, 7.7402678101288025, 3.7385632770106736, 2.9147287828638784, -1.2493549934763781, 2.9769191225149667, 7.2051875611073894)
(-7.736834353560959, -2.502599400656682, -1.357204414093165, 0.08823728154205956, 6.035469456565146, -0.12760675585521244, 1.686349342750246, 0.35723666582172275, -0.5993428822081048, -1.9667973240788483, 9.136744013591116, 5.590676320343253, 5.026876608331699, 2.9308734323701158, 3.358863593229933, 7.009628832782012, -9.169529600001841, -2.648288994190626, 1.0293696456484527, 1.4031890138218066, 6.487492648530545, 2.7061388682933707, -0.11018344816210468, 0.9130516717900696, -1.5135624840660693, -0.038755409860637524, 7.7402678101288025, 3.738563277010674, 2.914728782863878, -1.249354993476379, 2.976919122514966, 7.205187561107389)
 
(1.9374102817883092, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)</pre>
 
=={{header|javascript}}==
<langsyntaxhighlight lang="javascript">var CGAGA = function () {
// parts of this comes from https://github.com/weshoke/versor.js/
function e(n) {
var result = [];
result[1 << n] = 1;
return result;
}
function cdot(a, b) { return CGA.mul([0.5], CGA.add(CGA.mul(a, b), CGA.mul(b, a))) }
function neg(x) { return multiplymul([-1], x) }
function bitCount(i) {
// Note that unsigned shifting (>>>) is not required.
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;
}
function reorderingSign(a, b) {
a >>= 1;
var sum = 0;
while (a != 0) {
sum += bitCount(a & b);
a >>= 1;
}
}
return (sum & 1) == 0 ? 1 : -1;
}
function add(a, b) {
var result = a.slice(0);
for (var i in b) {
if (result[i]) {
result[i] += b[i];
} else {
result[i] = b[i];
}
}
}
return result;
}
function multiplymul(a, b)
{
var result = [];
for (var i in a) {
if (a[i]) {
for (var j in b) {
if (b[j]) {
var s = reorderingSign(i, j) * a[i] * b[j];
// if (i == 1 && j == 1) { s *= -1 } // e0*e0 == -1
var k = i ^ j;
if (result[k]) {
result[k] += s;
} else {
result[k] = s;
}
}
}
}
}
}
}
}
return result;
}
return {
e : e,
cdot : cdot,
neg : neg,
add : add,
mul : multiplymul
};
}();</lang>
</syntaxhighlight>
 
And then, from the console:
 
<langsyntaxhighlight lang="javascript">var e = CGAGA.e, cdot = GA.cdot;
function cdot(a, b) { return CGA.mul([0.5], CGA.add(CGA.mul(a, b), CGA.mul(b, a))) }
for (var i = 0; i < 5; i++) {
 
for (var ij = 0; ij < 45; ij++) {
for (var j = 0; j < 4; j++) {
if (i < j) {
if (cdot(e(i), e(j))[0]) { console.log("unexpected non-nul scalar product"); }
Line 459 ⟶ 1,447:
}
 
function randomVector() {
var v = e(0);
var result = [];
v = CGA.add(v, CGA.mul([-1], e(1)));
v for (var i = 0; i < 5; i++) { result = CGAGA.add(v result, CGAGA.mul([2Math.random()], e(2i))); }
return result;
v = CGA.add(v, CGA.mul([3], e(3)));
}
v = CGA.add(v, CGA.mul([-2], e(4)));
function randomMultiVector() {
var result = [];
for (var i = 0; i < 32; i++) { result[i] = Math.random(); }
return result;
}
 
var a = randomMultiVector(), b = randomMultiVector(), c = randomMultiVector();
console.log(CGA.mul(v, v)); // [19, 3: 0, 5: 0, 6: 0, 9: 0, 10: 0, 12: 0, 17: 0, 18: 0, 20: 0, 24: 0]
var x = randomVector();
 
// (ab)c == a(bc)
var i = CGA.mul(e(0), e(1));
var j = CGAconsole.log(GA.mul(eGA.mul(1a, b), e(2c));
var k = CGAconsole.log(GA.mul(e(0)a, eGA.mul(2b, c)));
console.log(CGA.mul(i, i)); // [-1]
console.log(CGA.mul(j, j)); // [-1]
console.log(CGA.mul(k, k)); // [-1]
console.log(CGA.mul(CGA.mul(i, j), k)); // [-1]
var I = CGA.mul(e(1), e(2));
var J = CGA.mul(e(2), e(3));
var K = CGA.mul(e(1), e(3));
console.log(CGA.mul(I, I)); // [-1]
console.log(CGA.mul(J, J)); // [-1]
console.log(CGA.mul(K, K)); // [-1]
console.log(CGA.mul(CGA.mul(I, J), K)); // [-1]</lang>
 
// a(b + c) == ab + ac
=={{header|Perl 6}}==
console.log(GA.mul(a, GA.add(b, c)));
console.log(GA.add(GA.mul(a,b), GA.mul(a, c)));
 
// (a + b)c == ac + bc
<lang perl6>unit class MultiVector;
console.log(GA.mul(GA.add(a, b), c));
has Real %.blades{UInt};
console.log(GA.add(GA.mul(a,c), GA.mul(b, c)));
method clean { for %!blades { %!blades{.key} :delete unless .value; } }
 
method narrow {
// x² is real
for %!blades { return self if .key > 0 && .value !== 0; }
console.log(GA.mul(x, x));</syntaxhighlight>
return %!blades{0} // 0;
{{out}}
<pre>[-7.834854130554672, -10.179405417124476, 5.696414143584243, -1.4014556169803851, 12.334288331422336, 11.690738709598888, -0.4279888274147221, 6.226618790084965, -10.904144874917206, -5.46919448234424, -5.647472225071031, -2.9801969751721744, -8.284532508545746, -3.3280413654836494, -2.2182526412098493, 0.4191036292473347, 3.0485450100607103, -0.20619687045226742, 2.1369938048939527, 3.730913391951158, 10.929856967963905, 8.301187183717643, -4.874133827873075, 0.7918650606624789, -8.520661635525103, -7.732342981599732, -6.494750491582618, -2.458749173402162, 3.573788336699224, 2.784339193089742, -1.6479372032388944, -0.35120747879544256]
[-7.83485413055467, -10.179405417124475, 5.696414143584248, -1.4014556169803827, 12.334288331422337, 11.690738709598893, -0.4279888274147213, 6.226618790084964, -10.90414487491721, -5.46919448234424, -5.647472225071032, -2.9801969751721726, -8.284532508545746, -3.3280413654836507, -2.218252641209847, 0.41910362924733874, 3.048545010060707, -0.20619687045226748, 2.136993804893955, 3.7309133919511575, 10.929856967963904, 8.301187183717648, -4.8741338278730755, 0.7918650606624811, -8.520661635525107, -7.732342981599734, -6.494750491582625, -2.45874917340216, 3.5737883366992262, 2.7843391930897443, -1.6479372032388935, -0.351207478795442]
[-4.5157935996060425, -3.9762419076273514, -2.653425845411889, -1.2899302330562412, 6.161562884801266, 3.664812215240675, -0.4471521091019873, 2.39303455739218, -1.6486347268701103, 1.156714478904937, 4.5859158357958965, 6.879356425817299, 1.3341425863947358, 5.641350122882839, 6.378155334673649, 6.466962714879142, -3.645688408496504, -1.9659188980662032, 1.3062519818876646, 1.7973392350972788, 2.4770203476100843, 1.258017836002405, 1.3794942194985413, 3.993871627961031, -3.3620439843097127, -0.4228490927003264, 0.27245046364398495, 3.813642689561589, 2.6785051915908604, 5.409359105713415, 2.9578168177883555, 4.425426168284635]
[-4.515793599606042, -3.976241907627351, -2.653425845411889, -1.2899302330562417, 6.161562884801263, 3.664812215240676, -0.44715210910198766, 2.393034557392179, -1.6486347268701103, 1.156714478904937, 4.585915835795897, 6.8793564258172974, 1.3341425863947352, 5.641350122882839, 6.378155334673649, 6.466962714879143, -3.645688408496502, -1.9659188980662032, 1.3062519818876661, 1.7973392350972783, 2.4770203476100843, 1.258017836002407, 1.379494219498544, 3.99387162796103, -3.3620439843097127, -0.42284909270032545, 0.2724504636439853, 3.8136426895615894, 2.67850519159086, 5.409359105713415, 2.9578168177883555, 4.425426168284636]
[-5.8903316026132755, -6.619647679486295, -1.8140191326116537, -2.519531799741982, 6.604158362571294, 6.352401943423508, 0.9412086471616096, 3.719341486246096, -2.209111542028446, 1.9980997124233557, 5.717878641652222, 7.351597777237362, -2.9037939632499974, 1.497897713658653, 6.811544238648882, 5.861907187665564, -3.2638975880372363, -2.2659714695119115, 1.227221599808634, 0.8343365341022846, 2.72461491531054, 2.728833585944902, 2.226404227376565, 3.888097816250177, 0.35867175462798684, 2.3965356477571302, -1.7151608532791172, 1.403673323043394, -2.1441532262277607, 2.5435142440445646, 2.00110597707534, 1.9825972651495558]
[-5.8903316026132755, -6.6196476794862935, -1.8140191326116533, -2.5195317997419817, 6.604158362571292, 6.352401943423505, 0.9412086471616091, 3.719341486246094, -2.209111542028446, 1.9980997124233555, 5.71787864165222, 7.351597777237364, -2.9037939632499974, 1.4978977136586529, 6.81154423864888, 5.861907187665565, -3.263897588037235, -2.2659714695119124, 1.2272215998086353, 0.8343365341022843, 2.72461491531054, 2.7288335859449018, 2.226404227376565, 3.8880978162501783, 0.3586717546279864, 2.396535647757131, -1.715160853279117, 1.4036733230433938, -2.1441532262277603, 2.543514244044564, 2.0011059770753405, 1.9825972651495565]
[3.193752260485546, 3: 0, 5: 0, 6: 0, 9: 0, 10: 0, 12: 0, 17: 0, 18: 0, 20: 0, 24: 0]</pre>
 
=={{header|Jsish}}==
From Javascript.
 
<syntaxhighlight lang="javascript">/* Geometric Algebra, in Jsih */
 
var GA = function () {
function e(n) {
var result = [];
result[1 << n] = 1;
return result;
}
function cdot(a, b) { return mul([0.5], add(mul(a, b), mul(b, a))); }
function neg(x) { return mul([-1], x); }
function bitCount(i) {
// Note that unsigned shifting (>>>) is not required.
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;
}
function reorderingSign(a, b) {
a >>= 1;
var sum = 0;
while (a != 0) {
sum += bitCount(a & b);
a >>= 1;
}
return (sum & 1) == 0 ? 1 : -1;
}
function add(a, b) {
var result = a.slice(0);
for (var i in b) {
if (result[i]) result[i] += b[i]; else result[i] = b[i];
}
return result;
}
function mul(a, b) {
var result = [];
for (var i in a) {
if (a[i]) {
for (var j in b) {
if (b[j]) {
var s = reorderingSign(i, j) * a[i] * b[j];
// if (i == 1 && j == 1) { s *= -1 } // e0*e0 == -1
var k = i ^ j;
if (result[k]) result[k] += s; else result[k] = s;
}
}
}
}
for (var i = 0; i < result.length; i++) result[i] = (result[i]) ? result[i] : 0;
return result;
}
 
return {
e:e,
cdot:cdot,
neg:neg,
add:add,
mul:mul
};
}();
 
if (Interp.conf('unitTest')) {
var e = GA.e, cdot = GA.cdot;
 
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
if (i < j) {
if (cdot(e(i), e(j))[0]) { console.log("unexpected non-nul scalar product"); }
} else if (i === j) {
if (!cdot(e(i), e(j))[0]) { console.log("unexpected nul scalar product"); }
}
}
}
 
function randomVector() {
var result = new Array(32).fill(0);
for (var i = 0; i < 5; i++) { result = GA.add( result, GA.mul([Math.random()], e(i))); }
return result;
}
function randomMultiVector() {
var result = new Array(32).fill(0);
for (var i = 0; i < 32; i++) { result[i] = Math.random(); }
return result;
}
 
Math.srand(0);
var a = randomMultiVector(), b = randomMultiVector(), c = randomMultiVector();
var x = randomVector();
 
; a;
; b;
; c;
 
// (ab)c == a(bc)
; GA.mul(GA.mul(a, b), c);
; GA.mul(a, GA.mul(b, c));
 
// a(b + c) == ab + ac
; GA.mul(a, GA.add(b, c));
; GA.add(GA.mul(a,b), GA.mul(a, c));
 
// (a + b)c == ac + bc
; GA.mul(GA.add(a, b), c);
; GA.add(GA.mul(a,c), GA.mul(b, c));
 
 
// x² is real
; x;
; GA.mul(x, x);
}
 
/*
sub e(UInt $n?) returns MultiVector is export {
=!EXPECTSTART!=
$n.defined ?? MultiVector.new(:blades(my Real %{UInt} = (1 +< $n) => 1)) !! MultiVector.new
a ==> [ 0.1708280361062897, 0.7499019804849638, 0.09637165562356742, 0.8704652270270756, 0.5773035067951078, 0.7857992588396741, 0.6921941534586402, 0.3687662699204211, 0.8739040768618089, 0.7450950984500651, 0.4460459090931117, 0.3537282030933753, 0.7325196320025391, 0.2602220010828802, 0.3942937749238773, 0.7767899512256164, 0.845035137580286, 0.5757882004827763, 0.7155385951686632, 0.08300424607387669, 0.4558251286597574, 0.1099468141806454, 0.5452280238165734, 0.3906865706486755, 0.5685854232144472, 0.9590664494883754, 0.8677190964591368, 0.1631895102523586, 0.2755089268683157, 0.2603610948720672, 0.9240947418691654, 0.435922637102685 ]
b ==> [ 0.7894608655520905, 0.1276170168117403, 0.08220568604043521, 0.9406420164478462, 0.02557492625301805, 0.1542109313278246, 0.382182425278156, 0.1547366996666923, 0.5293334181169804, 0.8768484910832512, 0.4306114383383992, 0.2639062263420797, 0.313594499023214, 0.7700916858547231, 0.107390883054105, 0.7710422551956455, 0.7051955588944487, 0.2186396587077581, 0.7617939928559956, 0.4117130455789564, 0.648826822929113, 0.929956254907367, 0.5024185655986706, 0.6874406794288674, 0.4360909481473279, 0.6083009079497401, 0.5765586336353685, 0.6326217107140693, 0.4634256476287426, 0.6322437896100865, 0.1382949326493268, 0.9607614179251911 ]
c ==> [ 0.1443750010878411, 0.4466830710677812, 0.3245844598453793, 0.9525840775924692, 0.358183910481177, 0.3982082224922436, 0.1012815422323818, 0.9550857356528795, 0.9846169476710749, 0.5759700814514872, 0.8659137353852593, 0.1498758912327744, 0.9091504302816595, 0.6512525086400416, 0.06386085476492198, 0.9549993865624558, 0.9662627642756583, 0.7855433852139697, 0.8051648178950011, 0.5712536797957526, 0.2825857199542448, 0.9625510519679636, 0.5794770589463063, 0.4368586269705688, 0.3754361745372741, 0.9234076091930206, 0.02869938006311301, 0.7688599777155005, 0.7231067717175854, 0.5909693498129656, 0.4258885385798372, 0.6421430590830184 ]
GA.mul(GA.mul(a, b), c) ==> [ 1.541918542712994, 4.115829300591508, 6.756686908265433, 1.237835072374462, 10.35373455425321, 15.27788368572946, -10.02377587769663, -7.963603479812443, -4.551812682204639, -2.063312081493453, 6.501355951540042, 7.264555440540969, -8.486452071298562, -4.822494555299121, -4.759231263111541, -10.77800945200822, -7.362166274344194, -4.396761648257096, -4.546442029824131, -5.48725057173969, 7.12307450722373, 12.97562340826319, -15.0237414847673, -14.51557782429663, -4.883430414017697, -4.901409415740756, 7.906069132188758, 6.734848434665599, -9.783158191139472, -6.519424552890571, -2.139880496917612, -9.858645000418766 ]
GA.mul(a, GA.mul(b, c)) ==> [ 1.541918542712995, 4.11582930059151, 6.756686908265435, 1.23783507237446, 10.35373455425321, 15.27788368572945, -10.02377587769663, -7.963603479812441, -4.551812682204639, -2.06331208149345, 6.501355951540043, 7.264555440540969, -8.486452071298562, -4.822494555299119, -4.759231263111545, -10.77800945200822, -7.362166274344201, -4.396761648257097, -4.546442029824129, -5.48725057173969, 7.12307450722373, 12.97562340826319, -15.0237414847673, -14.51557782429663, -4.883430414017695, -4.901409415740756, 7.906069132188759, 6.734848434665598, -9.783158191139472, -6.519424552890572, -2.139880496917614, -9.858645000418766 ]
GA.mul(a, GA.add(b, c)) ==> [ -4.618544334910429, -1.861355248134714, -1.344616248842651, -0.2493092523303422, 2.805076632862419, 7.011456497501809, -2.595903465496111, -2.470668530528046, 2.219481357349965, 1.819582156863502, 7.750350045338696, 7.672479893390893, -0.4578513259004232, -0.2416326854384544, 6.428349361134747, 6.656718281504274, -5.564788398161922, -3.02924871963873, -0.2716453262784845, 2.840935952141899, 0.0859121820261296, 4.694618143418901, -5.096817957116206, -0.4737762603304853, -1.385313600482476, -3.455075469132893, 6.134561343411066, 4.384932175234187, -0.6284984442281132, -1.060102630996634, 6.555893195756837, 8.364446730582344 ]
GA.add(GA.mul(a,b), GA.mul(a, c)) ==> [ -4.618544334910429, -1.861355248134714, -1.344616248842651, -0.2493092523303427, 2.805076632862418, 7.011456497501809, -2.595903465496112, -2.470668530528046, 2.219481357349964, 1.819582156863503, 7.750350045338696, 7.672479893390893, -0.4578513259004234, -0.2416326854384541, 6.42834936113475, 6.656718281504276, -5.564788398161921, -3.029248719638729, -0.2716453262784859, 2.840935952141899, 0.08591218202612916, 4.6946181434189, -5.096817957116205, -0.4737762603304851, -1.385313600482476, -3.455075469132893, 6.134561343411068, 4.384932175234186, -0.6284984442281131, -1.060102630996634, 6.555893195756836, 8.364446730582346 ]
GA.mul(GA.add(a, b), c) ==> [ -4.443021937525184, -3.701220635832722, -0.6818565879668145, 0.239151370235406, 3.458768472629645, 6.988109725549518, -3.684631030647005, -0.8507257226324562, 2.724894692072849, 4.331141304914477, 6.87324809064668, 5.39527557728919, -1.338732261664156, 0.5042890433991951, 3.524762387495515, 6.138868250703226, -5.595434900923999, -5.095415369801449, -2.668271896337068, 0.6569878447501574, -0.03973787332027184, 4.991106401646302, -5.122908058541086, -1.273551488694048, -2.981638879697476, -2.047004560822915, 6.135097056892218, 5.062423121634416, -1.370651481167422, -0.9463086012211376, 5.574441079445841, 8.892885715782024 ]
GA.add(GA.mul(a,c), GA.mul(b, c)) ==> [ -4.443021937525184, -3.701220635832721, -0.6818565879668153, 0.2391513702354063, 3.458768472629644, 6.988109725549519, -3.684631030647005, -0.8507257226324556, 2.724894692072848, 4.331141304914478, 6.873248090646679, 5.39527557728919, -1.338732261664156, 0.5042890433991953, 3.524762387495516, 6.138868250703224, -5.595434900923999, -5.095415369801452, -2.668271896337069, 0.6569878447501573, -0.03973787332027234, 4.991106401646301, -5.122908058541086, -1.273551488694048, -2.981638879697477, -2.047004560822915, 6.135097056892217, 5.062423121634419, -1.370651481167422, -0.946308601221137, 5.57444107944584, 8.892885715782022 ]
x ==> [ 0, 0.7467627291006274, 0.06901854981410338, 0, 0.05329494862236217, 0, 0, 0, 0.7743136455713469, 0, 0, 0, 0, 0, 0, 0, 0.7035034807394887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
GA.mul(x, x) ==> [ 1.659737254471485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
=!EXPECTEND!=
*/</syntaxhighlight>
 
{{out}}
<pre>prompt$ jsish -u geometricAlgebra.jsi
[PASS] geometricAlgebra.jsi</pre>
 
=={{header|Julia}}==
{{trans|Kotlin}}
<syntaxhighlight lang="julia">using GeometryTypes
import Base.*
 
CliffordVector = Point{32, Float64}
 
e(n) = (v = zeros(32); v[(1 << n) + 1] = 1.0; CliffordVector(v))
 
randommultivector() = CliffordVector(rand(32))
 
randomvector() = sum(i -> rand() * e(i), 0:4)
 
bitcount(n) = (count = 0; while n != 0 n &= n - 1; count += 1 end; count)
 
function reorderingsign(i, j)
ssum, i = 0, i >> 1
while i != 0
ssum += bitcount(i & j)
i >>= 1
end
return iseven(ssum) ? 1.0 : -1.0
end
 
function Base.:*(v1::CliffordVector, v2::CliffordVector)
result = zeros(32)
for (i, x1) in enumerate(v1)
if x1 != 0.0
for (j, x2) in enumerate(v2)
if x2 != 0.0
s = reorderingsign(i - 1, j - 1) * x1 * x2
k = (i - 1) ⊻ (j - 1)
result[k + 1] += s
end
end
end
end
return CliffordVector(result)
end
 
function testcliffordvector()
allorthonormal = true
for i in 0:4, j in 0:4
i < j && all(iszero, e(i) * e(j)) != 0.0 && (allorthonormal = false)
i == j && !all(iszero, e(i) * e(j)) == 0.0 && (allorthonormal = false)
end
println("e(i) * e(j) are orthonormal for i, j ϵ [0, 4]: ", allorthonormal)
a, b, c = randommultivector(), randommultivector(), randommultivector()
x = randomvector()
 
@show (a * b) * c ≈ a * (b * c)
@show a * (b + c) ≈ a * b + a * c
@show (a + b) * c ≈ a * c + b * c
 
isreal(x) = x[1] isa Real && all(iszero, x[2:end])
@show isreal(x * x)
end
 
 
testcliffordvector()
</syntaxhighlight>{{out}}
<pre>
e(i) * e(j) are orthonormal for i, j ϵ [0, 4]: true
(a * b) * c ≈ a * (b * c) = true
a * (b + c) ≈ a * b + a * c = true
(a + b) * c ≈ a * c + b * c = true
isreal(x * x) = true
</pre>
 
=={{header|Kotlin}}==
{{trans|Go}}
<syntaxhighlight lang="scala">fun bitCount(i: Int): Int {
var j = i
j -= ((j shr 1) and 0x55555555)
j = (j and 0x33333333) + ((j shr 2) and 0x33333333)
j = (j + (j shr 4)) and 0x0F0F0F0F
j += (j shr 8)
j += (j shr 16)
return j and 0x0000003F
}
 
fun reorderingSign(i: Int, j: Int): Double {
my sub order(UInt:D $i is copy, UInt:D $j) is cached {
myvar $nk = 0;i shr 1
repeatvar {sum = 0
while (k != 0) {
$i +>= 1;
sum += bitCount(k and j)
$n += [+] ($i +& $j).base(2).comb;
} until $i k == 0;k shr 1
}
return $n +& 1 ?? -1 !! 1;
return if (sum and 1 == 0) 1.0 else -1.0
}
 
class Vector(private val dims: DoubleArray) {
multi infix:<+>(MultiVector $A, MultiVector $B) returns MultiVector is export {
 
my Real %blades{UInt} = $A.blades.clone;
infix fun dot(rhs: Vector): Vector {
for $B.blades {
return (this * rhs + rhs * this) * 0.5
%blades{.key} += .value;
}
%blades{.key} :delete unless %blades{.key};
 
operator fun unaryMinus(): Vector {
return this * -1.0
}
 
operator fun plus(rhs: Vector): Vector {
val result = DoubleArray(32)
dims.copyInto(result)
for (i in 0 until rhs.dims.size) {
result[i] += rhs[i]
}
return Vector(result)
}
 
operator fun times(rhs: Vector): Vector {
val result = DoubleArray(32)
for (i in 0 until dims.size) {
if (dims[i] != 0.0) {
for (j in 0 until rhs.dims.size) {
if (rhs[j] != 0.0) {
val s = reorderingSign(i, j) * dims[i] * rhs[j]
val k = i xor j
result[k] += s
}
}
}
}
return Vector(result)
}
 
operator fun times(scale: Double): Vector {
val result = dims.clone()
for (i in 0 until 5) {
dims[i] = dims[i] * scale
}
return Vector(result)
}
 
operator fun get(index: Int): Double {
return dims[index]
}
 
operator fun set(index: Int, value: Double) {
dims[index] = value
}
 
override fun toString(): String {
val sb = StringBuilder("(")
val it = dims.iterator()
if (it.hasNext()) {
sb.append(it.next())
}
while (it.hasNext()) {
sb.append(", ").append(it.next())
}
return sb.append(")").toString()
}
return MultiVector.new: :%blades;
}
 
multi infix:<+>(Real $s, MultiVector $A) returns MultiVector is export {
fun e(n: Int): Vector {
my Real %blades{UInt} = $A.blades.clone;
%blades{0}if +=(n $s;> 4) {
throw IllegalArgumentException("n must be less than 5")
%blades{0} :delete unless %blades{0};
}
return MultiVector.new: :%blades;
val result = Vector(DoubleArray(32))
result[1 shl n] = 1.0
return result
}
 
multi infix:<+>(MultiVector $A, Real $s) returns MultiVector is export { $s + $A }
val rand = java.util.Random()
multi infix:<*>(MultiVector $A, MultiVector $B) returns MultiVector is export {
 
my Real %blades{UInt};
fun randomVector(): Vector {
for $A.blades -> $a {
var result = Vector(DoubleArray(32))
for $B.blades -> $b {
myfor $c(i =in $a.key0 +^until $b.key;5) {
result += Vector(doubleArrayOf(rand.nextDouble())) * e(i)
%blades{$c} += $a.value * $b.value * order($a.key, $b.key);
%blades{$c} :delete unless %blades{$c};
}
}
return MultiVector.new: :%blades;result
}
multi infix:<**>(MultiVector $ , 0) returns MultiVector is export { MultiVector.new }
multi infix:<**>(MultiVector $A, 1) returns MultiVector is export { $A }
multi infix:<**>(MultiVector $A, 2) returns MultiVector is export { $A * $A }
multi infix:<**>(MultiVector $A, UInt $n where $n %% 2) returns MultiVector is export { ($A ** ($n div 2)) ** 2 }
multi infix:<**>(MultiVector $A, UInt $n) returns MultiVector is export { $A * ($A ** ($n div 2)) ** 2 }
 
fun randomMultiVector(): Vector {
multi infix:<*>(MultiVector $, 0) returns MultiVector is export { MultiVector.new }
val result = Vector(DoubleArray(32))
multi infix:<*>(MultiVector $A, 1) returns MultiVector is export { $A }
for (i in 0 until 32) {
multi infix:<*>(MultiVector $A, Real $s) returns MultiVector is export {
result[i] = rand.nextDouble()
return MultiVector.new: :blades(my Real %{UInt} = map { .key => $s * .value }, $A.blades);
}
return result
}
multi infix:<*>(Real $s, MultiVector $A) returns MultiVector is export { $A * $s }
multi infix:</>(MultiVector $A, Real $s) returns MultiVector is export { $A * (1/$s) }
multi prefix:<->(MultiVector $A) returns MultiVector is export { return -1 * $A }
multi infix:<->(MultiVector $A, MultiVector $B) returns MultiVector is export { $A + -$B }
multi infix:<->(MultiVector $A, Real $s) returns MultiVector is export { $A + -$s }
multi infix:<->(Real $s, MultiVector $A) returns MultiVector is export { $s + -$A }
 
fun main() {
multi infix:<==>(MultiVector $A, MultiVector $B) returns Bool is export { $A - $B == 0 }
for (i in 0..4) {
multi infix:<==>(Real $x, MultiVector $A) returns Bool is export { $A == $x }
for (j in 0..4) {
multi infix:<==>(MultiVector $A, Real $x) returns Bool is export {
if (i < j) {
my $narrowed = $A.narrow;
if ((e(i) dot e(j))[0] != 0.0) {
$narrowed ~~ Real and $narrowed == $x;
println("Unexpected non-null scalar product.")
}</lang>
return
} else if (i == j) {
if ((e(i) dot e(j))[0] == 0.0) {
println("Unexpected null scalar product.")
}
}
}
}
}
 
val a = randomMultiVector()
val b = randomMultiVector()
val c = randomMultiVector()
val x = randomVector()
 
// (ab)c == a(bc)
println((a * b) * c)
println(a * (b * c))
println()
 
// a(b+c) == ab + ac
println(a * (b + c))
println(a * b + a * c)
println()
 
// (a+b)c == ac + bc
println((a + b) * c)
println(a * c + b * c)
println()
 
// x^2 is real
println(x * x)
}</syntaxhighlight>
{{out}}
<pre>(-6.38113123172589, -6.025395204580336, 0.5762054454373319, -2.224611121553874, -0.03467815839340305, -0.6665488550665257, -3.012105902847624, 0.7315782457554153, -4.183528079943369, -1.8391037440709876, -0.137654892093293, 0.10852885457965271, -6.021317788342983, -5.486453322362711, -3.524908677069778, -1.030729377561671, -6.858194536947578, -8.724962937014816, 0.4660400096706247, -1.6434599565678671, 4.212637141194194, 2.916899539720754, -1.365566480297562, 1.898991559248674, -2.5943503153384517, -0.7167616808942235, 1.2152416665362584, 2.9936787524618067, -5.394453145898911, -4.180356766796923, -6.622391097517418, -4.249450373116712)
(-6.381131231725885, -6.025395204580336, 0.5762054454373331, -2.2246111215538744, -0.034678158393403866, -0.6665488550665265, -3.012105902847625, 0.7315782457554131, -4.183528079943374, -1.83910374407099, -0.13765489209329423, 0.1085288545796525, -6.021317788342984, -5.486453322362712, -3.524908677069777, -1.0307293775616722, -6.858194536947579, -8.724962937014814, 0.46604000967062464, -1.6434599565678658, 4.212637141194197, 2.916899539720756, -1.3655664802975644, 1.8989915592486726, -2.5943503153384526, -0.716761680894223, 1.2152416665362615, 2.9936787524618076, -5.394453145898909, -4.1803567667969235, -6.622391097517417, -4.24945037311671)
 
(-5.001996874378833, -5.342863347345118, 0.5930301138931318, 1.8495242515856356, 5.226690714239807, 5.60029170092836, 1.9264816320512175, 2.9647400073622383, -1.231074336132209, -0.03574406666207321, 2.0490593688751666, 2.709392811857615, -0.534934380183112, 0.9566513059906786, 0.581531676517317, 2.6867651675849284, -6.072314695960932, -5.780622914352332, -2.264083859970755, -0.29904973719224437, 3.1693202958893196, 3.710947660874322, -0.3876119148699613, 0.28047758363117253, 0.4891346543855399, 1.1102262337923456, 1.9059090529704015, 2.2175302024987404, 3.6850877929174954, 4.798530127158409, 0.6243236143375706, 2.5910748978446576)
(-5.001996874378833, -5.3428633473451175, 0.5930301138931321, 1.8495242515856363, 5.22669071423981, 5.600291700928359, 1.9264816320512164, 2.9647400073622387, -1.231074336132209, -0.035744066662073595, 2.0490593688751657, 2.7093928118576143, -0.5349343801831126, 0.9566513059906783, 0.5815316765173175, 2.6867651675849284, -6.072314695960929, -5.78062291435233, -2.264083859970754, -0.2990497371922432, 3.169320295889319, 3.7109476608743237, -0.3876119148699616, 0.2804775836311723, 0.4891346543855406, 1.1102262337923452, 1.9059090529704013, 2.21753020249874, 3.6850877929174954, 4.798530127158408, 0.6243236143375701, 2.591074897844657)
 
(-3.583945607396393, -3.5239300960595137, 0.801943558725803, 2.9686354622847357, 4.064529783603304, 3.6456241887862015, 0.5954304494585552, 1.2819925842824296, 0.6768216109361052, 0.352207714198545, 2.843092732483635, 2.680239849424965, -0.04943045827884884, 0.19653339086911384, 2.875432393192088, 2.8657275256839823, -4.689497942711508, -3.42309859067624, -2.830665114554725, -0.017676578013020444, 3.635425127096899, 3.10264457980534, -1.2355052114199154, 0.02671272974814648, 2.5200281685651413, 2.2030677245192627, 2.727374336905742, 1.7812768180621927, 1.901781821035387, 2.8306551025240863, 3.9572153730448463, 2.9611369534401093)
(-3.5839456073963945, -3.5239300960595115, 0.8019435587258037, 2.968635462284734, 4.064529783603305, 3.6456241887862024, 0.5954304494585542, 1.2819925842824302, 0.6768216109361052, 0.3522077141985451, 2.843092732483634, 2.6802398494249644, -0.04943045827884848, 0.1965333908691129, 2.875432393192088, 2.8657275256839827, -4.689497942711507, -3.4230985906762403, -2.8306651145547246, -0.017676578013019806, 3.6354251270968985, 3.1026445798053395, -1.2355052114199154, 0.026712729748146535, 2.5200281685651413, 2.2030677245192627, 2.7273743369057417, 1.7812768180621923, 1.9017818210353874, 2.830655102524086, 3.957215373044847, 2.9611369534401097)
 
(2.6501903002573224, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)</pre>
 
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import bitops, random, sequtils, strutils
 
type Vector = seq[float]
 
func reorderingSign(i, j: int): float =
var i = i shr 1
var sum = 0
while i != 0:
sum += countSetBits(i and j)
i = i shr 1
result = if (sum and 1) == 0: 1 else: -1
 
func e(n: Natural): Vector =
result.setLen(32)
assert n < 5, "index must be less than 5; got $#.".format(n)
result[1 shl n] = 1
 
func `+`(a, b: Vector): Vector =
result.setLen(32)
for i in 0..b.high:
result[i] = a[i] + b[i]
 
func `*`(a, b: Vector): Vector =
result.setLen(32)
for i in 0..a.high:
if a[i] != 0:
for j in 0..b.high:
if b[j] != 0:
let s = reorderingSign(i, j) * a[i] * b[j]
let k = i xor j
result[k] += s
 
func dot(a, b: Vector): Vector =
(a * b + b * a) * @[0.5]
 
proc randomVector(): Vector =
result.setLen(32)
for i in 0..4:
result = result + @[rand(1.0)] * e(i)
 
proc randomMultiVector(): Vector =
newSeqWith(32, rand(1.0))
 
 
when isMainModule:
 
randomize()
for i in 0..4:
for j in 0..4:
if i < j:
if dot(e(i), e(j))[0] != 0:
raise newException(ValueError, "Unexpected non-null scalar product.")
elif i == j:
if dot(e(i), e(j))[0] == 0:
raise newException(ValueError, "Unexpected null scalar product.")
 
let a = randomMultiVector()
let b = randomMultiVector()
let c = randomMultiVector()
let x = randomVector()
 
# (ab)c == a(bc).
echo (a * b) * c
echo a * (b * c)
echo()
 
# a(b + c) == ab + ac.
echo a * (b + c)
echo a * b + a * c
echo()
 
# (a + b)c == ac + bc.
echo (a + b) * c
echo a * c + b * c
echo()
 
# x² is real.
echo x * x</syntaxhighlight>
 
{{out}}
<pre>@[-9.297288337196365, -13.59127999209494, 0.8722218109740326, 1.226935672314977, 7.508102247367465, 4.724948516329687, -5.033061024827017, -1.610503728288931, -3.33431529299565, 0.3532979194154671, 4.301275797990844, 0.515295984242726, 4.687736789474281, 2.172013218653572, 1.231492215423554, 0.3536950472866263, -2.327900412362799, -9.527999065273885, -1.555602751234329, 5.382767377500711, 6.267283581472086, 2.76910363753004, -2.301420318996988, 3.652383163769268, 1.752589228395532, 5.939099169023176, 4.479735695808257, 0.01446097776030125, -2.363384273037976, -5.720151847201447, -0.9397636030508162, -6.25507506195876]
@[-9.297288337196365, -13.59127999209493, 0.872221810974033, 1.226935672314978, 7.508102247367463, 4.72494851632969, -5.033061024827017, -1.610503728288931, -3.334315292995649, 0.3532979194154663, 4.301275797990842, 0.5152959842427232, 4.687736789474281, 2.172013218653572, 1.231492215423554, 0.3536950472866283, -2.327900412362798, -9.527999065273882, -1.55560275123433, 5.382767377500712, 6.267283581472084, 2.76910363753004, -2.301420318996988, 3.652383163769271, 1.752589228395533, 5.939099169023176, 4.47973569580826, 0.01446097776030148, -2.363384273037971, -5.720151847201445, -0.9397636030508175, -6.255075061958758]
 
@[-2.586487554821921, -2.653533704207625, 2.766021230656747, 2.036067471647896, 3.190493529679435, 2.42809912090021, 0.6900349473229486, 2.878934763823856, -3.935215841511595, -0.7288825987300381, 6.463778612248242, 4.417536841852129, 0.636912176867748, 4.413110019589562, 2.623393232840747, 1.608010580836939, -0.5328933745526506, -3.058074932298209, 2.178373565254037, 2.495618455562951, 4.609639873172126, 2.906729883514136, -0.934662696267724, 0.1369174733899857, 0.7572410282960323, 2.600596775217479, 4.079925278716743, 2.378076954647832, -1.529999013986847, 4.451662845891456, 0.07968415835836305, 0.7302442935297417]
@[-2.586487554821921, -2.653533704207625, 2.766021230656746, 2.036067471647896, 3.190493529679435, 2.42809912090021, 0.6900349473229492, 2.878934763823857, -3.935215841511596, -0.7288825987300391, 6.463778612248241, 4.417536841852128, 0.6369121768677473, 4.413110019589563, 2.623393232840748, 1.60801058083694, -0.5328933745526511, -3.058074932298209, 2.178373565254037, 2.495618455562951, 4.609639873172125, 2.906729883514135, -0.9346626962677241, 0.1369174733899854, 0.7572410282960332, 2.600596775217479, 4.079925278716742, 2.378076954647831, -1.529999013986847, 4.451662845891456, 0.0796841583583624, 0.7302442935297415]
 
@[-4.043970500041602, -6.87480031917386, 2.141017248170762, 0.3993395131802852, 0.8031440447491957, 3.401648770759057, 1.607243807621857, 3.522447744273161, -1.991055803046583, -0.7625625003549232, 6.536037328177198, 3.860062375500871, 2.237849358894385, 4.651754451010404, 8.300896571599077, 4.846096568587825, -2.0442907200416, -4.305082016141705, -0.9716874582456112, 0.214856705219781, 3.6445786747822, 2.050775132011032, -2.303468928921437, -1.111677463505033, 2.776551776801528, 1.829715078662076, 4.565478899003429, 1.874485695211426, -2.682597285575913, 1.056667802512815, 4.075588220758377, 1.609677009616234]
@[-4.043970500041601, -6.874800319173863, 2.141017248170761, 0.3993395131802844, 0.8031440447491961, 3.401648770759058, 1.607243807621859, 3.522447744273161, -1.991055803046583, -0.7625625003549237, 6.536037328177197, 3.860062375500871, 2.237849358894385, 4.651754451010405, 8.300896571599079, 4.846096568587828, -2.044290720041601, -4.305082016141704, -0.9716874582456119, 0.2148567052197807, 3.6445786747822, 2.050775132011031, -2.303468928921436, -1.111677463505034, 2.776551776801528, 1.829715078662075, 4.565478899003429, 1.874485695211426, -2.682597285575913, 1.056667802512815, 4.075588220758375, 1.609677009616233]
 
@[2.298735784397904, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</pre>
 
=={{header|Phix}}==
{{trans|Go}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">bitCount</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_eq</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%b"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">),</span><span style="color: #008000;">'1'</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- (idea cribbed from Python)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">reorderingSign</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">tot</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">bitCount</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">0</span> <span style="color: #0000FF;">?</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">:</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">reorderingSign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
<span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">s</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">cdot</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">></span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"n must be less than 5"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1.0</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">--function neg(sequence x) -- (not actually used here)
-- return mul({-1}, x)
--end function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">randomVector</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">({</span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()},</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">randomMultiVector</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">32</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">j</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">cdot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">))[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Unexpected non-null scalar product."</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">j</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">cdot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">))[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Unexpected null scalar product."</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">randomMultiVector</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">randomMultiVector</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">randomMultiVector</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">randomVector</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">xsq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">txt</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- bool eq = (a==b) -- no!</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">eq</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)==</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- ok!</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-20s: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">txt</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">eq</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"true"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"false"</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(ab)c == a(bc)"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)))</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"a(b + c) == ab + ac"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)))</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(a + b)c == ac + bc"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)))</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"x^2 is real"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xsq</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xsq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]&</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">31</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
Note the comparison of string representations of floats, rather than the floats themselves. That effectively ensures they
all match to 10 significant digits, and avoids a few tiny (~1e-16) discrepancies.
<pre>
(ab)c == a(bc) : true
a(b + c) == ab + ac : true
(a + b)c == ac + bc : true
x^2 is real : true
</pre>
 
=={{header|Python}}==
{{trans|D}}
<syntaxhighlight lang="python">import copy, random
 
def bitcount(n):
return bin(n).count("1")
 
def reoderingSign(i, j):
k = i >> 1
sum = 0
while k != 0:
sum += bitcount(k & j)
k = k >> 1
return 1.0 if ((sum & 1) == 0) else -1.0
 
class Vector:
def __init__(self, da):
self.dims = da
 
def dot(self, other):
return (self * other + other * self) * 0.5
 
def __getitem__(self, i):
return self.dims[i]
 
def __setitem__(self, i, v):
self.dims[i] = v
 
def __neg__(self):
return self * -1.0
 
def __add__(self, other):
result = copy.copy(other.dims)
for i in xrange(0, len(self.dims)):
result[i] += self.dims[i]
return Vector(result)
 
def __mul__(self, other):
if isinstance(other, Vector):
result = [0.0] * 32
for i in xrange(0, len(self.dims)):
if self.dims[i] != 0.0:
for j in xrange(0, len(self.dims)):
if other.dims[j] != 0.0:
s = reoderingSign(i, j) * self.dims[i] * other.dims[j]
k = i ^ j
result[k] += s
return Vector(result)
else:
result = copy.copy(self.dims)
for i in xrange(0, len(self.dims)):
self.dims[i] *= other
return Vector(result)
 
def __str__(self):
return str(self.dims)
 
def e(n):
assert n <= 4, "n must be less than 5"
result = Vector([0.0] * 32)
result[1 << n] = 1.0
return result
 
def randomVector():
result = Vector([0.0] * 32)
for i in xrange(0, 5):
result += Vector([random.uniform(0, 1)]) * e(i)
return result
 
def randomMultiVector():
result = Vector([0.0] * 32)
for i in xrange(0, 32):
result[i] = random.uniform(0, 1)
return result
 
def main():
for i in xrange(0, 5):
for j in xrange(0, 5):
if i < j:
if e(i).dot(e(j))[0] != 0.0:
print "Unexpected non-null scalar product"
return
elif i == j:
if e(i).dot(e(j))[0] == 0.0:
print "Unexpected non-null scalar product"
 
a = randomMultiVector()
b = randomMultiVector()
c = randomMultiVector()
x = randomVector()
 
# (ab)c == a(bc)
print (a * b) * c
print a * (b * c)
print
 
# a(b+c) == ab + ac
print a * (b + c)
print a * b + a * c
print
 
# (a+b)c == ac + bc
print (a + b) * c
print a * c + b * c
print
 
# x^2 is real
print x * x
 
main()</syntaxhighlight>
{{out}}
<pre>[2.646777769717816, -5.480686120935684, -8.183342078006843, -9.178717618666656, -0.21247781959240397, -3.1560121872423172, -14.210376795019405, -7.975576839132462, -2.963314079857538, -8.128489630952732, 8.84291288803876, 6.849688422048398, -3.948403894153645, -6.3295864734054295, 0.858339386946704, 0.04073276768257372, -0.8170168057484614, -5.987310468330181, -5.089567141509365, -6.5916164371098205, 1.066652018944462, -0.7553724661211869, -16.61957782752131, -10.74332838047719, -0.22326945346944393, -5.502857138805277, 11.833089760883906, 11.020055749901102, -3.7471254230186233, -3.5483496341413763, 7.788213699886802, 5.385261642366723]
[2.6467777697178145, -5.480686120935683, -8.183342078006845, -9.178717618666658, -0.2124778195924022, -3.156012187242318, -14.210376795019414, -7.975576839132467, -2.9633140798575406, -8.128489630952735, 8.842912888038763, 6.849688422048397, -3.9484038941536435, -6.329586473405431, 0.8583393869467044, 0.04073276768257594, -0.8170168057484637, -5.987310468330179, -5.089567141509367, -6.591616437109819, 1.0666520189444642, -0.7553724661211856, -16.61957782752132, -10.743328380477191, -0.22326945346944407, -5.502857138805281, 11.83308976088391, 11.0200557499011, -3.7471254230186246, -3.5483496341413807, 7.7882136998868035, 5.385261642366723]
 
[-4.45416862548425, -4.007728055936393, 2.2599167577088886, -0.5008511526260965, 6.404388731518947, 3.553799027487341, -1.4559344997025763, 1.200629741306491, 0.28084755190469957, 1.6881017142666677, 4.622735951152484, 2.042861306698215, -1.1859431529346458, -0.23268120656473645, 3.3088499800790308, 6.272881551311293, -6.283417063207868, -6.059129990387314, 0.9004412097752342, 0.540839567518711, 2.9772708785233157, 2.2875667777090625, 1.6049404915540564, 4.551625497411361, 3.4613544600410537, 4.601629280006443, 4.934029921827034, 3.0257810667323715, -1.280636387447562, -0.21306231994217983, 6.089428007073901, 8.128821330734313]
[-4.454168625484251, -4.007728055936392, 2.259916757708888, -0.5008511526260957, 6.404388731518948, 3.553799027487342, -1.455934499702577, 1.2006297413064915, 0.2808475519046991, 1.688101714266668, 4.622735951152485, 2.0428613066982155, -1.1859431529346458, -0.23268120656473568, 3.30884998007903, 6.272881551311293, -6.283417063207869, -6.059129990387315, 0.9004412097752316, 0.5408395675187101, 2.9772708785233157, 2.287566777709062, 1.6049404915540577, 4.551625497411363, 3.4613544600410533, 4.601629280006441, 4.934029921827035, 3.025781066732372, -1.2806363874475617, -0.21306231994217995, 6.0894280070738995, 8.128821330734311]
 
[-4.713407548689167, -5.470701972164317, 0.2834720300902142, -1.8843569665485043, 2.8883659013514302, 3.6276355158044815, -2.7614493177411843, 0.14095340884428206, -1.191066813989091, 1.1017933922740846, 2.995254519836379, 1.5249479602578073, 2.153333527417164, 1.999841187299821, 6.220565393668025, 8.730809912614522, -7.61200478654088, -9.557862449328784, 1.432009511995673, 0.14006605762543944, 1.450154388175902, 2.5115288790301835, -1.5609458922816675, 1.9148273860716452, 3.56683599400551, 3.9854109527025505, 3.6838872880534086, 3.059534508634617, 3.237048050921782, 2.674541802512928, 6.252577743980652, 7.309261452099341]
[-4.713407548689167, -5.470701972164316, 0.28347203009021416, -1.8843569665485043, 2.8883659013514302, 3.6276355158044815, -2.761449317741185, 0.14095340884428198, -1.1910668139890919, 1.101793392274085, 2.9952545198363785, 1.5249479602578067, 2.153333527417164, 1.9998411872998219, 6.220565393668025, 8.730809912614523, -7.612004786540879, -9.557862449328784, 1.4320095119956717, 0.14006605762543944, 1.4501543881759016, 2.511528879030183, -1.5609458922816672, 1.9148273860716456, 3.5668359940055105, 3.985410952702549, 3.683887288053409, 3.0595345086346164, 3.2370480509217803, 2.6745418025129273, 6.252577743980652, 7.30926145209934]
 
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
Here we write a simplified version of the [https://github.com/grondilu/clifford Clifford] module. It is very general as it is of infinite dimension and also contains an anti-euclidean basis @ē in addition to the euclidean basis @e.
 
<syntaxhighlight lang="raku" line>class MultiVector is Mix {
subset Vector of ::?CLASS is export where *.grades.all == 1;
 
method narrow { self.keys.any > 0 ?? self !! (self{0} // 0) }
method grades { self.keys.map: *.base(2).comb.sum }
 
multi method new(Real $x) returns ::?CLASS { self.new-from-pairs: 0 => $x }
multi method new(Str $ where /^^e(\d+)$$/) { self.new-from-pairs: (1 +< (2*$0)) => 1 }
 
our @e is export = map { ::?CLASS.new: "e$_" }, ^Inf;
 
my sub order(UInt:D $i is copy, UInt:D $j) {
(state %){$i}{$j} //= do {
my $n = 0;
repeat {
$i +>= 1;
$n += [+] ($i +& $j).polymod(2 xx *);
} until $i == 0;
$n +& 1 ?? -1 !! 1;
}
}
 
sub infix:<·>(Vector $x, Vector $y) returns Real is export { (($x*$y + $y*$x)/2){0} }
multi infix:<+>(::?CLASS $A, ::?CLASS $B) returns ::?CLASS is export {
return ::?CLASS.new-from-pairs: |$A.pairs, |$B.pairs;
}
multi infix:<+>(Real $s, ::?CLASS $B) returns ::?CLASS is export {
samewith $B.new($s), $B
}
multi infix:<+>(::?CLASS $A, Real $s) returns ::?CLASS is export {
samewith $s, $A
}
 
multi infix:<*>(::?CLASS $, 0) is export { 0 }
multi infix:<*>(::?CLASS $A, 1) returns ::?CLASS is export { $A }
multi infix:<*>(::?CLASS $A, Real $s) returns ::?CLASS is export {
::?CLASS.new-from-pairs: $A.pairs.map({Pair.new: .key, $s*.value})
}
multi infix:<*>(::?CLASS $A, ::?CLASS $B) returns ::?CLASS is export {
::?CLASS.new-from-pairs: gather
for $A.pairs -> $a {
for $B.pairs -> $b {
take ($a.key +^ $b.key) => [*]
$a.value, $b.value,
order($a.key, $b.key),
|grep +*, (
|(1, -1) xx * Z*
($a.key +& $b.key).polymod(2 xx *)
)
}
}
}
multi infix:<**>(::?CLASS $ , 0) returns ::?CLASS is export { ::?CLASS.new: (0 => 1).Mix }
multi infix:<**>(::?CLASS $A, 1) returns ::?CLASS is export { $A }
multi infix:<**>(::?CLASS $A, 2) returns ::?CLASS is export { $A * $A }
multi infix:<**>(::?CLASS $A, UInt $n where $n %% 2) returns ::?CLASS is export { ($A ** ($n div 2)) ** 2 }
multi infix:<**>(::?CLASS $A, UInt $n) returns ::?CLASS is export { $A * ($A ** ($n div 2)) ** 2 }
 
multi infix:<*>(Real $s, ::?CLASS $A) returns ::?CLASS is export { $A * $s }
multi infix:</>(::?CLASS $A, Real $s) returns ::?CLASS is export { $A * (1/$s) }
multi prefix:<->(::?CLASS $A) returns ::?CLASS is export { return -1 * $A }
multi infix:<->(::?CLASS $A, ::?CLASS $B) returns ::?CLASS is export { $A + -$B }
multi infix:<->(::?CLASS $A, Real $s) returns ::?CLASS is export { $A + -$s }
multi infix:<->(Real $s, ::?CLASS $A) returns ::?CLASS is export { $s + -$A }
 
multi infix:<==>(::?CLASS $A, 0) returns Bool is export { $A.elems == 0 }
multi infix:<==>(::?CLASS $A, ::?CLASS $B) returns Bool is export { samewith $A - $B, 0 }
multi infix:<==>(Real $x, ::?CLASS $A) returns Bool is export { samewith $A, $x }
multi infix:<==>(::?CLASS $A, Real $x) returns Bool is export { samewith $A, $A.new($x); }
 
sub random is export {
[+] map {
::?CLASS.new-from-pairs: $_ => rand.round(.01)
}, ^32;
}
}
 
#########################################
And here is the code implementing and verifying quaternions:
## Test code to verify the solution: ##
#########################################
 
<lang perl6>useimport MultiVector;
use Test;
constant N = 10;
plan 13;
plan 5;
subtest "Orthonormality", {
sub infix:<cdot>($a, $b) { ($a*$b + $b*$a) / 2 }
for ^N X ^N -> ($i, $j) {
my $s = $i == $j ?? 1 !! 0;
ok @e[$i]·@e[$j] == $s, "e$i·e$j = $s";
}
}
my ($a, $b, $c) = random() xx 3;
ok ($a*$b)*$c == $a*($b*$c), 'associativity';
ok $a*($b + $c) == $a*$b + $a*$c, 'left distributivity';
ok ($a + $b)*$c == $a*$c + $b*$c, 'right distributivity';
my @coeff = (.5 - rand) xx 5;
my $v = [+] @coeff Z* @e[^5];
ok ($v**2).narrow ~~ Real, 'contraction';</syntaxhighlight>
 
=={{header|Visual Basic .NET}}==
for ^4 X ^4 -> ($i, $j) {
{{trans|C#}}
next if $i > $j;
<syntaxhighlight lang="vbnet">Option Strict On
ok e($i) cdot e($j) == +($i == $j);
 
Imports System.Text
 
Module Module1
 
Structure Vector
Private ReadOnly dims() As Double
 
Public Sub New(da() As Double)
dims = da
End Sub
 
Public Shared Operator -(v As Vector) As Vector
Return v * -1.0
End Operator
 
Public Shared Operator +(lhs As Vector, rhs As Vector) As Vector
Dim result(31) As Double
Array.Copy(lhs.dims, 0, result, 0, lhs.Length)
For i = 1 To result.Length
Dim i2 = i - 1
result(i2) = lhs(i2) + rhs(i2)
Next
Return New Vector(result)
End Operator
 
Public Shared Operator *(lhs As Vector, rhs As Vector) As Vector
Dim result(31) As Double
For i = 1 To lhs.Length
Dim i2 = i - 1
If lhs(i2) <> 0.0 Then
For j = 1 To lhs.Length
Dim j2 = j - 1
If rhs(j2) <> 0.0 Then
Dim s = ReorderingSign(i2, j2) * lhs(i2) * rhs(j2)
Dim k = i2 Xor j2
result(k) += s
End If
Next
End If
Next
Return New Vector(result)
End Operator
 
Public Shared Operator *(v As Vector, scale As Double) As Vector
Dim result = CType(v.dims.Clone, Double())
For i = 1 To result.Length
Dim i2 = i - 1
result(i2) *= scale
Next
Return New Vector(result)
End Operator
 
Default Public Property Index(key As Integer) As Double
Get
Return dims(key)
End Get
Set(value As Double)
dims(key) = value
End Set
End Property
 
Public ReadOnly Property Length As Integer
Get
Return dims.Length
End Get
End Property
 
Public Function Dot(rhs As Vector) As Vector
Return (Me * rhs + rhs * Me) * 0.5
End Function
 
Private Shared Function BitCount(i As Integer) As Integer
i -= ((i >> 1) And &H55555555)
i = (i And &H33333333) + ((i >> 2) And &H33333333)
i = (i + (i >> 4)) And &HF0F0F0F
i += (i >> 8)
i += (i >> 16)
Return i And &H3F
End Function
 
Private Shared Function ReorderingSign(i As Integer, j As Integer) As Double
Dim k = i >> 1
Dim sum = 0
While k <> 0
sum += BitCount(k And j)
k >>= 1
End While
Return If((sum And 1) = 0, 1.0, -1.0)
End Function
 
Public Overrides Function ToString() As String
Dim it = dims.GetEnumerator
 
Dim sb As New StringBuilder("[")
If it.MoveNext() Then
sb.Append(it.Current)
End If
While it.MoveNext
sb.Append(", ")
sb.Append(it.Current)
End While
sb.Append("]")
Return sb.ToString
End Function
End Structure
 
Function DoubleArray(size As Integer) As Double()
Dim result(size - 1) As Double
For i = 1 To size
Dim i2 = i - 1
result(i2) = 0.0
Next
Return result
End Function
 
Function E(n As Integer) As Vector
If n > 4 Then
Throw New ArgumentException("n must be less than 5")
End If
 
Dim result As New Vector(DoubleArray(32))
result(1 << n) = 1.0
Return result
End Function
 
ReadOnly r As New Random()
 
Function RandomVector() As Vector
Dim result As New Vector(DoubleArray(32))
For i = 1 To 5
Dim i2 = i - 1
Dim singleton() As Double = {r.NextDouble()}
result += New Vector(singleton) * E(i2)
Next
Return result
End Function
 
Function RandomMultiVector() As Vector
Dim result As New Vector(DoubleArray(32))
For i = 1 To result.Length
Dim i2 = i - 1
result(i2) = r.NextDouble()
Next
Return result
End Function
 
Sub Main()
For i = 1 To 5
Dim i2 = i - 1
For j = 1 To 5
Dim j2 = j - 1
If i2 < j2 Then
If E(i2).Dot(E(j2))(0) <> 0.0 Then
Console.Error.WriteLine("Unexpected non-null scalar product")
Return
End If
ElseIf i2 = j2 Then
If E(i2).Dot(E(j2))(0) = 0.0 Then
Console.Error.WriteLine("Unexpected null scalar product")
Return
End If
End If
Next
Next
 
Dim a = RandomMultiVector()
Dim b = RandomMultiVector()
Dim c = RandomMultiVector()
Dim x = RandomVector()
 
' (ab)c == a(bc)
Console.WriteLine((a * b) * c)
Console.WriteLine(a * (b * c))
Console.WriteLine()
 
' a(b+c) == ab + ac
Console.WriteLine(a * (b + c))
Console.WriteLine(a * b + a * c)
Console.WriteLine()
 
' (a+b)c == ac + bc
Console.WriteLine((a + b) * c)
Console.WriteLine(a * c + b * c)
Console.WriteLine()
 
' x^2 is real
Console.WriteLine(x * x)
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>[0.574263754349833, -1.04033308353824, -0.776121961159351, 2.00792496222078, 3.16921091358851, 6.73557610270275, -13.4327886840529, -7.74195172209513, -7.21674283588092, -5.86045645950882, 2.22312083899981, 1.32215440847646, -6.14796858424355, -6.31067579900569, -8.24016821785677, -7.13138966213629, 1.70037903072841, -1.61670055512076, -1.53920826677554, 0.0830404550813257, 3.93618132588852, 7.40029585163889, -6.36594388310886, 2.14605789872596, -12.3353817163416, -9.51720072572794, 4.57164353732716, 3.11601890765627, -3.45821025466289, -4.2333151576991, -5.88080545860622, -6.53549242641427]
[0.574263754349836, -1.04033308353825, -0.776121961159348, 2.00792496222078, 3.16921091358851, 6.73557610270275, -13.4327886840529, -7.74195172209514, -7.21674283588092, -5.86045645950883, 2.2231208389998, 1.32215440847646, -6.14796858424355, -6.31067579900569, -8.24016821785676, -7.13138966213629, 1.70037903072841, -1.61670055512076, -1.53920826677554, 0.0830404550813244, 3.93618132588852, 7.40029585163889, -6.36594388310886, 2.14605789872596, -12.3353817163416, -9.51720072572794, 4.57164353732716, 3.11601890765627, -3.4582102546629, -4.2333151576991, -5.88080545860622, -6.53549242641427]
 
[-4.47297646716049, -5.51675159908628, -2.0422292306007, -2.10280367601528, 4.45365145957714, 3.36803601730516, -1.14571129439412, -0.425208328771765, 1.55145295736126, 1.59542278752789, 5.96209903766593, 3.43000773717995, -1.93701906000176, -0.282031417434974, 2.27435916727966, 5.57909608271093, -4.5313823118833, -5.23492105300004, -1.61573387363407, -2.77225954890565, 2.7749883436186, 2.47317184825279, -1.66854919690689, -1.04001004327011, 0.314038463700274, 0.354414497531512, 6.65882395905864, 4.84274526210668, -1.26994943017024, 0.867830239054973, 5.4316876690133, 8.85070336472853]
[-4.47297646716048, -5.51675159908628, -2.0422292306007, -2.10280367601528, 4.45365145957714, 3.36803601730516, -1.14571129439412, -0.425208328771764, 1.55145295736126, 1.59542278752789, 5.96209903766592, 3.43000773717995, -1.93701906000176, -0.282031417434974, 2.27435916727966, 5.57909608271093, -4.5313823118833, -5.23492105300004, -1.61573387363407, -2.77225954890565, 2.7749883436186, 2.47317184825279, -1.66854919690689, -1.04001004327011, 0.314038463700274, 0.354414497531512, 6.65882395905864, 4.84274526210668, -1.26994943017024, 0.867830239054973, 5.4316876690133, 8.85070336472853]
 
[-5.22293180574195, -5.83486719133951, -1.69911127655253, -0.239172378976677, 2.88101068267363, 3.97970294192276, -3.56156896393757, -2.61790431554284, -0.736020241689734, -0.776473740587332, 3.0171422268862, 2.15992705303214, -3.20043960767084, -0.644050812810021, 0.714338263909879, 1.74591314489993, -4.38202839888319, -3.26051280533051, -4.05531615492948, -2.93703039040279, 3.56583825504966, 4.17636250632614, -1.11524349520128, -3.21090579244331, 1.27680857237575, 2.37418947249269, 4.48848909104827, 3.7920821695994, -3.71929857788004, 0.286175312382222, 6.0485010014393, 8.27326094456212]
[-5.22293180574195, -5.83486719133951, -1.69911127655253, -0.239172378976677, 2.88101068267363, 3.97970294192276, -3.56156896393757, -2.61790431554284, -0.736020241689734, -0.776473740587333, 3.0171422268862, 2.15992705303214, -3.20043960767084, -0.644050812810022, 0.71433826390988, 1.74591314489993, -4.38202839888319, -3.2605128053305, -4.05531615492948, -2.93703039040279, 3.56583825504966, 4.17636250632614, -1.11524349520128, -3.21090579244331, 1.27680857237575, 2.37418947249269, 4.48848909104827, 3.7920821695994, -3.71929857788004, 0.286175312382223, 6.0485010014393, 8.27326094456212]
 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">import "random" for Random
 
var bitCount = Fn.new { |i|
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
}
 
var ReorderingSign = Fn.new { |i, j|
my $v = e(0) - e(1) + 2*e(2) + 3*e(3) - 2*e(4);
var k = i >> 1
var sum = 0
while (k != 0) {
sum = sum + bitCount.call(k & j)
k = k >> 1
}
return (sum & 1 == 0) ? 1 : -1
}
 
class Vector {
ok $v**2 == 19, 'v² = 19';
construct new(dims) {
_dims = dims
}
 
dims { _dims }
my constant i = e(0)*e(1);
 
my constant j = e(1)*e(2);
dot(rhs) { (this * rhs + rhs * this) * 0.5 }
my constant k = e(0)*e(2);
 
- { this * -1 }
ok i**2 == j**2 == k**2 == i*j*k == -1, "i² = j² = k² = ijk = -1";
 
+(rhs) {
var result = List.filled(32, 0)
for (i in 0..._dims.count) result[i] = _dims[i]
for (i in 0...rhs.dims.count) result[i] = result[i] + rhs[i]
return Vector.new(result)
}
 
*(rhs) {
if (rhs is Vector) {
var result = List.filled(32, 0)
for (i in 0..._dims.count) {
if (_dims[i] != 0) {
for (j in 0...rhs.dims.count) {
if (rhs[j] != 0) {
var s = ReorderingSign.call(i, j) * _dims[i] * rhs[j]
var k = i ^ j
result[k] = result[k] + s
}
}
}
}
return Vector.new(result)
} else if (rhs is Num) {
var result = _dims.toList
for (i in 0..4) dims[i] = dims[i] * rhs
return Vector.new(result)
} else {
Fiber.abort("rhs must either be a Vector or a number")
}
}
 
[index] { _dims[index] }
 
[index]=(value) { _dims[index] = value }
 
toString { "(" + _dims.join(", ") + ")" }
}
 
var e = Fn.new { |n|
if (n > 4) Fiber.abort("n must be less than 5")
var result = Vector.new(List.filled(32, 0))
result[1 << n] = 1
return result
}
 
var rand = Random.new()
 
var randomVector = Fn.new {
var result = Vector.new(List.filled(32, 0))
for (i in 0..4) {
result = result + Vector.new([rand.float()]) * e.call(i)
}
return result
}
 
var randomMultiVector = Fn.new {
var result = Vector.new(List.filled(32, 0))
for (i in 0..31) result[i] = rand.float()
return result
}
 
for (i in 0..4) {
for (j in 0..4) {
if (i < j) {
if (e.call(i).dot(e.call(j))[0] != 0) {
System.print("Unexpected non-null scalar product.")
return
} else if (i == j) {
if (e.call(i).dot(e.call(j))[0] == 0) {
System.print("Unexpected null scalar product.")
}
}
}
}
}
 
var a = randomMultiVector.call()
var b = randomMultiVector.call()
var c = randomMultiVector.call()
var x = randomVector.call()
 
// (ab)c == a(bc)
System.print((a * b) * c)
System.print(a * (b * c))
System.print()
 
// a(b+c) == ab + ac
System.print(a * (b + c))
System.print(a * b + a * c)
System.print()
 
// (a+b)c == ac + bc
System.print((a + b) * c)
System.print(a * c + b * c)
System.print()
 
// x^2 is real
System.print(x * x)</syntaxhighlight>
 
my constant I = e(1)*e(2);
my constant J = e(2)*e(3);
my constant K = e(1)*e(3);
ok I**2 == J**2 == K**2 == I*J*K == -1, "I² = J² = K² = IJK = -1";</lang>
{{out}}
<pre>1..13
(-6.1279343499972, -12.172471890613, -0.43596654360835, -9.4733600789769, 7.7468131011607, -1.0197449680744, -8.3386053167094, -4.514411938465, -0.85417113341489, 5.814264590591, 4.7534441812565, 3.6983892972325, -1.9487633151975, 1.0081516771802, 3.793528331478, -0.71739309800609, -5.0930834896765, -10.389798935116, -0.21991874396827, -9.2747185990727, 2.4902263109011, -1.217404792573, -7.5648404539069, -5.1713187775853, -4.9297458419615, -2.5365579590808, 5.6741886500532, -5.3820954955896, 0.84309276379896, -0.83865672543758, -6.6627947524069, -6.5068089919902)
ok 1 -
(-6.1279343499972, -12.172471890613, -0.43596654360835, -9.4733600789769, 7.7468131011607, -1.0197449680744, -8.3386053167094, -4.514411938465, -0.85417113341489, 5.814264590591, 4.7534441812565, 3.6983892972325, -1.9487633151975, 1.0081516771802, 3.793528331478, -0.71739309800609, -5.0930834896765, -10.389798935116, -0.21991874396827, -9.2747185990727, 2.4902263109011, -1.217404792573, -7.5648404539069, -5.1713187775853, -4.9297458419615, -2.5365579590808, 5.6741886500532, -5.3820954955896, 0.84309276379896, -0.83865672543757, -6.6627947524069, -6.5068089919902)
ok 2 -
 
ok 3 -
(-4.5670205884692, -5.406285276749, 0.20435321499717, -4.7297569961965, 3.1536400277791, 4.3228858614581, -2.648422809333, -1.1833380429978, -1.7564258015137, 3.3290322042955, 4.1877600392827, 5.7622202559563, -2.6969120760046, 1.6040264499734, 1.7140507294369, 3.3982272822008, -2.7897066050195, -2.800819409065, 2.2770258183891, -1.3567979021271, 2.4379457462826, 4.9315720878673, -1.8523904994524, 0.57286280886659, 0.78942446076958, 3.2321401010964, 2.7052700803603, 4.1875465627791, -1.9573353620592, 3.042768958901, 0.55331226143665, 3.4813647018728)
ok 4 -
(-4.5670205884692, -5.406285276749, 0.20435321499716, -4.7297569961965, 3.1536400277791, 4.3228858614581, -2.648422809333, -1.1833380429978, -1.7564258015137, 3.3290322042955, 4.1877600392827, 5.7622202559563, -2.6969120760046, 1.6040264499734, 1.7140507294369, 3.3982272822008, -2.7897066050195, -2.800819409065, 2.2770258183891, -1.3567979021271, 2.4379457462826, 4.9315720878673, -1.8523904994524, 0.57286280886659, 0.78942446076958, 3.2321401010964, 2.7052700803603, 4.1875465627791, -1.9573353620592, 3.042768958901, 0.55331226143665, 3.4813647018728)
ok 5 -
 
ok 6 -
(-6.4947965411446, -7.5334457985612, -0.48336700984287, -2.6235798111818, 3.6406622303652, 3.6398682775911, -1.8835092927705, -4.0165723310492, 1.6332945757193, 5.2056992102457, 4.202039318349, 7.3784879794787, -2.4843920053947, -0.47893361628939, 1.1220802570638, 2.693375877108, -1.278951846965, -2.5982492127516, 0.85382005828955, -0.077629574978695, 5.211354827205, 6.5199779982554, 0.85742615796087, -0.062281151554669, -1.4540738133743, 1.6710486134883, 3.8433969630048, 6.4484021393956, 2.8236029776283, 2.9302728085944, 1.3066828942527, 3.7490534064109)
ok 7 -
(-6.4947965411446, -7.5334457985612, -0.48336700984287, -2.6235798111818, 3.6406622303652, 3.6398682775912, -1.8835092927705, -4.0165723310492, 1.6332945757193, 5.2056992102457, 4.202039318349, 7.3784879794787, -2.4843920053947, -0.47893361628939, 1.1220802570638, 2.693375877108, -1.278951846965, -2.5982492127516, 0.85382005828955, -0.077629574978696, 5.211354827205, 6.5199779982554, 0.85742615796087, -0.062281151554668, -1.4540738133743, 1.6710486134883, 3.8433969630048, 6.4484021393956, 2.8236029776283, 2.9302728085944, 1.3066828942527, 3.7490534064109)
ok 8 -
 
ok 9 -
(0.96552083436649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
ok 10 -
</pre>
ok 11 - v² = 19
ok 12 - i² = j² = k² = ijk = -1
ok 13 - I² = J² = K² = IJK = -1</pre>
2,130

edits