In answering this earlier question about getting a use of ceil()
on a CGFloat to compile for all architectures, I suggested a solution along these lines:
var f : CGFloat = 0.5
var result : CGFloat
result = CGFloat(ceil(Double(f)))
Tell me what I'm missing, but that seems pretty simple to me.
Note that with current version of Swift the solution below is already implemented in the standard library and all mathematical functions are properly overloaded for Double
, Float
and CGFloat
.
Ceil
is an arithmetic operation and in the same way as any other arithmetic operation, there should be an overloaded version for both Double
and Float
.
var f1: Float = 1.0
var f2: Float = 2.0
var d1: Double = 1.0
var d2: Double = 2.0
var f = f1 + f2
var d = d1 + d2
This works because +
is overloaded and works for both types.
Unfortunately, by pulling the math functions from the C library which doesn't support function overloading, we are left with two functions instead of one - ceil
and ceilf
.
I think the best solution is to overload ceil
for Float
types:
func ceil(f: CFloat) -> CFloat {
return ceilf(f)
}
Allowing us to do:
var f: Float = 0.5
var d: Double = 0.5
var f: Float = ceil(f)
var d: Double = ceil(d)
Once we have the same operations defined for both Float
and Double
, even CGFloat
handling will be much simpler.
To answer the comment:
Depending on target processor architecture, CGFloat
can be defined either as Float
or a Double
. That means we should use ceil
or ceilf
depending on target architecture.
var cgFloat: CGFloat = 1.5
//on 64bit it's a Double
var rounded: CGFloat = ceil(cgFloat)
//on 32bit it's a Float
var rounded: CGFloat = ceilf(cgFloat)
However, we would have to use the ugly #if
.
Another option is to use clever casts
var cgFloat: CGFloat = 1.5
var rounded: CGFloat = CGFloat(ceil(Double(cgFloat))
(casting first to Double
, then casting the result to CGFloat
)
However, when we are working with numbers, we want math functions to be transparent.
var cgFloat1: CGFloat = 1.5
var cgFloat2: CGFloat = 2.5
// this works on both 32 and 64bit architectures!
var sum: CGFloat = cgFloat1 + cgFloat 2
If we overload ceil
for Float
as shown above, we are able to do
var cgFloat: CGFloat = 1.5
// this works on both 32 and 64bit architectures!
var rounded: CGFloat = ceil(cgFloat)
Matt,
Building on your solution, and if you use it in several places, then a little extension might make it more palatable:
extension CGFloat {
var ceil: CGFloat {
#if arch(x86_64) || arch(arm64)
return ceil(x)
#else
return ceilf(x)
#endif
}
}
The rest of the code will be cleaner:
var x = CGFloat(0.5)
x.ceil