content: /*
   * Copyright (C) 2023 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package android.support.constraintLayout.extlib.graph3d;
  
  import java.text.DecimalFormat;
  import java.util.Arrays;
  
  /**
   * Matrix math class.  (For the purposes of this application it is more efficient as has no JNI)
   */
  public class Matrix {
  
      public double []m;
  
      public void makeRotation(){
          {
              double []v = {m[0],m[4],m[8]};
              VectorUtil.normalize(v);
              m[0] = v[0];
              m[4] = v[1];
              m[8] = v[2];
          }
          {
              double []v = {m[1],m[5],m[9]};
              VectorUtil.normalize(v);
              m[1] = v[0];
              m[5] = v[1];
              m[9] = v[2];
          }
          {
              double []v = {m[2],m[6],m[10]};
              VectorUtil.normalize(v);
              m[2] = v[0];
              m[6] = v[1];
              m[10] = v[2];
          }
  
      }
  
      private static String trim(String s){
          return  s.substring(s.length()-7);
      }
      public void print(){
          DecimalFormat df =new DecimalFormat("      ##0.000");
          for (int i = 0; i < 4; i++) {
              for (int j = 0; j < 4; j++) {
                  System.out.print(((j==0)?"[ ":" , ")+trim(df.format(m[i*4+j])));
              }
              System.out.println("]");
          }
      }
  
      public Matrix() {
          m = new double[4*4];
          setToUnit();
      }
      public Matrix(Matrix matrix){
          this(Arrays.copyOf(matrix.m, matrix.m.length));
      }
      protected Matrix(double []m){
          this.m = m;
      }
  
      public void setToUnit(){
          for (int i = 1; i < m.length; i++) {
              m[i] = 0;
          }
          m[0]=1;
          m[5]=1;
          m[10]=1;
          m[15]=1;
      }
  
      public void mult4(float[]src,float [] dest){
          for (int i = 0; i < 4; i++) {
              int col = i*4;
              double sum = 0;
              for (int j = 0; j < 4; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] = (float) sum;
          }
      }
  
      public void mult3(float[]src,float [] dest){
          for (int i = 0; i < 3; i++) {
              int col = i*4;
              double sum =  m[col+3];
              for (int j = 0; j < 3; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] =(float) sum;
          }
      }
      public void mult3v(float[]src,float [] dest){
          for (int i = 0; i < 3; i++) {
              int col = i*4;
              double sum =  0;
              for (int j = 0; j < 3; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] =(float) sum;
          }
      }
      public void mult3v(float[]src,int off,float [] dest){
          for (int i = 0; i < 3; i++) {
              int col = i*4;
              double sum =  0;
              for (int j = 0; j < 3; j++) {
                  sum += m[col+j]*src[off+j];
              }
              dest[i] =(float) sum;
          }
      }
  
      public void mult4(double[]src,double [] dest){
          for (int i = 0; i < 4; i++) {
              int col = i*4;
              double sum = 0;
              for (int j = 0; j < 4; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] = (float) sum;
          }
      }
  
      public void mult3(double[]src,double [] dest){
          for (int i = 0; i < 3; i++) {
              int col = i*4;
              double sum =  m[col+3];
              for (int j = 0; j < 3; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] =(float) sum;
          }
      }
      public void mult3v(double[]src,double [] dest){
          for (int i = 0; i < 3; i++) {
              int col = i*4;
              double sum =  0;
              for (int j = 0; j < 3; j++) {
                  sum += m[col+j]*src[j];
              }
              dest[i] =(float) sum;
          }
      }
  
      public double[] vecmult(double[]src){
          double [] ret = new double[3];
          mult3v(src,ret);
          return ret;
      }
  
      public void mult3(float[] src, int off1, float[] dest, int off2) {
  
          int col = 0*4;
          double sum =  m[col+3];
          for (int j = 0; j < 3; j++) {
              sum += m[col+j]*src[j+off1];
          }
          float v0 =(float) sum;
  
  
          col = 1*4;
          sum =  m[col+3];
          for (int j = 0; j < 3; j++) {
              sum += m[col+j]*src[j+off1];
          }
  
          float v1 =(float) sum;
  
  
  
          col = 2*4;
          sum =  m[col+3];
          for (int j = 0; j < 3; j++) {
              sum += m[col+j]*src[j+off1];
          }
          float v2 =(float) sum;
  
          dest[off2]   = v0;
          dest[1+off2] = v1;
          dest[2+off2] = v2;
  
      }
  
  
      public Matrix invers(Matrix ret)
      {
         double []inv =  ret.m;
  
          inv[0] = m[5]  * m[10] * m[15] -
                  m[5]  * m[11] * m[14] -
                  m[9]  * m[6]  * m[15] +
                  m[9]  * m[7]  * m[14] +
                  m[13] * m[6]  * m[11] -
                  m[13] * m[7]  * m[10];
  
          inv[4] = -m[4]  * m[10] * m[15] +
                  m[4]  * m[11] * m[14] +
                  m[8]  * m[6]  * m[15] -
                  m[8]  * m[7]  * m[14] -
                  m[12] * m[6]  * m[11] +
                  m[12] * m[7]  * m[10];
  
          inv[8] = m[4]  * m[9] * m[15] -
                  m[4]  * m[11] * m[13] -
                  m[8]  * m[5] * m[15] +
                  m[8]  * m[7] * m[13] +
                  m[12] * m[5] * m[11] -
                  m[12] * m[7] * m[9];
  
          inv[12] = -m[4]  * m[9] * m[14] +
                  m[4]  * m[10] * m[13] +
                  m[8]  * m[5] * m[14] -
                  m[8]  * m[6] * m[13] -
                  m[12] * m[5] * m[10] +
                  m[12] * m[6] * m[9];
  
          inv[1] = -m[1]  * m[10] * m[15] +
                  m[1]  * m[11] * m[14] +
                  m[9]  * m[2] * m[15] -
                  m[9]  * m[3] * m[14] -
                  m[13] * m[2] * m[11] +
                  m[13] * m[3] * m[10];
  
          inv[5] = m[0]  * m[10] * m[15] -
                  m[0]  * m[11] * m[14] -
                  m[8]  * m[2] * m[15] +
                  m[8]  * m[3] * m[14] +
                  m[12] * m[2] * m[11] -
                  m[12] * m[3] * m[10];
  
          inv[9] = -m[0]  * m[9] * m[15] +
                  m[0]  * m[11] * m[13] +
                  m[8]  * m[1] * m[15] -
                  m[8]  * m[3] * m[13] -
                  m[12] * m[1] * m[11] +
                  m[12] * m[3] * m[9];
  
          inv[13] = m[0]  * m[9] * m[14] -
                  m[0]  * m[10] * m[13] -
                  m[8]  * m[1] * m[14] +
                  m[8]  * m[2] * m[13] +
                  m[12] * m[1] * m[10] -
                  m[12] * m[2] * m[9];
  
          inv[2] = m[1]  * m[6] * m[15] -
                  m[1]  * m[7] * m[14] -
                  m[5]  * m[2] * m[15] +
                  m[5]  * m[3] * m[14] +
                  m[13] * m[2] * m[7] -
                  m[13] * m[3] * m[6];
  
          inv[6] = -m[0]  * m[6] * m[15] +
                  m[0]  * m[7] * m[14] +
                  m[4]  * m[2] * m[15] -
                  m[4]  * m[3] * m[14] -
                  m[12] * m[2] * m[7] +
                  m[12] * m[3] * m[6];
  
          inv[10] = m[0]  * m[5] * m[15] -
                  m[0]  * m[7] * m[13] -
                  m[4]  * m[1] * m[15] +
                  m[4]  * m[3] * m[13] +
                  m[12] * m[1] * m[7] -
                  m[12] * m[3] * m[5];
  
          inv[14] = -m[0]  * m[5] * m[14] +
                  m[0]  * m[6] * m[13] +
                  m[4]  * m[1] * m[14] -
                  m[4]  * m[2] * m[13] -
                  m[12] * m[1] * m[6] +
                  m[12] * m[2] * m[5];
  
          inv[3] = -m[1] * m[6] * m[11] +
                  m[1] * m[7] * m[10] +
                  m[5] * m[2] * m[11] -
                  m[5] * m[3] * m[10] -
                  m[9] * m[2] * m[7] +
                  m[9] * m[3] * m[6];
  
          inv[7] = m[0] * m[6] * m[11] -
                  m[0] * m[7] * m[10] -
                  m[4] * m[2] * m[11] +
                  m[4] * m[3] * m[10] +
                  m[8] * m[2] * m[7] -
                  m[8] * m[3] * m[6];
  
          inv[11] = -m[0] * m[5] * m[11] +
                  m[0] * m[7] * m[9] +
                  m[4] * m[1] * m[11] -
                  m[4] * m[3] * m[9] -
                  m[8] * m[1] * m[7] +
                  m[8] * m[3] * m[5];
  
          inv[15] = m[0] * m[5] * m[10] -
                  m[0] * m[6] * m[9] -
                  m[4] * m[1] * m[10] +
                  m[4] * m[2] * m[9] +
                  m[8] * m[1] * m[6] -
                  m[8] * m[2] * m[5];
  
  
          double det;
          det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
  
          if (det == 0) {
              return null;
          }
  
          det = 1.0 / det;
  
  
  
          for (int i = 0; i < 16; i++) {
              inv[i] = inv[i] * det;
          }
  
  
          return ret;
      }
  
      Matrix mult(Matrix b){
          return new Matrix(multiply(this.m,b.m));
      }
      Matrix premult(Matrix b){
          return new Matrix(multiply(b.m,this.m));
      }
  
      private static double[] multiply(double a[], double b[]) {
          double[] resultant = new double[16];
          for(int i = 0; i < 4; i++) {
              for(int j = 0; j < 4; j++) {
                  for(int k = 0; k < 4; k++) {
                      resultant[i+4*j] += a[i+4*k] * b[k+4*j];
                  }
              }
          }
  
          return resultant;
      }
      public static void main(String[] args) {
          Matrix m = new Matrix();
          Matrix inv = new Matrix();
          m.m[0] = 100;
          m.m[5] = 12;
          m.m[10] = 63;
          m.m[3] = 12;
          m.m[7] = 34;
          m.m[11] =  17;
          System.out.println(" matrix ");
          m.print();
          System.out.println(" inv ");
          m.invers(inv).print();
          System.out.println(" inv*matrix ");
  
          m.mult(m.invers(inv)).print();
      }
  
  }
  