Skip to content

Instantly share code, notes, and snippets.

@pauljohanneskraft
Last active July 3, 2016 19:10
Show Gist options
  • Save pauljohanneskraft/1d588532177638152fdc88491c7bb5d6 to your computer and use it in GitHub Desktop.
Save pauljohanneskraft/1d588532177638152fdc88491c7bb5d6 to your computer and use it in GitHub Desktop.
Implementation of common mathematical fields, such as R, N, Z, Q, C

Common Fields

typealias R = Double 
typealias N = UInt 
typealias Z = Int
typealias Q = RationalNumber
typealias C = ComplexNumber<Double>

Complex Numbers

struct containing two numbers (real and imaginary part). Currently the following operators are implemented:

*, +, -

TODO: maybe add more in the future?

Rational Numbers

prefix      -
infix       +,  -,   *,  / 
assignment  +=, -=, *=, /=

TODO: add more functionality

typealias R = Double
typealias N = UInt
typealias Z = Int
func Z_(_ v: UInt) -> Set<UInt> {
var zSet = Set<UInt>()
for i in 0..<v {
zSet.insert(i)
}
return zSet
}
typealias C = ComplexNumber<Double>
struct ComplexNumber < Number : Numeric > {
var real: Number
var imaginary: Number
init(_ v: Number) {
self.real = v
self.imaginary = 0
}
init(real: Number, imaginary: Number) {
self.real = real
self.imaginary = imaginary
}
init(_ v: ComplexNumber) {
self.real = v.real
self.imaginary = v.imaginary
}
init(integerLiteral value: Number) {
self.real = value
self.imaginary = 0
}
}
extension ComplexNumber : CustomStringConvertible {
var description : String {
let r = "\(self.real)"
if imaginary.isZero { return r }
return r + " \(self.imaginary < 0 ? "-" : "+") " + "\(self.imaginary.abs)i"
}
}
func *= <N : Numeric>(lhs: inout ComplexNumber<N>, rhs: ComplexNumber<N>) {
let l = lhs
lhs.real = l.real * rhs.real - l.imaginary * rhs.imaginary
lhs.imaginary = l.real * rhs.imaginary + l.imaginary * rhs.imaginary
}
func * <N : Numeric>(lhs: ComplexNumber<N>, rhs: ComplexNumber<N>) -> ComplexNumber<N> {
var l = lhs
l *= rhs
return l
}
func += <N : Numeric>(lhs: inout ComplexNumber<N>, rhs: ComplexNumber<N>) {
lhs.real += rhs.real
lhs.imaginary += rhs.imaginary
}
func + <N : Numeric>(lhs: ComplexNumber<N>, rhs: ComplexNumber<N>) -> ComplexNumber<N> {
var l = lhs
l += rhs
return l
}
func -= <N : Numeric>(lhs: inout ComplexNumber<N>, rhs: ComplexNumber<N>) {
lhs.real -= rhs.real
lhs.imaginary -= rhs.imaginary
}
func - <N : Numeric>(lhs: ComplexNumber<N>, rhs: ComplexNumber<N>) -> ComplexNumber<N> {
var l = lhs
l -= rhs
return l
}
func < <N : Numeric>(lhs: ComplexNumber<N>, rhs: ComplexNumber<N>) -> Bool {
return lhs.real < rhs.real
}
func == <N : Numeric>(lhs: ComplexNumber<N>, rhs: ComplexNumber<N>) -> Bool {
return lhs.real == rhs.real && lhs.imaginary == rhs.imaginary
}
extension Double : Numeric {}
extension Int : Numeric {}
protocol Numeric : IntegerLiteralConvertible {
func * (lhs: Self, rhs: Self) -> Self
func *= (lhs: inout Self, rhs: Self)
func + (lhs: Self, rhs: Self) -> Self
func += (lhs: inout Self, rhs: Self)
func - (lhs: Self, rhs: Self) -> Self
func -= (lhs: inout Self, rhs: Self)
func < (lhs: Self, rhs: Self) -> Bool
func == (lhs: Self, rhs: Self) -> Bool
}
extension Numeric {
var abs : Self {
return self < 0 ? 0 - self : self
}
var isZero : Bool {
return self == 0
}
}
typealias Q = RationalNumber
struct RationalNumber {
private var numerator : Int
private var denominator : Int
init(numerator: Int, denominator: Int) {
self.numerator = numerator
self.denominator = denominator
}
init(_ value: Int) {
self.numerator = value
self.denominator = 1
}
mutating func reduce() {
let gcd = numerator.greatestCommonDivisor(with: denominator)
self.numerator /= gcd
self.denominator /= gcd
if self.denominator.sign {
numerator = -numerator
denominator = -denominator
}
}
var reduced : RationalNumber {
var this = self
this.reduce()
return this
}
var max : RationalNumber {
return RationalNumber(Int.max)
}
var min : RationalNumber {
return RationalNumber(Int.min)
}
var sign : Bool {
if numerator < 0 {
return !(denominator < 0)
}
return denominator < 0
}
var abs : RationalNumber {
return RationalNumber(
numerator: self.numerator.abs,
denominator: self.denominator.abs)
}
}
extension RationalNumber : IntegerLiteralConvertible {
init(integerLiteral value: Int) {
self.numerator = value
self.denominator = 1
}
}
extension RationalNumber : Equatable {}
extension RationalNumber : CustomStringConvertible {
var description: String {
if denominator == 1 { return "\(numerator)" }
if denominator == 0 { return "nan" }
return "\(numerator)/\(denominator)"
}
}
extension RationalNumber {
// source: http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions
init(_ value: Double) {
assert(value.isNormal)
let sign = value < 0
var value = value.abs
var numerator = 0
var denominator = 1
while value > 0 {
let intValue = Int(value)
value -= Double(intValue)
numerator += intValue
value *= 2
numerator *= 2
denominator *= 2
}
if sign { numerator = -numerator }
self = RationalNumber(numerator: numerator, denominator: denominator)
}
// source: http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions
init(readable value: Double, accuracy: Double = 0.00000001) {
let sign = value < 0
let val : Double
if sign {
val = -value
} else {
val = value
}
var n = 1
var d = 1
var frac = Double(n) / Double(d)
while (frac - val).abs > accuracy {
if frac < value {
n += 1
} else {
d += 1
n = Int(val * Double(d))
}
frac = Double(n) / Double(d)
}
self = RationalNumber(numerator: sign ? -n : n, denominator: d)
}
}
extension Int {
var abs : Int {
return self < 0 ? -self : self
}
var sign : Bool {
return self < 0
}
}
extension Double {
var abs : Double {
return self < 0 ? -self : self
}
var sign : Bool {
return self < 0
}
}
prefix func - (rhs: inout RationalNumber) {
if rhs.denominator < 0 {
rhs.denominator = -rhs.denominator
} else {
rhs.numerator = -rhs.numerator
}
}
func *= (lhs: inout RationalNumber, rhs: RationalNumber) {
let rhs = rhs.reduced
lhs.reduce()
lhs.denominator = rhs.denominator * lhs.denominator
lhs.numerator = lhs.numerator * rhs.numerator
lhs.reduce()
}
func * (lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
var lhs = lhs
lhs *= rhs
return lhs
}
func /= (lhs: inout RationalNumber, rhs: RationalNumber) {
let rhs = rhs.reduced
lhs.reduce()
lhs.denominator = rhs.denominator * lhs.numerator
lhs.numerator = lhs.numerator * rhs.denominator
lhs.reduce()
}
func / (lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
var lhs = lhs
lhs /= rhs
return lhs
}
func += (lhs: inout RationalNumber, rhs: RationalNumber) {
let rhs = rhs.reduced
lhs.reduce()
lhs.numerator = lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator
lhs.denominator = rhs.denominator * lhs.denominator
lhs.reduce()
}
func + (lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
var lhs = lhs
lhs += rhs
return lhs
}
func -= (lhs: inout RationalNumber, rhs: RationalNumber) {
let rhs = rhs.reduced
lhs.reduce()
lhs.numerator = lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator
lhs.denominator = rhs.denominator * lhs.denominator
lhs.reduce()
}
func - (lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
var lhs = lhs
lhs -= rhs
return lhs
}
func == (lhs: RationalNumber, rhs: RationalNumber) -> Bool {
if lhs.sign != rhs.sign { return false }
if lhs.numerator == rhs.numerator && lhs.denominator == rhs.denominator {
return true
}
return lhs.numerator == -rhs.numerator && lhs.denominator == -rhs.denominator
}
extension IntegerArithmetic where Self : IntegerLiteralConvertible {
func greatestCommonDivisor(with other: Self) -> Self {
var a = self > other ? self : other
var b = self < other ? self : other
while b != 0 {
let t = b
b = a % b
a = t
}
return a
}
}
extension Double {
init(_ rat: RationalNumber) {
self = Double(rat.numerator) / Double(rat.denominator)
}
}
@pauljohanneskraft
Copy link
Author

pauljohanneskraft commented Jun 22, 2016

Possibly enhancing to "real" Numeric-protocol in the future

see: https://gist.github.com/pauljohanneskraft/56f3757bf4026a1330e601e3af167e24#file-numeric-swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment