clifford icon indicating copy to clipboard operation
clifford copied to clipboard

Implement optimised sandwich product via product table

Open hugohadfield opened this issue 5 years ago • 4 comments

hugohadfield avatar Jun 19 '19 20:06 hugohadfield

@enkimute any chance you could link your reference implementation here so we can have a think about implementing it in clifford?

hugohadfield avatar Oct 16 '19 16:10 hugohadfield

Sure !

Here's the result of optimizing the sandwich product between a motor (in arg A, 16 floats) and a vector (in arg B, 5 floats) :

function sw_mot_vec(A,B,R=new vector()){
  var X=B[0],Y=B[1],Z=B[2],P=B[3],M=B[4],a0=A[0],a1=A[1],a2=A[2],a3=A[3],a4=A[4],a5=A[5],a6=A[6],a7=A[7],a8=A[8],a9=A[9],a10=A[10],a11=A[11],a12=A[12],a13=A[13],a14=A[14],a15=A[15];
  var _2a0=2*a0, _2a11=2*a11, _2a10=2*a10, _2a12=2*a12, _2a1=2*a1, _2a14=2*a14, _2a15=2*a15, _2a2=2*a2, _2a6=2*a6, _2a4=2*a4, _2a5=2*a5, a0a0=a0*a0, a1a1=a1*a1, a10a10=a10*a10, a11a11=a11*a11, a12a12=a12*a12, a13a13=a13*a13, a14a14=a14*a14, a15a15=a15*a15, a2a2=a2*a2, a3a3=a3*a3, a4a4=a4*a4, a5a5=a5*a5, a6a6=a6*a6, a7a7=a7*a7, a8a8=a8*a8, a9a9=a9*a9, _2a13=2*a13, _2a8=2*a8, _2a7=2*a7, _2a0a1=_2a0*a1, _2a0a10=_2a0*a10, _2a0a2=_2a0*a2, _2a0a3=_2a0*a3, _2a0a4=_2a0*a4, _2a0a5=_2a0*a5, _2a0a6=_2a0*a6, _2a0a7=_2a0*a7, _2a0a8=_2a0*a8, _2a0a9=_2a0*a9, _2a1a13=_2a1*a13, _2a1a2=_2a1*a2, _2a1a3=_2a1*a3, _2a1a4=_2a1*a4, _2a1a5=_2a1*a5, _2a1a6=_2a1*a6, _2a1a7=_2a1*a7, _2a10a13=_2a10*a13, _2a10a14=_2a10*a14, _2a10a15=_2a10*a15, _2a10a3=_2a10*a3, _2a10a4=_2a10*a4, _2a10a6=_2a10*a6, _2a10a7=_2a10*a7, _2a10a8=_2a10*a8, _2a10a9=_2a10*a9, _2a11a1=_2a11*a1, _2a11a12=_2a11*a12, _2a11a13=_2a11*a13, _2a11a14=_2a11*a14, _2a11a15=_2a11*a15, _2a11a2=_2a11*a2, _2a11a3=_2a11*a3, _2a11a5=_2a11*a5, _2a11a6=_2a11*a6, _2a11a8=_2a11*a8, _2a12a1=_2a12*a1, _2a12a13=_2a12*a13, _2a12a14=_2a12*a14, _2a12a15=_2a12*a15, _2a12a2=_2a12*a2, _2a12a4=_2a12*a4, _2a12a5=_2a12*a5, _2a12a7=_2a12*a7, _2a12a9=_2a12*a9, _2a13a3=_2a13*a3, _2a13a7=_2a13*a7, _2a14a13=_2a14*a13, _2a14a15=_2a14*a15, _2a14a2=_2a14*a2, _2a14a3=_2a14*a3, _2a14a4=_2a14*a4, _2a14a8=_2a14*a8, _2a14a9=_2a14*a9, _2a15a13=_2a15*a13, _2a15a5=_2a15*a5, _2a15a6=_2a15*a6, _2a15a7=_2a15*a7, _2a15a8=_2a15*a8, _2a15a9=_2a15*a9, _2a2a3=_2a2*a3, _2a2a4=_2a2*a4, _2a2a5=_2a2*a5, _2a2a8=_2a2*a8, _2a2a9=_2a2*a9, _2a4a13=_2a4*a13, _2a4a3=_2a4*a3, _2a4a7=_2a4*a7, _2a4a9=_2a4*a9, _2a5a7=_2a5*a7, _2a5a8=_2a5*a8, _2a5a9=_2a5*a9, _2a6a13=_2a6*a13, _2a6a3=_2a6*a3, _2a6a5=_2a6*a5, _2a6a7=_2a6*a7, _2a6a8=_2a6*a8, _2a7a9=_2a7*a9, _2a8a3=_2a8*a3, _2a8a9=_2a8*a9;
  R[0] =(-_2a6a13-_2a10a3-_2a0a4-_2a11a15-_2a12a5-_2a1a7-_2a14a8-_2a2a9)*M+(_2a0a3+_2a10a4+_2a12a15+_2a11a5+_2a1a6+_2a13a7+_2a2a8+_2a14a9)*P+(a0a0-a10a10-a11a11-a1a1+a12a12-a2a2+a13a13-a3a3+a14a14+a4a4-a15a15+a5a5+a6a6-a7a7+a8a8-a9a9)*X+(_2a0a1-_2a10a13-_2a6a3+_2a14a15-_2a2a5+_2a4a7+_2a11a8-_2a12a9)*Y+(_2a0a2-_2a15a13-_2a8a3-_2a10a14+_2a1a5-_2a11a6+_2a12a7+_2a4a9)*Z
  R[1] =(_2a12a2+_2a13a3+_2a11a14+_2a1a4-_2a10a6-_2a0a7-_2a15a8-_2a5a9)*M+(_2a0a6+_2a10a7+_2a5a8+_2a15a9-_2a4a13-_2a1a3-_2a12a14-_2a11a2)*P+(_2a10a13-_2a0a1-_2a6a3+_2a14a15-_2a2a5+_2a4a7-_2a11a8+_2a12a9)*X+(a0a0-a10a10-a11a11-a1a1+a12a12+a2a2+a13a13+a3a3-a14a14-a4a4+a15a15-a5a5-a6a6+a7a7+a8a8-a9a9)*Y+(_2a14a13-_2a1a2+_2a11a3-_2a12a4-_2a10a15+_2a0a5-_2a6a8+_2a7a9)*Z
  R[2] =(_2a14a3+_2a2a4+_2a15a6+_2a5a7-_2a11a13-_2a12a1-_2a10a8-_2a0a9)*M+(_2a11a1+_2a12a13-_2a2a3-_2a14a4-_2a6a5-_2a15a7+_2a0a8+_2a10a9)*P+(_2a10a14+_2a1a5+_2a11a6-_2a15a13-_2a8a3-_2a0a2-_2a12a7+_2a4a9)*X+(_2a14a13-_2a1a2-_2a11a3+_2a12a4+_2a10a15-_2a0a5-_2a6a8+_2a7a9)*Y+(a0a0-a10a10-a11a11+a1a1+a12a12-a2a2-a13a13+a3a3+a14a14-a4a4+a15a15-a5a5+a6a6-a7a7-a8a8+a9a9)*Z
  R[3] =(_2a11a12-_2a0a10-_2a14a2-_2a1a13+_2a4a3-_2a15a5+_2a6a7+_2a8a9)*M+(a10a10+a0a0-a11a11+a1a1-a12a12+a2a2+a13a13-a3a3+a14a14-a4a4+a15a15+a5a5-a6a6-a7a7-a8a8-a9a9)*P+(_2a10a4-_2a0a3+_2a12a15-_2a11a5+_2a1a6-_2a13a7+_2a2a8-_2a14a9)*X+(_2a11a2+_2a4a13-_2a1a3-_2a12a14-_2a0a6+_2a10a7+_2a5a8-_2a15a9)*Y+(_2a12a13-_2a11a1-_2a2a3+_2a14a4-_2a6a5+_2a15a7-_2a0a8+_2a10a9)*Z
  R[4] =(a10a10+a0a0+a11a11+a1a1+a12a12+a2a2+a13a13+a3a3+a14a14+a4a4+a15a15+a5a5+a6a6+a7a7+a8a8+a9a9)*M+(-_2a0a10-_2a11a12-_2a14a2-_2a1a13-_2a4a3-_2a15a5-_2a6a7-_2a8a9)*P+(_2a10a3-_2a6a13-_2a0a4+_2a11a15-_2a12a5+_2a1a7-_2a14a8+_2a2a9)*X+(_2a12a2+_2a13a3-_2a11a14-_2a1a4+_2a10a6-_2a0a7-_2a15a8+_2a5a9)*Y+(_2a11a13-_2a12a1+_2a14a3-_2a2a4+_2a15a6-_2a5a7+_2a10a8-_2a0a9)*Z
  // muls : 135 from 640
  // adds : 237 from 239
  return R
}

