Skip to content

Instantly share code, notes, and snippets.

@edwardsanchez
Last active November 25, 2017 21:44
Show Gist options
  • Save edwardsanchez/12a31dddd50f622060baf05220ef0e2a to your computer and use it in GitHub Desktop.
Save edwardsanchez/12a31dddd50f622060baf05220ef0e2a to your computer and use it in GitHub Desktop.
A series of operators that work across multiple types

Available Operations

  • Operate Point or Size to Point or Size
  • Operate Point or Size to single Number
  • Assign Number to Point or Size
  • Use ** as replacement for pow - e.g. 8 + (2 ** 3)
  • % mod operator
  • min max takes and returns point or size
  • Shortcut for sqrt e.g. √256
  • Convert a point to size by appending .size or size to point by appending .point. e.g. mySize.point //returns point
  • Make point or size negative with prefix - operator.

Examples

Add two points together and get a point.

let point1 = CGPoint(x: 30, y: 40)
let point2 = CGPoint(x: 10, y: 20)
let addedPoints = point1 + point2 //added points is now CGPoint(x: 40, y: 60)

Or you can add a CGPoint to a CGSize or vice versa.

let point = CGPoint(x: 30, y: 40)
let size = CGSize(width: 100, height: 200)
let added = point + size //since point is on the left most spot, added will be set to a point of x: 130, y: 200

You can also operate an Int to a Float, or any common numeric type to any common numeric type.

The left most value will decide the type of the variable if none is set.

let integer = Int(30)
let cgfloat = CGFloat(20.5)
let addedValues = integer + cgfloat //value is Int 50
let addedValues2 = cgfloat + integer // value is CGFloat 50.5
let addedValues3: Double = integer + cgfloat // value is Double 50.5

And you can assign across multiple types with the (alt x) operator.

let integer = Int(30)
var cgfloat = CGFloat(4.4)
cgfloat  integer //cgfloat is set to 30.0

Or assign and operate across types.

