使用哪种算法在GNU C ++标准库中计算指数函数?

时间:2018-04-21 20:36:18

标签: c++ gnu libstdc++ exponentiation

请考虑C ++ std::exp库中标题cmath中定义的numerics。现在,请考虑C ++标准库的实现,比如说libstdc++

考虑有各种算法来计算基本函数,例如计算指数函数的arithmetic-geometric mean iteration algorithm和显示here的其他三个;

如果可能的话,你能否指出libstdc++中用于计算指数函数的特定算法?

PS:我无法确定包含std :: exp实现的正确tar包还是理解相关的文件内容,我担心。

1 个答案:

答案 0 :(得分:2)

它根本不使用任何复杂的算法。请注意,# models.py---------------------------------------------------- class Ingredient(models.Model): name = models.CharField(unique=True, max_length=30) alcoholic = models.BooleanField(null=False, default=True) def __str__(self): return self.name class Cocktail(models.Model): name = models.CharField(unique=True, max_length=30) garnish = models.CharField(max_length=30) recipe = models.ManyToManyField(Ingredient, through='IngredientAmount') def __str__(self): return self.name class IngredientAmount(models.Model): cocktail = models.ForeignKey(Cocktail, on_delete=models.CASCADE) ingredients = models.ForeignKey(Ingredient, on_delete=models.CASCADE) amount_in_oz = models.FloatField(null=False) def __float__(self): return self.amount_in_oz # admin.py----------------------------------------------------- class CocktailAdmin(admin.ModelAdmin): fields = (('name', 'garnish'), ) filter_horizontal = ('recipe', ) # Ideally, this line would have allowed it. admin.site.register(Ingredient) admin.site.register(Cocktail, CocktailAdmin) 仅针对数量非常有限的类型定义:std::expfloatdouble +任何可投放到long double的积分类型。这使得没有必要实现复杂的数学。

目前,它使用内置double,可以从the source code进行验证。这会编译为我的计算机上的__builtin_expf来电,这是来自expf的来自libm的来电。让我们看看我们在他们的source code中找到了什么。当我们搜索glibc时,我们发现这内部调用expf,这是一个依赖于系统的实现。 i686和x86_64都只包含一个__ieee754_expf,它最终为我们提供了一个实现(为简洁而简化,外观into the sources

它基本上是浮点数的3阶多项式逼近:

glibc/sysdeps/ieee754/flt-32/e_expf.c

同样地,对于128位static inline uint32_t top12 (float x) { return asuint (x) >> 20; } float __expf (float x) { uint64_t ki, t; /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ double_t kd, xd, z, r, r2, y, s; xd = (double_t) x; // [...] skipping fast under/overflow handling /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k. */ z = InvLn2N * xd; /* Round and convert z to int, the result is in [-150*N, 128*N] and ideally ties-to-even rule is used, otherwise the magnitude of r can be bigger which gives larger approximation error. */ kd = roundtoint (z); ki = converttoint (z); r = z - kd; /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ t = T[ki % N]; t += ki << (52 - EXP2F_TABLE_BITS); s = asdouble (t); z = C[0] * r + C[1]; r2 = r * r; y = C[2] * r + 1; y = z * r2 + y; y = y * s; return (float) y; } ,它是order 7 approximationlong double他们使用more complicated algorithm,我无法理解现在。