Override typecasting with custom operators - ios

Let say I have something like this:
var x: Int = 6
var y: Float = 11.5
so, the result has to be written like this
var result = Float(x) * y
or
var result = x * Int(y)
This makes sense, right ? However, I think that a little clumsy, so I'm trying to make some custom operators for this:
infix operator *~ { associativity left precedence 150 } //floating
func *~ (lhs: Float, rhs: Int) -> Float {
return lhs * Float(rhs)
}
func *~ (lhs: Int, rhs: Float) -> Float {
return rhs * Float(lhs)
}
infix operator *| { associativity left precedence 150 } //Integer
func *| (lhs: Float, rhs: Int) -> Int {
return Int(lhs) * rhs
}
func *| (lhs: Int, rhs: Float) -> Int {
return Int(rhs) * lhs
}
It works but there are too many of them, so I'm trying to make a generic version for these functions. My attempt so far:
func *~ <T: FloatingPointType, V:IntegerType>(lhs: T, rhs: V) -> T {
return lhs * T(rhs)
// error:
// Could not find an overload for 'init' that accepts the supplied arguments
}
Can somebody help please ? Thank you.

protocol Fraction {
init(_ value: Double)
var asDouble: Double { get }
}
extension Int : Fraction { var asDouble : Double { return Double(self) } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
infix operator ** { associativity left precedence 170 }
func **(lhs:Int, rhs:Int) -> Int {
return lhs * rhs
}
func **<T:Fraction, U:Fraction>(lhs:T, rhs:U) -> Double {
return lhs.asDouble * rhs.asDouble
}
2 ** 2 // 4
2 ** 2.2 // 4.4
2.5 ** 2 // 5.0
2.2 ** 2.2 // 4.84

What you are doing is more than counter productive.
What you are calling clumsy is preventing one of the biggest sources of errors. So you want to invest lots of time and work to undo this, and make your source code unreadable in the process.
Anybody ever getting hold of your source code will first spend hours undoing your work and turning everything into normal Swift code.

Related

Binary operator '*' cannot be applied to operands of type 'SCNVector3' and 'Double'

I have a need where i have to multiply SCNVector3 with 0.1 to get a new position. When i try to do this, i am getting below error. This was working before in earlier Xcode Versions. I am using Xcode 10.1 with compiler of Swift 4 version. I have seen other answers for same kind of question but the data type differs here.
Binary operator '*' cannot be applied to operands of type 'SCNVector3' and 'Double'
And the code i am using is below,
guard let pointOfView = sceneView.pointOfView else { return }
let mat = pointOfView.transform
let dir = SCNVector3(-1 * mat.m31, -1 * mat.m32, -1 * mat.m33)
let currentPosition = pointOfView.position + (dir * 0.1) ------>
Getting error here
let projectedPlaneCenter = self.sceneView.projectPoint(currentPosition)
zVal = Double(projectedPlaneCenter.z)
The operator * is not defined for the operands SCNVector3 and Double.
I am guessing that by someVector * 0.1, you mean multiplying each component of the vector by 0.1?
In that case, you could define your own * operator:
// put this in the global scope
func *(lhs: SCNVector3, rhs: Double) -> SCNVector3 {
return SCNVector3(lhs.x * CGFloat(rhs), lhs.y * CGFloat(rhs), lhs.z * CGFloat(rhs))
}
// usage
SCNVector3(1, 2, 3) * 0.1 // (0.1, 0.2, 0.3)
Drop this into your project, and it should work.
public static func * (lhs: SCNVector3, rhs: Double) -> SCNVector3 {
return SCNVector3(lhs.x * .init(rhs), lhs.y * .init(rhs), lhs.z * .init(rhs))
}
public static func * (lhs: Double, rhs: SCNVector3) -> SCNVector3 {
return rhs * lhs
}
}

Single-line function in Swift

Can someone explain me how to write this function, which should return the factorial of x.
The way I tried to do it gives me an error.
This line is inside a dictionary and refers to Operation.UnaryOperation that is (Double) -> Double
I tried to write the function I need extensively, It should look like this:
private func factorial(n: Double) -> Double {
if (n<=1) {
return 1
}
return n * factorial(n-1)
}
Now I need to convert it to a single-line function, how do I do it? would it look something like this?, why am I getting an error?
"x!" : Operation.UnaryOperation({if ($0<=1) {return 1} else {return $0 * factorial($0-1)}}),
Just embed the named function in the closure - like this
enum Operation {
case UnaryOperation( (Double) -> Double)
case BinaryOperation( (Double, Double) -> Double)
}
let dictionary: [String: Operation] = [
"+" : Operation.BinaryOperation({ return $0 + $1 }),
"!" : Operation.UnaryOperation({
arg: Double in
func factorial(x: Double) -> Double {
if x <= 1 {
return 1
} else {
return x * factorial(x - 1)
}
}
return factorial(arg)
})
]
let x = Operation.UnaryOperation(factorial{if ($0<=1) {return 1} else {return $0 * factorial($0-1)}})
func factorial(_ x: UInt) -> UInt {
return x == 0 ? 1 : x * factorial(x - 1)
}
// Example:
print(factorial(6))
// 720

