Search code examples
swiftquartz-graphicsquartz-coreaccelerate-frameworkcgfloat

How to determine if CGFloat is Float or Double


Quartz uses CGFloat for its graphics. CGFloat is either Float or Double, depending on the processor.

The Accelerate framework has different variations of the same function. For example dgetrf_ for Double's and sgetrf_ for Float's.

I have to make these two work together. Either I can use Double's everywhere and convert them to CGFloat every time I use quartz, or I can (try to) determine the actual type of CGFloat and use the appropriate Accelerate function.

Mixing CGFloat's and Double types all over my code base is not very appealing and converting thousands or millions of values to CGFloat every time doesn't strike me as very efficient either.

At this moment I would go with the second option. (Or shouldn't I?)

My question is: how do I know the actual type of CGFloat?

if ??? //pseudo-code: CGFloat is Double
{
   dgetrf_(...)
}
else
{
   sgetrf_(...)
}

Solution

  • Documentation on Swift Floating-Point Numbers:

    Floating-point types can represent a much wider range of values than integer types, and can store numbers that are much larger or smaller than can be stored in an Int. Swift provides two signed floating-point number types:

    • Double represents a 64-bit floating-point number.
    • Float represents a 32-bit floating-point number.

    You can test using the sizeof function:

    if sizeof(CGFloat) == sizeof(Double) {
      // CGFloat is a Double
    } else {
      // CGFloat is a Float
    }
    

    Probably the easiest way to deal with this is to use conditional compilation to define a wrapper which will call the proper version:

    import Accelerate
    
    func getrf_(__m: UnsafeMutablePointer<__CLPK_integer>,
                __n: UnsafeMutablePointer<__CLPK_integer>,
                __a: UnsafeMutablePointer<CGFloat>,
                __lda: UnsafeMutablePointer<__CLPK_integer>,
                __ipiv: UnsafeMutablePointer<__CLPK_integer>,
                __info: UnsafeMutablePointer<__CLPK_integer>) -> Int32 {
    
      #if __LP64__ // CGFloat is Double on 64 bit archetecture
        return dgetrf_(__m, __n, UnsafeMutablePointer<__CLPK_doublereal>(__a), __lda, __ipiv, __info)
      #else
        return sgetrf_(__m, __n, UnsafeMutablePointer<__CLPK_real>(__a), __lda, __ipiv, __info)
      #endif
    }