Инициализировать переменную статически (во время компиляции)
1) У меня много констант в моем алгоритме. 2) мой код работает как с плавающей, так и с фиксированной точкой.
Прямо сейчас эти константы инициализируются функцией float2fixed, в результате чего в плавающей точке она ничего не делает, а в фиксированной точке находит свое представление с фиксированной точкой. Например, 0.5f остается равным 0.5f, если работает с плавающей запятой, тогда как он использует подпрограмму pow() и становится 32768, если работает с фиксированной запятой, а представление с фиксированной запятой - Qx.16.
Это легко поддерживать, но на самом деле требуется много времени для вычисления этих констант с фиксированной запятой (pow - это функция с плавающей запятой). В C++ я бы использовал некоторое метапрограммирование, поэтому компилятор вычисляет эти значения во время компиляции, так что нет никакого попадания во время выполнения. Но в Си это невозможно. Либо это? Кто-нибудь знает такой трюк? Любой компилятор достаточно умен, чтобы сделать это?
Ждем любых ответов.
4 ответа
Вместо того, чтобы использовать (unsigned)(x*pow(2,16))
чтобы сделать ваше преобразование с фиксированной запятой, запишите его как (unsigned)(0.5f * (1 << 16))
Это должно быть приемлемым в качестве константного выражения во время компиляции, поскольку оно включает только встроенные операторы.
При использовании фиксированной точки вы можете написать программу, которая берет ваши значения с плавающей запятой и преобразует их в правильные, постоянные инициализаторы для типа с фиксированной запятой, так что вы эффективно добавляете шаг к компиляции, который генерирует значения с фиксированной запятой.
Одним из преимуществ этого будет то, что вы можете определить и объявить свои константы с помощью const
так что они не изменятся во время выполнения - тогда как с функциями инициализации, конечно, значения должны быть модифицируемыми, потому что они вычисляются один раз.
Я имею в виду написать простую программу, которая может сканировать формульные строки, которые могут выглядеть так:
const double somename = 3.14159;
это прочитало бы это и произвело бы:
const fixedpoint_t somename = { ...whatever is needed... };
Вы разрабатываете операцию, чтобы облегчить управление обеими нотациями, поэтому, возможно, ваш конвертер всегда читает файл, а иногда переписывает его.
datafile.c: datafile.constants converter
converter datafile.constants > datafile.c
В последних версиях GCC (около 4.3) добавлена возможность использовать GMP и MPFR для выполнения некоторых оптимизаций во время компиляции путем оценки более сложных постоянных функций. Такой подход делает ваш код простым и переносимым и доверяет компилятору выполнять тяжелую работу.
Конечно, существуют ограничения на то, что он может сделать, и было бы трудно понять, оптимизирует ли он данный экземпляр, не обращаясь к сборке. Но это может стоить проверить. Вот ссылка на описание в журнале изменений
В простом С вы мало что можете сделать. В какой-то момент вам нужно выполнить преобразование, и компилятор не дает вам никакого доступа к вызову интересных пользовательских функций во время компиляции. Теоретически, вы можете попытаться уговорить препроцессор сделать это за вас, но это быстрый путь к полному безумию (то есть вам придется реализовать pow() в макросах, что довольно отвратительно).
Некоторые варианты, которые я могу придумать:
Поддерживать постоянный кеш на диске. По крайней мере, тогда он будет медленным только один раз, хотя вам все равно придется загрузить его, убедиться, что он не поврежден и т. Д.
Как уже упоминалось в другом комментарии, в любом случае используйте шаблонное метапрограммирование и компилируйте его с помощью компилятора C++. Большинство C прекрасно работает (возможно, лучше) с компилятором C++.
Хм, наверное, это все, о чем я могу думать. Удачи.