Home Reference Source

src/math/SymmetricMatrix3.js

/**
 * A symmetric 3x3 matrix.
 */

export class SymmetricMatrix3 {

	/**
	 * Constructs a new symmetric matrix.
	 */

	constructor() {

		/**
		 * The matrix elements.
		 *
		 * @type {Float32Array}
		 */

		this.elements = new Float32Array([

			1, 0, 0,
			1, 0,
			1

		]);

	}

	/**
	 * Sets the values of this matrix.
	 *
	 * @param {Number} m00 - The value of the first row, first column.
	 * @param {Number} m01 - The value of the first row, second column and the second row, first column.
	 * @param {Number} m02 - The value of the first row, third column and the third row, first column.
	 * @param {Number} m11 - The value of the second row, second column.
	 * @param {Number} m12 - The value of the second row, third column and third row, second column.
	 * @param {Number} m22 - The value of the third row, third column.
	 * @return {SymmetricMatrix3} This matrix.
	 */

	set(m00, m01, m02, m11, m12, m22) {

		const e = this.elements;

		e[0] = m00;
		e[1] = m01; e[3] = m11;
		e[2] = m02; e[4] = m12; e[5] = m22;

		return this;

	}

	/**
	 * Sets this matrix to the identity matrix.
	 *
	 * @return {SymmetricMatrix3} This matrix.
	 */

	identity() {

		this.set(

			1, 0, 0,
			1, 0,
			1

		);

		return this;

	}

	/**
	 * Copies the values of a given symmetric matrix.
	 *
	 * @param {SymmetricMatrix3} m - A matrix.
	 * @return {SymmetricMatrix3} This matrix.
	 */

	copy(m) {

		const me = m.elements;

		this.set(

			me[0], me[1], me[2],
			me[3], me[4],
			me[5]

		);

		return this;

	}

	/**
	 * Clones this matrix.
	 *
	 * @return {SymmetricMatrix3} A clone of this matrix.
	 */

	clone() {

		return new this.constructor().copy(this);

	}

	/**
	 * Copies this symmetric matrix into a given 3x3 matrix.
	 *
	 * @param {Matrix3} m - The target matrix.
	 */

	toMatrix3(m) {

		const me = m.elements;

		m.set(

			me[0], me[1], me[2],
			me[1], me[3], me[4],
			me[2], me[4], me[5]

		);

	}

	/**
	 * Adds the values of a given symmetric matrix to this one.
	 *
	 * @param {SymmetricMatrix3} m - A matrix.
	 * @return {SymmetricMatrix3} This matrix.
	 */

	add(m) {

		const te = this.elements;
		const me = m.elements;

		te[0] += me[0];
		te[1] += me[1]; te[3] += me[3];
		te[2] += me[2]; te[4] += me[4]; te[5] += me[5];

		return this;

	}

	/**
	 * Calculates the Frobenius norm of this matrix.
	 *
	 * @return {Number} The norm of this matrix.
	 */

	norm() {

		const e = this.elements;

		const m01m01 = e[1] * e[1];
		const m02m02 = e[2] * e[2];
		const m12m12 = e[4] * e[4];

		return Math.sqrt(

			e[0] * e[0] + m01m01 + m02m02 +
			m01m01 + e[3] * e[3] + m12m12 +
			m02m02 + m12m12 + e[5] * e[5]

		);

	}

	/**
	 * Calculates the absolute sum of all matrix components except for the main
	 * diagonal.
	 *
	 * @return {Number} The offset of this matrix.
	 */

	off() {

		const e = this.elements;

		return Math.sqrt(2 * (

			// Diagonal = [0, 3, 5].
			e[1] * e[1] + e[2] * e[2] + e[4] * e[4]

		));

	}

	/**
	 * Applies this symmetric matrix to a vector.
	 *
	 * @param {Vector3} v - The vector to modify.
	 * @return {Vector3} The modified vector.
	 */

	applyToVector3(v) {

		const x = v.x, y = v.y, z = v.z;
		const e = this.elements;

		v.x = e[0] * x + e[1] * y + e[2] * z;
		v.y = e[1] * x + e[3] * y + e[4] * z;
		v.z = e[2] * x + e[4] * y + e[5] * z;

		return v;

	}

	/**
	 * Checks if this matrix equals the given one.
	 *
	 * @param {SymmetricMatrix3} m - A matrix.
	 * @return {Boolean} Whether the matrices are equal.
	 */

	equals(m) {

		const te = this.elements;
		const me = m.elements;

		let result = true;
		let i;

		for(i = 0; result && i < 6; ++i) {

			if(te[i] !== me[i]) {

				result = false;

			}

		}

		return result;

	}

	/**
	 * Calculates the linear index of an element from this matrix.
	 *
	 * Let N be the dimension of the symmetric matrix:
	 *
	 *     index = N * (N - 1) / 2 - (N - i) * (N - i - 1) / 2 + j
	 *
	 * @param {Number} i - The row.
	 * @param {Number} j - The column.
	 * @return {Number} The index into the elements of this matrix.
	 */

	static calculateIndex(i, j) {

		return (3 - (3 - i) * (2 - i) / 2 + j);

	}

}