12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef UI_GFX_MATRIX3_F_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define UI_GFX_MATRIX3_F_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector3d_f.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gfx {
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class GFX_EXPORT Matrix3F {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~Matrix3F();
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Matrix3F Zeros();
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Matrix3F Ones();
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Matrix3F Identity();
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Matrix3F FromOuterProduct(const Vector3dF& a, const Vector3dF& bt);
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsEqual(const Matrix3F& rhs) const;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Element-wise comparison with given precision.
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsNear(const Matrix3F& rhs, float precision) const;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float get(int i, int j) const {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return data_[MatrixToArrayCoords(i, j)];
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set(int i, int j, float v) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[MatrixToArrayCoords(i, j)] = v;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set(float m00, float m01, float m02,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           float m10, float m11, float m12,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           float m20, float m21, float m22) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[0] = m00;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[1] = m01;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[2] = m02;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[3] = m10;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[4] = m11;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[5] = m12;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[6] = m20;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[7] = m21;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[8] = m22;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Vector3dF get_column(int i) const {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Vector3dF(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data_[MatrixToArrayCoords(0, i)],
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data_[MatrixToArrayCoords(1, i)],
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data_[MatrixToArrayCoords(2, i)]);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_column(int i, const Vector3dF& c) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[MatrixToArrayCoords(0, i)] = c.x();
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[MatrixToArrayCoords(1, i)] = c.y();
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_[MatrixToArrayCoords(2, i)] = c.z();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns an inverse of this if the matrix is non-singular, zero (== Zero())
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // otherwise.
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Matrix3F Inverse() const;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Value of the determinant of the matrix.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float Determinant() const;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Trace (sum of diagonal elements) of the matrix.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float Trace() const {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return data_[MatrixToArrayCoords(0, 0)] +
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        data_[MatrixToArrayCoords(1, 1)] +
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        data_[MatrixToArrayCoords(2, 2)];
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute eigenvalues and (optionally) normalized eigenvectors of
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a positive defnite matrix *this. Eigenvectors are computed only if
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // non-null |eigenvectors| matrix is passed. If it is NULL, the routine
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will not attempt to compute eigenvectors but will still return eigenvalues
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if they can be computed.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If eigenvalues cannot be computed (the matrix does not meet constraints)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the 0-vector is returned. Note that to retrieve eigenvalues, the matrix
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only needs to be symmetric while eigenvectors require it to be
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // positive-definite. Passing a non-positive definite matrix will result in
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NaNs in vectors which cannot be computed.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Eigenvectors are placed as column in |eigenvectors| in order corresponding
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to eigenvalues.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Vector3dF SolveEigenproblem(Matrix3F* eigenvectors) const;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Matrix3F();  // Uninitialized default.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int MatrixToArrayCoords(int i, int j) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(i >= 0 && i < 3);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(j >= 0 && j < 3);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return i * 3 + j;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float data_[9];
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)inline bool operator==(const Matrix3F& lhs, const Matrix3F& rhs) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return lhs.IsEqual(rhs);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace gfx
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // UI_GFX_MATRIX3_F_H_
109