matrix.c 4.0 KB

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