For this scenario, my optimizer is able to reduce the number of needed multiplies from 640 to 135 .. quite a save. Additionally, no inbetween storage (which would need to be a full multivector) is required.

Also notice how the optimizer ends in a 'matrix like' form, which means you can do much bigger savings when transforming a list of vectors with the same motor. (I generate specific functions for that to).

Savings are even bigger for the sandwich product between a motor (16 floats) and a full multivector (32 floats) :

function sw_mot_mv(A,B,R=new multivector()){
  var s0=B[0],v0=B[1],v1=B[2],v2=B[3],v3=B[4],v4=B[5],b0=B[6],b1=B[7],b2=B[8],b3=B[9],b4=B[10],b5=B[11],b6=B[12],b7=B[13],b8=B[14],b9=B[15],t0=B[16],t1=B[17],t2=B[18],t3=B[19],t4=B[20],t5=B[21],t6=B[22],t7=B[23],t8=B[24],t9=B[25],q0=B[26],q1=B[27],q2=B[28],q3=B[29],q4=B[30],p1=B[31],a0=A[0],a1=A[1],a2=A[2],a3=A[3],a4=A[4],a5=A[5],a6=A[6],a7=A[7],a8=A[8],a9=A[9],a10=A[10],a11=A[11],a12=A[12],a13=A[13],a14=A[14],a15=A[15];
  var a0a0=a0*a0, a1a1=a1*a1, a10a10=a10*a10, a11a11=a11*a11, a12a12=a12*a12, a13a13=a13*a13, a14a14=a14*a14, a15a15=a15*a15, a2a2=a2*a2, a3a3=a3*a3, a4a4=a4*a4, a5a5=a5*a5, a6a6=a6*a6, a7a7=a7*a7, a8a8=a8*a8, a9a9=a9*a9, a0a1=a0*a1, a0a10=a0*a10, a0a11=a0*a11, a0a12=a0*a12, a0a13=a0*a13, a0a14=a0*a14, a0a15=a0*a15, a0a2=a0*a2, a0a3=a0*a3, a0a4=a0*a4, a0a5=a0*a5, a0a6=a0*a6, a0a7=a0*a7, a0a8=a0*a8, a0a9=a0*a9, a1a10=a1*a10, a1a11=a1*a11, a1a12=a1*a12, a1a13=a1*a13, a1a14=a1*a14, a1a15=a1*a15, a1a2=a1*a2, a1a3=a1*a3, a1a4=a1*a4, a1a5=a1*a5, a1a6=a1*a6, a1a7=a1*a7, a1a8=a1*a8, a1a9=a1*a9, a10a11=a10*a11, a10a12=a10*a12, a10a13=a10*a13, a10a14=a10*a14, a10a15=a10*a15, a10a2=a10*a2, a10a3=a10*a3, a10a4=a10*a4, a10a5=a10*a5, a10a6=a10*a6, a10a7=a10*a7, a10a8=a10*a8, a10a9=a10*a9, a11a12=a11*a12, a11a13=a11*a13, a11a14=a11*a14, a11a15=a11*a15, a11a2=a11*a2, a11a3=a11*a3, a11a4=a11*a4, a11a5=a11*a5, a11a6=a11*a6, a11a7=a11*a7, a11a8=a11*a8, a11a9=a11*a9, a12a13=a12*a13, a12a14=a12*a14, a12a15=a12*a15, a12a2=a12*a2, a12a3=a12*a3, a12a4=a12*a4, a12a5=a12*a5, a12a6=a12*a6, a12a7=a12*a7, a12a8=a12*a8, a12a9=a12*a9, a13a14=a13*a14, a13a15=a13*a15, a13a2=a13*a2, a13a3=a13*a3, a13a4=a13*a4, a13a5=a13*a5, a13a6=a13*a6, a13a7=a13*a7, a13a8=a13*a8, a13a9=a13*a9, a14a15=a14*a15, a14a2=a14*a2, a14a3=a14*a3, a14a4=a14*a4, a14a5=a14*a5, a14a6=a14*a6, a14a7=a14*a7, a14a8=a14*a8, a14a9=a14*a9, a15a2=a15*a2, a15a3=a15*a3, a15a4=a15*a4, a15a5=a15*a5, a15a6=a15*a6, a15a7=a15*a7, a15a8=a15*a8, a15a9=a15*a9, a2a3=a2*a3, a2a4=a2*a4, a2a5=a2*a5, a2a6=a2*a6, a2a7=a2*a7, a2a8=a2*a8, a2a9=a2*a9, a3a4=a3*a4, a3a5=a3*a5, a3a6=a3*a6, a3a7=a3*a7, a3a8=a3*a8, a3a9=a3*a9, a4a5=a4*a5, a4a6=a4*a6, a4a7=a4*a7, a4a8=a4*a8, a4a9=a4*a9, a5a6=a5*a6, a5a7=a5*a7, a5a8=a5*a8, a5a9=a5*a9, a6a7=a6*a7, a6a8=a6*a8, a6a9=a6*a9, a7a8=a7*a8, a7a9=a7*a9, a8a9=a8*a9;
  R[0] =(a0a11*2+a10a12*2-a15a4*2-a3a5*2+a2a6*2+a14a7*2-a1a8*2-a13a9*2)*q0+(a0a0-a10a10+a11a11+a1a1-a12a12+a2a2-a13a13+a3a3-a14a14-a4a4-a15a15+a5a5+a6a6-a7a7+a8a8-a9a9)*s0+(a15a3*2+a4a5*2-a0a12*2-a10a11*2-a14a6*2-a2a7*2+a13a8*2+a1a9*2)*q1+(a1a10*2-a15a2*2-a0a13*2+a14a5*2+a4a6*2-a3a7*2-a12a8*2+a11a9*2)*q2+(a10a2*2-a0a14*2+a1a15*2-a13a5*2+a12a6*2-a11a7*2+a4a8*2-a3a9*2)*q3+(a13a2*2-a12a3*2-a1a14*2+a11a4*2-a0a15*2+a10a5*2+a7a8*2-a6a9*2)*q4
  R[1] =(a0a0-a10a10-a11a11-a1a1+a12a12-a2a2+a13a13-a3a3+a14a14+a4a4-a15a15+a5a5+a6a6-a7a7+a8a8-a9a9)*v0+(a12a3*2-a13a2*2+a1a14*2-a11a4*2-a0a15*2+a10a5*2+a7a8*2-a6a9*2)*p1+(a0a1*2-a10a13*2+a14a15*2-a2a5*2-a3a6*2+a4a7*2+a11a8*2-a12a9*2)*v1+(a0a2*2-a10a14*2-a13a15*2+a1a5*2-a11a6*2+a12a7*2-a3a8*2+a4a9*2)*v2+(a0a3*2+a10a4*2+a12a15*2+a11a5*2+a1a6*2+a13a7*2+a2a8*2+a14a9*2)*v3+(-a10a3*2-a0a4*2-a11a15*2-a12a5*2-a13a6*2-a1a7*2-a14a8*2-a2a9*2)*v4
  R[2] =(a10a13*2-a0a1*2+a14a15*2-a2a5*2-a3a6*2+a4a7*2-a11a8*2+a12a9*2)*v0+(a0a14*2-a10a2*2+a1a15*2-a13a5*2+a12a6*2-a11a7*2-a4a8*2+a3a9*2)*p1+(a0a0-a10a10-a11a11-a1a1+a12a12+a2a2+a13a13+a3a3-a14a14-a4a4+a15a15-a5a5-a6a6+a7a7+a8a8-a9a9)*v1+(a11a3*2-a1a2*2+a13a14*2-a12a4*2-a10a15*2+a0a5*2-a6a8*2+a7a9*2)*v2+(a0a6*2+a10a7*2+a5a8*2+a15a9*2-a1a3*2-a12a14*2-a13a4*2-a11a2*2)*v3+(a12a2*2+a13a3*2+a11a14*2+a1a4*2-a10a6*2-a0a7*2-a15a8*2-a5a9*2)*v4
  R[3] =(a10a14*2-a0a2*2-a13a15*2+a1a5*2+a11a6*2-a12a7*2-a3a8*2+a4a9*2)*v0+(a1a10*2+a15a2*2-a0a13*2-a14a5*2+a4a6*2-a3a7*2+a12a8*2-a11a9*2)*p1+(a13a14*2+a12a4*2+a10a15*2-a11a3*2-a1a2*2-a0a5*2-a6a8*2+a7a9*2)*v1+(a0a0-a10a10-a11a11+a1a1+a12a12-a2a2-a13a13+a3a3+a14a14-a4a4+a15a15-a5a5+a6a6-a7a7-a8a8+a9a9)*v2+(a1a11*2+a12a13*2-a2a3*2-a14a4*2-a5a6*2-a15a7*2+a0a8*2+a10a9*2)*v3+(a14a3*2+a2a4*2+a15a6*2+a5a7*2-a11a13*2-a1a12*2-a10a8*2-a0a9*2)*v4
  R[4] =(a10a4*2-a0a3*2+a12a15*2-a11a5*2+a1a6*2-a13a7*2+a2a8*2-a14a9*2)*v0+(a0a12*2-a10a11*2+a15a3*2-a4a5*2-a14a6*2+a2a7*2+a13a8*2-a1a9*2)*p1+(a11a2*2-a1a3*2-a12a14*2+a13a4*2-a0a6*2+a10a7*2+a5a8*2-a15a9*2)*v1+(a12a13*2-a1a11*2-a2a3*2+a14a4*2-a5a6*2+a15a7*2-a0a8*2+a10a9*2)*v2+(a10a10+a0a0-a11a11+a1a1-a12a12+a2a2+a13a13-a3a3+a14a14-a4a4+a15a15+a5a5-a6a6-a7a7-a8a8-a9a9)*v3+(a11a12*2-a0a10*2-a14a2*2-a1a13*2+a3a4*2-a15a5*2+a6a7*2+a8a9*2)*v4
  R[5] =(a10a3*2-a0a4*2+a11a15*2-a12a5*2-a13a6*2+a1a7*2-a14a8*2+a2a9*2)*v0+(a0a11*2-a10a12*2+a15a4*2-a3a5*2+a2a6*2-a14a7*2-a1a8*2+a13a9*2)*p1+(a12a2*2+a13a3*2-a11a14*2-a1a4*2+a10a6*2-a0a7*2-a15a8*2+a5a9*2)*v1+(a11a13*2-a1a12*2+a14a3*2-a2a4*2+a15a6*2-a5a7*2+a10a8*2-a0a9*2)*v2+(-a0a10*2-a11a12*2-a14a2*2-a1a13*2-a3a4*2-a15a5*2-a6a7*2-a8a9*2)*v3+(a10a10+a0a0+a11a11+a1a1+a12a12+a2a2+a13a13+a3a3+a14a14+a4a4+a15a15+a5a5+a6a6+a7a7+a8a8+a9a9)*v4
  R[6] =(a0a0-a10a10+a11a11+a1a1-a12a12-a2a2-a13a13-a3a3+a14a14+a4a4+a15a15-a5a5-a6a6+a7a7+a8a8-a9a9)*b0+(a1a2*2-a11a3*2-a13a14*2+a12a4*2-a10a15*2+a0a5*2-a6a8*2+a7a9*2)*b1+(a11a2*2+a1a3*2+a12a14*2+a13a4*2+a0a6*2+a10a7*2+a5a8*2+a15a9*2)*b2+(-a12a2*2-a13a3*2-a11a14*2-a1a4*2-a10a6*2-a0a7*2-a15a8*2-a5a9*2)*b3+(a10a14*2-a0a2*2-a13a15*2+a1a5*2-a11a6*2+a12a7*2+a3a8*2-a4a9*2)*b4+(a12a15*2+a11a5*2+a1a6*2+a13a7*2-a10a4*2-a0a3*2-a2a8*2-a14a9*2)*b5+(a10a3*2+a0a4*2-a11a15*2-a12a5*2-a13a6*2-a1a7*2+a14a8*2+a2a9*2)*b6+(a2a6*2+a14a7*2+a1a8*2+a13a9*2-a10a12*2-a15a4*2-a3a5*2-a0a11*2)*b7+(a10a11*2+a0a12*2+a15a3*2+a4a5*2-a14a6*2-a2a7*2-a13a8*2-a1a9*2)*b8+(a0a13*2+a14a5*2+a4a6*2-a15a2*2-a1a10*2-a3a7*2+a12a8*2-a11a9*2)*b9
  R[7] =(a1a2*2+a11a3*2-a13a14*2-a12a4*2+a10a15*2-a0a5*2-a6a8*2+a7a9*2)*b0+(a0a0-a10a10+a11a11-a1a1-a12a12+a2a2+a13a13-a3a3-a14a14+a4a4+a15a15-a5a5+a6a6-a7a7-a8a8+a9a9)*b1+(a2a3*2+a14a4*2-a12a13*2-a1a11*2-a5a6*2-a15a7*2+a0a8*2+a10a9*2)*b2+(a1a12*2+a11a13*2-a14a3*2-a2a4*2+a15a6*2+a5a7*2-a10a8*2-a0a9*2)*b3+(a0a1*2-a10a13*2-a14a15*2+a2a5*2-a3a6*2+a4a7*2-a11a8*2+a12a9*2)*b4+(a0a11*2+a10a12*2+a15a4*2+a3a5*2+a2a6*2+a14a7*2+a1a8*2+a13a9*2)*b5+(-a10a11*2-a0a12*2-a15a3*2-a4a5*2-a14a6*2-a2a7*2-a13a8*2-a1a9*2)*b6+(a12a15*2+a11a5*2-a10a4*2-a0a3*2-a1a6*2-a13a7*2+a2a8*2+a14a9*2)*b7+(a10a3*2+a0a4*2-a11a15*2-a12a5*2+a13a6*2+a1a7*2-a14a8*2-a2a9*2)*b8+(a0a14*2-a10a2*2+a1a15*2-a13a5*2-a12a6*2+a11a7*2+a4a8*2-a3a9*2)*b9
  R[8] =(a1a3*2-a11a2*2+a12a14*2-a13a4*2-a0a6*2+a10a7*2+a5a8*2-a15a9*2)*b0+(a1a11*2-a12a13*2+a2a3*2-a14a4*2-a5a6*2+a15a7*2-a0a8*2+a10a9*2)*b1+(a10a10+a0a0+a11a11-a1a1+a12a12-a2a2-a13a13+a3a3-a14a14+a4a4+a15a15+a5a5-a6a6-a7a7-a8a8-a9a9)*b2+(a14a2*2+a1a13*2-a11a12*2-a0a10*2-a3a4*2-a15a5*2+a6a7*2+a8a9*2)*b3+(a10a12*2-a0a11*2-a15a4*2+a3a5*2+a2a6*2-a14a7*2-a1a8*2+a13a9*2)*b4+(a0a1*2+a10a13*2-a14a15*2-a2a5*2+a3a6*2+a4a7*2-a11a8*2-a12a9*2)*b5+(a15a2*2-a1a10*2-a0a13*2+a14a5*2-a4a6*2-a3a7*2+a12a8*2+a11a9*2)*b6+(a0a2*2+a10a14*2+a13a15*2+a1a5*2+a11a6*2+a12a7*2+a3a8*2+a4a9*2)*b7+(-a10a2*2-a0a14*2-a1a15*2-a13a5*2-a12a6*2-a11a7*2-a4a8*2-a3a9*2)*b8+(a0a4*2-a10a3*2-a11a15*2+a12a5*2-a13a6*2+a1a7*2-a14a8*2+a2a9*2)*b9
  R[9] =(a11a14*2+a1a4*2+a10a6*2-a13a3*2-a12a2*2-a0a7*2-a15a8*2+a5a9*2)*b0+(a1a12*2-a11a13*2-a14a3*2+a2a4*2+a15a6*2-a5a7*2+a10a8*2-a0a9*2)*b1+(a11a12*2-a0a10*2+a14a2*2+a1a13*2+a3a4*2-a15a5*2-a6a7*2-a8a9*2)*b2+(a10a10+a0a0-a11a11-a1a1-a12a12-a2a2-a13a13-a3a3-a14a14-a4a4+a15a15+a5a5+a6a6+a7a7+a8a8+a9a9)*b3+(a10a11*2-a0a12*2-a15a3*2+a4a5*2-a14a6*2+a2a7*2+a13a8*2-a1a9*2)*b4+(a15a2*2-a1a10*2-a0a13*2+a14a5*2+a4a6*2+a3a7*2-a12a8*2-a11a9*2)*b5+(a0a1*2+a10a13*2-a14a15*2-a2a5*2-a3a6*2-a4a7*2+a11a8*2+a12a9*2)*b6+(a12a6*2+a11a7*2+a4a8*2+a3a9*2-a0a14*2-a1a15*2-a13a5*2-a10a2*2)*b7+(a0a2*2+a10a14*2+a13a15*2+a1a5*2-a11a6*2-a12a7*2-a3a8*2-a4a9*2)*b8+(a0a3*2-a10a4*2-a12a15*2+a11a5*2+a1a6*2-a13a7*2+a2a8*2-a14a9*2)*b9
  R[10] =(a0a2*2-a10a14*2-a13a15*2+a1a5*2+a11a6*2-a12a7*2+a3a8*2-a4a9*2)*b0+(a10a13*2-a0a1*2-a14a15*2+a2a5*2-a3a6*2+a4a7*2+a11a8*2-a12a9*2)*b1+(a15a4*2+a3a5*2+a2a6*2+a14a7*2-a10a12*2-a0a11*2-a1a8*2-a13a9*2)*b2+(a10a11*2+a0a12*2-a15a3*2-a4a5*2-a14a6*2-a2a7*2+a13a8*2+a1a9*2)*b3+(a0a0-a10a10+a11a11-a1a1-a12a12-a2a2+a13a13+a3a3+a14a14-a4a4-a15a15+a5a5-a6a6+a7a7-a8a8+a9a9)*b4+(a5a6*2+a15a7*2+a0a8*2+a10a9*2-a12a13*2-a2a3*2-a14a4*2-a1a11*2)*b5+(a1a12*2+a11a13*2+a14a3*2+a2a4*2-a15a6*2-a5a7*2-a10a8*2-a0a9*2)*b6+(a1a3*2-a11a2*2-a12a14*2+a13a4*2-a0a6*2-a10a7*2+a5a8*2+a15a9*2)*b7+(a12a2*2-a13a3*2+a11a14*2-a1a4*2+a10a6*2+a0a7*2-a15a8*2-a5a9*2)*b8+(a13a2*2+a12a3*2-a1a14*2-a11a4*2+a0a15*2-a10a5*2+a7a8*2-a6a9*2)*b9
  R[11] =(a0a3*2-a10a4*2+a12a15*2-a11a5*2+a1a6*2-a13a7*2-a2a8*2+a14a9*2)*b0+(a0a11*2-a10a12*2-a15a4*2+a3a5*2+a2a6*2-a14a7*2+a1a8*2-a13a9*2)*b1+(a3a6*2+a4a7*2+a11a8*2+a12a9*2-a10a13*2-a14a15*2-a2a5*2-a0a1*2)*b2+(a1a10*2+a15a2*2+a0a13*2+a14a5*2-a4a6*2-a3a7*2-a12a8*2-a11a9*2)*b3+(a1a11*2-a12a13*2-a2a3*2+a14a4*2+a5a6*2-a15a7*2-a0a8*2+a10a9*2)*b4+(a10a10+a0a0+a11a11-a1a1+a12a12+a2a2-a13a13-a3a3+a14a14-a4a4-a15a15-a5a5+a6a6+a7a7-a8a8-a9a9)*b5+(a1a13*2+a3a4*2+a15a5*2-a11a12*2-a14a2*2-a0a10*2-a6a7*2+a8a9*2)*b6+(a10a15*2+a0a5*2+a6a8*2+a7a9*2-a11a3*2-a13a14*2-a12a4*2-a1a2*2)*b7+(a13a2*2+a12a3*2+a1a14*2+a11a4*2-a0a15*2-a10a5*2-a7a8*2-a6a9*2)*b8+(a13a3*2-a12a2*2+a11a14*2-a1a4*2-a10a6*2+a0a7*2-a15a8*2+a5a9*2)*b9
  R[12] =(a0a4*2-a10a3*2+a11a15*2-a12a5*2-a13a6*2+a1a7*2+a14a8*2-a2a9*2)*b0+(a0a12*2-a10a11*2-a15a3*2+a4a5*2-a14a6*2+a2a7*2-a13a8*2+a1a9*2)*b1+(a1a10*2+a15a2*2+a0a13*2+a14a5*2+a4a6*2+a3a7*2+a12a8*2+a11a9*2)*b2+(-a0a1*2-a10a13*2-a14a15*2-a2a5*2-a3a6*2-a4a7*2-a11a8*2-a12a9*2)*b3+(a1a12*2-a11a13*2+a14a3*2-a2a4*2-a15a6*2+a5a7*2+a10a8*2-a0a9*2)*b4+(a11a12*2-a0a10*2-a14a2*2+a1a13*2-a3a4*2+a15a5*2+a6a7*2-a8a9*2)*b5+(a10a10+a0a0-a11a11-a1a1-a12a12+a2a2-a13a13+a3a3+a14a14+a4a4-a15a15-a5a5-a6a6-a7a7+a8a8+a9a9)*b6+(a13a2*2-a12a3*2+a1a14*2-a11a4*2-a0a15*2-a10a5*2+a7a8*2+a6a9*2)*b7+(a11a3*2-a1a2*2-a13a14*2+a12a4*2+a10a15*2+a0a5*2-a6a8*2-a7a9*2)*b8+(a12a14*2+a13a4*2+a0a6*2-a1a3*2-a11a2*2-a10a7*2+a5a8*2-a15a9*2)*b9
  R[13] =(a10a12*2-a0a11*2+a15a4*2-a3a5*2+a2a6*2-a14a7*2+a1a8*2-a13a9*2)*b0+(a0a3*2-a10a4*2+a12a15*2-a11a5*2-a1a6*2+a13a7*2+a2a8*2-a14a9*2)*b1+(a13a15*2+a1a5*2-a10a14*2-a0a2*2-a11a6*2-a12a7*2+a3a8*2+a4a9*2)*b2+(a10a2*2+a0a14*2-a1a15*2-a13a5*2+a12a6*2+a11a7*2-a4a8*2-a3a9*2)*b3+(a11a2*2+a1a3*2-a12a14*2-a13a4*2+a0a6*2-a10a7*2+a5a8*2-a15a9*2)*b4+(a11a3*2-a1a2*2-a13a14*2+a12a4*2-a10a15*2-a0a5*2+a6a8*2+a7a9*2)*b5+(a13a2*2-a12a3*2+a1a14*2-a11a4*2+a0a15*2+a10a5*2-a7a8*2-a6a9*2)*b6+(a10a10+a0a0+a11a11+a1a1+a12a12-a2a2+a13a13-a3a3-a14a14-a4a4-a15a15-a5a5-a6a6-a7a7+a8a8+a9a9)*b7+(a14a2*2-a11a12*2-a0a10*2-a1a13*2+a3a4*2+a15a5*2+a6a7*2-a8a9*2)*b8+(a1a12*2-a11a13*2+a14a3*2-a2a4*2+a15a6*2-a5a7*2-a10a8*2+a0a9*2)*b9
  R[14] =(a10a11*2-a0a12*2+a15a3*2-a4a5*2-a14a6*2+a2a7*2-a13a8*2+a1a9*2)*b0+(a0a4*2-a10a3*2+a11a15*2-a12a5*2+a13a6*2-a1a7*2-a14a8*2+a2a9*2)*b1+(a10a2*2+a0a14*2-a1a15*2-a13a5*2-a12a6*2-a11a7*2+a4a8*2+a3a9*2)*b2+(a13a15*2+a1a5*2+a11a6*2+a12a7*2-a10a14*2-a0a2*2-a3a8*2-a4a9*2)*b3+(a12a2*2-a13a3*2-a11a14*2+a1a4*2-a10a6*2+a0a7*2-a15a8*2+a5a9*2)*b4+(a13a2*2+a12a3*2+a1a14*2+a11a4*2+a0a15*2+a10a5*2+a7a8*2+a6a9*2)*b5+(-a1a2*2-a11a3*2-a13a14*2-a12a4*2-a10a15*2-a0a5*2-a6a8*2-a7a9*2)*b6+(a11a12*2-a0a10*2+a14a2*2-a1a13*2-a3a4*2+a15a5*2-a6a7*2+a8a9*2)*b7+(a10a10+a0a0-a11a11+a1a1-a12a12-a2a2+a13a13+a3a3-a14a14+a4a4-a15a15-a5a5+a6a6+a7a7-a8a8-a9a9)*b8+(a1a11*2-a12a13*2-a2a3*2+a14a4*2-a5a6*2+a15a7*2+a0a8*2-a10a9*2)*b9
  R[15] =(a1a10*2-a15a2*2-a0a13*2+a14a5*2-a4a6*2+a3a7*2+a12a8*2-a11a9*2)*b0+(a10a2*2-a0a14*2+a1a15*2-a13a5*2-a12a6*2+a11a7*2-a4a8*2+a3a9*2)*b1+(a10a3*2+a0a4*2+a11a15*2+a12a5*2-a13a6*2-a1a7*2-a14a8*2-a2a9*2)*b2+(a1a6*2+a13a7*2+a2a8*2+a14a9*2-a10a4*2-a12a15*2-a11a5*2-a0a3*2)*b3+(a13a2*2+a12a3*2-a1a14*2-a11a4*2-a0a15*2+a10a5*2-a7a8*2+a6a9*2)*b4+(a13a3*2-a12a2*2-a11a14*2+a1a4*2+a10a6*2+a0a7*2-a15a8*2-a5a9*2)*b5+(a11a2*2-a1a3*2+a12a14*2-a13a4*2-a0a6*2-a10a7*2+a5a8*2+a15a9*2)*b6+(a1a12*2+a11a13*2+a14a3*2+a2a4*2+a15a6*2+a5a7*2+a10a8*2+a0a9*2)*b7+(-a1a11*2-a12a13*2-a2a3*2-a14a4*2-a5a6*2-a15a7*2-a0a8*2-a10a9*2)*b8+(a0a0-a10a10-a11a11+a1a1+a12a12+a2a2-a13a13-a3a3-a14a14+a4a4-a15a15+a5a5-a6a6+a7a7-a8a8+a9a9)*b9
  R[16] =(a0a0-a10a10-a11a11+a1a1+a12a12+a2a2-a13a13-a3a3-a14a14+a4a4-a15a15+a5a5-a6a6+a7a7-a8a8+a9a9)*t0+(a1a11*2+a12a13*2+a2a3*2+a14a4*2+a5a6*2+a15a7*2+a0a8*2+a10a9*2)*t1+(-a1a12*2-a11a13*2-a14a3*2-a2a4*2-a15a6*2-a5a7*2-a10a8*2-a0a9*2)*t2+(a11a2*2-a1a3*2+a12a14*2-a13a4*2-a0a6*2-a10a7*2+a5a8*2+a15a9*2)*t3+(a13a3*2-a12a2*2-a11a14*2+a1a4*2+a10a6*2+a0a7*2-a15a8*2-a5a9*2)*t4+(a1a14*2+a11a4*2+a0a15*2-a12a3*2-a13a2*2-a10a5*2+a7a8*2-a6a9*2)*t5+(a0a3*2+a10a4*2+a12a15*2+a11a5*2-a1a6*2-a13a7*2-a2a8*2-a14a9*2)*t6+(a13a6*2+a1a7*2+a14a8*2+a2a9*2-a0a4*2-a11a15*2-a12a5*2-a10a3*2)*t7+(a10a2*2-a0a14*2+a1a15*2-a13a5*2-a12a6*2+a11a7*2-a4a8*2+a3a9*2)*t8+(a15a2*2-a1a10*2+a0a13*2-a14a5*2+a4a6*2-a3a7*2-a12a8*2+a11a9*2)*t9
  R[17] =(a12a13*2-a1a11*2+a2a3*2-a14a4*2+a5a6*2-a15a7*2-a0a8*2+a10a9*2)*t0+(a10a10+a0a0-a11a11+a1a1-a12a12-a2a2+a13a13+a3a3-a14a14+a4a4-a15a15-a5a5+a6a6+a7a7-a8a8-a9a9)*t1+(a11a12*2-a0a10*2+a14a2*2-a1a13*2-a3a4*2+a15a5*2-a6a7*2+a8a9*2)*t2+(a1a2*2+a11a3*2+a13a14*2+a12a4*2+a10a15*2+a0a5*2+a6a8*2+a7a9*2)*t3+(-a13a2*2-a12a3*2-a1a14*2-a11a4*2-a0a15*2-a10a5*2-a7a8*2-a6a9*2)*t4+(a12a2*2-a13a3*2-a11a14*2+a1a4*2-a10a6*2+a0a7*2-a15a8*2+a5a9*2)*t5+(a13a15*2+a1a5*2+a11a6*2+a12a7*2-a10a14*2-a0a2*2-a3a8*2-a4a9*2)*t6+(a10a2*2+a0a14*2-a1a15*2-a13a5*2-a12a6*2-a11a7*2+a4a8*2+a3a9*2)*t7+(a10a3*2-a0a4*2-a11a15*2+a12a5*2-a13a6*2+a1a7*2+a14a8*2-a2a9*2)*t8+(a10a11*2-a0a12*2+a15a3*2-a4a5*2-a14a6*2+a2a7*2-a13a8*2+a1a9*2)*t9
  R[18] =(a11a13*2-a1a12*2-a14a3*2+a2a4*2-a15a6*2+a5a7*2+a10a8*2-a0a9*2)*t0+(a14a2*2-a11a12*2-a0a10*2-a1a13*2+a3a4*2+a15a5*2+a6a7*2-a8a9*2)*t1+(a10a10+a0a0+a11a11+a1a1+a12a12-a2a2+a13a13-a3a3-a14a14-a4a4-a15a15-a5a5-a6a6-a7a7+a8a8+a9a9)*t2+(a12a3*2-a13a2*2-a1a14*2+a11a4*2-a0a15*2-a10a5*2+a7a8*2+a6a9*2)*t3+(a1a2*2-a11a3*2+a13a14*2-a12a4*2+a10a15*2+a0a5*2-a6a8*2-a7a9*2)*t4+(a11a2*2+a1a3*2-a12a14*2-a13a4*2+a0a6*2-a10a7*2+a5a8*2-a15a9*2)*t5+(a10a2*2+a0a14*2-a1a15*2-a13a5*2+a12a6*2+a11a7*2-a4a8*2-a3a9*2)*t6+(a13a15*2+a1a5*2-a10a14*2-a0a2*2-a11a6*2-a12a7*2+a3a8*2+a4a9*2)*t7+(a10a4*2-a0a3*2-a12a15*2+a11a5*2+a1a6*2-a13a7*2-a2a8*2+a14a9*2)*t8+(a10a12*2-a0a11*2+a15a4*2-a3a5*2+a2a6*2-a14a7*2+a1a8*2-a13a9*2)*t9
  R[19] =(a12a14*2+a13a4*2+a0a6*2-a1a3*2-a11a2*2-a10a7*2+a5a8*2-a15a9*2)*t0+(a1a2*2-a11a3*2+a13a14*2-a12a4*2-a10a15*2-a0a5*2+a6a8*2+a7a9*2)*t1+(a12a3*2-a13a2*2-a1a14*2+a11a4*2+a0a15*2+a10a5*2-a7a8*2-a6a9*2)*t2+(a10a10+a0a0-a11a11-a1a1-a12a12+a2a2-a13a13+a3a3+a14a14+a4a4-a15a15-a5a5-a6a6-a7a7+a8a8+a9a9)*t3+(a11a12*2-a0a10*2-a14a2*2+a1a13*2-a3a4*2+a15a5*2+a6a7*2-a8a9*2)*t4+(a11a13*2-a1a12*2-a14a3*2+a2a4*2+a15a6*2-a5a7*2-a10a8*2+a0a9*2)*t5+(a0a1*2+a10a13*2+a14a15*2+a2a5*2+a3a6*2+a4a7*2+a11a8*2+a12a9*2)*t6+(-a1a10*2-a15a2*2-a0a13*2-a14a5*2-a4a6*2-a3a7*2-a12a8*2-a11a9*2)*t7+(a0a12*2-a10a11*2-a15a3*2+a4a5*2-a14a6*2+a2a7*2-a13a8*2+a1a9*2)*t8+(a10a3*2-a0a4*2-a11a15*2+a12a5*2+a13a6*2-a1a7*2-a14a8*2+a2a9*2)*t9
  R[20] =(a13a3*2-a12a2*2+a11a14*2-a1a4*2-a10a6*2+a0a7*2-a15a8*2+a5a9*2)*t0+(a0a15*2+a10a5*2+a7a8*2+a6a9*2-a12a3*2-a1a14*2-a11a4*2-a13a2*2)*t1+(a1a2*2+a11a3*2+a13a14*2+a12a4*2-a10a15*2-a0a5*2-a6a8*2-a7a9*2)*t2+(a1a13*2+a3a4*2+a15a5*2-a11a12*2-a14a2*2-a0a10*2-a6a7*2+a8a9*2)*t3+(a10a10+a0a0+a11a11-a1a1+a12a12+a2a2-a13a13-a3a3+a14a14-a4a4-a15a15-a5a5+a6a6+a7a7-a8a8-a9a9)*t4+(a12a13*2-a1a11*2+a2a3*2-a14a4*2-a5a6*2+a15a7*2+a0a8*2-a10a9*2)*t5+(a4a6*2+a3a7*2+a12a8*2+a11a9*2-a15a2*2-a0a13*2-a14a5*2-a1a10*2)*t6+(a0a1*2+a10a13*2+a14a15*2+a2a5*2-a3a6*2-a4a7*2-a11a8*2-a12a9*2)*t7+(a0a11*2-a10a12*2-a15a4*2+a3a5*2+a2a6*2-a14a7*2+a1a8*2-a13a9*2)*t8+(a10a4*2-a0a3*2-a12a15*2+a11a5*2-a1a6*2+a13a7*2+a2a8*2-a14a9*2)*t9
  R[21] =(a1a14*2+a11a4*2-a12a3*2-a13a2*2-a0a15*2+a10a5*2-a7a8*2+a6a9*2)*t0+(a12a2*2-a13a3*2+a11a14*2-a1a4*2+a10a6*2+a0a7*2-a15a8*2-a5a9*2)*t1+(a1a3*2-a11a2*2-a12a14*2+a13a4*2-a0a6*2-a10a7*2+a5a8*2+a15a9*2)*t2+(a15a6*2+a5a7*2+a10a8*2+a0a9*2-a11a13*2-a14a3*2-a2a4*2-a1a12*2)*t3+(a1a11*2+a12a13*2+a2a3*2+a14a4*2-a5a6*2-a15a7*2-a0a8*2-a10a9*2)*t4+(a0a0-a10a10+a11a11-a1a1-a12a12-a2a2+a13a13+a3a3+a14a14-a4a4-a15a15+a5a5-a6a6+a7a7-a8a8+a9a9)*t5+(a10a11*2+a0a12*2-a15a3*2-a4a5*2-a14a6*2-a2a7*2+a13a8*2+a1a9*2)*t6+(a15a4*2+a3a5*2+a2a6*2+a14a7*2-a10a12*2-a0a11*2-a1a8*2-a13a9*2)*t7+(a0a1*2-a10a13*2+a14a15*2-a2a5*2+a3a6*2-a4a7*2-a11a8*2+a12a9*2)*t8+(a0a2*2-a10a14*2-a13a15*2+a1a5*2+a11a6*2-a12a7*2+a3a8*2-a4a9*2)*t9
  R[22] =(a10a4*2-a0a3*2+a12a15*2-a11a5*2-a1a6*2+a13a7*2-a2a8*2+a14a9*2)*t0+(a0a2*2+a10a14*2+a13a15*2+a1a5*2-a11a6*2-a12a7*2-a3a8*2-a4a9*2)*t1+(a12a6*2+a11a7*2+a4a8*2+a3a9*2-a0a14*2-a1a15*2-a13a5*2-a10a2*2)*t2+(a14a15*2+a2a5*2+a3a6*2+a4a7*2-a10a13*2-a0a1*2-a11a8*2-a12a9*2)*t3+(a1a10*2-a15a2*2+a0a13*2-a14a5*2-a4a6*2-a3a7*2+a12a8*2+a11a9*2)*t4+(a10a11*2-a0a12*2-a15a3*2+a4a5*2-a14a6*2+a2a7*2+a13a8*2-a1a9*2)*t5+(a10a10+a0a0-a11a11-a1a1-a12a12-a2a2-a13a13-a3a3-a14a14-a4a4+a15a15+a5a5+a6a6+a7a7+a8a8+a9a9)*t6+(a11a12*2-a0a10*2+a14a2*2+a1a13*2+a3a4*2-a15a5*2-a6a7*2-a8a9*2)*t7+(a11a13*2-a1a12*2+a14a3*2-a2a4*2-a15a6*2+a5a7*2-a10a8*2+a0a9*2)*t8+(a11a14*2+a1a4*2+a10a6*2-a13a3*2-a12a2*2-a0a7*2-a15a8*2+a5a9*2)*t9
  R[23] =(a10a3*2-a0a4*2+a11a15*2-a12a5*2+a13a6*2-a1a7*2+a14a8*2-a2a9*2)*t0+(-a10a2*2-a0a14*2-a1a15*2-a13a5*2-a12a6*2-a11a7*2-a4a8*2-a3a9*2)*t1+(a0a2*2+a10a14*2+a13a15*2+a1a5*2+a11a6*2+a12a7*2+a3a8*2+a4a9*2)*t2+(a1a10*2-a15a2*2+a0a13*2-a14a5*2+a4a6*2+a3a7*2-a12a8*2-a11a9*2)*t3+(a14a15*2+a2a5*2-a10a13*2-a0a1*2-a3a6*2-a4a7*2+a11a8*2+a12a9*2)*t4+(a10a12*2-a0a11*2-a15a4*2+a3a5*2+a2a6*2-a14a7*2-a1a8*2+a13a9*2)*t5+(a14a2*2+a1a13*2-a11a12*2-a0a10*2-a3a4*2-a15a5*2+a6a7*2+a8a9*2)*t6+(a10a10+a0a0+a11a11-a1a1+a12a12-a2a2-a13a13+a3a3-a14a14+a4a4+a15a15+a5a5-a6a6-a7a7-a8a8-a9a9)*t7+(a12a13*2-a1a11*2-a2a3*2+a14a4*2+a5a6*2-a15a7*2+a0a8*2-a10a9*2)*t8+(a1a3*2-a11a2*2+a12a14*2-a13a4*2-a0a6*2+a10a7*2+a5a8*2-a15a9*2)*t9
  R[24] =(a0a14*2-a10a2*2+a1a15*2-a13a5*2-a12a6*2+a11a7*2+a4a8*2-a3a9*2)*t0+(a11a15*2+a12a5*2-a0a4*2-a10a3*2-a13a6*2-a1a7*2+a14a8*2+a2a9*2)*t1+(a0a3*2+a10a4*2-a12a15*2-a11a5*2+a1a6*2+a13a7*2-a2a8*2-a14a9*2)*t2+(-a10a11*2-a0a12*2-a15a3*2-a4a5*2-a14a6*2-a2a7*2-a13a8*2-a1a9*2)*t3+(a0a11*2+a10a12*2+a15a4*2+a3a5*2+a2a6*2+a14a7*2+a1a8*2+a13a9*2)*t4+(a10a13*2-a0a1*2+a14a15*2-a2a5*2+a3a6*2-a4a7*2+a11a8*2-a12a9*2)*t5+(a14a3*2+a2a4*2-a11a13*2-a1a12*2-a15a6*2-a5a7*2+a10a8*2+a0a9*2)*t6+(a1a11*2+a12a13*2-a2a3*2-a14a4*2+a5a6*2+a15a7*2-a0a8*2-a10a9*2)*t7+(a0a0-a10a10+a11a11-a1a1-a12a12+a2a2+a13a13-a3a3-a14a14+a4a4+a15a15-a5a5+a6a6-a7a7-a8a8+a9a9)*t8+(a13a14*2+a12a4*2-a11a3*2-a1a2*2-a10a15*2+a0a5*2+a6a8*2-a7a9*2)*t9
  R[25] =(a1a10*2+a15a2*2-a0a13*2-a14a5*2-a4a6*2+a3a7*2-a12a8*2+a11a9*2)*t0+(a10a11*2+a0a12*2+a15a3*2+a4a5*2-a14a6*2-a2a7*2-a13a8*2-a1a9*2)*t1+(a2a6*2+a14a7*2+a1a8*2+a13a9*2-a10a12*2-a15a4*2-a3a5*2-a0a11*2)*t2+(a11a15*2+a12a5*2+a13a6*2+a1a7*2-a0a4*2-a10a3*2-a14a8*2-a2a9*2)*t3+(a0a3*2+a10a4*2-a12a15*2-a11a5*2-a1a6*2-a13a7*2+a2a8*2+a14a9*2)*t4+(a10a14*2-a0a2*2-a13a15*2+a1a5*2-a11a6*2+a12a7*2+a3a8*2-a4a9*2)*t5+(-a12a2*2-a13a3*2-a11a14*2-a1a4*2-a10a6*2-a0a7*2-a15a8*2-a5a9*2)*t6+(a11a2*2+a1a3*2+a12a14*2+a13a4*2+a0a6*2+a10a7*2+a5a8*2+a15a9*2)*t7+(a11a3*2-a1a2*2+a13a14*2-a12a4*2+a10a15*2-a0a5*2+a6a8*2-a7a9*2)*t8+(a0a0-a10a10+a11a11+a1a1-a12a12-a2a2-a13a13-a3a3+a14a14+a4a4+a15a15-a5a5-a6a6+a7a7+a8a8-a9a9)*t9
  R[26] =(a10a10+a0a0+a11a11+a1a1+a12a12+a2a2+a13a13+a3a3+a14a14+a4a4+a15a15+a5a5+a6a6+a7a7+a8a8+a9a9)*q0+(a0a11*2-a10a12*2+a15a4*2-a3a5*2+a2a6*2-a14a7*2-a1a8*2+a13a9*2)*s0+(-a0a10*2-a11a12*2-a14a2*2-a1a13*2-a3a4*2-a15a5*2-a6a7*2-a8a9*2)*q1+(a1a12*2-a11a13*2-a14a3*2+a2a4*2-a15a6*2+a5a7*2-a10a8*2+a0a9*2)*q2+(a12a2*2+a13a3*2-a11a14*2-a1a4*2+a10a6*2-a0a7*2-a15a8*2+a5a9*2)*q3+(a0a4*2-a10a3*2-a11a15*2+a12a5*2+a13a6*2-a1a7*2+a14a8*2-a2a9*2)*q4
  R[27] =(a11a12*2-a0a10*2-a14a2*2-a1a13*2+a3a4*2-a15a5*2+a6a7*2+a8a9*2)*q0+(a0a12*2-a10a11*2+a15a3*2-a4a5*2-a14a6*2+a2a7*2+a13a8*2-a1a9*2)*s0+(a10a10+a0a0-a11a11+a1a1-a12a12+a2a2+a13a13-a3a3+a14a14-a4a4+a15a15+a5a5-a6a6-a7a7-a8a8-a9a9)*q1+(a1a11*2-a12a13*2+a2a3*2-a14a4*2+a5a6*2-a15a7*2+a0a8*2-a10a9*2)*q2+(a11a2*2-a1a3*2-a12a14*2+a13a4*2-a0a6*2+a10a7*2+a5a8*2-a15a9*2)*q3+(a0a3*2-a10a4*2-a12a15*2+a11a5*2-a1a6*2+a13a7*2-a2a8*2+a14a9*2)*q4
  R[28] =(a1a12*2+a11a13*2-a14a3*2-a2a4*2-a15a6*2-a5a7*2+a10a8*2+a0a9*2)*q0+(a0a13*2+a14a5*2-a15a2*2-a1a10*2-a4a6*2+a3a7*2-a12a8*2+a11a9*2)*s0+(a2a3*2+a14a4*2+a5a6*2+a15a7*2-a12a13*2-a1a11*2-a0a8*2-a10a9*2)*q1+(a0a0-a10a10-a11a11+a1a1+a12a12-a2a2-a13a13+a3a3+a14a14-a4a4+a15a15-a5a5+a6a6-a7a7-a8a8+a9a9)*q2+(a1a2*2+a11a3*2-a13a14*2-a12a4*2-a10a15*2+a0a5*2+a6a8*2-a7a9*2)*q3+(a10a14*2-a0a2*2-a13a15*2+a1a5*2+a11a6*2-a12a7*2-a3a8*2+a4a9*2)*q4
  R[29] =(a12a2*2+a13a3*2+a11a14*2+a1a4*2-a10a6*2-a0a7*2-a15a8*2-a5a9*2)*q0+(a0a14*2-a10a2*2+a1a15*2-a13a5*2+a12a6*2-a11a7*2-a4a8*2+a3a9*2)*s0+(a0a6*2+a10a7*2+a5a8*2+a15a9*2-a1a3*2-a12a14*2-a13a4*2-a11a2*2)*q1+(a1a2*2-a11a3*2-a13a14*2+a12a4*2+a10a15*2-a0a5*2+a6a8*2-a7a9*2)*q2+(a0a0-a10a10-a11a11-a1a1+a12a12+a2a2+a13a13+a3a3-a14a14-a4a4+a15a15-a5a5-a6a6+a7a7+a8a8-a9a9)*q3+(a0a1*2-a10a13*2-a14a15*2+a2a5*2+a3a6*2-a4a7*2+a11a8*2-a12a9*2)*q4
  R[30] =(a10a3*2+a0a4*2+a11a15*2+a12a5*2+a13a6*2+a1a7*2+a14a8*2+a2a9*2)*q0+(a13a2*2-a12a3*2-a1a14*2+a11a4*2+a0a15*2-a10a5*2-a7a8*2+a6a9*2)*s0+(-a0a3*2-a10a4*2-a12a15*2-a11a5*2-a1a6*2-a13a7*2-a2a8*2-a14a9*2)*q1+(a0a2*2-a10a14*2-a13a15*2+a1a5*2-a11a6*2+a12a7*2-a3a8*2+a4a9*2)*q2+(a10a13*2-a0a1*2-a14a15*2+a2a5*2+a3a6*2-a4a7*2-a11a8*2+a12a9*2)*q3+(a0a0-a10a10-a11a11-a1a1+a12a12-a2a2+a13a13-a3a3+a14a14+a4a4-a15a15+a5a5+a6a6-a7a7+a8a8-a9a9)*q4
  R[31] =(a12a3*2-a13a2*2+a1a14*2-a11a4*2+a0a15*2-a10a5*2-a7a8*2+a6a9*2)*v0+(a0a0-a10a10+a11a11+a1a1-a12a12+a2a2-a13a13+a3a3-a14a14-a4a4-a15a15+a5a5+a6a6-a7a7+a8a8-a9a9)*p1+(a10a2*2-a0a14*2+a1a15*2-a13a5*2+a12a6*2-a11a7*2+a4a8*2-a3a9*2)*v1+(a15a2*2-a1a10*2+a0a13*2-a14a5*2-a4a6*2+a3a7*2+a12a8*2-a11a9*2)*v2+(a15a3*2+a4a5*2-a0a12*2-a10a11*2-a14a6*2-a2a7*2+a13a8*2+a1a9*2)*v3+(a0a11*2+a10a12*2-a15a4*2-a3a5*2+a2a6*2+a14a7*2-a1a8*2-a13a9*2)*v4
  // muls : 2328 from 6784
  // adds : 2416 from 2420
  return R
}

That's quite a save imho .. this latest version should be pretty easy to convert to python .. simply adjust the indexes in A in the first line ..

Let me know how much faster this is !

Cheers,

S.

enkimute avatar Oct 16 '19 18:10 enkimute

Oh as to linking the piece of code that generated this .. it's a total mess .. I'm taking it to my grave. I am planning a rewrite tho which I should be happy to share. Roughly it does this :

  • implements a symbolic version of the target algebra.
  • evaluates the expression symbolically
  • takes that output and performs a custom simplification step (figuring out all the canceling terms)
  • implements a custom CSE that runs on the entire function (not just per expression).

enkimute avatar Oct 16 '19 18:10 enkimute

oh and I just noticed that I'm not CSE'ing the two's in that last piece of code (probably cause I didn't test in CGA yet) .. so it can be even better .. I'll have you guys fix it and just copy back the result ? ;)

enkimute avatar Oct 16 '19 18:10 enkimute