matrix.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * ident(m) store identity matrix in m
  3. * matmul(a, b) matrix multiply a*=b
  4. * matmulr(a, b) matrix multiply a=b*a
  5. * determinant(m) returns det(m)
  6. * adjoint(m, minv) minv=adj(m)
  7. * invertmat(m, minv) invert matrix m, result in minv, returns det(m)
  8. * if m is singular, minv=adj(m)
  9. */
  10. #include <u.h>
  11. #include <libc.h>
  12. #include <draw.h>
  13. #include <geometry.h>
  14. void ident(Matrix m){
  15. register double *s=&m[0][0];
  16. *s++=1;*s++=0;*s++=0;*s++=0;
  17. *s++=0;*s++=1;*s++=0;*s++=0;
  18. *s++=0;*s++=0;*s++=1;*s++=0;
  19. *s++=0;*s++=0;*s++=0;*s=1;
  20. }
  21. void matmul(Matrix a, Matrix b){
  22. register i, j, k;
  23. double sum;
  24. Matrix tmp;
  25. for(i=0;i!=4;i++) for(j=0;j!=4;j++){
  26. sum=0;
  27. for(k=0;k!=4;k++)
  28. sum+=a[i][k]*b[k][j];
  29. tmp[i][j]=sum;
  30. }
  31. for(i=0;i!=4;i++) for(j=0;j!=4;j++)
  32. a[i][j]=tmp[i][j];
  33. }
  34. void matmulr(Matrix a, Matrix b){
  35. register i, j, k;
  36. double sum;
  37. Matrix tmp;
  38. for(i=0;i!=4;i++) for(j=0;j!=4;j++){
  39. sum=0;
  40. for(k=0;k!=4;k++)
  41. sum+=b[i][k]*a[k][j];
  42. tmp[i][j]=sum;
  43. }
  44. for(i=0;i!=4;i++) for(j=0;j!=4;j++)
  45. a[i][j]=tmp[i][j];
  46. }
  47. /*
  48. * Return det(m)
  49. */
  50. double determinant(Matrix m){
  51. return m[0][0]*(m[1][1]*(m[2][2]*m[3][3]-m[2][3]*m[3][2])+
  52. m[1][2]*(m[2][3]*m[3][1]-m[2][1]*m[3][3])+
  53. m[1][3]*(m[2][1]*m[3][2]-m[2][2]*m[3][1]))
  54. -m[0][1]*(m[1][0]*(m[2][2]*m[3][3]-m[2][3]*m[3][2])+
  55. m[1][2]*(m[2][3]*m[3][0]-m[2][0]*m[3][3])+
  56. m[1][3]*(m[2][0]*m[3][2]-m[2][2]*m[3][0]))
  57. +m[0][2]*(m[1][0]*(m[2][1]*m[3][3]-m[2][3]*m[3][1])+
  58. m[1][1]*(m[2][3]*m[3][0]-m[2][0]*m[3][3])+
  59. m[1][3]*(m[2][0]*m[3][1]-m[2][1]*m[3][0]))
  60. -m[0][3]*(m[1][0]*(m[2][1]*m[3][2]-m[2][2]*m[3][1])+
  61. m[1][1]*(m[2][2]*m[3][0]-m[2][0]*m[3][2])+
  62. m[1][2]*(m[2][0]*m[3][1]-m[2][1]*m[3][0]));
  63. }
  64. /*
  65. * Store the adjoint (matrix of cofactors) of m in madj.
  66. * Works fine even if m and madj are the same matrix.
  67. */
  68. void adjoint(Matrix m, Matrix madj){
  69. double m00=m[0][0], m01=m[0][1], m02=m[0][2], m03=m[0][3];
  70. double m10=m[1][0], m11=m[1][1], m12=m[1][2], m13=m[1][3];
  71. double m20=m[2][0], m21=m[2][1], m22=m[2][2], m23=m[2][3];
  72. double m30=m[3][0], m31=m[3][1], m32=m[3][2], m33=m[3][3];
  73. madj[0][0]=m11*(m22*m33-m23*m32)+m21*(m13*m32-m12*m33)+m31*(m12*m23-m13*m22);
  74. madj[0][1]=m01*(m23*m32-m22*m33)+m21*(m02*m33-m03*m32)+m31*(m03*m22-m02*m23);
  75. madj[0][2]=m01*(m12*m33-m13*m32)+m11*(m03*m32-m02*m33)+m31*(m02*m13-m03*m12);
  76. madj[0][3]=m01*(m13*m22-m12*m23)+m11*(m02*m23-m03*m22)+m21*(m03*m12-m02*m13);
  77. madj[1][0]=m10*(m23*m32-m22*m33)+m20*(m12*m33-m13*m32)+m30*(m13*m22-m12*m23);
  78. madj[1][1]=m00*(m22*m33-m23*m32)+m20*(m03*m32-m02*m33)+m30*(m02*m23-m03*m22);
  79. madj[1][2]=m00*(m13*m32-m12*m33)+m10*(m02*m33-m03*m32)+m30*(m03*m12-m02*m13);
  80. madj[1][3]=m00*(m12*m23-m13*m22)+m10*(m03*m22-m02*m23)+m20*(m02*m13-m03*m12);
  81. madj[2][0]=m10*(m21*m33-m23*m31)+m20*(m13*m31-m11*m33)+m30*(m11*m23-m13*m21);
  82. madj[2][1]=m00*(m23*m31-m21*m33)+m20*(m01*m33-m03*m31)+m30*(m03*m21-m01*m23);
  83. madj[2][2]=m00*(m11*m33-m13*m31)+m10*(m03*m31-m01*m33)+m30*(m01*m13-m03*m11);
  84. madj[2][3]=m00*(m13*m21-m11*m23)+m10*(m01*m23-m03*m21)+m20*(m03*m11-m01*m13);
  85. madj[3][0]=m10*(m22*m31-m21*m32)+m20*(m11*m32-m12*m31)+m30*(m12*m21-m11*m22);
  86. madj[3][1]=m00*(m21*m32-m22*m31)+m20*(m02*m31-m01*m32)+m30*(m01*m22-m02*m21);
  87. madj[3][2]=m00*(m12*m31-m11*m32)+m10*(m01*m32-m02*m31)+m30*(m02*m11-m01*m12);
  88. madj[3][3]=m00*(m11*m22-m12*m21)+m10*(m02*m21-m01*m22)+m20*(m01*m12-m02*m11);
  89. }
  90. /*
  91. * Store the inverse of m in minv.
  92. * If m is singular, minv is instead its adjoint.
  93. * Returns det(m).
  94. * Works fine even if m and minv are the same matrix.
  95. */
  96. double invertmat(Matrix m, Matrix minv){
  97. double d, dinv;
  98. int i, j;
  99. d=determinant(m);
  100. adjoint(m, minv);
  101. if(d!=0.){
  102. dinv=1./d;
  103. for(i=0;i!=4;i++) for(j=0;j!=4;j++) minv[i][j]*=dinv;
  104. }
  105. return d;
  106. }