I want multiple non-random numbers in swift

I am using swift and want to have a number of duplicatable patterns throughout my game.
Ideally I would have some sort of shared class that worked sort of like this (this is sort of pseudo-Swift code):
class RandomNumberUtility {
static var sharedInstance = RandomNumberUtility()
var random1 : Random()
var random2 : Random()
func seedRandom1(seed : Int){
random1 = Random(seed)
}
func seedRandom2(seed : Int){
random2 = Random(seed)
}
func getRandom1() -> Int {
return random1.next(1,10)
}
func getRandom2() -> Int {
return random2.next(1,100)
}
}
Then, to begin the series, anywhere in my program I could go like this:
RandomNumberUtility.sharedInstance.seedNumber1(7)
RandomNumberUtility.sharedInstance.seedNumber2(12)
And then I would know that (for example) the first 4 times I called
RandomNumberUtility.sharedInstance.getRandom1()
I would always get the same values (for example: 6, 1, 2, 6)
This would continue until at some point I seeded the number again, and then I would either get the exact same series back (if I used the same seed), or a different series (if I used a different seed).
And I want to have multiple series of numbers (random1 & random2) at the same time.
I am not sure how to begin to turn this into an actual Swift class.
Here is a possible implementation. It uses the jrand48 pseudo random number generator,
which produces 32-bit numbers.
This PRNG is not as good as arc4random(), but has the advantage
that all its state is stored in a user-supplied array, so that multiple
instances can run independently.
struct RandomNumberGenerator {
// 48 bit internal state for jrand48()
private var state : [UInt16] = [0, 0, 0]
// Return pseudo-random number in the range 0 ... upper_bound-1:
mutating func next(upper_bound: UInt32) -> UInt32 {
// Implementation avoiding the "module bias" problem,
// taken from: http://stackoverflow.com/a/10989061/1187415,
// Swift translation here: http://stackoverflow.com/a/26550169/1187415
let range = UInt32.max - UInt32.max % upper_bound
var rnd : UInt32
do {
rnd = UInt32(truncatingBitPattern: jrand48(&state))
} while rnd >= range
return rnd % upper_bound
}
mutating func seed(newSeed : Int) {
state[0] = UInt16(truncatingBitPattern: newSeed)
state[1] = UInt16(truncatingBitPattern: (newSeed >> 16))
state[2] = UInt16(truncatingBitPattern: (newSeed >> 32))
}
}
Example:
var rnd1 = RandomNumberGenerator()
rnd1.seed(7)
var rnd2 = RandomNumberGenerator()
rnd2.seed(12)
println(rnd1.next(10)) // 2
println(rnd1.next(10)) // 8
println(rnd1.next(10)) // 1
println(rnd2.next(10)) // 6
println(rnd2.next(10)) // 0
println(rnd2.next(10)) // 5
If rnd1 is seeded with the same value as above then it
produces the same numbers again:
rnd1.seed(7)
println(rnd1.next(10)) // 2
println(rnd1.next(10)) // 8
println(rnd1.next(10)) // 1
What you need is a singleton that generates pseudo-random numbers and make sure all your code that need a random number call via this class. The trick is to reset the seed for each run of your code. Here is a simple RandomGenerator class that will do the trick for you (it's optimized for speed which is a good thing when writing games):
import Foundation
// This random number generator comes from: Klimov, A. and Shamir, A.,
// "A New Class of Invertible Mappings", Cryptographic Hardware and Embedded
// Systems 2002, http://dl.acm.org/citation.cfm?id=752741
//
// Very fast, very simple, and passes Diehard and other good statistical
// tests as strongly as cryptographically-secure random number generators (but
// is not itself cryptographically-secure).
class RandomNumberGenerator {
static let sharedInstance = RandomNumberGenerator()
private init(seed: UInt64 = 12347) {
self.seed = seed
}
func nextInt() -> Int {
return next(32)
}
private func isPowerOfTwo(x: Int) -> Bool { return x != 0 && ((x & (x - 1)) == 0) }
func nextInt(max: Int) -> Int {
assert(!(max < 0))
// Fast path if max is a power of 2.
if isPowerOfTwo(max) {
return Int((Int64(max) * Int64(next(31))) >> 31)
}
while (true) {
var rnd = next(31)
var val = rnd % max
if rnd - val + (max - 1) >= 0 {
return val
}
}
}
func nextBool() -> Bool {
return next(1) != 0
}
func nextDouble() -> Double {
return Double((Int64(next(26)) << 27) + Int64(next(27))) /
Double(Int64(1) << 53)
}
func nextInt64() -> Int64 {
let lo = UInt(next(32))
let hi = UInt(next(32))
return Int64(UInt64(lo) | UInt64(hi << 32))
}
func nextBytes(inout buffer: [UInt8]) {
for n in 0..<buffer.count {
buffer[n] = UInt8(next(8))
}
}
var seed: UInt64 {
get {
return _seed
}
set(seed) {
_initialSeed = seed
_seed = seed
}
}
var initialSeed: UInt64 {
return _initialSeed!
}
private func randomNumber() -> UInt32 {
_seed = _seed &+ ((_seed &* _seed) | 5)
return UInt32(_seed >> 32)
}
private func next(bits: Int) -> Int {
assert(bits > 0)
assert(!(bits > 32))
return Int(randomNumber() >> UInt32(32 - bits))
}
private var _initialSeed: UInt64?
private var _seed: UInt64 = 0
}

Array of Arithmetic Operators in Swift

Is it possible to have an array of arithmetic operators in Swift? Something like:
var operatorArray = ['+', '-', '*', '/'] // or =[+, -, *, /] ?
I just want to randomly generate numbers and then randomly pick an arithmetic operator from the array above and perform the equation. For example,
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = firstNum + operatorArray[Int(arc4random_uniform(3))] + secondNum //
Will the above 'equation' work?
Thank you.
It will - but you need to use the operators a little differently.
Single operator:
// declare a variable that holds a function
let op: (Int,Int)->Int = (+)
// run the function on two arguments
op(10,10)
And with an array, you could use map to apply each one:
// operatorArray is an array of functions that take two ints and return an int
let operatorArray: [(Int,Int)->Int] = [(+), (-), (*), (/)]
// apply each operator to two numbers
let result = map(operatorArray) { op in op(10,10) }
// result is [20, 0, 100, 1]
You can use NSExpression class for doing the same.
var operatorArray = ["+", "-", "*", "/"]
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = "\(firstNum) \(operatorArray[Int(arc4random_uniform(3))]) \(secondNum)"
var exp = NSExpression(format: equation, argumentArray: [])
println(exp.expressionValueWithObject(nil, context: nil))
This is an old fashion Object Oriented approach.
protocol Operation {
func calculate(op1:Int, op2:Int) -> Int
}
class Addition : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 + op2
}
}
class Subtraction : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 - op2
}
}
class Multiplication : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 * op2
}
}
class Division : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 / op2
}
}
var operatorArray : [Operation] = [Addition(), Subtraction(), Multiplication(), Division()]
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = operatorArray[Int(arc4random_uniform(3))].calculate(firstNum, op2: secondNum)

Swift zero divided by zero gives NAN

I am doing some calculation using Swift. I understand that in Swift, 0/0 gives NAN (not a number) instead of 0. Is there anyway for it to return 0 instead?
for x in 0..<n {
for y in 0..<n {
if(B[0,y,x]==NAN) {B[0,y,x]=0 } //use of undeclared identifier 'NAN'
println("\((Float)B[0,y,x])")
}
}
NaN is defined in FloatingPointType protocol.
Which is the Swift equivalent of isnan()?
Then, if you want zero, how about using Overflow Operators?
let x = 1
let y = x &/ 0
// y is equal to 0
[UPDATED]
You can define custom overflow operator like this.
func &/(lhs: Float, rhs: Float) -> Float {
if rhs == 0 {
return 0
}
return lhs/rhs
}
var a: Float = 1.0
var b: Float = 0
// this is 0
a &/ b
good answer from #bluedome, in case you want this as an extension and\or have any errors there is an answer
infix operator &/ {}
extension CGFloat {
public static func &/(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
if rhs == 0 {
return 0
}
return lhs/rhs
}
}
then you can divide by zero
let a = 5
let b = 0
print(a &/ b) // outputs 0

Resources