Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
name: Swift

on: [push]
on: [push, pull_request]

jobs:
build:

runs-on: macOS-latest

strategy:
matrix:
os: [macOS-latest, ubuntu-latest]
swift: ["5.1"]
runs-on: ${{ matrix.os }}
env:
SWIFT_VERSION: ${{ matrix.swift }}
SWIFT_EXEC: .swiftenv/shims/swift
steps:
- uses: actions/checkout@v2
- name: Install Swift
run: |
git clone https://github.com/kylef/swiftenv.git ~/.swiftenv
~/.swiftenv/bin/swiftenv install $SWIFT_VERSION --skip-existing
~/.swiftenv/bin/swiftenv rehash
- name: Build
run: swift build -v
- name: Run Tests
run: swift test -v
run: |
~/$SWIFT_EXEC --version
~/$SWIFT_EXEC build -v
- name: Test
run: |
~/$SWIFT_EXEC test -v
4 changes: 4 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ opt_in_rules:

reporter: "xcode"

excluded:
- Tests/LinuxMain.swift
- Tests/ComplexTests/XCTestManifests.swift

identifier_name:
excluded:
- i
Expand Down
3 changes: 1 addition & 2 deletions Complex.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ Pod::Spec.new do |s|

s.source = { :git => "https://github.com/SomeRandomiOSDev/Complex.git", :tag => s.version.to_s }
s.source_files = 'Sources/**/*.swift'
s.frameworks = 'Foundation'
s.swift_versions = ['4.0', '4.2', '5.0']
s.swift_versions = ['4.2', '5.0']
s.cocoapods_version = '>= 1.7.3'

end
2 changes: 2 additions & 0 deletions Complex.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
DDB8126F23FA2C210079FEB5 /* Functions.swift.gyb */ = {isa = PBXFileReference; explicitFileType = text.script.python; path = Functions.swift.gyb; sourceTree = "<group>"; };
DDB8127123FA4DA50079FEB5 /* ATTRIBUTIONS */ = {isa = PBXFileReference; lastKnownFileType = text; path = ATTRIBUTIONS; sourceTree = "<group>"; };
DDB8128523FB1A430079FEB5 /* FunctionsTests.swift.gyb */ = {isa = PBXFileReference; explicitFileType = text.script.python; path = FunctionsTests.swift.gyb; sourceTree = "<group>"; };
DDC7FF972412922500A5832A /* Package@swift-4.2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Package@swift-4.2.swift"; sourceTree = "<group>"; };
DDFEEC3323EF13900096015C /* Complex.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Complex.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DDFEEC3723EF13900096015C /* Complex-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Complex-Info.plist"; path = "Info/Complex-Info.plist"; sourceTree = "<group>"; };
DDFEEC3C23EF13910096015C /* ComplexTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ComplexTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -325,6 +326,7 @@
children = (
DDFEECAB23F1BA550096015C /* Complex.podspec */,
DDFEECAC23F1BA550096015C /* Package.swift */,
DDC7FF972412922500A5832A /* Package@swift-4.2.swift */,
DD6F08D02400808300749359 /* codecov.yml */,
DDFEECAE23F1BA5E0096015C /* .swiftlint.yml */,
DDFEECAD23F1BA5E0096015C /* .travis.yml */,
Expand Down
21 changes: 21 additions & 0 deletions Package@swift-4.2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// swift-tools-version:4.2
import PackageDescription

