From 96c6439fd082771d1c51157a33ed71c2c1564b62 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:52:42 +0200 Subject: [PATCH 01/16] Added `SurgeBenchmarkTests` as a dedicated benchmarks target --- Metadata/Info-BenchmarkTests.plist | 22 +++ Metadata/Info-Tests.plist | 2 +- Package.swift | 4 + Surge.xcodeproj/project.pbxproj | 132 +++++++++++++++++- .../xcschemes/SurgeBenchmarkTests.xcscheme | 52 +++++++ 5 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 Metadata/Info-BenchmarkTests.plist create mode 100644 Surge.xcodeproj/xcshareddata/xcschemes/SurgeBenchmarkTests.xcscheme diff --git a/Metadata/Info-BenchmarkTests.plist b/Metadata/Info-BenchmarkTests.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/Metadata/Info-BenchmarkTests.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Metadata/Info-Tests.plist b/Metadata/Info-Tests.plist index 6c40a6cd..64d65ca4 100644 --- a/Metadata/Info-Tests.plist +++ b/Metadata/Info-Tests.plist @@ -13,7 +13,7 @@ CFBundleName $(PRODUCT_NAME) CFBundlePackageType - BNDL + $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion diff --git a/Package.swift b/Package.swift index fbc4fd8c..59c8dcc8 100644 --- a/Package.swift +++ b/Package.swift @@ -39,5 +39,9 @@ let package = Package( name: "SurgeTests", dependencies: ["Surge"] ), + .testTarget( + name: "SurgeBenchmarkTests", + dependencies: ["Surge"] + ), ] ) diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 30b9c425..e0adeb3b 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -89,6 +89,7 @@ CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; + CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; @@ -132,6 +133,13 @@ remoteGlobalIDString = 614AD3501FC0B001002BFE1C; remoteInfo = "Surge-tvOS"; }; + CAAF500D233A7B6700CC0AA7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F8A1E1A119917A79009735E2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 614AD31E1FC0AD99002BFE1C; + remoteInfo = "Surge-macOS"; + }; F84A6AB719A9A771007B53E1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F8A1E1A119917A79009735E2 /* Project object */; @@ -176,6 +184,8 @@ 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ArraySlice+Extensions.swift"; sourceTree = ""; }; CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalarTests.swift; sourceTree = ""; }; CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; + CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-BenchmarkTests.plist"; sourceTree = ""; }; CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorPrecedences.swift; sourceTree = ""; }; CAEC79C323192FE300516E10 /* Scalar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scalar.swift; sourceTree = ""; }; CAEC79D12319343100516E10 /* Logarithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logarithm.swift; sourceTree = ""; }; @@ -226,6 +236,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + CAAF5004233A7B6700CC0AA7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F84A6AAB19A9A72F007B53E1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -288,6 +306,13 @@ path = SurgeTests; sourceTree = ""; }; + CAAF5008233A7B6700CC0AA7 /* SurgeBenchmarkTests */ = { + isa = PBXGroup; + children = ( + ); + path = SurgeBenchmarkTests; + sourceTree = ""; + }; CAEC79C8231932E900516E10 /* Utilities */ = { isa = PBXGroup; children = ( @@ -364,6 +389,7 @@ isa = PBXGroup; children = ( 61A0AD6C1F70D22600B99FFB /* SurgeTests */, + CAAF5008233A7B6700CC0AA7 /* SurgeBenchmarkTests */, ); path = Tests; sourceTree = ""; @@ -392,6 +418,7 @@ 614AD3511FC0B001002BFE1C /* Surge.framework */, 614AD3591FC0B001002BFE1C /* SurgeTests-tvOS.xctest */, 614AD3821FC0B125002BFE1C /* Surge.framework */, + CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */, ); name = Products; sourceTree = ""; @@ -401,6 +428,7 @@ children = ( 614AD3221FC0AD99002BFE1C /* Info-macOS.plist */, 614AD3361FC0AEBD002BFE1C /* Info-Tests.plist */, + CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */, 614AD3541FC0B001002BFE1C /* Info.plist */, ); path = Metadata; @@ -546,6 +574,24 @@ productReference = 614AD3821FC0B125002BFE1C /* Surge.framework */; productType = "com.apple.product-type.framework"; }; + CAAF5006233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CAAF5011233A7B6700CC0AA7 /* Build configuration list for PBXNativeTarget "SurgeBenchmarkTests-macOS" */; + buildPhases = ( + CAAF5003233A7B6700CC0AA7 /* Sources */, + CAAF5004233A7B6700CC0AA7 /* Frameworks */, + CAAF5005233A7B6700CC0AA7 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CAAF500E233A7B6700CC0AA7 /* PBXTargetDependency */, + ); + name = "SurgeBenchmarkTests-macOS"; + productName = SurgeBenchmarkTests; + productReference = CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; F84A6AAD19A9A72F007B53E1 /* SurgeTests-iOS */ = { isa = PBXNativeTarget; buildConfigurationList = F84A6AB419A9A72F007B53E1 /* Build configuration list for PBXNativeTarget "SurgeTests-iOS" */; @@ -590,7 +636,7 @@ isa = PBXProject; attributes = { LastSwiftMigration = 0710; - LastSwiftUpdateCheck = 0910; + LastSwiftUpdateCheck = 1100; LastUpgradeCheck = 0930; ORGANIZATIONNAME = "Mattt Thompson"; TargetAttributes = { @@ -614,6 +660,10 @@ CreatedOnToolsVersion = 9.1; ProvisioningStyle = Automatic; }; + CAAF5006233A7B6700CC0AA7 = { + CreatedOnToolsVersion = 11.0; + ProvisioningStyle = Automatic; + }; F84A6AAD19A9A72F007B53E1 = { CreatedOnToolsVersion = 6.0; LastSwiftMigration = 0900; @@ -645,6 +695,7 @@ 614AD3501FC0B001002BFE1C /* Surge-tvOS */, 614AD3581FC0B001002BFE1C /* SurgeTests-tvOS */, 614AD3811FC0B125002BFE1C /* Surge-watchOS */, + CAAF5006233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS */, ); }; /* End PBXProject section */ @@ -685,6 +736,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + CAAF5005233A7B6700CC0AA7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; F84A6AAC19A9A72F007B53E1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -872,6 +930,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + CAAF5003233A7B6700CC0AA7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; F84A6AAA19A9A72F007B53E1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -927,6 +992,11 @@ target = 614AD3501FC0B001002BFE1C /* Surge-tvOS */; targetProxy = 614AD35B1FC0B001002BFE1C /* PBXContainerItemProxy */; }; + CAAF500E233A7B6700CC0AA7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 614AD31E1FC0AD99002BFE1C /* Surge-macOS */; + targetProxy = CAAF500D233A7B6700CC0AA7 /* PBXContainerItemProxy */; + }; F84A6AB819A9A771007B53E1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = F8A1E1A919917A79009735E2 /* Surge-iOS */; @@ -1207,6 +1277,57 @@ }; name = Release; }; + CAAF500F233A7B6700CC0AA7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Metadata/Info-BenchmarkTests.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.mattt.SurgeBenchmarkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + CAAF5010233A7B6700CC0AA7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Metadata/Info-BenchmarkTests.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.mattt.SurgeBenchmarkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; F84A6AB519A9A72F007B53E1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1443,6 +1564,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + CAAF5011233A7B6700CC0AA7 /* Build configuration list for PBXNativeTarget "SurgeBenchmarkTests-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CAAF500F233A7B6700CC0AA7 /* Debug */, + CAAF5010233A7B6700CC0AA7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F84A6AB419A9A72F007B53E1 /* Build configuration list for PBXNativeTarget "SurgeTests-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Surge.xcodeproj/xcshareddata/xcschemes/SurgeBenchmarkTests.xcscheme b/Surge.xcodeproj/xcshareddata/xcschemes/SurgeBenchmarkTests.xcscheme new file mode 100644 index 00000000..1040fb13 --- /dev/null +++ b/Surge.xcodeproj/xcshareddata/xcschemes/SurgeBenchmarkTests.xcscheme @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + From ebbd2649b0f6ba915720b9d5f4882cf1fa11f5b0 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 20:51:29 +0200 Subject: [PATCH 02/16] =?UTF-8?q?Added=20`void=5Freturn`=20&=20`redundant?= =?UTF-8?q?=5Fdiscardable=5Flet`=20to=20swiftlint=E2=80=99s=20ignore=20lis?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .swiftlint.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 434b91d1..cc3923ad 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,7 +3,9 @@ disabled_rules: - identifier_name - line_length - trailing_comma - + - redundant_discardable_let + - void_return + opt_in_rules: - array_init - attributes From d387b7784a7e24dc3d69c84e829e7c3e27350a08 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 20:54:08 +0200 Subject: [PATCH 03/16] =?UTF-8?q?Changed=20tests=20to=20only=20check=20eac?= =?UTF-8?q?h=20operation=E2=80=99s=20base=20function=20(e.g.=20`func=20add?= =?UTF-8?q?InPlace`),=20not=20a=20derived=20wrapper=20function=20(e.g.=20`?= =?UTF-8?q?func=20add`=20or=20`func=20+`,=20etc.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also removed any previously added benchmarks. But not to worry we’ll add them back in a dedicated `SurgeBenchmarkTests` test target. --- Tests/SurgeTests/ArithmeticTests.swift | 463 ++++++------------------- 1 file changed, 110 insertions(+), 353 deletions(-) diff --git a/Tests/SurgeTests/ArithmeticTests.swift b/Tests/SurgeTests/ArithmeticTests.swift index ad9fd4ff..018fed55 100644 --- a/Tests/SurgeTests/ArithmeticTests.swift +++ b/Tests/SurgeTests/ArithmeticTests.swift @@ -19,47 +19,14 @@ // THE SOFTWARE. import Foundation -import Surge import XCTest +@testable import Surge + // swiftlint:disable nesting type_body_length class ArithmeticTests: XCTestCase { - let n = 100_000 - - // MARK: - Addition - - func test_add_array_array_float() { - typealias Scalar = Float - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .+ rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 + $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - - func test_add_array_array_double() { - typealias Scalar = Double - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .+ rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 + $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } + let n = 1_000 // MARK: - Addition: In Place @@ -69,14 +36,8 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .+= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.addInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 + $1 } @@ -89,54 +50,14 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .+= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.addInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 + $1 } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Subtraction - - func test_sub_array_array_float() { - typealias Scalar = Float - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .- rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 - $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - - func test_sub_array_array_double() { - typealias Scalar = Double - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .- rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 - $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - // MARK: - Subtraction: In Place func test_sub_in_place_array_array_float() { @@ -145,14 +66,8 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .-= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.subInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 - $1 } @@ -165,54 +80,14 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .-= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.subInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 - $1 } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Multiplication - - func test_mul_array_array_float() { - typealias Scalar = Float - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .* rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 * $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - - func test_mul_array_array_double() { - typealias Scalar = Double - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs .* rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 * $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - // MARK: - Multiplication: In Place func test_mul_in_place_array_array_float() { @@ -221,14 +96,8 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .*= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.mulInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 * $1 } @@ -241,54 +110,14 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual .*= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.mulInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 * $1 } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Division - - func test_div_array_array_float() { - typealias Scalar = Float - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs ./ rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 / $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-6) - } - - func test_div_array_array_double() { - typealias Scalar = Double - - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - - var actual: [Scalar] = [] - measure { - actual = lhs ./ rhs - } - - let expected = Swift.zip(lhs, rhs).map { $0 / $1 } - - XCTAssertEqual(actual, expected, accuracy: 1e-8) - } - // MARK: - Division: In Place func test_div_in_place_array_array_float() { @@ -297,14 +126,8 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual ./= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.divInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 / $1 } @@ -317,276 +140,238 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { - actual = lhs - - startMeasuring() - actual ./= rhs - stopMeasuring() - } + var actual: [Scalar] = lhs + Surge.divInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { $0 / $1 } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Modulo + // MARK: - Modulo: In Place - func test_mod_array_array_float() { + func test_mod_in_place_array_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) } let rhs: [Scalar] = Array(repeating: 42, count: n) - var actual: [Scalar] = [] - measure { - actual = lhs .% rhs - } + var actual: [Scalar] = lhs + Surge.modInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { fmod($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - func test_mod_array_array_double() { + func test_mod_in_place_array_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) } let rhs: [Scalar] = Array(repeating: 42, count: n) - var actual: [Scalar] = [] - measure { - actual = lhs .% rhs - } + var actual: [Scalar] = lhs + Surge.modInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { fmod($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Remainder + // MARK: - Remainder: In Place - func test_remainder_array_array_float() { + func test_remainder_in_place_array_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) } let rhs: [Scalar] = Array(repeating: -42, count: n) - var actual: [Scalar] = [] - measure { - actual = Surge.remainder(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.remainderInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { remainder($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - func test_remainder_array_array_double() { + func test_remainder_in_place_array_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) } let rhs: [Scalar] = Array(repeating: -42, count: n) - var actual: [Scalar] = [] - measure { - actual = Surge.remainder(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.remainderInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { remainder($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Exponential + // MARK: - Exponential: In Place - func test_exp_array_float() { + func test_exp_in_place_array_float() { typealias Scalar = Float - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.exp(values) - } + var actual: [Scalar] = lhs + Surge.expInPlace(&actual) - let expected = values.map { exp($0) } + let expected = lhs.map { exp($0) } XCTAssertEqual(actual, expected, accuracy: 1e-6) } - func test_exp_array_double() { + func test_exp_in_place_array_double() { typealias Scalar = Double - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.exp(values) - } + var actual: [Scalar] = lhs + Surge.expInPlace(&actual) - let expected = values.map { exp($0) } + let expected = lhs.map { exp($0) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Square Exponentiation + // MARK: - Square Exponential: In Place - func test_exp2_array_float() { + func test_exp2_in_place_array_float() { typealias Scalar = Float - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.exp2(values) - } + var actual: [Scalar] = lhs + Surge.exp2InPlace(&actual) - let expected = values.map { exp2($0) } + let expected = lhs.map { exp2($0) } XCTAssertEqual(actual, expected, accuracy: 1e-6) } - func test_exp2_array_double() { + func test_exp2_in_place_array_double() { typealias Scalar = Double - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.exp2(values) - } + var actual: [Scalar] = lhs + Surge.exp2InPlace(&actual) - let expected = values.map { exp2($0) } + let expected = lhs.map { exp2($0) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Power + // MARK: - Power: In Place - func test_pow_array_array_float() { + func test_pow_in_place_array_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = Array(repeating: 2.0, count: n) - var actual: [Scalar] = [] - measure { - actual = Surge.pow(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.powInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { pow($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-5) } - func test_pow_array_array_double() { + func test_pow_in_place_array_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = Array(repeating: 2.0, count: n) - var actual: [Scalar] = [] - measure { - actual = Surge.pow(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.powInPlace(&actual, rhs) let expected = Swift.zip(lhs, rhs).map { pow($0, $1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - func test_pow_array_scalar_float() { + func test_pow_in_place_array_scalar_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: Scalar = 2.0 - var actual: [Scalar] = [] - measure { - actual = Surge.pow(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.powInPlace(&actual, rhs) let expected = lhs.map { pow($0, rhs) } XCTAssertEqual(actual, expected, accuracy: 1e-5) } - func test_pow_array_scalar_double() { + func test_pow_in_place_array_scalar_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: Scalar = 2.0 - var actual: [Scalar] = [] - measure { - actual = Surge.pow(lhs, rhs) - } + var actual: [Scalar] = lhs + Surge.powInPlace(&actual, rhs) let expected = lhs.map { pow($0, rhs) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Square + // MARK: - Square: In Place - func test_sq_array_float() { + func test_sq_in_place_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.sq(lhs) - } + var actual: [Scalar] = lhs + Surge.sqInPlace(&actual) let expected = lhs.map { pow($0, 2.0) } XCTAssertEqual(actual, expected, accuracy: 1e-5) } - func test_sq_array_double() { + func test_sq_in_place_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.sq(lhs) - } + var actual: [Scalar] = lhs + Surge.sqInPlace(&actual) let expected = lhs.map { pow($0, 2.0) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - // MARK: - Square Root + // MARK: - Square Root: In Place - func test_sqrt_array_array_float() { + func test_sqrt_in_place_array_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) } - var actual: [Scalar] = [] - measure { - actual = Surge.sqrt(lhs) - } + var actual: [Scalar] = lhs + Surge.sqrtInPlace(&actual) let expected = lhs.map { sqrt($0) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } - func test_sqrt_array_array_double() { + func test_sqrt_in_place_array_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) } - var actual: [Scalar] = [] - measure { - actual = Surge.sqrt(lhs) - } + var actual: [Scalar] = lhs + Surge.sqrtInPlace(&actual) let expected = lhs.map { sqrt($0) } @@ -601,14 +386,9 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0 - measure { - actual = lhs • rhs - } + let actual: Scalar = Surge.dot(lhs, rhs) - let expected = Swift.zip(lhs, rhs).reduce(0) { - $0 + $1.0 * $1.1 - } + let expected = Swift.zip(lhs, rhs).reduce(0) { $0 + ($1.0 * $1.1) } XCTAssertEqual(actual, expected, accuracy: 1e-1) } @@ -619,78 +399,61 @@ class ArithmeticTests: XCTestCase { let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0 - measure { - actual = lhs • rhs - } + let actual: Scalar = Surge.dot(lhs, rhs) - let expected = Swift.zip(lhs, rhs).reduce(0) { - $0 + $1.0 * $1.1 - } + let expected = Swift.zip(lhs, rhs).reduce(0) { $0 + ($1.0 * $1.1) } XCTAssertEqual(actual, expected, accuracy: 1e-8) } // MARK: - Summation - func test_sum_array_double() { - typealias Scalar = Double + func test_sum_array_float() { + typealias Scalar = Float - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = sum(values) - } + let actual: Scalar = Surge.sum(lhs) - let expected: Scalar = values.reduce(0, +) + let expected: Scalar = lhs.reduce(0, +) - XCTAssertEqual(actual, expected, accuracy: 1e-8) + XCTAssertEqual(actual, expected, accuracy: 1e-1) } - func test_sum_array_float() { - typealias Scalar = Float + func test_sum_array_double() { + typealias Scalar = Double - let values: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = sum(values) - } + let actual: Scalar = Surge.sum(lhs) - let expected: Scalar = values.reduce(0, +) + let expected: Scalar = lhs.reduce(0, +) - XCTAssertEqual(actual, expected, accuracy: 1e-1) + XCTAssertEqual(actual, expected, accuracy: 1e-8) } // MARK: - Distance - func test_dist_array_array_double() { - typealias Scalar = Double + func test_dist_array_array_float() { + typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = dist(lhs, rhs) - } + let actual: Scalar = Surge.dist(lhs, rhs) let expected: Scalar = sqrt(Swift.zip(lhs, rhs).map({ $0 - $1 }).map({ $0 * $0 }).reduce(0.0, +)) XCTAssertEqual(actual, expected, accuracy: 1e-6) } - func test_dist_array_array_float() { - typealias Scalar = Float + func test_dist_array_array_double() { + typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = dist(lhs, rhs) - } + let actual: Scalar = Surge.dist(lhs, rhs) let expected: Scalar = sqrt(Swift.zip(lhs, rhs).map({ $0 - $1 }).map({ $0 * $0 }).reduce(0.0, +)) @@ -699,16 +462,13 @@ class ArithmeticTests: XCTestCase { // MARK: - Distance Squared - func test_distsq_array_array_double() { - typealias Scalar = Double + func test_distsq_array_array_float() { + typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = distSq(lhs, rhs) - } + let actual: Scalar = Surge.distSq(lhs, rhs) let partialDistances: [Scalar] = Swift.zip(lhs, rhs).map { $0 - $1 } let partialDistancesSquared: [Scalar] = partialDistances.map { $0 * $0 } @@ -717,16 +477,13 @@ class ArithmeticTests: XCTestCase { XCTAssertEqual(actual, expected, accuracy: 1e-6) } - func test_distsq_array_array_float() { - typealias Scalar = Float + func test_distsq_array_array_double() { + typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: Scalar = 0.0 - measure { - actual = distSq(lhs, rhs) - } + let actual: Scalar = Surge.distSq(lhs, rhs) let partialDistances: [Scalar] = Swift.zip(lhs, rhs).map { $0 - $1 } let partialDistancesSquared: [Scalar] = partialDistances.map { $0 * $0 } From f5ce17ada11f8f1beb0023d39be573048c30f3b5 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:08:18 +0200 Subject: [PATCH 04/16] =?UTF-8?q?Added=20=E2=80=98XCTestCase+Surge.swift?= =?UTF-8?q?=E2=80=99=20with=20benchmarking=20helpers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge.xcodeproj/project.pbxproj | 4 + .../XCTestCase+Surge.swift | 183 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index e0adeb3b..0c7b8ef7 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -91,6 +91,7 @@ CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; + CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */; }; CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; CAEC79C02319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; @@ -186,6 +187,7 @@ CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-BenchmarkTests.plist"; sourceTree = ""; }; + CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Surge.swift"; sourceTree = ""; }; CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorPrecedences.swift; sourceTree = ""; }; CAEC79C323192FE300516E10 /* Scalar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scalar.swift; sourceTree = ""; }; CAEC79D12319343100516E10 /* Logarithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logarithm.swift; sourceTree = ""; }; @@ -309,6 +311,7 @@ CAAF5008233A7B6700CC0AA7 /* SurgeBenchmarkTests */ = { isa = PBXGroup; children = ( + CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */, ); path = SurgeBenchmarkTests; sourceTree = ""; @@ -934,6 +937,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift b/Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift new file mode 100644 index 00000000..0bd6e8a1 --- /dev/null +++ b/Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift @@ -0,0 +1,183 @@ +// Copyright © 2014-2018 the Surge contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation +import XCTest + +// swiftlint:disable nesting + +// Why on earth do we need these abominations, you ask? +// +// Well, you see … XCTest is not —to put it mildly— the best unit testing framework out there. +// As such, while `XCTAssert` and its cousins have hidden `file: StaticString = #file, line: UInt = #line` parameters, +// which allow for Xcode to associate a particular failure with a different line than the actual invocation, +// its `measure(_:)` and the more elaborate `measureMetrics(_:automaticallyStartMeasuring:for:)` variant do not +// provide such hidden `file:line:` parameters. As such it's impossible to wrap the call to either of those functions +// in a convenience wrapper of some kind in order to reduce testing code bloat and redundancies. +// +// And due to the nature of Surge's `…InPlace` functions' use of `inout` invocations of such functions is not idempotent. +// So we need to make sure we're passing a freshly prepared test value to each invocation of the measure block. +// But at the same time we do not want to include such house-keeping things in our benchmarks, as it may involve +// quite costly memory allocations and copying. +// +// As such we are forced to make use of `measureMetrics(_:automaticallyStartMeasuring:for:)`, instead of the simpler `measure(_:)` +// and do some trampolin gymnastics to keep as much of the nasty and redundant stuff out of sight of the user. +// +// And this my dear friend is why we're having this conversion right now. I'm sorry. + +extension XCTestCase { + typealias LhsFunction = (Lhs) -> T + typealias LhsFunctionWrapper = (LhsFunction) -> () + + typealias LhsRhsFunction = (Lhs, Rhs) -> T + typealias LhsRhsFunctionWrapper = (LhsRhsFunction) -> () + + typealias InOutLhsFunction = (inout Lhs) -> T + typealias InOutLhsFunctionWrapper = (InOutLhsFunction) -> () + + typealias InOutLhsRhsFunction = (inout Lhs, Rhs) -> T + typealias InOutLhsRhsFunctionWrapper = (InOutLhsRhsFunction) -> () + + typealias Producer = () -> T + + static func normalizedMonotonic(n: Int = ArithmeticTests.n) -> Producer<[T]> where T: FloatingPoint { + typealias Scalar = T + + return { + (1...n).map { Scalar($0) / Scalar(n) } + } + } + + static func scalar(constant: T = 2.0) -> Producer where T: FloatingPoint & ExpressibleByFloatLiteral { + return { + constant + } + } + + func measure_array( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + _ closure: (LhsFunctionWrapper<[T], U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + + closure({ innerClosure in + startMeasuring() + let _ = innerClosure(lhs) + stopMeasuring() + }) + } + + func measure_inout_array( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + _ closure: (InOutLhsFunctionWrapper<[T], U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + + closure({ innerClosure in + var lhs = lhs + + startMeasuring() + let _ = innerClosure(&lhs) + stopMeasuring() + }) + } + + func measure_array_array( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + rhs produceRhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + _ closure: (LhsRhsFunctionWrapper<[T], [T], U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + let rhs = produceRhs() + + closure({ innerClosure in + startMeasuring() + let _ = innerClosure(lhs, rhs) + stopMeasuring() + }) + } + + func measure_inout_array_array( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + rhs produceRhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + _ closure: (InOutLhsRhsFunctionWrapper<[T], [T], U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + let rhs = produceRhs() + + closure({ innerClosure in + var lhs = lhs + + startMeasuring() + let _ = innerClosure(&lhs, rhs) + stopMeasuring() + }) + } + + func measure_array_scalar( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + rhs produceRhs: Producer = ArithmeticTests.scalar(), + _ closure: (LhsRhsFunctionWrapper<[T], T, U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + let rhs = produceRhs() + + closure({ innerClosure in + startMeasuring() + let _ = innerClosure(lhs, rhs) + stopMeasuring() + }) + } + + func measure_inout_array_scalar( + of: T.Type, + lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + rhs produceRhs: Producer = ArithmeticTests.scalar(), + _ closure: (InOutLhsRhsFunctionWrapper<[T], T, U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + let rhs = produceRhs() + + closure({ innerClosure in + var lhs = lhs + + startMeasuring() + let _ = innerClosure(&lhs, rhs) + stopMeasuring() + }) + } +} From 5ffac906dc7d8bfe824461c5d9e986f2efc8f241 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:11:02 +0200 Subject: [PATCH 05/16] Added benchmarks corresponding to those previously found in `SurgeTests/ArithmeticTests.swift` --- Surge.xcodeproj/project.pbxproj | 4 + .../SurgeBenchmarkTests/ArithmeticTests.swift | 314 ++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 Tests/SurgeBenchmarkTests/ArithmeticTests.swift diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 0c7b8ef7..64112010 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -91,6 +91,7 @@ CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; + CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */; }; CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */; }; CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; @@ -187,6 +188,7 @@ CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-BenchmarkTests.plist"; sourceTree = ""; }; + CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArithmeticTests.swift; sourceTree = ""; }; CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Surge.swift"; sourceTree = ""; }; CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorPrecedences.swift; sourceTree = ""; }; CAEC79C323192FE300516E10 /* Scalar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scalar.swift; sourceTree = ""; }; @@ -311,6 +313,7 @@ CAAF5008233A7B6700CC0AA7 /* SurgeBenchmarkTests */ = { isa = PBXGroup; children = ( + CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */, CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */, ); path = SurgeBenchmarkTests; @@ -938,6 +941,7 @@ buildActionMask = 2147483647; files = ( CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */, + CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/SurgeBenchmarkTests/ArithmeticTests.swift b/Tests/SurgeBenchmarkTests/ArithmeticTests.swift new file mode 100644 index 00000000..1aac6047 --- /dev/null +++ b/Tests/SurgeBenchmarkTests/ArithmeticTests.swift @@ -0,0 +1,314 @@ +// Copyright © 2014-2018 the Surge contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation +import XCTest + +@testable import Surge + +class ArithmeticTests: XCTestCase { + static let n = 100_000 + + // MARK: - Addition: In Place + + func test_add_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.addInPlace) + } + } + } + + func test_add_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.addInPlace) + } + } + } + + // MARK: - Subtraction: In Place + + func test_sub_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.subInPlace) + } + } + } + + func test_sub_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.subInPlace) + } + } + } + + // MARK: - Multiplication: In Place + + func test_mul_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.mulInPlace) + } + } + } + + func test_mul_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.mulInPlace) + } + } + } + + // MARK: - Division: In Place + + func test_div_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.divInPlace) + } + } + } + + func test_div_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.divInPlace) + } + } + } + + // MARK: - Modulo: In Place + + func test_mod_in_place_array_array_float() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.modInPlace) + } + } + } + + func test_mod_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.modInPlace) + } + } + } + + // MARK: - Remainder + + func test_remainder_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.remainderInPlace) + } + } + } + + func test_remainder_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.remainderInPlace) + } + } + } + + // MARK: - Exponential + + func test_exp_in_place_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.expInPlace) + } + } + } + + func test_exp_in_place_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.expInPlace) + } + } + } + + // MARK: - Square Exponentiation + + func test_exp2_in_place_array_float() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.exp2InPlace) + } + } + } + + func test_exp2_in_place_array_double() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.exp2InPlace) + } + } + } + + // MARK: - Power + + func test_pow_in_place_array_array_float() { + measure_inout_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.powInPlace) + } + } + } + + func test_pow_in_place_array_array_double() { + measure_inout_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.powInPlace) + } + } + } + + func test_pow_in_place_array_scalar_float() { + measure_inout_array_scalar(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.powInPlace) + } + } + } + + func test_pow_in_place_array_scalar_double() { + measure_inout_array_scalar(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.powInPlace) + } + } + } + + // MARK: - Square + + func test_sq_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sqInPlace) + } + } + } + + func test_sq_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sqInPlace) + } + } + } + + // MARK: - Square Root + + func test_sqrt_array_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sqrtInPlace) + } + } + } + + func test_sqrt_array_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sqrtInPlace) + } + } + } + + // MARK: - Dot Product + + func test_dot_array_array_float() { + measure_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.dot) + } + } + } + + func test_dot_array_array_double() { + measure_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.dot) + } + } + } + + // MARK: - Summation + + func test_sum_array_float() { + measure_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sum) + } + } + } + + func test_sum_array_double() { + measure_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.sum) + } + } + } + + // MARK: - Distance + + func test_dist_array_array_float() { + measure_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.dist) + } + } + } + + func test_dist_array_array_double() { + measure_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.dist) + } + } + } + + // MARK: - Distance Squared + + func test_distsq_array_array_float() { + measure_array_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.distSq) + } + } + } + + func test_distsq_array_array_double() { + measure_array_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.distSq) + } + } + } +} From f6b27f62fe17c6a77f5748b7a16d14abfdfa09d0 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:09:30 +0200 Subject: [PATCH 06/16] Added `*.xcbaseline` to ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d164ac4..5a2c379f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ xcuserdata/ ## Other *.moved-aside *.xcuserstate +*.xcbaseline ## Obj-C/Swift specific *.hmap From 38abb148e0f2189cf610d0ea20db06e1e56840b8 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:15:12 +0200 Subject: [PATCH 07/16] =?UTF-8?q?Removed=20redundant=20=E2=80=98Exponentia?= =?UTF-8?q?lTests.swift=E2=80=99=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge.xcodeproj/project.pbxproj | 8 ------ Tests/SurgeTests/ExponentialTests.swift | 37 ------------------------- 2 files changed, 45 deletions(-) delete mode 100644 Tests/SurgeTests/ExponentialTests.swift diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 64112010..e0addcec 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -19,7 +19,6 @@ 614AD3431FC0AF77002BFE1C /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6D1F70D22600B99FFB /* ArithmeticTests.swift */; }; 614AD3441FC0AF77002BFE1C /* AuxiliaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6E1F70D22600B99FFB /* AuxiliaryTests.swift */; }; 614AD3451FC0AF77002BFE1C /* ConvolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6F1F70D22600B99FFB /* ConvolutionTests.swift */; }; - 614AD3461FC0AF77002BFE1C /* ExponentialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD701F70D22600B99FFB /* ExponentialTests.swift */; }; 614AD3471FC0AF77002BFE1C /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 614AD3481FC0AF77002BFE1C /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 614AD34A1FC0AF77002BFE1C /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; @@ -36,7 +35,6 @@ 614AD3741FC0B0D2002BFE1C /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6D1F70D22600B99FFB /* ArithmeticTests.swift */; }; 614AD3751FC0B0D2002BFE1C /* AuxiliaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6E1F70D22600B99FFB /* AuxiliaryTests.swift */; }; 614AD3761FC0B0D2002BFE1C /* ConvolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6F1F70D22600B99FFB /* ConvolutionTests.swift */; }; - 614AD3771FC0B0D2002BFE1C /* ExponentialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD701F70D22600B99FFB /* ExponentialTests.swift */; }; 614AD3781FC0B0D2002BFE1C /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 614AD3791FC0B0D2002BFE1C /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 614AD37B1FC0B0D2002BFE1C /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; @@ -64,7 +62,6 @@ 61A0AD761F70D22600B99FFB /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6D1F70D22600B99FFB /* ArithmeticTests.swift */; }; 61A0AD771F70D22600B99FFB /* AuxiliaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6E1F70D22600B99FFB /* AuxiliaryTests.swift */; }; 61A0AD781F70D22600B99FFB /* ConvolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD6F1F70D22600B99FFB /* ConvolutionTests.swift */; }; - 61A0AD791F70D22600B99FFB /* ExponentialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD701F70D22600B99FFB /* ExponentialTests.swift */; }; 61A0AD7A1F70D22600B99FFB /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 61A0AD7B1F70D22600B99FFB /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 61A0AD7D1F70D22600B99FFB /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; @@ -172,7 +169,6 @@ 61A0AD6D1F70D22600B99FFB /* ArithmeticTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArithmeticTests.swift; sourceTree = ""; }; 61A0AD6E1F70D22600B99FFB /* AuxiliaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuxiliaryTests.swift; sourceTree = ""; }; 61A0AD6F1F70D22600B99FFB /* ConvolutionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvolutionTests.swift; sourceTree = ""; }; - 61A0AD701F70D22600B99FFB /* ExponentialTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExponentialTests.swift; sourceTree = ""; }; 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HyperbolicTests.swift; sourceTree = ""; }; 61A0AD721F70D22600B99FFB /* MatrixTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatrixTests.swift; sourceTree = ""; }; 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrigonometricTests.swift; sourceTree = ""; }; @@ -297,7 +293,6 @@ 61A0AD6D1F70D22600B99FFB /* ArithmeticTests.swift */, 61A0AD6E1F70D22600B99FFB /* AuxiliaryTests.swift */, 61A0AD6F1F70D22600B99FFB /* ConvolutionTests.swift */, - 61A0AD701F70D22600B99FFB /* ExponentialTests.swift */, 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */, CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */, 61A0AD721F70D22600B99FFB /* MatrixTests.swift */, @@ -867,7 +862,6 @@ CAFE5DA622F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 614AD3471FC0AF77002BFE1C /* HyperbolicTests.swift in Sources */, 614AD3431FC0AF77002BFE1C /* ArithmeticTests.swift in Sources */, - 614AD3461FC0AF77002BFE1C /* ExponentialTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -909,7 +903,6 @@ CAFE5DA722F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 614AD3781FC0B0D2002BFE1C /* HyperbolicTests.swift in Sources */, 614AD3741FC0B0D2002BFE1C /* ArithmeticTests.swift in Sources */, - 614AD3771FC0B0D2002BFE1C /* ExponentialTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -960,7 +953,6 @@ CAFE5DA522F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 61A0AD7A1F70D22600B99FFB /* HyperbolicTests.swift in Sources */, 61A0AD761F70D22600B99FFB /* ArithmeticTests.swift in Sources */, - 61A0AD791F70D22600B99FFB /* ExponentialTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/SurgeTests/ExponentialTests.swift b/Tests/SurgeTests/ExponentialTests.swift deleted file mode 100644 index 6c782e2e..00000000 --- a/Tests/SurgeTests/ExponentialTests.swift +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright © 2014-2018 the Surge contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation -import Surge -import XCTest - -class ExponentialTests: XCTestCase { - let n = 10_000 - - func test_exp() { - let values = (0...n).map { _ in Double(arc4random_uniform(10)) } - measureAndValidateMappedFunctionWithAccuracy(source: values, member: exp, mapped: exp, accuracy: 1e-4) - } - - func test_exp2() { - let values = (0...n).map { _ in Double(arc4random_uniform(10)) } - measureAndValidateMappedFunctionWithAccuracy(source: values, member: exp2, mapped: exp2, accuracy: 1e-4) - } -} From 3c0dead23d9a758767c8e2f2a5e360dc659d2bf8 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:25:51 +0200 Subject: [PATCH 08/16] =?UTF-8?q?Changed=20tests=20to=20only=20check=20eac?= =?UTF-8?q?h=20operation=E2=80=99s=20base=20function=20(e.g.=20`func=20log?= =?UTF-8?q?InPlace`),=20not=20a=20derived=20wrapper=20function=20(e.g.=20`?= =?UTF-8?q?func=20log`)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also removed any previously added benchmarks. But not to worry we’ll add them back in a dedicated `SurgeBenchmarkTests` test target. --- Tests/SurgeTests/LogarithmTests.swift | 69 +++++++++++---------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/Tests/SurgeTests/LogarithmTests.swift b/Tests/SurgeTests/LogarithmTests.swift index 5ef9645c..b1ed7adf 100644 --- a/Tests/SurgeTests/LogarithmTests.swift +++ b/Tests/SurgeTests/LogarithmTests.swift @@ -19,40 +19,37 @@ // THE SOFTWARE. import Foundation -import Surge import XCTest +@testable import Surge + // swiftlint:disable nesting class LogarithmTests: XCTestCase { - let n = 100_000 + let n = 1_000 // MARK: - Base-e Logarithm - func test_log_array_float() { + func test_log_in_place_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log(lhs) - } + var actual: [Scalar] = lhs + Surge.logInPlace(&actual) let expected = lhs.map { log($0) } XCTAssertEqual(actual, expected, accuracy: 1e-4) } - func test_log_array_double() { + func test_log_in_place_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log(lhs) - } + var actual: [Scalar] = lhs + Surge.logInPlace(&actual) let expected = lhs.map { log($0) } @@ -61,30 +58,26 @@ class LogarithmTests: XCTestCase { // MARK: - Base-2 Logarithm - func test_log2_array_float() { + func test_log2_in_place_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log2(lhs) - } + var actual: [Scalar] = lhs + Surge.log2InPlace(&actual) let expected = lhs.map { log2($0) } XCTAssertEqual(actual, expected, accuracy: 1e-4) } - func test_log2_array_double() { + func test_log2_in_place_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log2(lhs) - } + var actual: [Scalar] = lhs + Surge.log2InPlace(&actual) let expected = lhs.map { log2($0) } @@ -93,30 +86,26 @@ class LogarithmTests: XCTestCase { // MARK: - Base-10 Logarithm - func test_log10_array_float() { + func test_log10_in_place_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log10(lhs) - } + var actual: [Scalar] = lhs + Surge.log10InPlace(&actual) let expected = lhs.map { log10($0) } XCTAssertEqual(actual, expected, accuracy: 1e-4) } - func test_log10_array_double() { + func test_log10_in_place_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.log10(lhs) - } + var actual: [Scalar] = lhs + Surge.log10InPlace(&actual) let expected = lhs.map { log10($0) } @@ -125,30 +114,26 @@ class LogarithmTests: XCTestCase { // MARK: - Base-b Logarithm - func test_logb_array_float() { + func test_logb_in_place_array_float() { typealias Scalar = Float let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.logb(lhs) - } + var actual: [Scalar] = lhs + Surge.logbInPlace(&actual) let expected = lhs.map { logb($0) } XCTAssertEqual(actual, expected, accuracy: 1e-4) } - func test_logb_array_double() { + func test_logb_in_place_array_double() { typealias Scalar = Double let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - var actual: [Scalar] = [] - measure { - actual = Surge.logb(lhs) - } + var actual: [Scalar] = lhs + Surge.logbInPlace(&actual) let expected = lhs.map { logb($0) } From cb700bddd44d9455177a75a91715af100f8754dc Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:27:01 +0200 Subject: [PATCH 09/16] Added benchmarks corresponding to those previously found in `SurgeTests/LogarithmTests.swift` --- Surge.xcodeproj/project.pbxproj | 8 +- .../SurgeBenchmarkTests/LogarithmTests.swift | 100 ++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 Tests/SurgeBenchmarkTests/LogarithmTests.swift diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index e0addcec..80594731 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -82,15 +82,16 @@ 61E930C92070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */; }; 61E930CA2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */; }; 61E930CB2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */; }; + CA945C24233AA36D00D95127 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C23233AA36D00D95127 /* LogarithmTests.swift */; }; CAAF4FFC2339651600CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; - CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; + CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; + CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */; }; CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */; }; - CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; CAEC79C02319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; CAEC79C12319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; @@ -180,6 +181,7 @@ 61E930BC2070104600694FCB /* Array+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; 61E930C12070B69300694FCB /* UnsafeMutableMemory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsafeMutableMemory.swift; sourceTree = ""; }; 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ArraySlice+Extensions.swift"; sourceTree = ""; }; + CA945C23233AA36D00D95127 /* LogarithmTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalarTests.swift; sourceTree = ""; }; CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -309,6 +311,7 @@ isa = PBXGroup; children = ( CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */, + CA945C23233AA36D00D95127 /* LogarithmTests.swift */, CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */, ); path = SurgeBenchmarkTests; @@ -934,6 +937,7 @@ buildActionMask = 2147483647; files = ( CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */, + CA945C24233AA36D00D95127 /* LogarithmTests.swift in Sources */, CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Tests/SurgeBenchmarkTests/LogarithmTests.swift b/Tests/SurgeBenchmarkTests/LogarithmTests.swift new file mode 100644 index 00000000..d03b6379 --- /dev/null +++ b/Tests/SurgeBenchmarkTests/LogarithmTests.swift @@ -0,0 +1,100 @@ +// Copyright © 2014-2018 the Surge contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation +import XCTest + +@testable import Surge + +class LogarithmTests: XCTestCase { + let n = 100_000 + + // MARK: - Base-e Logarithm: In Place + + func test_log_in_place_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.logInPlace) + } + } + } + + func test_log_in_place_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.logInPlace) + } + } + } + + // MARK: - Base-2 Logarithm: In Place + + func test_log2_in_place_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.log2InPlace) + } + } + } + + func test_log2_in_place_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.log2InPlace) + } + } + } + + // MARK: - Base-10 Logarithm: In Place + + func test_log10_in_place_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.log10InPlace) + } + } + } + + func test_log10_in_place_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.log10InPlace) + } + } + } + + // MARK: - Base-b Logarithm: In Place + + func test_logb_in_place_array_float() { + measure_inout_array(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.logbInPlace) + } + } + } + + func test_logb_in_place_array_double() { + measure_inout_array(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.logbInPlace) + } + } + } +} From 21accbca77d1f84a36c9c6df98246d8cf9a85d5e Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 21:48:45 +0200 Subject: [PATCH 10/16] =?UTF-8?q?Removed=20redundancies=20from=20=E2=80=98?= =?UTF-8?q?SurgeTests/ArithmeticTests.swift=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tests/SurgeTests/ArithmeticTests.swift | 119 ++++++++++++++----------- 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/Tests/SurgeTests/ArithmeticTests.swift b/Tests/SurgeTests/ArithmeticTests.swift index 018fed55..3c2e1901 100644 --- a/Tests/SurgeTests/ArithmeticTests.swift +++ b/Tests/SurgeTests/ArithmeticTests.swift @@ -26,15 +26,28 @@ import XCTest // swiftlint:disable nesting type_body_length class ArithmeticTests: XCTestCase { - let n = 1_000 + static let n = 1_000 + + func monotonic(count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { + return (1...count).map { Scalar($0) } + } + + func monotonicNormalized(count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { + let scalarCount = Scalar(count) + return (1...count).map { Scalar($0) / scalarCount } + } + + func constant(_ value: Scalar, count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { + return Array(repeating: value, count: count) + } // MARK: - Addition: In Place func test_add_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.addInPlace(&actual, rhs) @@ -47,8 +60,8 @@ class ArithmeticTests: XCTestCase { func test_add_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.addInPlace(&actual, rhs) @@ -63,8 +76,8 @@ class ArithmeticTests: XCTestCase { func test_sub_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.subInPlace(&actual, rhs) @@ -77,8 +90,8 @@ class ArithmeticTests: XCTestCase { func test_sub_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.subInPlace(&actual, rhs) @@ -93,8 +106,8 @@ class ArithmeticTests: XCTestCase { func test_mul_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.mulInPlace(&actual, rhs) @@ -107,8 +120,8 @@ class ArithmeticTests: XCTestCase { func test_mul_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.mulInPlace(&actual, rhs) @@ -123,8 +136,8 @@ class ArithmeticTests: XCTestCase { func test_div_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.divInPlace(&actual, rhs) @@ -137,8 +150,8 @@ class ArithmeticTests: XCTestCase { func test_div_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.divInPlace(&actual, rhs) @@ -153,8 +166,8 @@ class ArithmeticTests: XCTestCase { func test_mod_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) } - let rhs: [Scalar] = Array(repeating: 42, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(2.0) var actual: [Scalar] = lhs Surge.modInPlace(&actual, rhs) @@ -167,8 +180,8 @@ class ArithmeticTests: XCTestCase { func test_mod_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) } - let rhs: [Scalar] = Array(repeating: 42, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(2.0) var actual: [Scalar] = lhs Surge.modInPlace(&actual, rhs) @@ -183,8 +196,8 @@ class ArithmeticTests: XCTestCase { func test_remainder_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) } - let rhs: [Scalar] = Array(repeating: -42, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(-2.0) var actual: [Scalar] = lhs Surge.remainderInPlace(&actual, rhs) @@ -197,8 +210,8 @@ class ArithmeticTests: XCTestCase { func test_remainder_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) } - let rhs: [Scalar] = Array(repeating: -42, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(-2.0) var actual: [Scalar] = lhs Surge.remainderInPlace(&actual, rhs) @@ -213,7 +226,7 @@ class ArithmeticTests: XCTestCase { func test_exp_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.expInPlace(&actual) @@ -226,7 +239,7 @@ class ArithmeticTests: XCTestCase { func test_exp_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.expInPlace(&actual) @@ -241,7 +254,7 @@ class ArithmeticTests: XCTestCase { func test_exp2_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.exp2InPlace(&actual) @@ -254,7 +267,7 @@ class ArithmeticTests: XCTestCase { func test_exp2_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.exp2InPlace(&actual) @@ -269,8 +282,8 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = Array(repeating: 2.0, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(2.0) var actual: [Scalar] = lhs Surge.powInPlace(&actual, rhs) @@ -283,8 +296,8 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = Array(repeating: 2.0, count: n) + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = constant(2.0) var actual: [Scalar] = lhs Surge.powInPlace(&actual, rhs) @@ -297,7 +310,7 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_scalar_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() let rhs: Scalar = 2.0 var actual: [Scalar] = lhs @@ -311,7 +324,7 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_scalar_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() let rhs: Scalar = 2.0 var actual: [Scalar] = lhs @@ -327,7 +340,7 @@ class ArithmeticTests: XCTestCase { func test_sq_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.sqInPlace(&actual) @@ -340,7 +353,7 @@ class ArithmeticTests: XCTestCase { func test_sq_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.sqInPlace(&actual) @@ -355,7 +368,7 @@ class ArithmeticTests: XCTestCase { func test_sqrt_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.sqrtInPlace(&actual) @@ -368,7 +381,7 @@ class ArithmeticTests: XCTestCase { func test_sqrt_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) } + let lhs: [Scalar] = monotonicNormalized() var actual: [Scalar] = lhs Surge.sqrtInPlace(&actual) @@ -383,8 +396,8 @@ class ArithmeticTests: XCTestCase { func test_dot_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.dot(lhs, rhs) @@ -396,8 +409,8 @@ class ArithmeticTests: XCTestCase { func test_dot_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.dot(lhs, rhs) @@ -411,7 +424,7 @@ class ArithmeticTests: XCTestCase { func test_sum_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.sum(lhs) @@ -423,7 +436,7 @@ class ArithmeticTests: XCTestCase { func test_sum_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.sum(lhs) @@ -437,8 +450,8 @@ class ArithmeticTests: XCTestCase { func test_dist_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.dist(lhs, rhs) @@ -450,8 +463,8 @@ class ArithmeticTests: XCTestCase { func test_dist_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.dist(lhs, rhs) @@ -465,8 +478,8 @@ class ArithmeticTests: XCTestCase { func test_distsq_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.distSq(lhs, rhs) @@ -480,8 +493,8 @@ class ArithmeticTests: XCTestCase { func test_distsq_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } - let rhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = monotonicNormalized() + let rhs: [Scalar] = monotonicNormalized() let actual: Scalar = Surge.distSq(lhs, rhs) From 2345be4981d2b3b0b613966f53969289908a3807 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 22:30:58 +0200 Subject: [PATCH 11/16] Improved benchmark fixtures --- Surge.xcodeproj/project.pbxproj | 8 +- .../SurgeBenchmarkTests/ArithmeticTests.swift | 2 - .../SurgeBenchmarkTests/LogarithmTests.swift | 2 - ...t => SurgeBenchmarkTests+Extensions.swift} | 75 +++++++++++++------ 4 files changed, 55 insertions(+), 32 deletions(-) rename Tests/SurgeBenchmarkTests/{XCTestCase+Surge.swift => SurgeBenchmarkTests+Extensions.swift} (73%) diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 80594731..3a945c6f 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -91,7 +91,7 @@ CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */; }; CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; }; CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */; }; - CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */; }; + CAAF501A233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */; }; CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; CAEC79C02319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; CAEC79C12319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; }; @@ -187,7 +187,7 @@ CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-BenchmarkTests.plist"; sourceTree = ""; }; CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArithmeticTests.swift; sourceTree = ""; }; - CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Surge.swift"; sourceTree = ""; }; + CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SurgeBenchmarkTests+Extensions.swift"; sourceTree = ""; }; CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorPrecedences.swift; sourceTree = ""; }; CAEC79C323192FE300516E10 /* Scalar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scalar.swift; sourceTree = ""; }; CAEC79D12319343100516E10 /* Logarithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logarithm.swift; sourceTree = ""; }; @@ -312,7 +312,7 @@ children = ( CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */, CA945C23233AA36D00D95127 /* LogarithmTests.swift */, - CAAF5019233A9E6300CC0AA7 /* XCTestCase+Surge.swift */, + CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */, ); path = SurgeBenchmarkTests; sourceTree = ""; @@ -936,7 +936,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CAAF501A233A9E6300CC0AA7 /* XCTestCase+Surge.swift in Sources */, + CAAF501A233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift in Sources */, CA945C24233AA36D00D95127 /* LogarithmTests.swift in Sources */, CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */, ); diff --git a/Tests/SurgeBenchmarkTests/ArithmeticTests.swift b/Tests/SurgeBenchmarkTests/ArithmeticTests.swift index 1aac6047..84e2ae3e 100644 --- a/Tests/SurgeBenchmarkTests/ArithmeticTests.swift +++ b/Tests/SurgeBenchmarkTests/ArithmeticTests.swift @@ -24,8 +24,6 @@ import XCTest @testable import Surge class ArithmeticTests: XCTestCase { - static let n = 100_000 - // MARK: - Addition: In Place func test_add_in_place_array_array_float() { diff --git a/Tests/SurgeBenchmarkTests/LogarithmTests.swift b/Tests/SurgeBenchmarkTests/LogarithmTests.swift index d03b6379..cd89a00f 100644 --- a/Tests/SurgeBenchmarkTests/LogarithmTests.swift +++ b/Tests/SurgeBenchmarkTests/LogarithmTests.swift @@ -24,8 +24,6 @@ import XCTest @testable import Surge class LogarithmTests: XCTestCase { - let n = 100_000 - // MARK: - Base-e Logarithm: In Place func test_log_in_place_array_float() { diff --git a/Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift similarity index 73% rename from Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift rename to Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift index 0bd6e8a1..095f288c 100644 --- a/Tests/SurgeBenchmarkTests/XCTestCase+Surge.swift +++ b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift @@ -23,6 +23,47 @@ import XCTest // swiftlint:disable nesting +extension ExpressibleByFloatLiteral { + static func constant() -> Self { + return 1.0 + } +} + +extension Array { + static var defaultCount: Int { + return 100_000 + } + + static func monotonic() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return monotonic(count: Array.defaultCount) + } + + static func monotonic(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return (1...count).map { Scalar($0) } + } + + static func monotonicNormalized() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return monotonicNormalized(count: Array.defaultCount) + } + + static func monotonicNormalized(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + let scalarCount = Scalar(count) + return (1...count).map { Scalar($0) / scalarCount } + } + + static func constant() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return constant(1.0) + } + + static func constant(_ scalar: Scalar) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return constant(scalar, count: Array.defaultCount) + } + + static func constant(_ scalar: Scalar, count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return [Scalar](repeating: scalar, count: count) + } +} + // Why on earth do we need these abominations, you ask? // // Well, you see … XCTest is not —to put it mildly— the best unit testing framework out there. @@ -57,23 +98,9 @@ extension XCTestCase { typealias Producer = () -> T - static func normalizedMonotonic(n: Int = ArithmeticTests.n) -> Producer<[T]> where T: FloatingPoint { - typealias Scalar = T - - return { - (1...n).map { Scalar($0) / Scalar(n) } - } - } - - static func scalar(constant: T = 2.0) -> Producer where T: FloatingPoint & ExpressibleByFloatLiteral { - return { - constant - } - } - func measure_array( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, _ closure: (LhsFunctionWrapper<[T], U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -89,7 +116,7 @@ extension XCTestCase { func measure_inout_array( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, _ closure: (InOutLhsFunctionWrapper<[T], U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -107,8 +134,8 @@ extension XCTestCase { func measure_array_array( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), - rhs produceRhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, + rhs produceRhs: Producer<[T]> = [T].monotonicNormalized, _ closure: (LhsRhsFunctionWrapper<[T], [T], U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -125,8 +152,8 @@ extension XCTestCase { func measure_inout_array_array( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), - rhs produceRhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, + rhs produceRhs: Producer<[T]> = [T].monotonicNormalized, _ closure: (InOutLhsRhsFunctionWrapper<[T], [T], U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -145,8 +172,8 @@ extension XCTestCase { func measure_array_scalar( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), - rhs produceRhs: Producer = ArithmeticTests.scalar(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, + rhs produceRhs: Producer = T.constant, _ closure: (LhsRhsFunctionWrapper<[T], T, U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -163,8 +190,8 @@ extension XCTestCase { func measure_inout_array_scalar( of: T.Type, - lhs produceLhs: Producer<[T]> = ArithmeticTests.normalizedMonotonic(), - rhs produceRhs: Producer = ArithmeticTests.scalar(), + lhs produceLhs: Producer<[T]> = [T].monotonicNormalized, + rhs produceRhs: Producer = T.constant, _ closure: (InOutLhsRhsFunctionWrapper<[T], T, U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T From 7bd4653695842132ec9b3862829623fa9a0d62ab Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 23:09:49 +0200 Subject: [PATCH 12/16] Improved test fixtures --- Surge.xcodeproj/project.pbxproj | 16 +-- Tests/SurgeTests/ArithmeticTests.swift | 119 ++++++++---------- Tests/SurgeTests/LogarithmTests.swift | 18 ++- ...urge.swift => SurgeTests+Extensions.swift} | 41 ++++++ 4 files changed, 109 insertions(+), 85 deletions(-) rename Tests/SurgeTests/{XCTestCase+Surge.swift => SurgeTests+Extensions.swift} (54%) diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 3a945c6f..5d45f680 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -22,7 +22,6 @@ 614AD3471FC0AF77002BFE1C /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 614AD3481FC0AF77002BFE1C /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 614AD34A1FC0AF77002BFE1C /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; - 614AD34B1FC0AF77002BFE1C /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD751F70D22600B99FFB /* XCTestCase+Surge.swift */; }; 614AD35A1FC0B001002BFE1C /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD3511FC0B001002BFE1C /* Surge.framework */; }; 614AD3681FC0B0C6002BFE1C /* Surge.h in Headers */ = {isa = PBXBuildFile; fileRef = 615394541F762B58002A4AD2 /* Surge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 614AD3691FC0B0CC002BFE1C /* Arithmetic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6153944B1F762B58002A4AD2 /* Arithmetic.swift */; }; @@ -38,7 +37,6 @@ 614AD3781FC0B0D2002BFE1C /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 614AD3791FC0B0D2002BFE1C /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 614AD37B1FC0B0D2002BFE1C /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; - 614AD37C1FC0B0D2002BFE1C /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD751F70D22600B99FFB /* XCTestCase+Surge.swift */; }; 614AD38A1FC0B12F002BFE1C /* Surge.h in Headers */ = {isa = PBXBuildFile; fileRef = 615394541F762B58002A4AD2 /* Surge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 614AD38B1FC0B134002BFE1C /* Arithmetic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6153944B1F762B58002A4AD2 /* Arithmetic.swift */; }; 614AD38C1FC0B134002BFE1C /* Auxiliary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6153944C1F762B58002A4AD2 /* Auxiliary.swift */; }; @@ -65,7 +63,6 @@ 61A0AD7A1F70D22600B99FFB /* HyperbolicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */; }; 61A0AD7B1F70D22600B99FFB /* MatrixTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD721F70D22600B99FFB /* MatrixTests.swift */; }; 61A0AD7D1F70D22600B99FFB /* TrigonometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */; }; - 61A0AD7E1F70D22600B99FFB /* XCTestCase+Surge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AD751F70D22600B99FFB /* XCTestCase+Surge.swift */; }; 61E930B8207002EA00694FCB /* UnsafeMemory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930B7207002EA00694FCB /* UnsafeMemory.swift */; }; 61E930B9207002EA00694FCB /* UnsafeMemory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930B7207002EA00694FCB /* UnsafeMemory.swift */; }; 61E930BA207002EA00694FCB /* UnsafeMemory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930B7207002EA00694FCB /* UnsafeMemory.swift */; }; @@ -83,6 +80,9 @@ 61E930CA2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */; }; 61E930CB2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */; }; CA945C24233AA36D00D95127 /* LogarithmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C23233AA36D00D95127 /* LogarithmTests.swift */; }; + CA945C2D233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; + CA945C2E233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; + CA945C2F233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; CAAF4FFC2339651600CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; @@ -173,7 +173,6 @@ 61A0AD711F70D22600B99FFB /* HyperbolicTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HyperbolicTests.swift; sourceTree = ""; }; 61A0AD721F70D22600B99FFB /* MatrixTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatrixTests.swift; sourceTree = ""; }; 61A0AD741F70D22600B99FFB /* TrigonometricTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrigonometricTests.swift; sourceTree = ""; }; - 61A0AD751F70D22600B99FFB /* XCTestCase+Surge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Surge.swift"; sourceTree = ""; }; 61A0AD7F1F70D99B00B99FFB /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 61A0AD801F70D99B00B99FFB /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 61A0AD811F70D99B00B99FFB /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; @@ -182,6 +181,7 @@ 61E930C12070B69300694FCB /* UnsafeMutableMemory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsafeMutableMemory.swift; sourceTree = ""; }; 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ArraySlice+Extensions.swift"; sourceTree = ""; }; CA945C23233AA36D00D95127 /* LogarithmTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; + CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SurgeTests+Extensions.swift"; sourceTree = ""; }; CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalarTests.swift; sourceTree = ""; }; CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -302,7 +302,7 @@ CAFE5DAD22F9ED4900A34887 /* VectorTests.swift */, CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */, CAFE5DA422F9EC1D00A34887 /* XCTAssert+Surge.swift */, - 61A0AD751F70D22600B99FFB /* XCTestCase+Surge.swift */, + CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */, ); path = SurgeTests; sourceTree = ""; @@ -854,7 +854,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 614AD34B1FC0AF77002BFE1C /* XCTestCase+Surge.swift in Sources */, CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */, 614AD3481FC0AF77002BFE1C /* MatrixTests.swift in Sources */, CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */, @@ -864,6 +863,7 @@ 614AD34A1FC0AF77002BFE1C /* TrigonometricTests.swift in Sources */, CAFE5DA622F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 614AD3471FC0AF77002BFE1C /* HyperbolicTests.swift in Sources */, + CA945C2E233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */, 614AD3431FC0AF77002BFE1C /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -895,7 +895,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 614AD37C1FC0B0D2002BFE1C /* XCTestCase+Surge.swift in Sources */, CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */, 614AD3791FC0B0D2002BFE1C /* MatrixTests.swift in Sources */, CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */, @@ -905,6 +904,7 @@ 614AD37B1FC0B0D2002BFE1C /* TrigonometricTests.swift in Sources */, CAFE5DA722F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 614AD3781FC0B0D2002BFE1C /* HyperbolicTests.swift in Sources */, + CA945C2F233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */, 614AD3741FC0B0D2002BFE1C /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -946,7 +946,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 61A0AD7E1F70D22600B99FFB /* XCTestCase+Surge.swift in Sources */, CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */, 61A0AD7B1F70D22600B99FFB /* MatrixTests.swift in Sources */, CAAF4FFC2339651600CC0AA7 /* ScalarTests.swift in Sources */, @@ -956,6 +955,7 @@ 61A0AD7D1F70D22600B99FFB /* TrigonometricTests.swift in Sources */, CAFE5DA522F9EC1D00A34887 /* XCTAssert+Surge.swift in Sources */, 61A0AD7A1F70D22600B99FFB /* HyperbolicTests.swift in Sources */, + CA945C2D233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */, 61A0AD761F70D22600B99FFB /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Tests/SurgeTests/ArithmeticTests.swift b/Tests/SurgeTests/ArithmeticTests.swift index 3c2e1901..31ab6dc3 100644 --- a/Tests/SurgeTests/ArithmeticTests.swift +++ b/Tests/SurgeTests/ArithmeticTests.swift @@ -26,28 +26,13 @@ import XCTest // swiftlint:disable nesting type_body_length class ArithmeticTests: XCTestCase { - static let n = 1_000 - - func monotonic(count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { - return (1...count).map { Scalar($0) } - } - - func monotonicNormalized(count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { - let scalarCount = Scalar(count) - return (1...count).map { Scalar($0) / scalarCount } - } - - func constant(_ value: Scalar, count: Int = ArithmeticTests.n) -> [Scalar] where Scalar: FloatingPoint { - return Array(repeating: value, count: count) - } - // MARK: - Addition: In Place func test_add_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.addInPlace(&actual, rhs) @@ -60,8 +45,8 @@ class ArithmeticTests: XCTestCase { func test_add_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.addInPlace(&actual, rhs) @@ -76,8 +61,8 @@ class ArithmeticTests: XCTestCase { func test_sub_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.subInPlace(&actual, rhs) @@ -90,8 +75,8 @@ class ArithmeticTests: XCTestCase { func test_sub_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.subInPlace(&actual, rhs) @@ -106,8 +91,8 @@ class ArithmeticTests: XCTestCase { func test_mul_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.mulInPlace(&actual, rhs) @@ -120,8 +105,8 @@ class ArithmeticTests: XCTestCase { func test_mul_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.mulInPlace(&actual, rhs) @@ -136,8 +121,8 @@ class ArithmeticTests: XCTestCase { func test_div_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.divInPlace(&actual, rhs) @@ -150,8 +135,8 @@ class ArithmeticTests: XCTestCase { func test_div_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.divInPlace(&actual, rhs) @@ -166,8 +151,8 @@ class ArithmeticTests: XCTestCase { func test_mod_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(2.0) var actual: [Scalar] = lhs Surge.modInPlace(&actual, rhs) @@ -180,8 +165,8 @@ class ArithmeticTests: XCTestCase { func test_mod_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(2.0) var actual: [Scalar] = lhs Surge.modInPlace(&actual, rhs) @@ -196,8 +181,8 @@ class ArithmeticTests: XCTestCase { func test_remainder_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(-2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(-2.0) var actual: [Scalar] = lhs Surge.remainderInPlace(&actual, rhs) @@ -210,8 +195,8 @@ class ArithmeticTests: XCTestCase { func test_remainder_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(-2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(-2.0) var actual: [Scalar] = lhs Surge.remainderInPlace(&actual, rhs) @@ -226,7 +211,7 @@ class ArithmeticTests: XCTestCase { func test_exp_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.expInPlace(&actual) @@ -239,7 +224,7 @@ class ArithmeticTests: XCTestCase { func test_exp_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.expInPlace(&actual) @@ -254,7 +239,7 @@ class ArithmeticTests: XCTestCase { func test_exp2_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.exp2InPlace(&actual) @@ -267,7 +252,7 @@ class ArithmeticTests: XCTestCase { func test_exp2_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.exp2InPlace(&actual) @@ -282,8 +267,8 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(2.0) var actual: [Scalar] = lhs Surge.powInPlace(&actual, rhs) @@ -296,8 +281,8 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = constant(2.0) + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = [Scalar].constant(2.0) var actual: [Scalar] = lhs Surge.powInPlace(&actual, rhs) @@ -310,7 +295,7 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_scalar_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() let rhs: Scalar = 2.0 var actual: [Scalar] = lhs @@ -324,7 +309,7 @@ class ArithmeticTests: XCTestCase { func test_pow_in_place_array_scalar_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() let rhs: Scalar = 2.0 var actual: [Scalar] = lhs @@ -340,7 +325,7 @@ class ArithmeticTests: XCTestCase { func test_sq_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.sqInPlace(&actual) @@ -353,7 +338,7 @@ class ArithmeticTests: XCTestCase { func test_sq_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.sqInPlace(&actual) @@ -368,7 +353,7 @@ class ArithmeticTests: XCTestCase { func test_sqrt_in_place_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.sqrtInPlace(&actual) @@ -381,7 +366,7 @@ class ArithmeticTests: XCTestCase { func test_sqrt_in_place_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.sqrtInPlace(&actual) @@ -396,8 +381,8 @@ class ArithmeticTests: XCTestCase { func test_dot_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.dot(lhs, rhs) @@ -409,8 +394,8 @@ class ArithmeticTests: XCTestCase { func test_dot_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.dot(lhs, rhs) @@ -424,7 +409,7 @@ class ArithmeticTests: XCTestCase { func test_sum_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.sum(lhs) @@ -436,7 +421,7 @@ class ArithmeticTests: XCTestCase { func test_sum_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.sum(lhs) @@ -450,8 +435,8 @@ class ArithmeticTests: XCTestCase { func test_dist_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.dist(lhs, rhs) @@ -463,8 +448,8 @@ class ArithmeticTests: XCTestCase { func test_dist_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.dist(lhs, rhs) @@ -478,8 +463,8 @@ class ArithmeticTests: XCTestCase { func test_distsq_array_array_float() { typealias Scalar = Float - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.distSq(lhs, rhs) @@ -493,8 +478,8 @@ class ArithmeticTests: XCTestCase { func test_distsq_array_array_double() { typealias Scalar = Double - let lhs: [Scalar] = monotonicNormalized() - let rhs: [Scalar] = monotonicNormalized() + let lhs: [Scalar] = .monotonicNormalized() + let rhs: [Scalar] = .monotonicNormalized() let actual: Scalar = Surge.distSq(lhs, rhs) diff --git a/Tests/SurgeTests/LogarithmTests.swift b/Tests/SurgeTests/LogarithmTests.swift index b1ed7adf..a1dac1d1 100644 --- a/Tests/SurgeTests/LogarithmTests.swift +++ b/Tests/SurgeTests/LogarithmTests.swift @@ -26,14 +26,12 @@ import XCTest // swiftlint:disable nesting class LogarithmTests: XCTestCase { - let n = 1_000 - // MARK: - Base-e Logarithm func test_log_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.logInPlace(&actual) @@ -46,7 +44,7 @@ class LogarithmTests: XCTestCase { func test_log_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.logInPlace(&actual) @@ -61,7 +59,7 @@ class LogarithmTests: XCTestCase { func test_log2_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.log2InPlace(&actual) @@ -74,7 +72,7 @@ class LogarithmTests: XCTestCase { func test_log2_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.log2InPlace(&actual) @@ -89,7 +87,7 @@ class LogarithmTests: XCTestCase { func test_log10_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.log10InPlace(&actual) @@ -102,7 +100,7 @@ class LogarithmTests: XCTestCase { func test_log10_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.log10InPlace(&actual) @@ -117,7 +115,7 @@ class LogarithmTests: XCTestCase { func test_logb_in_place_array_float() { typealias Scalar = Float - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.logbInPlace(&actual) @@ -130,7 +128,7 @@ class LogarithmTests: XCTestCase { func test_logb_in_place_array_double() { typealias Scalar = Double - let lhs: [Scalar] = (1...n).map { Scalar($0) / Scalar(n) } + let lhs: [Scalar] = .monotonicNormalized() var actual: [Scalar] = lhs Surge.logbInPlace(&actual) diff --git a/Tests/SurgeTests/XCTestCase+Surge.swift b/Tests/SurgeTests/SurgeTests+Extensions.swift similarity index 54% rename from Tests/SurgeTests/XCTestCase+Surge.swift rename to Tests/SurgeTests/SurgeTests+Extensions.swift index 010038d6..6951e527 100644 --- a/Tests/SurgeTests/XCTestCase+Surge.swift +++ b/Tests/SurgeTests/SurgeTests+Extensions.swift @@ -35,3 +35,44 @@ extension XCTestCase { } } } + +extension ExpressibleByFloatLiteral { + static func constant() -> Self { + return 1.0 + } +} + +extension Array { + static var defaultCount: Int { + return 1_000 + } + + static func monotonic() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return monotonic(count: Array.defaultCount) + } + + static func monotonic(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return (1...count).map { Scalar($0) } + } + + static func monotonicNormalized() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return monotonicNormalized(count: Array.defaultCount) + } + + static func monotonicNormalized(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + let scalarCount = Scalar(count) + return (1...count).map { Scalar($0) / scalarCount } + } + + static func constant() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return constant(1.0) + } + + static func constant(_ scalar: Scalar) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return constant(scalar, count: Array.defaultCount) + } + + static func constant(_ scalar: Scalar, count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + return [Scalar](repeating: scalar, count: count) + } +} From 5e8713a7e0e16798845334eac836dd2edd7ace9c Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 24 Sep 2019 23:18:05 +0200 Subject: [PATCH 13/16] =?UTF-8?q?Add=20`muladd=E2=80=A6`=20to=20`Vector`=20and=20corresponding=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/Surge/Linear Algebra/Vector.swift | 28 +++++++++ Tests/SurgeTests/VectorTests.swift | 74 +++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/Sources/Surge/Linear Algebra/Vector.swift b/Sources/Surge/Linear Algebra/Vector.swift index 742ba35f..5d936a3a 100644 --- a/Sources/Surge/Linear Algebra/Vector.swift +++ b/Sources/Surge/Linear Algebra/Vector.swift @@ -257,6 +257,34 @@ public func -= (lhs: inout Vector, rhs: Double) { return subInPlace(&lhs, rhs) } +// MARK: - Multiply Addition + +public func muladd(_ lhs: Vector, _ rhs: Vector, _ alpha: Float) -> Vector { + var result = lhs + muladdInPlace(&result, rhs, alpha) + return result +} + +public func muladd(_ lhs: Vector, _ rhs: Vector, _ alpha: Double) -> Vector { + var result = lhs + muladdInPlace(&result, rhs, alpha) + return result +} + +// MARK: - Multiply Addition: In Place + +func muladdInPlace(_ lhs: inout Vector, _ rhs: Vector, _ alpha: Float) { + precondition(lhs.dimensions == rhs.dimensions, "Vector dimensions not compatible with addition") + + return muladdInPlace(&lhs.scalars, rhs.scalars, alpha) +} + +func muladdInPlace(_ lhs: inout Vector, _ rhs: Vector, _ alpha: Double) { + precondition(lhs.dimensions == rhs.dimensions, "Vector dimensions not compatible with addition") + + return muladdInPlace(&lhs.scalars, rhs.scalars, alpha) +} + // MARK: - Multiplication public func mul(_ lhs: Vector, _ rhs: Float) -> Vector { diff --git a/Tests/SurgeTests/VectorTests.swift b/Tests/SurgeTests/VectorTests.swift index 48906353..774e09ec 100644 --- a/Tests/SurgeTests/VectorTests.swift +++ b/Tests/SurgeTests/VectorTests.swift @@ -323,6 +323,80 @@ class VectorTests: XCTestCase { XCTAssertEqual(actual, expected, accuracy: 1e-8) } + // MARK: - Multiply Addition + + func test_muladd_vector_vector_double() { + typealias Scalar = Double + + let vector: Vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let scalar: Scalar = 2.0 + + var actual: Vector = [] + measure { + actual = Surge.muladd(vector, vector, scalar) + } + let expected: Vector = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30] + + XCTAssertEqual(actual, expected, accuracy: 1e-8) + } + + func test_muladd_vector_vector_float() { + typealias Scalar = Float + + let vector: Vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let scalar: Scalar = 2.0 + + var actual: Vector = [] + measure { + actual = Surge.muladd(vector, vector, scalar) + } + let expected: Vector = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30] + + XCTAssertEqual(actual, expected, accuracy: 1e-8) + } + + // MARK: - Multiply Addition: In Place + + func test_muladd_in_place_vector_vector_double() { + typealias Scalar = Double + + let vector: Vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let scalar: Scalar = 2.0 + + var actual: Vector = [] + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + actual = vector + + startMeasuring() + Surge.muladdInPlace(&actual, vector, scalar) + stopMeasuring() + } + + let expected: Vector = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30] + + XCTAssertEqual(actual, expected, accuracy: 1e-8) + } + + func test_muladd_in_place_vector_vector_float() { + typealias Scalar = Float + + let vector: Vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let scalar: Scalar = 2.0 + + var actual: Vector = [] + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + actual = vector + + startMeasuring() + Surge.muladdInPlace(&actual, vector, scalar) + stopMeasuring() + } + + let expected: Vector = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30] + + XCTAssertEqual(actual, expected, accuracy: 1e-8) + } + // MARK: - Multiplication func test_mul_vector_scalar_double() { From 88c1eae272f398d139cbe1f16fa3bcfb6b9a19d5 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 25 Sep 2019 00:48:00 +0200 Subject: [PATCH 14/16] Further extended test/benchmark fixtures --- .../SurgeBenchmarkTests+Extensions.swift | 130 ++++++++++++++++-- Tests/SurgeTests/SurgeTests+Extensions.swift | 110 +++++++++++++-- 2 files changed, 214 insertions(+), 26 deletions(-) diff --git a/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift index 095f288c..efb80f1f 100644 --- a/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift +++ b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift @@ -21,46 +21,130 @@ import Foundation import XCTest +@testable import Surge + // swiftlint:disable nesting extension ExpressibleByFloatLiteral { - static func constant() -> Self { + static func identity() -> Self { return 1.0 } + + static func constant() -> Self { + return 0.42 + } } -extension Array { +extension Array where Element: FloatingPoint & ExpressibleByFloatLiteral { static var defaultCount: Int { return 100_000 } - static func monotonic() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func monotonic() -> Array { return monotonic(count: Array.defaultCount) } - static func monotonic(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - return (1...count).map { Scalar($0) } + static func monotonic(count: Int) -> Array { + return (1...count).map { Element($0) } } - static func monotonicNormalized() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func monotonicNormalized() -> Array { return monotonicNormalized(count: Array.defaultCount) } - static func monotonicNormalized(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - let scalarCount = Scalar(count) - return (1...count).map { Scalar($0) / scalarCount } + static func monotonicNormalized(count: Int) -> Array { + let scalarCount = Element(count) + return (1...count).map { Element($0) / scalarCount } } - static func constant() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func constant() -> Array { return constant(1.0) } - static func constant(_ scalar: Scalar) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func constant(_ scalar: Element) -> Array { return constant(scalar, count: Array.defaultCount) } - static func constant(_ scalar: Scalar, count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - return [Scalar](repeating: scalar, count: count) + static func constant(_ scalar: Element, count: Int) -> Array { + return Array(repeating: scalar, count: count) + } +} + +extension Vector where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static var defaultDimensions: Int { + return 1_000 + } + + static func monotonic() -> Vector { + return monotonic(dimensions: Vector.defaultDimensions) + } + + static func monotonic(dimensions: Int) -> Vector { + return Vector([Scalar].monotonic(count: dimensions)) + } + + static func monotonicNormalized() -> Vector { + return monotonicNormalized(dimensions: Vector.defaultDimensions) + } + + static func monotonicNormalized(dimensions: Int) -> Vector { + return Vector([Scalar].monotonicNormalized(count: dimensions)) + } + + static func constant() -> Vector { + return constant(2.0) + } + + static func constant(_ scalar: Scalar) -> Vector { + return constant(scalar, dimensions: Vector.defaultDimensions) + } + + static func constant(_ scalar: Scalar, dimensions: Int) -> Vector { + return Vector([Scalar].constant(scalar, count: dimensions)) + } +} + +extension Matrix where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static var defaultRows: Int { + return 1_000 + } + + static var defaultColumns: Int { + return 1_000 + } + + static func monotonic() -> Matrix { + return monotonic(rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func monotonic(rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].monotonic(count: count) + return Matrix(rows: rows, columns: columns, grid: grid) + } + + static func monotonicNormalized() -> Matrix { + return monotonicNormalized(rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func monotonicNormalized(rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].monotonicNormalized(count: count) + return Matrix(rows: rows, columns: columns, grid: grid) + } + + static func constant() -> Matrix { + return constant(2.0) + } + + static func constant(_ scalar: Scalar) -> Matrix { + return constant(scalar, rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func constant(_ scalar: Scalar, rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].constant(scalar, count: count) + return Matrix(rows: rows, columns: columns, grid: grid) } } @@ -207,4 +291,24 @@ extension XCTestCase { stopMeasuring() }) } + + func measure_inout_vector_matrix( + of: T.Type, + lhs produceLhs: Producer> = Vector.monotonicNormalized, + rhs produceRhs: Producer> = Matrix.monotonicNormalized, + _ closure: (InOutLhsRhsFunctionWrapper, Matrix, U>) -> () + ) where T: FloatingPoint & ExpressibleByFloatLiteral { + typealias Scalar = T + + let lhs = produceLhs() + let rhs = produceRhs() + + closure({ innerClosure in + var lhs = lhs + + startMeasuring() + let _ = innerClosure(&lhs, rhs) + stopMeasuring() + }) + } } diff --git a/Tests/SurgeTests/SurgeTests+Extensions.swift b/Tests/SurgeTests/SurgeTests+Extensions.swift index 6951e527..2a73ac2e 100644 --- a/Tests/SurgeTests/SurgeTests+Extensions.swift +++ b/Tests/SurgeTests/SurgeTests+Extensions.swift @@ -21,6 +21,8 @@ import Foundation import XCTest +@testable import Surge + extension XCTestCase { func measureAndValidateMappedFunctionWithAccuracy(source: C, member: (C.Iterator.Element) -> (C.Iterator.Element), mapped: @escaping (C) -> ([C.Iterator.Element]), accuracy: C.Iterator.Element) where C.Iterator.Element: ExpressibleByFloatLiteral & FloatingPoint { let expected = source.map(member) @@ -37,42 +39,124 @@ extension XCTestCase { } extension ExpressibleByFloatLiteral { - static func constant() -> Self { + static func identity() -> Self { return 1.0 } + + static func constant() -> Self { + return 0.42 + } } -extension Array { +extension Array where Element: FloatingPoint & ExpressibleByFloatLiteral { static var defaultCount: Int { return 1_000 } - static func monotonic() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func monotonic() -> Array { return monotonic(count: Array.defaultCount) } - static func monotonic(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - return (1...count).map { Scalar($0) } + static func monotonic(count: Int) -> Array { + return (1...count).map { Element($0) } } - static func monotonicNormalized() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func monotonicNormalized() -> Array { return monotonicNormalized(count: Array.defaultCount) } - static func monotonicNormalized(count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - let scalarCount = Scalar(count) - return (1...count).map { Scalar($0) / scalarCount } + static func monotonicNormalized(count: Int) -> Array { + let scalarCount = Element(count) + return (1...count).map { Element($0) / scalarCount } } - static func constant() -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func constant() -> Array { return constant(1.0) } - static func constant(_ scalar: Scalar) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static func constant(_ scalar: Element) -> Array { return constant(scalar, count: Array.defaultCount) } - static func constant(_ scalar: Scalar, count: Int) -> [Scalar] where Scalar: FloatingPoint & ExpressibleByFloatLiteral { - return [Scalar](repeating: scalar, count: count) + static func constant(_ scalar: Element, count: Int) -> Array { + return Array(repeating: scalar, count: count) + } +} + +extension Vector where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static var defaultDimensions: Int { + return 1_000 + } + + static func monotonic() -> Vector { + return monotonic(dimensions: Vector.defaultDimensions) + } + + static func monotonic(dimensions: Int) -> Vector { + return Vector([Scalar].monotonic(count: dimensions)) + } + + static func monotonicNormalized() -> Vector { + return monotonicNormalized(dimensions: Vector.defaultDimensions) + } + + static func monotonicNormalized(dimensions: Int) -> Vector { + return Vector([Scalar].monotonicNormalized(count: dimensions)) + } + + static func constant() -> Vector { + return constant(2.0) + } + + static func constant(_ scalar: Scalar) -> Vector { + return constant(scalar, dimensions: Vector.defaultDimensions) + } + + static func constant(_ scalar: Scalar, dimensions: Int) -> Vector { + return Vector([Scalar].constant(scalar, count: dimensions)) + } +} + +extension Matrix where Scalar: FloatingPoint & ExpressibleByFloatLiteral { + static var defaultRows: Int { + return 1_000 + } + + static var defaultColumns: Int { + return 1_000 + } + + static func monotonic() -> Matrix { + return monotonic(rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func monotonic(rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].monotonic(count: count) + return Matrix(rows: rows, columns: columns, grid: grid) + } + + static func monotonicNormalized() -> Matrix { + return monotonicNormalized(rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func monotonicNormalized(rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].monotonicNormalized(count: count) + return Matrix(rows: rows, columns: columns, grid: grid) + } + + static func constant() -> Matrix { + return constant(2.0) + } + + static func constant(_ scalar: Scalar) -> Matrix { + return constant(scalar, rows: Matrix.defaultRows, columns: Matrix.defaultColumns) + } + + static func constant(_ scalar: Scalar, rows: Int, columns: Int) -> Matrix { + let count = rows * columns + let grid = [Scalar].constant(scalar, count: count) + return Matrix(rows: rows, columns: columns, grid: grid) } } From f179a1ed1193a8a7f6fa894ddb0815f567685845 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 25 Sep 2019 00:53:49 +0200 Subject: [PATCH 15/16] Added benchmarks for `Vector` --- Surge.xcodeproj/project.pbxproj | 4 ++ .../SurgeBenchmarkTests+Extensions.swift | 8 ++-- Tests/SurgeBenchmarkTests/VectorTests.swift | 47 +++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 Tests/SurgeBenchmarkTests/VectorTests.swift diff --git a/Surge.xcodeproj/project.pbxproj b/Surge.xcodeproj/project.pbxproj index 5d45f680..68c4f1de 100644 --- a/Surge.xcodeproj/project.pbxproj +++ b/Surge.xcodeproj/project.pbxproj @@ -83,6 +83,7 @@ CA945C2D233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; CA945C2E233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; CA945C2F233ABC0D00D95127 /* SurgeTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */; }; + CA945C31233AC89C00D95127 /* VectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA945C30233AC89C00D95127 /* VectorTests.swift */; }; CAAF4FFC2339651600CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */; }; @@ -182,6 +183,7 @@ 61E930C72070BCCD00694FCB /* ArraySlice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ArraySlice+Extensions.swift"; sourceTree = ""; }; CA945C23233AA36D00D95127 /* LogarithmTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SurgeTests+Extensions.swift"; sourceTree = ""; }; + CA945C30233AC89C00D95127 /* VectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VectorTests.swift; sourceTree = ""; }; CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalarTests.swift; sourceTree = ""; }; CAAF4FFF233A701A00CC0AA7 /* LogarithmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmTests.swift; sourceTree = ""; }; CAAF5007233A7B6700CC0AA7 /* SurgeBenchmarkTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SurgeBenchmarkTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -312,6 +314,7 @@ children = ( CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */, CA945C23233AA36D00D95127 /* LogarithmTests.swift */, + CA945C30233AC89C00D95127 /* VectorTests.swift */, CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */, ); path = SurgeBenchmarkTests; @@ -938,6 +941,7 @@ files = ( CAAF501A233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift in Sources */, CA945C24233AA36D00D95127 /* LogarithmTests.swift in Sources */, + CA945C31233AC89C00D95127 /* VectorTests.swift in Sources */, CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift index efb80f1f..9d880ec3 100644 --- a/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift +++ b/Tests/SurgeBenchmarkTests/SurgeBenchmarkTests+Extensions.swift @@ -292,11 +292,11 @@ extension XCTestCase { }) } - func measure_inout_vector_matrix( + func measure_vector_matrix( of: T.Type, lhs produceLhs: Producer> = Vector.monotonicNormalized, rhs produceRhs: Producer> = Matrix.monotonicNormalized, - _ closure: (InOutLhsRhsFunctionWrapper, Matrix, U>) -> () + _ closure: (LhsRhsFunctionWrapper, Matrix, U>) -> () ) where T: FloatingPoint & ExpressibleByFloatLiteral { typealias Scalar = T @@ -304,10 +304,8 @@ extension XCTestCase { let rhs = produceRhs() closure({ innerClosure in - var lhs = lhs - startMeasuring() - let _ = innerClosure(&lhs, rhs) + let _ = innerClosure(lhs, rhs) stopMeasuring() }) } diff --git a/Tests/SurgeBenchmarkTests/VectorTests.swift b/Tests/SurgeBenchmarkTests/VectorTests.swift new file mode 100644 index 00000000..32188b45 --- /dev/null +++ b/Tests/SurgeBenchmarkTests/VectorTests.swift @@ -0,0 +1,47 @@ +// Copyright © 2014-2018 the Surge contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import XCTest + +@testable import Surge + +/// - Note: Most functions of `Vector` simply call arithmetic functions +/// directly modifying the vector's `[Scalar]` storage with minimal overhead. +/// As such we're only explicitly benchmarking those function that actually +/// are implemented on `Vector` itself, rather than `[Scalar]` +class VectorTests: XCTestCase { + // MARK: - Multiplication: In Place + + func test_mul_vector_matrix_double() { + measure_vector_matrix(of: Double.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.mul) + } + } + } + + func test_mul_vector_matrix_float() { + measure_vector_matrix(of: Float.self) { measure in + measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) { + measure(Surge.mul) + } + } + } +} From 25772c91ae1fc115ae01d8cbda200c5124871883 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 25 Sep 2019 01:42:15 +0200 Subject: [PATCH 16/16] Reduced sizes of testing vectors/matrices from 1000 to 100 --- Tests/SurgeTests/SurgeTests+Extensions.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/SurgeTests/SurgeTests+Extensions.swift b/Tests/SurgeTests/SurgeTests+Extensions.swift index 2a73ac2e..8233189b 100644 --- a/Tests/SurgeTests/SurgeTests+Extensions.swift +++ b/Tests/SurgeTests/SurgeTests+Extensions.swift @@ -85,7 +85,7 @@ extension Array where Element: FloatingPoint & ExpressibleByFloatLiteral { extension Vector where Scalar: FloatingPoint & ExpressibleByFloatLiteral { static var defaultDimensions: Int { - return 1_000 + return 100 } static func monotonic() -> Vector { @@ -119,11 +119,11 @@ extension Vector where Scalar: FloatingPoint & ExpressibleByFloatLiteral { extension Matrix where Scalar: FloatingPoint & ExpressibleByFloatLiteral { static var defaultRows: Int { - return 1_000 + return 100 } static var defaultColumns: Int { - return 1_000 + return 100 } static func monotonic() -> Matrix {