инициализировать переменную статически (во время компиляции) - PullRequest
3 голосов
/ 11 июня 2009

1) У меня много констант в моем алгоритме. 2) мой код работает как с плавающей, так и с фиксированной точкой.

В данный момент эти константы инициализируются функцией float2fixed, в результате чего в плавающей точке она ничего не делает, а в фиксированной точке находит свое представление с фиксированной точкой. Например, 0,5f остается 0,5f, если работает с плавающей точкой, тогда как он использует подпрограмму pow () и становится 32768, если работает с фиксированной точкой, а представление с фиксированной точкой - Qx.16.

Это легко поддерживать, но на самом деле требуется много времени для вычисления этих констант с фиксированной запятой (pow - это функция с плавающей запятой). В C ++ я бы использовал некоторое метапрограммирование, поэтому компилятор вычисляет эти значения во время компиляции, так что нет никакого попадания во время выполнения. Но в Си это невозможно. Либо это? Кто-нибудь знает такой трюк? Любой компилятор достаточно умен, чтобы сделать это?

Жду любых ответов.

A

Ответы [ 4 ]

4 голосов
/ 11 июня 2009

Вместо того, чтобы использовать (unsigned)(x*pow(2,16)) для преобразования с фиксированной запятой, запишите его как (unsigned)(0.5f * (1 << 16))

Это должно быть приемлемым в качестве константного выражения во время компиляции, поскольку оно включает только встроенные операторы.

2 голосов
/ 11 июня 2009

При использовании с фиксированной запятой вы можете написать программу, которая принимает значения с плавающей запятой и преобразует их в правильные, постоянные инициализаторы для типа с фиксированной запятой, поэтому вы эффективно добавляете шаг в компиляцию, которая генерирует значения с фиксированной запятой.

Одним из преимуществ этого будет то, что вы можете затем определить и объявить свои константы с помощью const, чтобы они не изменились во время выполнения - тогда как с функциями инициализации, конечно, значения должны быть модифицируемыми, потому что они рассчитываются один раз.


Я имею в виду написать простую программу, которая может сканировать формульные строки, которые могут выглядеть следующим образом:

const double somename = 3.14159;

это прочтет это и сгенерирует:

const fixedpoint_t somename = { ...whatever is needed... };

Вы разрабатываете эту операцию, чтобы упростить управление обеими нотациями, поэтому, возможно, ваш преобразователь всегда читает файл, а иногда переписывает его.

datafile.c:   datafile.constants converter
        converter datafile.constants > datafile.c
1 голос
/ 11 июня 2009

В последних версиях GCC (около 4.3) добавлена ​​возможность использовать GMP и MPFR для выполнения некоторых оптимизаций во время компиляции путем оценки более сложных постоянных функций. Такой подход делает ваш код простым и переносимым и позволяет компилятору выполнять тяжелую работу.

Конечно, существуют ограничения на то, что он может сделать, и было бы трудно понять, оптимизирует ли он данный экземпляр, не обращаясь к сборке. Но это может стоить проверить. Вот ссылка на описание в журнале изменений

0 голосов
/ 11 июня 2009

В простом С вы мало что можете сделать. В какой-то момент вам нужно выполнить преобразование, и компилятор не дает вам никакого доступа к вызову интересных пользовательских функций во время компиляции. Теоретически, вы можете попытаться уговорить препроцессор сделать это за вас, но это быстрый путь к полному безумию (то есть вам придется реализовывать pow () в макросах, что довольно отвратительно).

Некоторые варианты, которые я могу придумать:

  1. Поддерживать постоянный кеш на диске. По крайней мере, тогда он будет медленным только один раз, хотя вам все равно придется загрузить его, убедиться, что он не поврежден и т. Д.

  2. Как уже упоминалось в другом комментарии, в любом случае используйте шаблонное метапрограммирование и компилируйте его с помощью компилятора C ++. Большинство C прекрасно работает (возможно, лучше) с компилятором C ++.

Хм, наверное, это все, о чем я могу думать. Удачи.

...