Тригонометрия во время компиляции в C - PullRequest
6 голосов
/ 08 января 2011

В настоящее время у меня есть код, который выглядит как

while (very_long_loop) {
    ...
    y1 = getSomeValue();
    ...
    x1 = y1*cos(PI/2);
    x2 = y2*cos(SOME_CONSTANT);
    ...
    outputValues(x1, x2, ...);
}

, очевидная оптимизация - вычисление косинусов заранее.Я мог бы сделать это, заполнив массив значениями, но мне было интересно, можно ли будет сделать так, чтобы компилятор вычислял их во время компиляции?

Редактировать: я знаю, что C не имеет оценки во время компиляциино я надеялся, что был бы какой-то странный и уродливый способ сделать это с помощью макросов.

Ответы [ 8 ]

6 голосов
/ 08 января 2011

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

1 голос
/ 08 января 2011

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

1 голос
/ 08 января 2011

Нет, к сожалению.

Я бы порекомендовал написать небольшую программу (или скрипт), которая генерирует список этих значений (который вы затем можете #include поместить в нужное место), который выполняется как часть процесса сборки.

Кстати: cos (pi / 2) = 0!

1 голос
/ 08 января 2011

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

0 голосов
/ 25 мая 2012

Я поражен благоговением из-за ответа Кристофа выше.

Так что ничего не нужно делать в этом случае, когда gcc имеет некоторые знания о математических функциях.Но если у вас есть функция (может быть, реализованная вами), которая не может быть рассчитана вашим компилятором C, или если ваш компилятор C не настолько умен (или вам нужно заполнить сложные структуры данных или по какой-либо другой причине), вы можете использовать язык более высокого уровнядействовать как макропроцессор.В прошлом я использовал для этой цели eRuby , но ( ePerl тоже должен работать очень хорошо, и это другой очевидный доступный и более или менее удобный выбор.

Вы можете указать make-правила для преобразования файлов с расширением .eruby (или .eperl или любого другого) в файлы с этим расширением, чтобы, например, если вы пишете файлы module.c.eruby или module.h.eruby, то makeавтоматически знает, как сгенерировать module.c или module.h, соответственно, и поддерживает их актуальность. В своем правиле make вы можете легко добавить генерацию комментария, который предупреждает о непосредственном редактировании файла.

Если выЕсли вы используете Windows или что-то подобное, я не могу объяснить, как добавить поддержку автоматического запуска этого преобразования для вашей любимой IDE, но я считаю, что это возможно, или вы могли бы просто запустить make за пределамиваш IDE всякий раз, когда вам нужно изменить эти .eruby (или что-то еще) файлы.

Кстати, я видел это с невероятномаленькие строки кода, которые я видел в eLua, для использования Lua в качестве макроязыка.Конечно, любой другой язык сценариев с поддержкой регулярных выражений и гибких правил компоновки также должен работать (но Python подходит для этой цели из-за строгих правил пробелов).

0 голосов
/ 08 января 2011

Если вы проверяете код, а компилятор не выводит значения констант из цикла, то сделайте это самостоятельно.

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

0 голосов
/ 08 января 2011

Нет, C не имеет понятия оценки времени компиляции функций и даже символических констант, если они имеют тип doubleЕдинственный способ получить их в качестве непосредственного операнда - это предварительно вычислить их, а затем определить их в макросах.Вот как библиотека C делает это, например, для pi.

0 голосов
/ 08 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...