From 4a649d9c1ae3dc7d3445e0d49127af96a7c707e7 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 6 Aug 2019 13:40:53 +0200 Subject: [PATCH] Added unit tests for matrix arithmetic --- Tests/SurgeTests/MatrixTests.swift | 613 ++++++++++++++++++++++++----- Tests/SurgeTests/VectorTests.swift | 34 ++ 2 files changed, 538 insertions(+), 109 deletions(-) diff --git a/Tests/SurgeTests/MatrixTests.swift b/Tests/SurgeTests/MatrixTests.swift index 015fad0..d4ceba2 100644 --- a/Tests/SurgeTests/MatrixTests.swift +++ b/Tests/SurgeTests/MatrixTests.swift @@ -21,15 +21,30 @@ @testable import Surge import XCTest -// swiftlint:disable nesting - class MatrixTests: XCTestCase { let floatAccuracy: Float = 1e-8 let doubleAccuracy: Double = 1e-11 - var matrix: Matrix = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) + let matrixFloat: Matrix = [ + [Float(1.0), 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12], + ] + let matrixDouble: Matrix = [ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12], + ] - func testInit() { + func getMatrix() -> Matrix { + return self.matrixFloat + } + + func getMatrix() -> Matrix { + return self.matrixDouble + } + + func test_init() { let m1 = Matrix([[1.0, 2.0]]) XCTAssertEqual(m1.grid, [1.0, 2.0]) @@ -37,63 +52,511 @@ class MatrixTests: XCTestCase { XCTAssertEqual(m2.grid, [1, 1, 1, -1]) } - func testSubscriptRow() { - XCTAssertEqual(matrix[row: 0], [1, 2, 3, 4]) - XCTAssertEqual(matrix[row: 1], [5, 6, 7, 8]) + func test_subscript_row_get() { + XCTAssertEqual(matrixDouble[row: 0], [1, 2, 3, 4]) + XCTAssertEqual(matrixDouble[row: 1], [5, 6, 7, 8]) } - func testSubscriptColumn() { - XCTAssertEqual(matrix[column: 0], [1, 5, 9]) - XCTAssertEqual(matrix[column: 1], [2, 6, 10]) + func test_subscript_column_get() { + XCTAssertEqual(matrixDouble[column: 0], [1, 5, 9]) + XCTAssertEqual(matrixDouble[column: 1], [2, 6, 10]) } - func testSetRow() { + func test_subscript_row_set() { + typealias Scalar = Double + + var matrix: Matrix = getMatrix() + matrix[row: 0] = [13.0, 14.0, 15.0, 16.0] - let expectedResult: Matrix = Matrix([[13, 14, 15, 16], [5, 6, 7, 8], [9, 10, 11, 12]]) - XCTAssertEqual(matrix, expectedResult) + + let expected: Matrix = [ + [13, 14, 15, 16], + [5, 6, 7, 8], + [9, 10, 11, 12], + ] + + XCTAssertEqual(matrix, expected) } - func testSetColumn() { + func test_subscript_column_set() { + typealias Scalar = Double + + var matrix: Matrix = getMatrix() + matrix[column: 0] = [20, 30, 40] - let expectedResult: Matrix = Matrix([[20, 2, 3, 4], [30, 6, 7, 8], [40, 10, 11, 12]]) - XCTAssertEqual(matrix, expectedResult) + + let expected: Matrix = [ + [20, 2, 3, 4], + [30, 6, 7, 8], + [40, 10, 11, 12], + ] + + XCTAssertEqual(matrix, expected) } - func testMatrixPower() { - let expectedResult = Matrix([[1, 4, 9, 16], [25, 36, 49, 64], [81, 100, 121, 144]]) - XCTAssertEqual(pow(matrix, 2), expectedResult) +// func test_pow() { +// let expectedResult = Matrix([[1, 4, 9, 16], [25, 36, 49, 64], [81, 100, 121, 144]]) +// XCTAssertEqual(pow(matrix, 2), expectedResult) +// } + + func test_add_matrix_matrix_float() { + typealias Scalar = Float + + let matrix: Matrix = getMatrix() + + let expected: Matrix = [ + [2, 4, 6, 8], + [10, 12, 14, 16], + [18, 20, 22, 24], + ] + + XCTAssertEqual(matrix + matrix, expected) + } + + func test_add_matrix_matrix_double() { + typealias Scalar = Double + + let matrix: Matrix = getMatrix() + + let expected: Matrix = [ + [2, 4, 6, 8], + [10, 12, 14, 16], + [18, 20, 22, 24], + ] + + XCTAssertEqual(matrix + matrix, expected) + } + + func test_sub_matrix_matrix_float() { + typealias Scalar = Float + + let matrix: Matrix = getMatrix() + + let expected: Matrix = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ] + + XCTAssertEqual(matrix - matrix, expected) + } + + func test_sub_matrix_matrix_double() { + typealias Scalar = Double + + let matrix: Matrix = getMatrix() + + let expected: Matrix = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ] + + XCTAssertEqual(matrix - matrix, expected) + } + + func test_mul_scalar_matrix_float() { + typealias Scalar = Float + + let lhs: Scalar = 2 + + let rhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let expected: Matrix = [ + [4, 8, 12], + [20, 24, 28], + ] + + XCTAssertEqual(lhs * rhs, expected) + } + + func test_mul_scalar_matrix_double() { + typealias Scalar = Double + + let lhs: Scalar = 2 + + let rhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let expected: Matrix = [ + [4, 8, 12], + [20, 24, 28], + ] + + XCTAssertEqual(lhs * rhs, expected) + } + + func test_mul_matrix_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [2, 4], + [10, 12], + [18, 20], + ] + + let rhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let expected: Matrix = [ + [44, 56, 68], + [140, 184, 228], + [236, 312, 388], + ] + + XCTAssertEqual(lhs * rhs, expected) + } + + func test_mul_matrix_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [2, 4], + [10, 12], + [18, 20], + ] + + let rhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let expected: Matrix = [ + [44, 56, 68], + [140, 184, 228], + [236, 312, 388], + ] + + XCTAssertEqual(lhs * rhs, expected) } - func testMatrixAddition() { - let expectedResult: Matrix = Matrix([[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]) - XCTAssertEqual(matrix + matrix, expectedResult) + func test_mul_matrix_vector_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let rhs: Vector = [1, 2, 4] + + let actual = lhs * rhs + let expected: Vector = [17, 38] + + XCTAssertEqual(actual, expected) } - func testMatrixSubtraction() { - let expectedResult: Matrix = Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) - XCTAssertEqual(matrix - matrix, expectedResult) + func test_mul_matrix_vector_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let rhs: Vector = [1, 2, 4] + + let actual = lhs * rhs + let expected: Vector = [17, 38] + + XCTAssertEqual(actual, expected) } - func testElementWiseMultiplication() { - let matrix2 = Matrix([[2, 3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13]]) - let expectedResult: Matrix = Matrix([[2, 6, 12, 20], [30, 42, 56, 72], [90, 110, 132, 156]]) - XCTAssertEqual(elmul(matrix, matrix2), expectedResult) + func test_div_matrix_scalar_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let rhs: Scalar = 2 + + let expected: Matrix = [ + [1, 2, 3], + [5, 6, 7], + ] + + XCTAssertEqual(lhs / rhs, expected, accuracy: 1e-6) } - - func testDeterminantFloat() { - let matrix = Matrix([[1, 2], [5, 6]]) - XCTAssertEqual(det(matrix)!, Float(6 - 10), accuracy: floatAccuracy) + + func test_div_matrix_scalar_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [2, 4, 6], + [10, 12, 14], + ] + + let rhs: Scalar = 2 + + let expected: Matrix = [ + [1, 2, 3], + [5, 6, 7], + ] + + XCTAssertEqual(lhs / rhs, expected, accuracy: 1e-8) } - - func testDeterminantDouble() { - let matrix = Matrix([[-4, -5], [5, 6]]) - XCTAssertEqual(det(matrix)!, Double(-24 + 25), accuracy: doubleAccuracy) + + func test_div_matrix_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [2, 3], + [2, 2], + ] + + let rhs: Matrix = [ + [-1, 3/2], + [1, -1], + ] + + let expected: Matrix = [ + [10, 12], + [8, 10], + ] + + XCTAssertEqual(lhs / rhs, expected, accuracy: 1e-5) } + + func test_div_matrix_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [2, 3], + [2, 2], + ] + + let rhs: Matrix = [ + [-1, 3/2], + [1, -1], + ] + + let expected: Matrix = [ + [10, 12], + [8, 10], + ] + + XCTAssertEqual(lhs / rhs, expected, accuracy: 1e-8) + } + + func test_pow_matrix_scalar_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let rhs: Scalar = 2 + + let expected: Matrix = .init( + lhs.map { row in + row.map { pow($0, rhs) } + } + ) + + // FIXME: Replace with `**` operator: + XCTAssertEqual(pow(lhs, rhs), expected, accuracy: 1e-5) + } + + func test_pow_matrix_scalar_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let rhs: Scalar = 2 + + let expected: Matrix = .init( + lhs.map { row in + row.map { pow($0, rhs) } + } + ) + + // FIXME: Replace with `**` operator: + XCTAssertEqual(pow(lhs, rhs), expected, accuracy: 1e-8) + } + + func test_exp_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let expected: Matrix = .init( + lhs.map { row in + row.map { exp($0) } + } + ) + + XCTAssertEqual(exp(lhs), expected, accuracy: 1e-5) + } + + func test_exp_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let expected: Matrix = .init( + lhs.map { row in + row.map { exp($0) } + } + ) + + XCTAssertEqual(exp(lhs), expected, accuracy: 1e-8) + } + + func test_sum_matrix_rows_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + // FIXME: replace with row iterator: + let expected: Matrix = [ + [6], + [15], + ] + + XCTAssertEqual(sum(lhs, axies: .row), expected, accuracy: 1e-5) + } + + func test_sum_matrix_columns_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + // FIXME: replace with column iterator: + let expected: Matrix = [ + [5, 7, 9], + ] + + XCTAssertEqual(sum(lhs, axies: .column), expected, accuracy: 1e-5) + } + + func test_inv_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [2, 3], + [2, 2], + ] - func testMultiplyEmpty() { - let x = Matrix([[1]]) - let y = Matrix([[]]) - let result = x*y + let expected: Matrix = [ + [-1, 1.5], + [1, -1], + ] + + XCTAssertEqual(inv(lhs), expected, accuracy: 1e-8) + } + + func test_inv_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [2, 3], + [2, 2], + ] + + let expected: Matrix = [ + [-1, 1.5], + [1, -1], + ] + + XCTAssertEqual(inv(lhs), expected, accuracy: 1e-6) + } + + func test_tranpose_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let expected: Matrix = [ + [1, 4], + [2, 5], + [3, 6], + ] + + XCTAssertEqual(transpose(lhs), expected) + } + + func test_tranpose_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + + let expected: Matrix = [ + [1, 4], + [2, 5], + [3, 6], + ] + + XCTAssertEqual(transpose(lhs), expected) + } + + func test_det_matrix_double() { + typealias Scalar = Double + + let lhs: Matrix = [ + [1, 2], + [5, 6], + ] + + let expected: Scalar = 6 - 10 + + XCTAssertEqual(det(lhs), expected) + } + + func test_det_matrix_float() { + typealias Scalar = Float + + let lhs: Matrix = [ + [1, 2], + [5, 6], + ] + + let expected: Scalar = 6 - 10 + + XCTAssertEqual(det(lhs), expected) + } + + func test_mul_empty_float() { + typealias Scalar = Float + + let x: Matrix = [ + [1] + ] + let y: Matrix = [ + [] + ] + + let result = x * y XCTAssertEqual(result.rows, 1) XCTAssertEqual(result.columns, 0) @@ -223,71 +686,3 @@ class MatrixTests: XCTestCase { } } } - -extension MatrixTests { - func test_mul_matrix_vector_float() { - typealias Scalar = Float - - let lhs: Matrix = [ - [1, 2, 3], - [4, 5, 6], - ] - - let rhs: Vector = [1, 2, 4] - - let actual = lhs * rhs - let expected: Vector = [17, 38] - - XCTAssertEqual(actual, expected) - } - - func test_mul_matrix_vector_double() { - typealias Scalar = Double - - let lhs: Matrix = [ - [1, 2, 3], - [4, 5, 6], - ] - - let rhs: Vector = [1, 2, 4] - - let actual = lhs * rhs - let expected: Vector = [17, 38] - - XCTAssertEqual(actual, expected) - } - - func test_mul_vector_matrix_float() { - typealias Scalar = Float - - let lhs: Vector = [1, 2, 4] - - let rhs: Matrix = [ - [1, 4], - [2, 5], - [3, 6], - ] - - let actual = lhs * rhs - let expected: Vector = [17, 38] - - XCTAssertEqual(actual, expected) - } - - func test_mul_vector_matrix_double() { - typealias Scalar = Double - - let lhs: Vector = [1, 2, 4] - - let rhs: Matrix = [ - [1, 4], - [2, 5], - [3, 6], - ] - - let actual = lhs * rhs - let expected: Vector = [17, 38] - - XCTAssertEqual(actual, expected) - } -} diff --git a/Tests/SurgeTests/VectorTests.swift b/Tests/SurgeTests/VectorTests.swift index 47decf6..88b37e6 100644 --- a/Tests/SurgeTests/VectorTests.swift +++ b/Tests/SurgeTests/VectorTests.swift @@ -294,6 +294,40 @@ class VectorTests: XCTestCase { XCTAssertEqual(actual, expected, accuracy: 1e-8) } + func test_mul_vector_matrix_float() { + typealias Scalar = Float + + let lhs: Vector = [1, 2, 4] + + let rhs: Matrix = [ + [1, 4], + [2, 5], + [3, 6], + ] + + let actual = lhs * rhs + let expected: Vector = [17, 38] + + XCTAssertEqual(actual, expected) + } + + func test_mul_vector_matrix_double() { + typealias Scalar = Double + + let lhs: Vector = [1, 2, 4] + + let rhs: Matrix = [ + [1, 4], + [2, 5], + [3, 6], + ] + + let actual = lhs * rhs + let expected: Vector = [17, 38] + + XCTAssertEqual(actual, expected) + } + func test_mul_in_place_vector_scalar_double() { typealias Scalar = Double