Quaternions

From Esolanging
(Redirected from Quaternerions)
Jump to navigationJump to search

inspiration

Quaternions is an esolang invented by user:phira, it is based on quaternions.

introduction to quaternions

a quaternion is a number with form a+bi+cj+dk where i, j, k are imaginary units, i2=j2=k2=1, and ijk=−1. NOTE: this means quaternions' multiplication is not commutative.

a quaternion 𝐪=a+bi+cj+dk has norm |𝐪|a2+b2+c2+d2, conjugate 𝐪¯a−bi−cj−dk, reciporial 𝐪−1=𝐪¯|𝐪|2 and negation −𝐪=−a−bi−cj−dk.

quaternions' addition do what you expect: (a+bi+cj+dk)+(e+fi+gj+hk)=(a+e)+(b+f)i+(c+g)j+(d+h)k.

quaternions' multiplication is defined as (a+bi+cj+dk)⋅(e+fi+gj+hk)=(ae−bf−cg−dh)+(af+be+ch−dg)i+(ag+ce+df−bh)j+(ah+bg−cf+de)k.

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=DP|DP|2. 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

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

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

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'?x.toExponential(8):strf(x[0],d+1)+String.fromCodePoint(d)+strf(x[1],d+1)}

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)