diff --git a/Sources/FirebladeMath/Functions/abs.swift b/Sources/FirebladeMath/Functions/abs.swift index 00796cd..7ea0232 100644 --- a/Sources/FirebladeMath/Functions/abs.swift +++ b/Sources/FirebladeMath/Functions/abs.swift @@ -10,6 +10,8 @@ import Foundation /// /// - Parameter x: floating point value /// - Returns: If successful, returns the absolute value of x (|x|). The value returned is exact and does not depend on any rounding modes. +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.abs(_:) or x.magnitude instead.", renamed: "Swift.abs") public func abs(_ x: Float) -> Float { #if canImport(Darwin) return Darwin.fabsf(x) @@ -24,6 +26,8 @@ public func abs(_ x: Float) -> Float { /// /// - Parameter x: floating point value /// - Returns: If successful, returns the absolute value of x (|x|). The value returned is exact and does not depend on any rounding modes. +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.abs(_:) or x.magnitude instead.", renamed: "Swift.abs") public func abs(_ x: Double) -> Double { #if canImport(Darwin) return Darwin.fabs(x) diff --git a/Sources/FirebladeMath/Functions/clamp.swift b/Sources/FirebladeMath/Functions/clamp.swift index efd06df..7fb8ed2 100644 --- a/Sources/FirebladeMath/Functions/clamp.swift +++ b/Sources/FirebladeMath/Functions/clamp.swift @@ -26,7 +26,7 @@ public func clamp(_ x: Double, _ minVal: Double, _ maxVal: Double) -> Double { #if FRB_MATH_USE_SIMD return simd_clamp(x, minVal, maxVal) #else - return FirebladeMath.min(FirebladeMath.max(x, minVal), maxVal) + return Swift.min(Swift.max(x, minVal), maxVal) #endif } @@ -42,7 +42,7 @@ public func clamp(_ x: Float, _ minVal: Float, _ maxVal: Float) -> Float { #if FRB_MATH_USE_SIMD return simd_clamp(x, minVal, maxVal) #else - return FirebladeMath.min(FirebladeMath.max(x, minVal), maxVal) + return Swift.min(Swift.max(x, minVal), maxVal) #endif } diff --git a/Sources/FirebladeMath/Functions/fract.swift b/Sources/FirebladeMath/Functions/fract.swift index 2e2fa0f..459e54e 100644 --- a/Sources/FirebladeMath/Functions/fract.swift +++ b/Sources/FirebladeMath/Functions/fract.swift @@ -13,7 +13,7 @@ public func fract(_ value: Double) -> Double { #if FRB_MATH_USE_SIMD return simd_fract(value) #else - return min(value - floor(value), Double(0x1.FFFFFFFFFFFFFp-1)) + return Swift.min(value - floor(value), Double(0x1.FFFFFFFFFFFFFp-1)) #endif } @@ -28,6 +28,6 @@ public func fract(_ value: Float) -> Float { #if FRB_MATH_USE_SIMD return simd_fract(value) #else - return min(value - floor(value), Float(0x1.FFFFFEp-1)) + return Swift.min(value - floor(value), Float(0x1.FFFFFEp-1)) #endif } diff --git a/Sources/FirebladeMath/Functions/max.swift b/Sources/FirebladeMath/Functions/max.swift index 5a9a286..3e8429a 100644 --- a/Sources/FirebladeMath/Functions/max.swift +++ b/Sources/FirebladeMath/Functions/max.swift @@ -13,6 +13,8 @@ import Foundation /// - y: floating point value /// - Returns: If successful, returns the larger of two floating point values. The value returned is exact and does not depend on any rounding modes. @inlinable +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.max(_:_:) instead.", renamed: "Swift.max") public func max(_ x: Float, _ y: Float) -> Float { #if canImport(Darwin) return Darwin.fmaxf(x, y) @@ -30,6 +32,8 @@ public func max(_ x: Float, _ y: Float) -> Float { /// - y: floating point value /// - Returns: If successful, returns the larger of two floating point values. The value returned is exact and does not depend on any rounding modes. @inlinable +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.max(_:_:) instead.", renamed: "Swift.max") public func max(_ x: Double, _ y: Double) -> Double { #if canImport(Darwin) return Darwin.fmax(x, y) diff --git a/Sources/FirebladeMath/Functions/min.swift b/Sources/FirebladeMath/Functions/min.swift index cff31b9..373e258 100644 --- a/Sources/FirebladeMath/Functions/min.swift +++ b/Sources/FirebladeMath/Functions/min.swift @@ -13,6 +13,8 @@ import Foundation /// - y: floating point value /// - Returns: If successful, returns the smaller of two floating point values. The value returned is exact and does not depend on any rounding modes. @inlinable +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.min(_:_:) instead.", renamed: "Swift.min") public func min(_ x: Float, _ y: Float) -> Float { #if canImport(Darwin) return Darwin.fminf(x, y) @@ -30,6 +32,8 @@ public func min(_ x: Float, _ y: Float) -> Float { /// - y: floating point value /// - Returns: If successful, returns the smaller of two floating point values. The value returned is exact and does not depend on any rounding modes. @inlinable +@_disfavoredOverload +@available(*, deprecated, message: "Use Swift.min(_:_:) instead.", renamed: "Swift.min") public func min(_ x: Double, _ y: Double) -> Double { #if canImport(Darwin) return Darwin.fmin(x, y) diff --git a/Tests/FirebladeMathTests/FunctionTests.swift b/Tests/FirebladeMathTests/FunctionTests.swift index 62a0c8d..ac1e8b6 100644 --- a/Tests/FirebladeMathTests/FunctionTests.swift +++ b/Tests/FirebladeMathTests/FunctionTests.swift @@ -9,7 +9,9 @@ import FirebladeMath import Testing struct FunctionTests { - @Test func absFunc() { + @Test + @available(*, deprecated, message: "Testing deprecated API") + func absFunc() { #expect(FirebladeMath.abs(Double(-123)) == 123) #expect(FirebladeMath.abs(Float(-123)) == 123) } @@ -139,11 +141,15 @@ struct FunctionTests { #expect(FirebladeMath.log10(Double(123)) == 2.089905111439398) #expect(FirebladeMath.log10(Float(123)) == 2.089905) } - @Test func maxFunc() { + @Test + @available(*, deprecated, message: "Testing deprecated API") + func maxFunc() { #expect(FirebladeMath.max(Double(123), Double(534)) == 534) #expect(FirebladeMath.max(Float(123), Float(33)) == 123) } - @Test func minFunc() { + @Test + @available(*, deprecated, message: "Testing deprecated API") + func minFunc() { #expect(FirebladeMath.min(Double(123), Double(22)) == 22) #expect(FirebladeMath.min(Float(123), Float(66)) == 66) } diff --git a/Tests/FirebladeMathTests/SwiftStandardLibraryRedundancyTests.swift b/Tests/FirebladeMathTests/SwiftStandardLibraryRedundancyTests.swift new file mode 100644 index 0000000..a05d2d6 --- /dev/null +++ b/Tests/FirebladeMathTests/SwiftStandardLibraryRedundancyTests.swift @@ -0,0 +1,263 @@ +// +// SwiftStandardLibraryRedundancyTests.swift +// FirebladeMathTests +// + +import FirebladeMath +import Testing + +struct SwiftStandardLibraryRedundancyTests { + // MARK: - Core Global Functions + + @Test + @available(*, deprecated, message: "Testing deprecated API") + func testAbsRedundancy() { + let doubleVal: Double = -123.45 + let floatVal: Float = -123.45 + + #expect(FirebladeMath.abs(doubleVal) == Swift.abs(doubleVal)) + #expect(FirebladeMath.abs(doubleVal) == doubleVal.magnitude) + #expect(FirebladeMath.abs(floatVal) == Swift.abs(floatVal)) + #expect(FirebladeMath.abs(floatVal) == floatVal.magnitude) + } + + @Test + @available(*, deprecated, message: "Testing deprecated API") + func testMinRedundancy() { + let doubleA: Double = 12.34 + let doubleB: Double = 56.78 + let floatA: Float = 12.34 + let floatB: Float = 56.78 + + #expect(FirebladeMath.min(doubleA, doubleB) == Swift.min(doubleA, doubleB)) + #expect(FirebladeMath.min(floatA, floatB) == Swift.min(floatA, floatB)) + } + + @Test + @available(*, deprecated, message: "Testing deprecated API") + func testMaxRedundancy() { + let doubleA: Double = 12.34 + let doubleB: Double = 56.78 + let floatA: Float = 12.34 + let floatB: Float = 56.78 + + #expect(FirebladeMath.max(doubleA, doubleB) == Swift.max(doubleA, doubleB)) + #expect(FirebladeMath.max(floatA, floatB) == Swift.max(floatA, floatB)) + } + + // MARK: - FloatingPoint Protocol Methods + + @Test func testSqrtRedundancy() { + let doubleVal: Double = 144.0 + let floatVal: Float = 144.0 + + #expect(FirebladeMath.sqrt(doubleVal) == doubleVal.squareRoot()) + #expect(FirebladeMath.sqrt(floatVal) == floatVal.squareRoot()) + } + + @Test func testFloorRedundancy() { + let doubleVal: Double = 123.45 + let floatVal: Float = 123.45 + + #expect(FirebladeMath.floor(doubleVal) == doubleVal.rounded(.down)) + #expect(FirebladeMath.floor(floatVal) == floatVal.rounded(.down)) + } + + @Test func testCeilRedundancy() { + let doubleVal: Double = 123.45 + let floatVal: Float = 123.45 + + #expect(FirebladeMath.ceil(doubleVal) == doubleVal.rounded(.up)) + #expect(FirebladeMath.ceil(floatVal) == floatVal.rounded(.up)) + } + + @Test func testCopySignRedundancy() { + let doubleMagnitude: Double = 10.0 + let doubleSign: Double = -1.0 + let floatMagnitude: Float = 10.0 + let floatSign: Float = -1.0 + + let expectedDouble = Double(signOf: doubleSign, magnitudeOf: doubleMagnitude) + let expectedFloat = Float(signOf: floatSign, magnitudeOf: floatMagnitude) + + #expect(FirebladeMath.copysign(doubleMagnitude, doubleSign) == expectedDouble) + #expect(FirebladeMath.copysign(floatMagnitude, floatSign) == expectedFloat) + } + + @Test func testModRedundancy() { + let doubleX: Double = 123.0 + let doubleY: Double = 5.0 + let floatX: Float = 123.0 + let floatY: Float = 5.0 + + #expect(FirebladeMath.mod(doubleX, doubleY) == doubleX.truncatingRemainder(dividingBy: doubleY)) + #expect(FirebladeMath.mod(floatX, floatY) == floatX.truncatingRemainder(dividingBy: floatY)) + } + + @Test func testIsInfiniteRedundancy() { + let doubleInf = Double.infinity + let floatInf = Float.infinity + let doubleFinite = 123.45 + let floatFinite: Float = 123.45 + + #expect(FirebladeMath.isInfinite(doubleInf) == doubleInf.isInfinite) + #expect(FirebladeMath.isInfinite(floatInf) == floatInf.isInfinite) + #expect(FirebladeMath.isInfinite(doubleFinite) == doubleFinite.isInfinite) + #expect(FirebladeMath.isInfinite(floatFinite) == floatFinite.isInfinite) + } + + @Test func testIsNegativeInfinityRedundancy() { + let doubleNegInf = -Double.infinity + let doublePosInf = Double.infinity + let floatNegInf = -Float.infinity + let floatPosInf = Float.infinity + + #expect(FirebladeMath.isNegativeInfinity(doubleNegInf) == (doubleNegInf.isInfinite && doubleNegInf.sign == .minus)) + #expect(FirebladeMath.isNegativeInfinity(doublePosInf) == (doublePosInf.isInfinite && doublePosInf.sign == .minus)) + #expect(FirebladeMath.isNegativeInfinity(floatNegInf) == (floatNegInf.isInfinite && floatNegInf.sign == .minus)) + #expect(FirebladeMath.isNegativeInfinity(floatPosInf) == (floatPosInf.isInfinite && floatPosInf.sign == .minus)) + } + + @Test func testIsPositiveInfinityRedundancy() { + let doubleNegInf = -Double.infinity + let doublePosInf = Double.infinity + let floatNegInf = -Float.infinity + let floatPosInf = Float.infinity + + #expect(FirebladeMath.isPositiveInfinity(doubleNegInf) == (doubleNegInf.isInfinite && doubleNegInf.sign == .plus)) + #expect(FirebladeMath.isPositiveInfinity(doublePosInf) == (doublePosInf.isInfinite && doublePosInf.sign == .plus)) + #expect(FirebladeMath.isPositiveInfinity(floatNegInf) == (floatNegInf.isInfinite && floatNegInf.sign == .plus)) + #expect(FirebladeMath.isPositiveInfinity(floatPosInf) == (floatPosInf.isInfinite && floatPosInf.sign == .plus)) + } + + @Test func testIsNegativeZeroRedundancy() { + let doubleNegZero = -0.0 + let doublePosZero = 0.0 + let floatNegZero: Float = -0.0 + let floatPosZero: Float = 0.0 + + #expect(FirebladeMath.isNegativeZero(doubleNegZero) == (doubleNegZero.isZero && doubleNegZero.sign == .minus)) + #expect(FirebladeMath.isNegativeZero(doublePosZero) == (doublePosZero.isZero && doublePosZero.sign == .minus)) + #expect(FirebladeMath.isNegativeZero(floatNegZero) == (floatNegZero.isZero && floatNegZero.sign == .minus)) + #expect(FirebladeMath.isNegativeZero(floatPosZero) == (floatPosZero.isZero && floatPosZero.sign == .minus)) + } + + @Test func testIsPositiveZeroRedundancy() { + let doubleNegZero = -0.0 + let doublePosZero = 0.0 + let floatNegZero: Float = -0.0 + let floatPosZero: Float = 0.0 + + #expect(FirebladeMath.isPositiveZero(doubleNegZero) == (doubleNegZero.isZero && doubleNegZero.sign == .plus)) + #expect(FirebladeMath.isPositiveZero(doublePosZero) == (doublePosZero.isZero && doublePosZero.sign == .plus)) + #expect(FirebladeMath.isPositiveZero(floatNegZero) == (floatNegZero.isZero && floatNegZero.sign == .plus)) + #expect(FirebladeMath.isPositiveZero(floatPosZero) == (floatPosZero.isZero && floatPosZero.sign == .plus)) + } + + // MARK: - SIMD Vector Features + + @Test func testSIMDSequenceAndCollectionRedundancy() { + let simd2 = SIMD2(1.0, 2.0) + let simd3 = SIMD3(3.0, 4.0, 5.0) + let simd4 = SIMD4(6.0, 7.0, 8.0, 9.0) + + // Swift Standard Library natively constructs Arrays from SIMD vectors via Sequence/Collection + #expect(Array(simd2) == simd2.elements) + #expect(Array(simd3) == simd3.elements) + #expect(Array(simd4) == simd4.elements) + } + + @Test func testSIMDClampedRedundancy() { + let simd2 = SIMD2(10.0, -5.0) + let minBound = SIMD2(0.0, 0.0) + let maxBound = SIMD2(5.0, 5.0) + + // Native Swift.SIMD method + #expect(simd2.clamped(lowerBound: minBound, upperBound: maxBound) == SIMD2(5.0, 0.0)) + + let scalarVal: Float = 10.0 + #expect(FirebladeMath.clamp(scalarVal, 0.0, 5.0) == 5.0) + } + + @Test func testSIMDDotProductRedundancy() { + let v1 = SIMD3(1.0, 2.0, 3.0) + let v2 = SIMD3(4.0, 5.0, 6.0) + + // Native SIMD sum for dot product + let stdLibDot = (v1 * v2).sum() + #expect(FirebladeMath.dot(v1, v2) == stdLibDot) + } + + @Test func testSIMDIsNaNRedundancy() { + let validVec = SIMD3(1.0, 2.0, 3.0) + let nanVec = SIMD3(1.0, Float.nan, 3.0) + + let stdLibValidIsNaN = validVec.x.isNaN || validVec.y.isNaN || validVec.z.isNaN + let stdLibNanIsNaN = nanVec.x.isNaN || nanVec.y.isNaN || nanVec.z.isNaN + + #expect(validVec.isNaN == stdLibValidIsNaN) + #expect(nanVec.isNaN == stdLibNanIsNaN) + } + + // MARK: - Standard Math Overlays + + @Test func testTrigonometricFunctionsRedundancy() { + let d: Double = 0.5 + let f: Float = 0.5 + + #expect(FirebladeMath.sin(d) == sin(d)) + #expect(FirebladeMath.sin(f) == sin(f)) + #expect(FirebladeMath.cos(d) == cos(d)) + #expect(FirebladeMath.cos(f) == cos(f)) + #expect(FirebladeMath.tan(d) == tan(d)) + #expect(FirebladeMath.tan(f) == tan(f)) + #expect(FirebladeMath.asin(d) == asin(d)) + #expect(FirebladeMath.asin(f) == asin(f)) + #expect(FirebladeMath.acos(d) == acos(d)) + #expect(FirebladeMath.acos(f) == acos(f)) + #expect(FirebladeMath.atan(d) == atan(d)) + #expect(FirebladeMath.atan(f) == atan(f)) + #expect(FirebladeMath.atan2(d, d) == atan2(d, d)) + #expect(FirebladeMath.atan2(f, f) == atan2(f, f)) + } + + @Test func testHyperbolicFunctionsRedundancy() { + let d: Double = 0.5 + let f: Float = 0.5 + + #expect(FirebladeMath.sinh(d) == sinh(d)) + #expect(FirebladeMath.sinh(f) == sinh(f)) + #expect(FirebladeMath.cosh(d) == cosh(d)) + #expect(FirebladeMath.cosh(f) == cosh(f)) + #expect(FirebladeMath.tanh(d) == tanh(d)) + #expect(FirebladeMath.tanh(f) == tanh(f)) + #expect(FirebladeMath.asinh(d) == asinh(d)) + #expect(FirebladeMath.asinh(f) == asinh(f)) + #expect(FirebladeMath.acosh(123.0 as Double) == acosh(123.0 as Double)) + #expect(FirebladeMath.acosh(123.0 as Float) == acosh(123.0 as Float)) + #expect(FirebladeMath.atanh(d) == atanh(d)) + #expect(FirebladeMath.atanh(f) == atanh(f)) + } + + @Test func testExponentialAndLogarithmicFunctionsRedundancy() { + let d: Double = 2.0 + let f: Float = 2.0 + + #expect(FirebladeMath.exp(d) == exp(d)) + #expect(FirebladeMath.exp(f) == exp(f)) + #expect(FirebladeMath.exp2(d) == exp2(d)) + #expect(FirebladeMath.exp2(f) == exp2(f)) + #expect(FirebladeMath.log(d) == log(d)) + #expect(FirebladeMath.log(f) == log(f)) + #expect(FirebladeMath.log2(d) == log2(d)) + #expect(FirebladeMath.log2(f) == log2(f)) + #expect(FirebladeMath.log10(d) == log10(d)) + #expect(FirebladeMath.log10(f) == log10(f)) + #expect(FirebladeMath.pow(d, 3.0) == pow(d, 3.0)) + #expect(FirebladeMath.pow(f, 3.0) == pow(f, 3.0)) + #expect(FirebladeMath.pow2(d) == exp2(d)) + #expect(FirebladeMath.pow2(f) == exp2(f)) + #expect(FirebladeMath.hypot(3.0 as Double, 4.0 as Double) == hypot(3.0 as Double, 4.0 as Double)) + #expect(FirebladeMath.hypot(3.0 as Float, 4.0 as Float) == hypot(3.0 as Float, 4.0 as Float)) + } +}