We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Quaternions

From Esolang
(Redirected from Quaterions)
Jump to navigation Jump to search

Quaternions is an esolang by User:Cleverxia based on quaternions.

Introduction to quaternions

A quaternion is a number with form where , , are imaginary units, , and . NOTE: This means quaternions' multiplication is not commutative.

A quaternion has norm , conjugate , reciprocal and negation .

Quaternion addition do what you expect: .

Quaternion multiplication is defined as .

Subtracting a quaternion is equal to adding its negation; dividing a quaternion is equal to multiplying its reciporial.

Program flow

Quaternions is not stack based, but rather works on a array shaped like a 3d sphere called S. There is a data pointer DP which is initially 1. Let SP=. It also has an accumulator.

Caption text
command meaning
^ load S[SP] onto accumulator
1, i, j, k load corresponding imaginary unit onto accumulator
? load random thing from [1,i,j,k] onto accumulator
+, -, *, / accumulator (+=|-=|*=|/=) S[SP]
= stores accumulator into S[SP]
` DP*=acc. THIS IS THE ONLY WAY TO MODIFY DP. this is equivalent to rotating the DP
(...), [...], {...} if statements, while loops, and until loops. condition: acc==0
. output. implementation defined
, input. implementation defined

Examples

Truth machine

1=+=+=+=+=++=,.-{+.-}

(assuming IO inputs/outputs the character codes on the real part)

unary Looping counter

1=+=++=++++++=i`1=+=++++=i`1={i*`=i*={1+=i`^.i```^}i``^.i`1+=}

may be shorter... who knows? this version requires js Number can be arbitrarily large.

explanation: this uses 4 points on the unit circle on the complex plane to store things, SP=1 stores 42, SP=i stores 10, SP=-1 stores the outer counter (counts up), SP=-i stores the negation of the inner counter (to make things easier).

Interpreter

code='1=+=+=+=+=++=,.-{+.-}'
input='1'

function add(a,b){return typeof a=='number'?a+b:[add(a[0],b[0]),add(a[1],b[1])];}
function neg(a,b){return typeof a=='number'?-a:[neg(a[0]),neg(a[1])];}
function sub(a,b){return add(a,neg(b));}
function conj(a){return typeof a=='number'?a:[conj(a[0]),neg(a[1])];}
function mul(a,b){return typeof a=='number'?a*b:[sub(mul(a[0],b[0]),mul(conj(b[1]),a[1])),add(mul(b[1],a[0]),mul(a[1],conj(b[0])))];}//cayley dickson definition
function mul_scalar(a,b){return typeof a=='number'?a*b:[mul_scalar(a[0],b),mul_scalar(a[1],b)];}
function norm(a){return typeof a=='number'?Math.abs(a):Math.hypot(norm(a[0]),norm(a[1]));}
function recip(a){return mul_scalar(conj(a),norm(a)**-2);}
function div(a){return mul(a,recip(b));}
function unit(a){return mul_scalar(a,1/norm(a));}
function strf(x,d=33){return typeof x=='number'?(0+x).toExponential(8):strf(x[0],d+1)+String.fromCodePoint(d)+strf(x[1],d+1)}//avoid -0 problems

s={};iP=0;i=[[0,1],[0,0]];j=[[0,0],[1,0]];k=[[0,0],[0,1]];_1=[[1,0],[0,0]];
function gi(){return input.codePointAt(iP++)||-1;};function po(x){process.stdout.write(String.fromCodePoint(x[0][0]))};
e='acc=[[0,0],[0,0]];dp=[[1,0],[0,0]];';for(let i of code)switch(i){
case'^':e+='acc=s[strf(unit(dp))]||[[0,0],[0,0]];';break;
case'=':e+='s[strf(unit(dp))]=acc;';break;
case'1':e+='acc=_1;';break;
case'i':e+='acc=i;';break;
case'j':e+='acc=j;';break;
case'k':e+='acc=k;';break;
case'?':e+='acc=[i,j,k][~~(Math.random()*3)];';break;
case'+':e+='acc=add(acc,s[strf(unit(dp))]||[[0,0],[0,0]]);';break;
case'-':e+='acc=sub(acc,s[strf(unit(dp))]||[[0,0],[0,0]]);';break;
case'*':e+='acc=mul(acc,s[strf(unit(dp))]||[[0,0],[0,0]]);';break;
case'/':e+='acc=div(acc,s[strf(unit(dp))]||[[0,0],[0,0]]);';break;
case'`':e+='dp=mul(dp,acc);';break;
case'(':e+='if(norm(acc)==0){';break;
case'[':e+='while(norm(acc)==0){';break;
case'{':e+='while(norm(acc)!=0){';break;
case')':case']':case'}':e+='};';break;
case',':e+='acc=[[gi(),0],[0,0]];';break;
case'.':e+='po(acc);';break;}eval(e)