Numeric operator overloading in Swift

Numeric operator overloading in Swift

onedayitwillmake No Comment
math snippet sourcecode swift

Sometimes when developing in Swift if you’re trying to do seemingly simple things like divide 2 numbers:

let interval:Double = 1.0/fps;

You’ll get errors like these:

binary operator '*' cannot be applied to operands of type 'CGFloat' and 'Double'
binary operator '*' cannot be applied to operands of type 'Int' and 'CGFloat'
cannot convert value of type 'Float' to expected argument type 'Double'
binary operator '*' cannot be applied to operands of type 'CGFloat' and 'Int8'

This is because Swift is more strict about how it treats numeric types, and you have to manually cast them to the same type in order for those operations to work.

However cause we can write our own operator in Swift, we can make it so that when it encounters 2 types, it will check to see if we have a matching operator and use that instead.

So as I’ve encountered them, I’ve been appending to a my little NumericOperatorOverloadingExtensions.swift file:

import Foundation

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// ADDITION ////////////////////////////////////////////////////////////////
public func +(a: Float, scalar: Int)  -> Float  { return a + Float(scalar); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////// MULTIPLICATION  //////////////////////////////////////////////////////////////
// Int *
public func *(a: Int, scalar: CGFloat)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(a: Int, scalar: Float)    -> Float    { return Float(a) * scalar; }
public func *(a: Int, scalar: Double)   -> Double   { return Double(a) * scalar; }
public func *(scalar: CGFloat, a: Int)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(scalar: Float, a: Int)    -> Float    { return Float(a) * scalar; }
public func *(scalar: Double, a: Int)   -> Double   { return Double(a) * scalar; }

// Int8 *
public func *(a: Int8, scalar: CGFloat)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(a: Int8, scalar: Float)    -> Float    { return Float(a) * scalar; }
public func *(a: Int8, scalar: Double)   -> Double   { return Double(a) * scalar; }
public func *(scalar: CGFloat, a: Int8)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(scalar: Float, a: Int8)    -> Float    { return Float(a) * scalar; }
public func *(scalar: Double, a: Int8)   -> Double   { return Double(a) * scalar; }

// Int32 *
public func *(a: Int32, scalar: CGFloat)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(a: Int32, scalar: Float)    -> Float    { return Float(a) * scalar; }
public func *(a: Int32, scalar: Double)   -> Double   { return Double(a) * scalar; }
public func *(scalar: CGFloat, a: Int32)  -> CGFloat  { return CGFloat(a) * scalar; }
public func *(scalar: Float, a: Int32)    -> Float    { return Float(a) * scalar; }
public func *(scalar: Double, a: Int32)   -> Double   { return Double(a) * scalar; }

// Float *
public func *(a: Float, scalar: Double)  -> Float  { return a * Float(scalar); }
public func *(a: Float, scalar: Double)  -> CGFloat  { return CGFloat(a * Float(scalar)); }
public func *(a: Float, scalar: Double)  -> Double  { return Double(a) * scalar; }

// CGFLOAT  *
public func *(a: CGFloat, scalar: Double)  -> CGFloat  { return a * CGFloat(scalar); }
public func *(a: CGFloat, scalar: Double)  -> Float  { return Float(a) * Float(scalar); }
public func *(a: CGFloat, scalar: Double)  -> Double  { return Double(a) * scalar; }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// DIVISION ////////////////////////////////////////////////////////////////
// Double /
public func /(a: Double, b: Int)  -> Double  { return a / Double(b); }
public func /(a: Double, b: Float)  -> Double  { return a / Double(b); }
public func /(a: Double, b: Int)  -> Int  { return Int(a) / b; }
public func /(a: Int, b: Double)  -> Double  { return Double(a) / b; }
public func /(a: Int, b: Double)  -> Int  { return Int(Double(a) / b); }

// Float /
public func /(a: Float, b: Int)  -> Float  { return a / Float(b); }
public func /(a: Float, b: Int)  -> Int  { return Int(a) / b; }
public func /(a: Int, b: Float)  -> Float  { return Float(a) / b; }
public func /(a: Int, b: Float)  -> Int  { return Int(Float(a) / b); }
public func /(a: Float, scalar: Double)  -> Float  { return a / Float(scalar); }

Leave a Reply


*