let integer = Int(30)
var cgfloat = CGFloat(4.4)
cgfloat += integer // cgfloat is set to 34.4
///Shorthand for assigning value only if value is not nil
infix operator ?=
public func ?= <T>(left: inout T, right: T?) {
if let right = right {
left = right
}
}
let fl0 = CGFloat(0)
public protocol Operatable {
var float: CGFloat {get}
init(value: CGFloat)
}
extension Float: Operatable {
public var float: CGFloat {return CGFloat(self)}
public init(value: CGFloat) {self = Float(value)}
}
extension Double: Operatable {
public var float: CGFloat {return CGFloat(self)}
public init(value: CGFloat) {self = Double(value)}
}
extension Int: Operatable {
public var float: CGFloat {return CGFloat(self)}
public init(value: CGFloat) {self = Int(value)}
}
extension CGFloat: Operatable {
public var float: CGFloat {return CGFloat(self)}
public init(value: CGFloat) {self = value}
}
public protocol Tuple {
var first : CGFloat {get}
var second: CGFloat {get}
init(_ first: CGFloat, _ second: CGFloat)
}
extension CGPoint: Tuple {
public var first: CGFloat {return self.x}
public var second: CGFloat {return self.y}
public init(_ first: CGFloat, _ second: CGFloat) {
self.x = first
self.y = second
}
public var size: CGSize {return sz(self.x, self.y)}
}
extension CGSize: Tuple {
public var first: CGFloat {return self.width}
public var second: CGFloat {return self.height}
public init(_ first: CGFloat, _ second: CGFloat) {
self.width = first
self.height = second
}
public var point: CGPoint {return pt(self.width, self.height)}
}
extension CGVector: Tuple {
public var first: CGFloat {return self.dx}
public var second: CGFloat {return self.dy}
public init(_ first: CGFloat, _ second: CGFloat) {
self.dx = first
self.dy = second
}
}
//Numeric to Numeric operators –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
public func +<T: Operatable>(left: Operatable, right: T) -> T {
return T(value: left.float + right.float)
}
public func -<T: Operatable>(left: Operatable, right: T) -> T {
return T(value: left.float - right.float)
}
public func *<T: Operatable>(left: Operatable, right: T) -> T {
return T(value: left.float * right.float)
}
public func /<T: Operatable>(left: Operatable, right: T) -> T {
var result = fl0
//Prevent number from being divided by 0
if right.float != 0 {
result = left.float / right.float
}
return T(value: result)
}
//Forces swift to return 0 even when both left and right are the same type // alt + / to get the symbol
infix operator ÷
public func ÷<T: Operatable>(left: Operatable, right: T) -> T {
var result = fl0
//Prevent number from being divided by 0
if right.float != 0 {
result = left.float / right.float
}
return T(value: result)
}
//Assignment
//swift doesn't allow overriding the "=" operator, use alt + x to get the symbol
infix operator ≈
public func ≈<T: Operatable>(left: inout T, right: Operatable) {
left = T(value: right.float)
}
public func +=<T: Operatable>(left: inout T, right: Operatable) {
left = T(value: left.float + right.float)
}
public func -=<T: Operatable>(left: inout T, right: Operatable) {
left = T(value: left.float - right.float)
}
public func *=<T: Operatable>(left: inout T, right: Operatable) {
left = T(value: left.float * right.float)
}
public func /=<T: Operatable>(left: inout T, right: Operatable) {
var result = fl0
//Prevent number from being divided by 0
if right.float != 0 {
result = left.float / right.float
}
left = T(value: result)
}
//Tuple to Tuple Operators ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
public func +<T: Tuple>(left: T, right: Tuple) -> T {
return T(left.first + right.first, left.second + right.second)
}
public func -<T: Tuple>(left: T, right: Tuple) -> T {
return T(left.first - right.first, left.second - right.second)
}
public prefix func -<T: Tuple>(value: Tuple) -> T {
return T(-value.first, -value.second)
}
public func *<T: Tuple>(left: T, right: Tuple) -> T {
return T(left.first * right.first, left.second * right.second)
}
public func /<T: Tuple>(left: T, right: Tuple) -> T {
var firstResult = fl0
var secondResult = fl0
//Prevent number from being divided by 0
if right.first != 0 {
firstResult = left.first / right.first
}
if right.second != 0 {
secondResult = left.second / right.second
}
return T(firstResult, secondResult)
}
//Assignment
//swift doesn't allow overriding the "=" operator, use alt + x to get the symbol
public func ≈<T: Tuple>(left: inout T, right: Tuple) {
left = T(right.first, right.second)
}
public func +=<T: Tuple>(left: inout T, right: Tuple) {
left = T(left.first + right.first, left.second + right.second)
}
public func -=<T: Tuple>(left: inout T, right: Tuple) {
left = T(left.first - right.first, left.second - right.second)
}
public func *=<T: Tuple>(left: inout T, right: Tuple) {
left = T(left.first * right.first, left.second * right.second)
}
public func /=<T: Tuple>(left: inout T, right: Tuple) {
var firstResult = fl0
var secondResult = fl0
//Prevent number from being divided by 0
if right.first != 0 {
firstResult = left.first / right.first
}
if right.second != 0 {
secondResult = left.second / right.second
}
left = T(firstResult, secondResult)
}
//Tuple to Numeric Operators –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
public func +<T: Tuple>(left: T, right: Operatable) -> T {
return T(left.first + right.float, left.second + right.float)
}
public func -<T: Tuple>(left: T, right: Operatable) -> T {
return T(left.first - right.float, left.second - right.float)
}
public func *<T: Tuple>(left: T, right: Operatable) -> T {
return T(left.first * right.float, left.second * right.float)
}
public func /<T: Tuple>(left: T, right: Operatable) -> T {
//Prevent number from being divided by 0
if right.float == 0 {
return T(0, 0)
} else {
return T(left.first / right.float, left.second / right.float)
}
}
//Assignment
//swift doesn't allow overriding the "=" operator, use alt + x to get the symbol
public func ≈<T: Tuple>(left: inout T, right: Operatable) {
left = T(right.float, right.float)
}
public func +=<T: Tuple>(left: inout T, right: Operatable) {
left = T(left.first + right.float, left.second + right.float)
}
public func -=<T: Tuple>(left: inout T, right: Operatable) {
left = T(left.first - right.float, left.second - right.float)
}
public func *=<T: Tuple>(left: inout T, right: Operatable) {
left = T(left.first * right.float, left.second * right.float)
}
public func /=<T: Tuple>(left: inout T, right: Operatable) {
//Prevent number from being divided by 0
if right.float == 0 {
left = T(0, 0)
} else {
left = T(left.first / right.float, left.second / right.float)
}
}
//Extra Operators –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
public func max<T: Tuple>(_ L: T, _ R: Tuple) -> T {
return T(max(L.first, R.first), max(L.second, R.second))
}
public func min<T: Tuple>(_ L: T, _ R: Tuple) -> T {
return T(min(L.first, R.first), min(L.second, R.second))
}
prefix operator √
public prefix func √<T: Operatable>(value: T) -> T {
return T(value: sqrt(value.float))
}
infix operator **
public func **<T: Operatable>(left: T, right: Operatable) -> T {
return T(value: pow(left.float, right.float))
}
public func %<T: Operatable>(left: T, right: Operatable) -> T {
return T(value: left.float.truncatingRemainder(dividingBy: right.float))
}
public prefix func √<T: Tuple>(value: T) -> T {
return T(sqrt(value.first), sqrt(value.second))
}
public func **<T: Tuple>(left: T, right: Operatable) -> T {
return T(pow(left.first, right.float), pow(left.second, right.float))
}
public func %<T: Tuple>(left: T, right: Operatable) -> T {
return T(left.first.truncatingRemainder(dividingBy: right.float), left.second.truncatingRemainder(dividingBy: right.float))
}
public func %<T: Tuple>(left: T, right: Tuple) -> T {
return T(left.first.truncatingRemainder(dividingBy: right.first), left.second.truncatingRemainder(dividingBy: right.second))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment