fix exp/log performance-related issues on Linux/x86_64

metadata
Wenzel Jakob 2011-09-09 16:53:36 -04:00
parent 56cf1882fd
commit 999540bfcf
24 changed files with 110 additions and 64 deletions

View File

@ -51,9 +51,9 @@ public:
m_points.clear();
m_points.reserve(m_size.x*m_size.y);
m_size = size; m_pos = PointType(0);
const Float invLog2 = (Float) 1 / std::log((Float) 2);
const Float invLog2 = (Float) 1 / std::fastlog((Float) 2);
generate(
(int) std::ceil(invLog2 * std::log((Float) std::max(m_size.x, m_size.y))),
(int) std::ceil(invLog2 * std::fastlog((Float) std::max(m_size.x, m_size.y))),
ENorth, EEast, ESouth, EWest);
}

View File

@ -512,7 +512,7 @@ public:
inline Spectrum exp() const {
Spectrum value;
for (int i=0; i<SPECTRUM_SAMPLES; i++)
value.s[i] = std::exp(s[i]);
value.s[i] = std::fastexp(s[i]);
return value;
}

View File

@ -94,6 +94,49 @@ using std::compose1;
#endif
namespace std {
#if defined(__LINUX__) && defined(__x86_64__)
/*
The Linux/x86_64 single precision implementations of 'exp'
and 'log' suffer from a serious performance regression.
It is about 5x faster to use the double-precision versions
with the extra overhead of the involved FP conversion.
Until this is fixed, the following aliases make sure that
the fastest implementation is used in every case.
*/
inline float fastexp(float value) {
return (float) ::exp((double) value);
}
inline double fastexp(double value) {
return ::exp(value);
}
inline float fastlog(float value) {
return (float) ::log((double) value);
}
inline double fastlog(double value) {
return ::log(value);
}
#else
inline float fastexp(float value) {
return ::expf(value);
}
inline double fastexp(double value) {
return ::exp(value);
}
inline float fastlog(float value) {
return ::logf(value);
}
inline double fastlog(double value) {
return ::log(value);
}
#endif
#if defined(_GNU_SOURCE)
inline void sincos(float theta, float *sin, float *cos) {
::sincosf(theta, sin, cos);
@ -102,17 +145,18 @@ namespace std {
inline void sincos(double theta, double *sin, double *cos) {
::sincos(theta, sin, cos);
}
#else
inline void sincos(float theta, float *_sin, float *_cos) {
float sinValue = sinf(theta);
*_sin = sinValue;
*_cos = sqrtf(1.0f-sinValue*sinValue);
*_cos = sqrtf(std::max(0.0f, 1.0f-sinValue*sinValue));
}
inline void sincos(double theta, double *_sin, double *_cos) {
double sinValue = sin(theta);
*_sin = sinValue;
*_cos = sqrt(1.0-sinValue*sinValue);
*_cos = sqrt(std::max(0.0, 1.0-sinValue*sinValue));
}
#endif
};

View File

@ -258,7 +258,7 @@ public:
ref<Random> random = new Random(seed);
Float xi = random->nextFloat();
intensityVariation = std::min(-std::log(xi), (Float) 10.0f);
intensityVariation = std::min(-std::fastlog(xi), (Float) 10.0f);
}
result = yarn.ks * (intensityVariation * m_ksMultiplier * integrand);
@ -545,7 +545,7 @@ public:
}
inline Float atanh(Float arg) const {
return std::log((1.0f + arg) / (1.0f - arg)) / 2.0f;
return std::fastlog((1.0f + arg) / (1.0f - arg)) / 2.0f;
}
// von Mises Distribution
@ -560,12 +560,12 @@ public:
+ t*(0.2659732f + t*(0.0360768f + t*0.0045813f)))));
} else {
Float t = 3.75f / absB;
I0 = std::exp(absB) / std::sqrt(absB) * (0.39894228f + t*(0.01328592f
I0 = std::fastexp(absB) / std::sqrt(absB) * (0.39894228f + t*(0.01328592f
+ t*(0.00225319f + t*(-0.00157565f + t*(0.00916281f + t*(-0.02057706f
+ t*(0.02635537f + t*(-0.01647633f + t*0.00392377f))))))));
}
return std::exp(b * cos_x) / (2 * M_PI * I0);
return std::fastexp(b * cos_x) / (2 * M_PI * I0);
}
/// Attenuation term

View File

@ -117,7 +117,7 @@ public:
case EBeckmann: {
/* Beckmann distribution function for Gaussian random surfaces */
const Float ex = Frame::tanTheta(m) / alphaU;
result = std::exp(-(ex*ex)) / (M_PI * alphaU*alphaU *
result = std::fastexp(-(ex*ex)) / (M_PI * alphaU*alphaU *
std::pow(Frame::cosTheta(m), (Float) 4.0f));
}
break;
@ -244,7 +244,7 @@ public:
switch (m_type) {
case EBeckmann: {
Float tanThetaMSqr = -alphaU*alphaU * std::log(1.0f - sample.x);
Float tanThetaMSqr = -alphaU*alphaU * std::fastlog(1.0f - sample.x);
cosThetaM = 1.0f / std::sqrt(1 + tanThetaMSqr);
}
break;
@ -310,7 +310,7 @@ public:
switch (m_type) {
case EBeckmann: {
Float tanThetaMSqr = -alphaU*alphaU * std::log(1.0f - sample.x);
Float tanThetaMSqr = -alphaU*alphaU * std::fastlog(1.0f - sample.x);
cosThetaM = 1.0f / std::sqrt(1 + tanThetaMSqr);
Float cosThetaM2 = cosThetaM * cosThetaM,
cosThetaM3 = cosThetaM2 * cosThetaM;

View File

@ -210,7 +210,7 @@ public:
Float factor2 = H.x / alphaU, factor3 = H.y / alphaV;
Float exponent = -(factor2*factor2+factor3*factor3)/(H.z*H.z);
Float specRef = factor1 * std::exp(exponent);
Float specRef = factor1 * std::fastexp(exponent);
/* Important to prevent numeric issues when evaluating the
sampling density of the Ward model in places where it takes
on miniscule values (Veach-MLT does this for instance) */
@ -245,7 +245,7 @@ public:
Float factor2 = H.x / alphaU, factor3 = H.y / alphaV;
Float exponent = -(factor2*factor2+factor3*factor3)/(H.z*H.z);
specProb = factor1 * std::exp(exponent);
specProb = factor1 * std::fastexp(exponent);
}
if (hasDiffuse)
@ -298,7 +298,7 @@ public:
1.0f-cosPhiH*cosPhiH));
Float thetaH = std::atan(std::sqrt(std::max((Float) 0.0f,
-std::log(sample.x) / (
-std::fastlog(sample.x) / (
(cosPhiH*cosPhiH) / (alphaU*alphaU) +
(sinPhiH*sinPhiH) / (alphaV*alphaV)
))));

View File

@ -265,10 +265,10 @@ public:
Float invWeight = 1.0f;
if (pixel.weight != 0.0f)
invWeight = 1.0f / pixel.weight;
avgLogLuminance += std::log(0.001f + (pixel.spec * invWeight).getLuminance());
avgLogLuminance += std::fastlog(0.001f + (pixel.spec * invWeight).getLuminance());
}
}
avgLogLuminance = std::exp(avgLogLuminance/(m_cropSize.x*m_cropSize.y));
avgLogLuminance = std::fastexp(avgLogLuminance/(m_cropSize.x*m_cropSize.y));
reinhardKey = m_reinhardKey / avgLogLuminance;
reinhard = true;
pos = 0;

View File

@ -86,6 +86,8 @@ BeamRadianceEstimator::BeamRadianceEstimator(Stream *stream, InstanceManager *ma
}
void BeamRadianceEstimator::serialize(Stream *stream, InstanceManager *manager) const {
Log(EDebug, "Serializing a BRE data structure (%s)",
memString(m_photonCount * sizeof(BRENode)).c_str());
stream->writeSize(m_photonCount);
stream->writeSize(m_depth);
stream->writeFloat(m_scaleFactor);

View File

@ -435,7 +435,7 @@ Float BlackBodySpectrum::eval(Float l) const {
/* Watts per unit surface area (m^-2) per unit wavelength (nm^-1) per
steradian (sr^-1) */
const double I = (2*h*c*c) * std::pow(lambda, -5.0)
/ ((std::exp((h/k)*c/(lambda*m_temperature)) - 1.0) * 1e9);
/ ((std::fastexp((h/k)*c/(lambda*m_temperature)) - 1.0) * 1e9);
return (Float) I;
}
@ -463,7 +463,7 @@ RayleighSpectrum::RayleighSpectrum(EMode mode, Float eta, Float height) {
/* See ``Display of the Earth Taking into Account Atmospheric Scattering'',
* by Nishita et al., SIGGRAPH 1993 */
Float tmp = eta * eta - 1;
Float rho = std::exp(-height/7794.0f);
Float rho = std::fastexp(-height/7794.0f);
//Float Ns = <molecular number density of the standard atmosphere>;
Float N_s = 1;
Float K = 2 * M_PI * M_PI * tmp*tmp / (3 * N_s);

View File

@ -365,8 +365,8 @@ std::string getFQDN() {
}
Float log2(Float value) {
const Float invLn2 = (Float) 1.0f / std::log((Float) 2.0f);
return std::log(value) * invLn2;
const Float invLn2 = (Float) 1.0f / std::fastlog((Float) 2.0f);
return std::fastlog(value) * invLn2;
}
std::string formatString(const char *fmt, ...) {
@ -703,7 +703,7 @@ Vector squareToCone(Float cosCutoff, const Point2 &sample) {
}
Point2 squareToStdNormal(const Point2 &sample) {
Float r = std::sqrt(-2 * std::log(1-sample.x)),
Float r = std::sqrt(-2 * std::fastlog(1-sample.x)),
phi = 2 * M_PI * sample.y;
Point2 result;
std::sincos(phi, &result.y, &result.x);

View File

@ -119,7 +119,7 @@ MIPMap::MIPMap(int width, int height, Spectrum *pixels,
m_weightLut = static_cast<Float *>(allocAligned(sizeof(Float)*MIPMAP_LUTSIZE));
for (int i=0; i<MIPMAP_LUTSIZE; ++i) {
Float pos = (Float) i / (Float) (MIPMAP_LUTSIZE-1);
m_weightLut[i] = std::exp(-2.0f * pos) - std::exp(-2.0f);
m_weightLut[i] = std::fastexp(-2.0f * pos) - std::fastexp(-2.0f);
}
}
}

View File

@ -42,8 +42,8 @@ PhotonMap::PhotonMap(Stream *stream, InstanceManager *manager)
}
void PhotonMap::serialize(Stream *stream, InstanceManager *manager) const {
Log(EDebug, "Serializing a photon map (%.2f KB)",
m_kdtree.size() * sizeof(Photon) / 1024.0f);
Log(EDebug, "Serializing a photon map (%s)",
memString(m_kdtree.size() * sizeof(Photon)).c_str());
stream->writeFloat(m_scale);
stream->writeSize(m_kdtree.size());
stream->writeSize(m_kdtree.getDepth());

View File

@ -333,13 +333,13 @@ private:
inline Float getDistribution(const Float *lam, const Float theta,
const Float gamma) const {
const Float cosGamma = std::cos(gamma);
const Float num = ((1 + lam[0] * std::exp(lam[1] / std::cos(theta)))
* (1 + lam[2] * std::exp(lam[3] * gamma)
const Float num = ((1 + lam[0] * std::fastexp(lam[1] / std::cos(theta)))
* (1 + lam[2] * std::fastexp(lam[3] * gamma)
+ lam[4] * cosGamma * cosGamma));
const Float cosTheta = std::cos(m_thetaS);
const Float den = ( (1 + lam[0] * std::exp(lam[1] /* / cos 0 */))
* (1 + lam[2] * std::exp(lam[3] * m_thetaS)
const Float den = ( (1 + lam[0] * std::fastexp(lam[1] /* / cos 0 */))
* (1 + lam[2] * std::fastexp(lam[3] * m_thetaS)
+ lam[4] * cosTheta * cosTheta));
return num / den;

View File

@ -190,7 +190,7 @@ Spectrum computeSunRadiance(Float theta, Float turbidity) {
for(i = 0, lambda = 350; i < 91; i++, lambda+=5) {
// Rayleigh Scattering
// Results agree with the graph (pg 115, MI) */
Float tauR = std::exp(-m * 0.008735f * std::pow(lambda/1000.0f, (Float) -4.08));
Float tauR = std::fastexp(-m * 0.008735f * std::pow(lambda/1000.0f, (Float) -4.08));
// Aerosal (water + dust) attenuation
// beta - amount of aerosols present
@ -203,18 +203,18 @@ Spectrum computeSunRadiance(Float theta, Float turbidity) {
// lOzone - amount of ozone in cm(NTP)
// Results agree with the graph (pg 128, MI)
const Float lOzone = .35f;
Float tauO = std::exp(-m * k_oCurve.eval(lambda) * lOzone);
Float tauO = std::fastexp(-m * k_oCurve.eval(lambda) * lOzone);
// Attenuation due to mixed gases absorption
// Results agree with the graph (pg 131, MI)
Float tauG = std::exp(-1.41f * k_gCurve.eval(lambda) * m / std::pow(1 + 118.93f
Float tauG = std::fastexp(-1.41f * k_gCurve.eval(lambda) * m / std::pow(1 + 118.93f
* k_gCurve.eval(lambda) * m, (Float) 0.45f));
// Attenuation due to water vapor absorbtion
// w - precipitable water vapor in centimeters (standard = 2)
// Results agree with the graph (pg 132, MI)
const Float w = 2.0;
Float tauWA = std::exp(-0.2385f * k_waCurve.eval(lambda) * w * m /
Float tauWA = std::fastexp(-0.2385f * k_waCurve.eval(lambda) * w * m /
std::pow(1 + 20.07f * k_waCurve.eval(lambda) * w * m, (Float) 0.45f));
data[i] = (Float) 100.0f * solCurve.eval(lambda) * tauR * tauA * tauO * tauG * tauWA;

View File

@ -330,7 +330,7 @@ public:
+ lookupDensity(pLast, ray.d);
#if defined(HETVOL_EARLY_EXIT)
const Float stopAfterDensity = -std::log(Epsilon);
const Float stopAfterDensity = -std::fastlog(Epsilon);
const Float stopValue = stopAfterDensity*3.0f/(stepSize
* m_densityMultiplier);
#endif
@ -541,7 +541,7 @@ public:
Spectrum getTransmittance(const Ray &ray, Sampler *sampler) const {
if (m_method == ESimpsonQuadrature || sampler == NULL) {
return Spectrum(std::exp(-integrateDensity(ray)));
return Spectrum(std::fastexp(-integrateDensity(ray)));
} else {
/* When Woodcock tracking is selected as the sampling method,
we can use this method to get a noisy estimate of
@ -561,7 +561,7 @@ public:
for (int i=0; i<nSamples; ++i) {
Float t = mint;
while (true) {
t -= std::log(1-sampler->next1D()) * m_invMaxDensity;
t -= std::fastlog(1-sampler->next1D()) * m_invMaxDensity;
if (t >= maxt) {
result += 1;
break;
@ -588,7 +588,7 @@ public:
bool success = false;
if (m_method == ESimpsonQuadrature) {
Float desiredDensity = -std::log(1-sampler->next1D());
Float desiredDensity = -std::fastlog(1-sampler->next1D());
if (invertDensityIntegral(ray, desiredDensity, integratedDensity,
mRec.t, densityAtMinT, densityAtT)) {
mRec.p = ray(mRec.t);
@ -601,7 +601,7 @@ public:
? m_orientation->lookupVector(mRec.p) : Vector(0.0f);
}
Float expVal = std::exp(-integratedDensity);
Float expVal = std::fastexp(-integratedDensity);
mRec.pdfFailure = expVal;
mRec.pdfSuccess = expVal * densityAtT;
mRec.pdfSuccessRev = expVal * densityAtMinT;
@ -626,7 +626,7 @@ public:
Float t = mint, densityAtT = 0;
while (true) {
t -= std::log(1-sampler->next1D()) * m_invMaxDensity;
t -= std::fastlog(1-sampler->next1D()) * m_invMaxDensity;
if (t >= maxt)
break;
@ -656,7 +656,7 @@ public:
void pdfDistance(const Ray &ray, MediumSamplingRecord &mRec) const {
if (m_method == ESimpsonQuadrature) {
Float expVal = std::exp(-integrateDensity(ray));
Float expVal = std::fastexp(-integrateDensity(ray));
mRec.transmittance = Spectrum(expVal);
mRec.pdfFailure = expVal;

View File

@ -250,7 +250,7 @@ public:
Spectrum transmittance;
for (size_t i=0; i<SPECTRUM_SAMPLES; ++i)
transmittance[i] = m_sigmaT[i] != 0
? std::exp(m_sigmaT[i] * negLength) : (Float) 1.0f;
? std::fastexp(m_sigmaT[i] * negLength) : (Float) 1.0f;
return transmittance;
}
@ -267,7 +267,7 @@ public:
* SPECTRUM_SAMPLES), SPECTRUM_SAMPLES-1);
samplingDensity = m_sigmaT[channel];
}
sampledDistance = -std::log(1-rand) / samplingDensity;
sampledDistance = -std::fastlog(1-rand) / samplingDensity;
} else {
sampledDistance = m_maxExpDist->sample(1-rand, mRec.pdfSuccess);
}
@ -299,7 +299,7 @@ public:
mRec.pdfFailure = 0;
mRec.pdfSuccess = 0;
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
Float tmp = std::exp(-m_sigmaT[i] * sampledDistance);
Float tmp = std::fastexp(-m_sigmaT[i] * sampledDistance);
mRec.pdfFailure += tmp;
mRec.pdfSuccess += m_sigmaT[i] * tmp;
}
@ -309,7 +309,7 @@ public:
case ESingle:
case EManual:
mRec.pdfFailure = std::exp(-samplingDensity * sampledDistance);
mRec.pdfFailure = std::fastexp(-samplingDensity * sampledDistance);
mRec.pdfSuccess = samplingDensity * mRec.pdfFailure;
break;
@ -329,7 +329,7 @@ public:
switch (m_strategy) {
case EManual:
case ESingle: {
Float temp = std::exp(-m_samplingDensity * distance);
Float temp = std::fastexp(-m_samplingDensity * distance);
mRec.pdfSuccess = m_samplingDensity * temp;
mRec.pdfFailure = temp;
}
@ -339,7 +339,7 @@ public:
mRec.pdfSuccess = 0;
mRec.pdfFailure = 0;
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
Float temp = std::exp(-m_sigmaT[i] * distance);
Float temp = std::fastexp(-m_sigmaT[i] * distance);
mRec.pdfSuccess += m_sigmaT[i] * temp;
mRec.pdfFailure += temp;
}

View File

@ -41,7 +41,7 @@ public:
/* Store the interval covered by each f_i */
m_intervalStart[i] = (i == 0) ? 0
: std::log(m_sigmaT[i]/m_sigmaT[i-1]) / (m_sigmaT[i]-m_sigmaT[i-1]);
: std::fastlog(m_sigmaT[i]/m_sigmaT[i-1]) / (m_sigmaT[i]-m_sigmaT[i-1]);
}
/* Turn into a discrete CDF and keep the normalization factor */
@ -59,11 +59,11 @@ public:
SAssert(index >= 0 && index < (int) m_sigmaT.size());
/* Sample according to f_i */
Float t = -std::log(std::exp(-m_intervalStart[index] * m_sigmaT[index])
Float t = -std::fastlog(std::fastexp(-m_intervalStart[index] * m_sigmaT[index])
- m_normalization * (u - m_cdf[index])) / m_sigmaT[index];
/* Compute the probability of this sample */
pdf = m_sigmaT[index] * std::exp(-m_sigmaT[index] * t) * m_invNormalization;
pdf = m_sigmaT[index] * std::fastexp(-m_sigmaT[index] * t) * m_invNormalization;
return t;
}
@ -73,7 +73,7 @@ public:
&m_intervalStart[m_intervalStart.size()], t);
int index = std::max(0, (int) (lowerBound - &m_intervalStart[0]) - 1);
SAssert(index >= 0 && index < (int) m_sigmaT.size());
return m_sigmaT[index] * std::exp(-m_sigmaT[index] * t) * m_invNormalization;
return m_sigmaT[index] * std::fastexp(-m_sigmaT[index] * t) * m_invNormalization;
}
Float cdf(Float t) const {
@ -84,7 +84,7 @@ public:
Float lower = (index==0) ? -1 : -std::pow((m_sigmaT[index]/m_sigmaT[index-1]),
-m_sigmaT[index] / (m_sigmaT[index]-m_sigmaT[index-1]));
Float upper = -std::exp(-m_sigmaT[index] * t);
Float upper = -std::fastexp(-m_sigmaT[index] * t);
return m_cdf[index] + (upper - lower) * m_invNormalization;
}

View File

@ -850,7 +850,7 @@ Float GLWidget::autoFocus() const {
radicalInverse(3, sampleIndex) * filmSize.y);
scene->getCamera()->generateRay(sample, Point2(0, 0), 0, ray);
if (scene->rayIntersect(ray, t, ptr, n)) {
Float weight = std::exp(-0.5 / variance * (
Float weight = std::fastexp(-0.5 / variance * (
std::pow(sample.x - filmSize.x / (Float) 2, (Float) 2) +
std::pow(sample.y - filmSize.y / (Float) 2, (Float) 2)));
avgDistance += t * weight;
@ -1101,7 +1101,7 @@ void GLWidget::paintGL() {
m_downsamplingProgram->unbind();
Float logLuminance, maxLuminance, unused;
m_luminanceBuffer[target]->getPixel(0, 0).toLinearRGB(logLuminance, maxLuminance, unused);
logLuminance = std::exp(logLuminance / (size.x*size.y));
logLuminance = std::fastexp(logLuminance / (size.x*size.y));
if (mts_isnan(logLuminance) || std::isinf(logLuminance)) {
SLog(EWarn, "Could not determine the average log-luminance, since the image contains NaNs/infs/negative values");
logLuminance = 1;

View File

@ -1369,10 +1369,10 @@ void MainWindow::onExportDialogClose(int reason) {
Spectrum spec;
spec.fromLinearRGB(source[(y*width+x)*4+0],
source[(y*width+x)*4+1], source[(y*width+x)*4+2]);
avgLogLuminance += std::log(0.001f+spec.getLuminance());
avgLogLuminance += std::fastlog(0.001f+spec.getLuminance());
}
}
avgLogLuminance = std::exp(avgLogLuminance/(width*height));
avgLogLuminance = std::fastexp(avgLogLuminance/(width*height));
reinhardKey = ctx->reinhardKey / avgLogLuminance;
}

View File

@ -242,13 +242,13 @@ public:
/// Evaluate the density as a function of \cos\theta
inline Float pdfCosTheta(Float cosTheta) const {
return std::exp(-cosTheta*cosTheta
return std::fastexp(-cosTheta*cosTheta
/ (2*m_stddev*m_stddev)) * m_normalization;
}
/// Evaluate the density as a function of direction
inline Float pdf(const Vector &d) const {
return std::exp(-d.z*d.z
return std::fastexp(-d.z*d.z
/ (2*m_stddev*m_stddev)) * m_normalization;
}

View File

@ -39,7 +39,7 @@ public:
m_size = Vector2(halfSize, halfSize);
/* Negative offset pre-computation */
m_const = std::exp(-m_alpha * m_size.x * m_size.x);
m_const = std::fastexp(-m_alpha * m_size.x * m_size.x);
}
GaussianFilter(Stream *stream, InstanceManager *manager)
@ -61,8 +61,8 @@ public:
}
Float evaluate(Float x, Float y) const {
return std::max((Float) 0.0f, std::exp(-m_alpha * x * x) - m_const)
* std::max((Float) 0.0f, std::exp(-m_alpha * y * y) - m_const);
return std::max((Float) 0.0f, std::fastexp(-m_alpha * x * x) - m_const)
* std::max((Float) 0.0f, std::fastexp(-m_alpha * y * y) - m_const);
}
MTS_DECLARE_CLASS()

View File

@ -71,8 +71,8 @@ struct AnisotropicDipoleQuery {
Float zr = -xr[i].z, zv = xv[i].z;
temp[i] = detP[i]/(4*M_PI) * (
zr*(beta[i]*dr+1)*std::exp(-beta[i]*dr)/(dr*dr*dr) +
zv*(beta[i]*dv+1)*std::exp(-beta[i]*dv)/(dv*dv*dv)
zr*(beta[i]*dr+1)*std::fastexp(-beta[i]*dr)/(dr*dr*dr) +
zv*(beta[i]*dv+1)*std::fastexp(-beta[i]*dv)/(dv*dv*dv)
);
}
dMo.fromLinearRGB(temp[0], temp[1], temp[2]);

View File

@ -39,7 +39,7 @@ public:
}
inline Float gauss3(Vector x, Float stddev) const {
return std::exp(-0.5f * dot(x, x)/stddev)/(std::pow(2*M_PI * stddev, (Float) 3 / (Float) 2));
return std::fastexp(-0.5f * dot(x, x)/stddev)/(std::pow(2*M_PI * stddev, (Float) 3 / (Float) 2));
}
void testF3(size_t nPoints, const Float *in, Float *out) const {

View File

@ -52,7 +52,7 @@ public:
for (int i=0; i<(int) nPts; ++i) {
Vector d = sphericalDirection(in[2*i], in[2*i+1]);
Float sinTheta = std::sin(in[2*i]);
Float D = sinTheta * std::exp(-std::pow(d.z, 2)/(2*m_gamma*m_gamma)) /
Float D = sinTheta * std::fastexp(-std::pow(d.z, 2)/(2*m_gamma*m_gamma)) /
(std::pow(2*M_PI, (Float) 3 / (Float) 2) * m_gamma * erf(1/(std::sqrt(2)*m_gamma)));
for (size_t j=0; j<m_res; ++j)
out[j*nPts+i] = D * absDot(d, m_directions[j]);