docs: public static TrifocalTensor createTrifocal( DMatrixRMaj P1 , DMatrixRMaj P2 , DMatrixRMaj P3 ,
  												 @Nullable TrifocalTensor ret ) {
  		if( ret == null )
  			ret = new TrifocalTensor();
  
  		// invariant to scale. So pick something more reasonable and maybe reduce overflow
  		double scale = 0;
  		scale = Math.max(scale,CommonOps_DDRM.elementMaxAbs(P1));
  		scale = Math.max(scale,CommonOps_DDRM.elementMaxAbs(P2));
  		scale = Math.max(scale,CommonOps_DDRM.elementMaxAbs(P3));
  
  		DMatrixRMaj A = new DMatrixRMaj(4,4);
  
  		double sign = 1;
  		for( int i = 0; i < 3; i++ ) {
  			DMatrixRMaj T = ret.getT(i);
  
  			for (int row = 0,cnt=0; row < 3; row++) {
  				if( row != i ) {
  					CommonOps_DDRM.extract(P1, row, row + 1, 0, 4, A, cnt, 0);
  					for (int col = 0; col < 4; col++) {
  						A.data[cnt*4+col] /= scale;
  					}
  					cnt++;
  				}
  			}
  
  			for (int q = 0; q < 3; q++) {
  				CommonOps_DDRM.extract(P2,q,q+1,0,4,A,2,0);
  
  				for (int col = 0; col < 4; col++) {
  					A.data[2*4+col] /= scale;
  				}
  
  				for (int r = 0; r < 3; r++) {
  					CommonOps_DDRM.extract(P3,r,r+1,0,4,A,3,0);
  					for (int col = 0; col < 4; col++) {
  						A.data[3*4+col] /= scale;
  					}
  
  					double v = CommonOps_DDRM.det(A);
  					T.set(q,r,sign*v*scale);  // scale is to the power of 2, hence the *scale here
  				}
  			}
  
  			sign *= -1;
  		}
  
  		return ret;
  	}