できまの計算pow(10x)コンパイル時に。
-
21-08-2019 - |
質問
で計算するためのpow(10x)コンパイル時間がかかる?
私のプロセッサな浮動小数点支援ゆっくりす整数。ようにしているとともに、多くの計算できるコンパイルす。で飛躍的に加速特定の機能までしていただくためにも x
や C/pow(10,x)
引数として(x C、常に一定の整数が異なる定数れます。った場合でこれらの関数呼び出しで誤差なく導入によるマクロなの 1/pow(10,x)
自動的にではなく、強制的にプログラマによって算出してください?
あるプリプロセッサトリック?したいので、コンパイラの最適化を図書館電話のかけ方は?
解決
C 言語の一部である浮動小数点値の科学表記法を使用できます。次のようになります。
e = 1.602E-19 // == 1.602 * pow(10, -19)
の前の数字 E
( E
大資本か小規模かも知れません 1.602e-19
) は小数部であり、その後の (符号付き) 数字列は E
指数部です。デフォルトでは、数値のタイプは次のとおりです。 double
, ただし、浮動小数点接尾辞 (f
, F
, l
または L
) 必要な場合は、 float
または long double
.
このセマンティクスをマクロに詰め込むことはお勧めしません。
- 変数、浮動小数点値などには機能しません。
- 科学的表記法がより読みやすくなります。
他のヒント
の可能な非常にいくつかの値があります。 claritiesのために、そのテーブル作る!
編集:あなたはフロート(あなたがしているように見える)を使用している場合は、何も実際にmakeプロセスで実行され、に値を出力し、コードを記述せずにコンパイル時にPOW()関数を呼び出すことが可能であることを行っていないではないですその後、コンパイルされたファイル(例えば、ヘッダファイルなど)。
GCCは(-O1が私のためにそれをしない)十分に高い最適化レベルでこれを行います。たとえばます:
#include <math.h>
int test() {
double x = pow(10, 4);
return (int)x;
}
は、-O1に-m32でコンパイルします
.file "test.c"
.text
.globl test
.type test, @function
test:
pushl %ebp
movl %esp, %ebp
movl $10000, %eax
popl %ebp
ret
.size test, .-test
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
これは、同様に、キャストせずに動作します - もちろん、あなたがLinuxの<のhref =「https://en.wikipedia.org/wiki/Application_binary_interface」のrel =と、そこでの浮動小数点ロード命令を入手できますか"nofollowをnoreferrer"> ABI FPUレジスタ内の点の戻り値を浮動通過する。
あなたはBoost.Preprocessorでそれを行うことができます:
http://www.boost.org/ DOC / libsに/ 1_39_0 / libsに/プリプロセッサ/ DOC / index.htmlをする
コード:
#include <boost/preprocessor/repeat.hpp>
#define _TIMES_10(z, n, data) * 10
#define POW_10(n) (1 BOOST_PP_REPEAT(n, _TIMES_10, _))
int test[4] = {POW_10(0), POW_10(1), POW_10(2), POW_10(3)};
実際には、Cプリプロセッサを活用することにより、あなたはそれが任意の実際のC pow(10, x)
と積分C
ためx
を計算するために取得することができます。それを観察し、@quinmarsが述べたように、Cは、あなたが、数値定数を表現するために科学的な構文を使用することができます:
#define myexp 1.602E-19 // == 1.602 * pow(10, -19)
の定数に使用します。このことを考慮して、賢さのビットで、我々はC
とx
を取るプリプロセッサマクロを構築することができますし、指数トークンにそれらを組み合わせます:
#define EXP2(a, b) a ## b
#define EXP(a, b) EXP2(a ## e,b)
#define CONSTPOW(C,x) EXP(C, x)
これは、現在一定数値として使用することができます。
const int myint = CONSTPOW(3, 4); // == 30000
const double myfloat = CONSTPOW(M_PI, -2); // == 0.03141592653
実際には、あなたはGCCのより強力なプリプロセッサの方法であるM4を持っています。これらの2つの主な違いは、GCCのはM4であるのに対し、再帰的ではないです。これは、可能なコンパイル時に計算をしているようなものになり(とはるかに!)。以下のサンプルコードは、あなたがやりたいものです、そうではありませんか?私は、1ファイルソースで、それはかさばる製;私は通常、別のファイルやチューン私のMakefileのルールでM4のマクロ定義を置きます。この方法で、あなたのコードは、私がここでやったCのソースコードに醜い侵入M4定義から維持されます。
$ cat foo.c
define(M4_POW_AUX, `ifelse($2, 1, $1, `eval($1 * M4_POW_AUX($1, decr($2)))')')dnl
define(M4_POW, `ifelse($2, 0, 1, `M4_POW_AUX($1, $2)')')dnl
#include <stdio.h>
int main(void)
{
printf("2^0 = %d\n", M4_POW(2, 0));
printf("2^1 = %d\n", M4_POW(2, 1));
printf("2^4 = %d\n", M4_POW(2, 4));
return 0;
}
このサンプルコードをコンパイルするためのコマンドラインは、標準入力から読み取るためのGCCおよびM4の能力を使用します。
$ cat foo.c | m4 - | gcc -x c -o m4_pow -
$ ./m4_pow
2^0 = 1
2^1 = 2
2^4 = 16
このヘルプを願っています!
(周り4.3)GCCの最近のバージョンは一定であり、より複雑な機能を評価することによって、いくつかのコンパイル時の最適化を行うためにGMPとMPFRを使用する機能を追加しました。このアプローチは、あなたのコードはシンプルでポータブル葉、および重労働を行うには、コンパイラを信頼します。
もちろん、それは何ができるかには限界があります。 ここではリストが含まのchangelog の中の記述へのリンクですこのことにより、サポートされている機能の。 '捕虜' はそのうち1つです。
場合に使用する必要があり、価値で コンパイル時間, を使用 科学表記法 のように1e2用 pow(10, 2)
したい場合は移植の値はコンパイル時に用後で ランタイム そしてるのは簡単でルックアップテーブルがありますの 23異なる国の10 その 正確にrepresentable double精度で
double POW10[] = {1., 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
き大きな力の10実行時にルックアップテーブルを迅速に結果を得なく掛け算を10までに応じて変更することが可能で近い値電力は10のようなご利用の際は10eX X>22
double pow10(int x)
{
if (x > 22)
return POW10[22] * pow10(x - 22);
else if (x >= 0)
return POW10[x];
else
return 1/pow10(-x);
}
場合は負の指数を必要とせずその最終支店を取り除くことができます。
も軽減できるルックアップテーブルサイズの更なる場合のメモリが与えます。例えば、蓄積だけでも権力の10倍10時の指数が奇数、偶数のテーブルサイズに成立したことによって期待しております。
残念ながら、あなたはライブラリの呼び出しを事前計算するプリプロセッサを使用することはできません。 xが整数である場合は、独自の関数を書くことができ、それは浮動小数点型だ場合、私はこれを行うに何か良い方法は表示されません。
bdonlanのリプレイは、上のスポットが、覚えておいてくださいあなたはほとんどあなたがあなた自身のカスタムプリプロセッサのコードを解析し、解析して喜んで提供されるコンパイルボックスで選択した任意の最適化を行うことができるということです。それは、コンパイラを打つ前に、独自のカスタム・ステップを呼び出すために、コンパイラを呼び出す暗黙のルールを上書きするには、UNIXのほとんどのバージョンに簡単な作業です。