let package = Package(
name: "Complex",

products: [
.library(name: "Complex", targets: ["Complex"])
],

dependencies: [
.package(url: "https://github.com/SomeRandomiOSDev/Half", from: "1.2.0")
],

targets: [
.target(name: "Complex"),
.testTarget(name: "ComplexTests", dependencies: ["Complex", "Half"])
],

swiftLanguageVersions: [.v4_2]
)
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Complex
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Complex.svg)](https://cocoapods.org/pods/Complex)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Platform](https://img.shields.io/cocoapods/p/Complex.svg)](https://cocoapods.org/pods/Complex)
![Linux](https://img.shields.io/badge/platform-linux-lightgrey)
[![Build](https://travis-ci.com/SomeRandomiOSDev/Complex.svg?branch=master)](https://travis-ci.com/SomeRandomiOSDev/Complex)
![Swift](https://github.com/SomeRandomiOSDev/Complex/workflows/Swift/badge.svg)
[![Code Coverage](https://codecov.io/gh/SomeRandomiOSDev/Complex/branch/master/graph/badge.svg)](https://codecov.io/gh/SomeRandomiOSDev/Complex)
Expand Down
35 changes: 28 additions & 7 deletions Sources/Complex/Complex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation

// MARK: - Complex Definition

#if swift(>=5.1)
@frozen public struct Complex<Scalar: Numeric> {

// MARK: Public Properties
Expand All @@ -19,10 +20,30 @@ import Foundation
// MARK: Initialization

@_transparent
public init(real: Scalar = .zero, imaginary: Scalar = .zero) {
public init(real: Scalar = 0, imaginary: Scalar = 0) {
self.real = real
self.imaginary = imaginary
}
}
#else
public struct Complex<Scalar: Numeric> {

// MARK: Public Properties

public var real: Scalar
public var imaginary: Scalar

// MARK: Initialization

@_transparent
public init(real: Scalar = 0, imaginary: Scalar = 0) {
self.real = real
self.imaginary = imaginary
}
}
#endif // #if swift(>=5.1)

extension Complex {

@_transparent
public init(_ other: Complex<Scalar>) {
Expand All @@ -32,7 +53,7 @@ import Foundation

@_transparent
public init() {
self.init(real: .zero, imaginary: .zero)
self.init(real: 0, imaginary: 0)
}
}

Expand Down Expand Up @@ -137,7 +158,7 @@ extension Complex where Scalar: FixedWidthInteger {

// MARK: - ExpressibleByArrayLiteral Protocol Conformance

extension Complex: ExpressibleByArrayLiteral where Scalar: AdditiveArithmetic {
extension Complex: ExpressibleByArrayLiteral {

@_transparent
public init(arrayLiteral elements: Scalar...) {
Expand All @@ -146,7 +167,7 @@ extension Complex: ExpressibleByArrayLiteral where Scalar: AdditiveArithmetic {
if elements.isEmpty {
self.init()
} else if elements.count == 1 {
self.init(real: elements[0], imaginary: .zero)
self.init(real: elements[0], imaginary: 0)
} else {
self.init(real: elements[0], imaginary: elements[1])
}
Expand Down Expand Up @@ -261,7 +282,7 @@ extension Complex where Scalar: FloatingPoint {

@_transparent
public func rounded() -> Complex {
rounded(.toNearestOrAwayFromZero)
return rounded(.toNearestOrAwayFromZero)
}

//
Expand Down Expand Up @@ -354,15 +375,15 @@ extension Complex {

@_transparent
public static var i: Complex {
return Complex(real: .zero, imaginary: 1)
return Complex(real: 0, imaginary: 1)
}
}

extension Complex {

@_transparent
public static var one: Complex {
return Complex(real: 1, imaginary: .zero)
return Complex(real: 1, imaginary: 0)
}
}

Expand Down
16 changes: 9 additions & 7 deletions Sources/Complex/ComplexArithmetic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@
// Copyright © 2020 SomeRandomiOSDev. All rights reserved.
//

import Foundation

//swiftlint:disable shorthand_operator

// MARK: - AdditiveArithmetic Protocol Conformance

extension Complex: AdditiveArithmetic {
#if swift(>=5.0)
extension Complex: AdditiveArithmetic { }
#endif

extension Complex {

@_transparent
public static var zero: Complex<Scalar> {
return Complex<Scalar>(real: .zero, imaginary: .zero)
return Complex<Scalar>(real: 0, imaginary: 0)
}

@_transparent
Expand Down Expand Up @@ -163,7 +165,7 @@ extension Complex where Scalar: FixedWidthInteger {

@_transparent
public static func &- (lhs: Scalar, rhs: Complex<Scalar>) -> Complex<Scalar> {
return Complex<Scalar>(real: lhs &- rhs.real, imaginary: .zero &- rhs.imaginary)
return Complex<Scalar>(real: lhs &- rhs.real, imaginary: 0 &- rhs.imaginary)
}

@_transparent
Expand Down Expand Up @@ -325,7 +327,7 @@ extension Complex where Scalar: SignedInteger {

@_transparent
public static func / (lhs: Scalar, rhs: Complex<Scalar>) -> Complex<Scalar> {
return Complex<Scalar>(real: lhs, imaginary: .zero) / rhs
return Complex<Scalar>(real: lhs, imaginary: 0) / rhs
}
}

Expand Down Expand Up @@ -355,7 +357,7 @@ extension Complex where Scalar: FloatingPoint {

@_transparent
public static func / (lhs: Scalar, rhs: Complex<Scalar>) -> Complex<Scalar> {
return Complex<Scalar>(real: lhs, imaginary: .zero) / rhs
return Complex<Scalar>(real: lhs, imaginary: 0) / rhs
}

@_transparent
Expand Down
40 changes: 19 additions & 21 deletions Sources/Complex/ComplexOverflowingArithmetic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
// Copyright © 2020 SomeRandomiOSDev. All rights reserved.
//

import Foundation

// MARK: Overflowing Addition

extension Complex where Scalar: FixedWidthInteger {
Expand Down Expand Up @@ -127,7 +125,7 @@ extension Complex where Scalar: FixedWidthInteger {
//swiftlint:disable identifier_name
public func dividedReportingOverflow(by rhs: Complex<Scalar>) -> (partialValue: Complex<Scalar>, overflow: Bool) {
// (a + bi) / (c + di) -> ((ac + bd) + (bc - ad)i) / (c^2 + d^2)
guard rhs.real != .zero || rhs.imaginary != .zero else { return (rhs, true) }
guard rhs.real != 0 || rhs.imaginary != 0 else { return (rhs, true) }

let ac = self.real.multipliedFullWidth(by: rhs.real)
let ad = self.real.multipliedFullWidth(by: rhs.imaginary)
Expand Down Expand Up @@ -162,12 +160,12 @@ extension Complex where Scalar: FixedWidthInteger, Scalar: SignedInteger {
let a = (high: (high: dividend.high.high.real, low: dividend.high.low.real), low: (high: dividend.low.high.real, low: dividend.low.low.real))
let b = (high: (high: dividend.high.high.imaginary, low: dividend.high.low.imaginary), low: (high: dividend.low.high.imaginary, low: dividend.low.low.imaginary))

let ac = Complex<Scalar>.slowpathMultiply(real, a)
let ad = Complex<Scalar>.slowpathMultiply(imaginary, a)
let bc = Complex<Scalar>.slowpathMultiply(real, b)
let bd = Complex<Scalar>.slowpathMultiply(imaginary, b)
let cc = Complex<Scalar>.signExtend(real.multipliedFullWidth(by: real))
let dd = Complex<Scalar>.signExtend(imaginary.multipliedFullWidth(by: imaginary))
let ac = Complex<Scalar>.slowpathMultiply(self.real, a)
let ad = Complex<Scalar>.slowpathMultiply(self.imaginary, a)
let bc = Complex<Scalar>.slowpathMultiply(self.real, b)
let bd = Complex<Scalar>.slowpathMultiply(self.imaginary, b)
let cc = Complex<Scalar>.signExtend(self.real.multipliedFullWidth(by: self.real))
let dd = Complex<Scalar>.signExtend(self.imaginary.multipliedFullWidth(by: self.imaginary))

let real = Complex<Scalar>.add(ac, bd)
let imaginary = Complex<Scalar>.subtract(bc, ad)
Expand Down Expand Up @@ -197,7 +195,7 @@ extension Complex where Scalar: FixedWidthInteger {
//

internal static func signExtend(_ value: Scalar) -> ExtendedScalar {
let highHigh = (Scalar.isSigned && value.leadingZeroBitCount == 0) ? ~Scalar.zero : Scalar.zero
let highHigh = (Scalar.isSigned && value.leadingZeroBitCount == 0) ? ~Scalar(0) : Scalar(0)
let highLow = Scalar.Magnitude(truncatingIfNeeded: highHigh)
let lowHigh = Scalar.Magnitude(truncatingIfNeeded: highLow)
let lowLow = Scalar.Magnitude(truncatingIfNeeded: value)
Expand All @@ -206,7 +204,7 @@ extension Complex where Scalar: FixedWidthInteger {
}

internal static func signExtend(_ value: (high: Scalar, low: Scalar.Magnitude)) -> ExtendedScalar {
let highHigh = (Scalar.isSigned && value.high.leadingZeroBitCount == 0) ? ~Scalar.zero : Scalar.zero
let highHigh = (Scalar.isSigned && value.high.leadingZeroBitCount == 0) ? ~Scalar(0) : Scalar(0)
let highLow = Scalar.Magnitude(truncatingIfNeeded: highHigh)
let lowHigh = Scalar.Magnitude(truncatingIfNeeded: value.high)
let lowLow = value.low
Expand Down Expand Up @@ -276,10 +274,10 @@ extension Complex where Scalar: FixedWidthInteger {
internal static func slowpathMultiply(_ lhs: ExtendedScalar, _ rhs: ExtendedScalar) -> ExtendedScalar {
var result: ExtendedScalar = ((0, 0), (0, 0))

let lhsIsNegative = Scalar.isSigned && lhs.high.high < .zero
let lhsIsNegative = Scalar.isSigned && lhs.high.high < 0
let left = lhsIsNegative ? twosComplement(of: lhs) : lhs

let rhsIsNegative = Scalar.isSigned && rhs.high.high < .zero
let rhsIsNegative = Scalar.isSigned && rhs.high.high < 0
let right = rhsIsNegative ? twosComplement(of: rhs) : rhs

let (leftIsPowerOfTwo, lhsShift) = isPowerOfTwo(left)
Expand All @@ -295,7 +293,7 @@ extension Complex where Scalar: FixedWidthInteger {
var shifted = right
var bits = left

while bits.low.low != .zero || bits.low.high != .zero || bits.high.low != .zero || bits.high.high != .zero {
while bits.low.low != 0 || bits.low.high != 0 || bits.high.low != 0 || bits.high.high != 0 {
if (bits.low.low & 1) == 1 {
shifted = leftShift(shifted, by: shift - lastShift)
result = add(result, shifted)
Expand All @@ -316,7 +314,7 @@ extension Complex where Scalar: FixedWidthInteger {
}

internal static func slowpathMultiply(_ lhs: Scalar, _ rhs: ExtendedScalar) -> ExtendedScalar {
let lhsIsNegative = lhs < .zero
let lhsIsNegative = lhs < 0

let extended = signExtend(lhs)
var result = slowpathMultiply(lhsIsNegative ? twosComplement(of: extended) : extended, rhs)
Expand All @@ -329,10 +327,10 @@ extension Complex where Scalar: FixedWidthInteger {
}

internal static func slowpathDivide(_ lhs: ExtendedScalar, _ rhs: ExtendedScalar) -> (quotient: ExtendedScalar, remainder: ExtendedScalar) {
let dividendIsNegative = Scalar.isSigned && lhs.high.high < .zero
let dividendIsNegative = Scalar.isSigned && lhs.high.high < 0
var dividend = dividendIsNegative ? twosComplement(of: lhs) : lhs

let divisorIsNegative = Scalar.isSigned && rhs.high.high < .zero
let divisorIsNegative = Scalar.isSigned && rhs.high.high < 0
var divisor = divisorIsNegative ? twosComplement(of: rhs) : rhs

guard isLessThanOrEqual(divisor, to: dividend) else { return (quotient: ((0, 0), (0, 0)), remainder: lhs) }
Expand Down Expand Up @@ -469,7 +467,7 @@ extension Complex where Scalar: FixedWidthInteger {
var bits = value
var shift: Scalar.Magnitude = 0

while bits.low.low > 1 || bits.low.high != .zero || bits.high.low != .zero || bits.high.high != .zero {
while bits.low.low > 1 || bits.low.high != 0 || bits.high.low != 0 || bits.high.high != 0 {
bits = rightShift(bits, by: 1)
shift += 1
}
Expand Down Expand Up @@ -520,13 +518,13 @@ extension Complex where Scalar: FixedWidthInteger {
// non-zero or if the most significant bit of the least significant word
// is 1.

if value.high.high < .zero {
if value.high.high < 0 {
if value.high.high.nonzeroBitCount != Scalar.bitWidth || value.high.low.nonzeroBitCount != Scalar.bitWidth || value.low.high.nonzeroBitCount != Scalar.bitWidth {
overflow = true
} else if value.low.low.leadingZeroBitCount > 0 {
overflow = true
}
} else if value.high.high != .zero || value.high.low != .zero || value.low.high != .zero {
} else if value.high.high != 0 || value.high.low != 0 || value.low.high != 0 {
overflow = true
} else if value.low.low.leadingZeroBitCount == 0 {
overflow = true
Expand All @@ -535,7 +533,7 @@ extension Complex where Scalar: FixedWidthInteger {
// For unsigned integers overflow occurs when the any of the three most significant
// words are non-zero.

overflow = (value.high.high > .zero) || (value.high.low > .zero) || (value.low.high > .zero)
overflow = (value.high.high > 0) || (value.high.low > 0) || (value.low.high > 0)
}

return (partialValue, overflow)
Expand Down
Loading