Как определить, является ли CGFloat Float или Double

Quartz использует CGFloat для своей графики. CGFloat это либо Float, либо Double, в зависимости от процессора.

Фреймворк Accelerate имеет разные варианты одной и той же функции. Например, dgetrf_ для Double и sgetrf_ для Float.

Я должен заставить этих двоих работать вместе. Либо я могу использовать Double везде и преобразовывать их в CGFloat каждый раз, когда использую кварц, либо я могу (попытаться) определить фактический тип CGFloat и использовать соответствующую функцию Accelerate.

Смешивание типов CGFloat's и Double в моей кодовой базе не очень привлекательно, и преобразование тысяч или миллионов значений в CGFloat каждый раз также не кажется мне очень эффективным.

В данный момент я бы выбрал второй вариант. (Или не должен?)

Мой вопрос: как мне узнать фактический тип CGFloat?

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

person user965972    schedule 31.05.2016    source источник


Ответы (2)


Документация по числам с плавающей запятой Swift:

Типы с плавающей запятой могут представлять гораздо более широкий диапазон значений, чем целые типы, и могут хранить числа, которые намного больше или меньше, чем могут храниться в типе Int. Swift предоставляет два типа чисел с плавающей запятой со знаком:

  • Double представляет собой 64-битное число с плавающей запятой.
  • Float представляет собой 32-битное число с плавающей запятой.

Вы можете проверить, используя функцию sizeof:

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

Вероятно, самый простой способ справиться с этим — использовать условную компиляцию для определения оболочки, которая будет вызывать правильную версию:

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
}
person Community    schedule 31.05.2016
comment
Вы можете просто протестировать _LP64_ здесь вместо x86_64 + arm64. - person Ian Ollmann; 29.06.2016
comment
Спасибо, я добавлю это к ответу. - person ; 29.06.2016

В Core Graphics определен макрос CGFLOAT_IS_DOUBLE. Вы можете использовать его в Swift для прямого сравнения:

if CGFLOAT_IS_DOUBLE == 1 {
   print("Double") 
} else {
   print("Float")
}

Конечно, возможно и прямое сравнение размеров:

if sizeof(CGFloat) == sizeof(Double) {            
}

Однако, поскольку существуют перегруженные функции для всех Float, Double и CGFloat, редко возникает необходимость проверять размер типа.

person Sulthan    schedule 31.05.2016
comment
Я просто редактировал свой ответ, чтобы использовать CGFLOAT_IS_DOUBLE. Я не знал об этом, пока я просто не ковырялся. Хороший призыв использовать оба размера для прямого сравнения. - person ; 31.05.2016
comment
@ColGraff К сожалению, не похоже, что его можно использовать в условной компиляции. Мы можем проверить только то, что он определен... что всегда. - person Sulthan; 31.05.2016
comment
Ах, да. Я думал, что есть причина, по которой его нельзя использовать таким образом. Очень жаль. - person ; 31.05.2016