Explicit downcasting to float part 2.

Converting double to half includes an implicit intermediate cast to float.
That cast can be explicit through template specialization.
metadata
Edgar Velazquez-Armendariz 2014-01-26 02:44:12 -05:00
parent 7962cd2e20
commit 13e63e66df
5 changed files with 40 additions and 24 deletions

View File

@ -614,8 +614,8 @@ public:
const Value p11 = evalTexel(level, xPos+1, yPos+1);
Value tmp = p01 + p10 - p11;
gradient[0] = (p10 + p00*(dy-1) - tmp*dy) * size.x;
gradient[1] = (p01 + p00*(dx-1) - tmp*dx) * size.y;
gradient[0] = (p10 + p00*(dy-1) - tmp*dy) * static_cast<Float> (size.x);
gradient[1] = (p01 + p00*(dx-1) - tmp*dx) * static_cast<Float> (size.y);
}
/// \brief Perform a filtered texture lookup using the configured method

View File

@ -67,6 +67,17 @@ extern "C" {
MTS_NAMESPACE_BEGIN
namespace
{
// Safely convert between scalar types avoiding downcasting warning
template <typename T, typename S> inline T safe_cast(S a) {
return static_cast<T>(a);
}
template <> inline half safe_cast(double a) {
return static_cast<half>(static_cast<float>(a));
}
}
#if defined(MTS_HAS_OPENEXR)
/* ========================== *
* EXR helper classes *
@ -869,7 +880,7 @@ void Bitmap::convolve(const Bitmap *_kernel) {
* (double) input[(xs+ys*width)*m_channelCount+ch];
}
}
output[(x+y*width)*m_channelCount+ch] = (half) result;
output[(x+y*width)*m_channelCount+ch] = safe_cast<half>(result);
}
}
}
@ -982,7 +993,7 @@ void Bitmap::scale(Float value) {
half *data = (half *) m_data;
for (size_t i=0; i<nPixels; ++i) {
for (size_t j=0; j<nChannels-1; ++j) {
*data = (half) (*data * value); ++data;
*data = safe_cast<half> (*data * value); ++data;
}
++data;
}
@ -1046,7 +1057,7 @@ void Bitmap::scale(Float value) {
case EFloat16: {
half *data = (half *) m_data;
for (size_t i=0; i<nEntries; ++i)
data[i] = (half) (data[i] * value);
data[i] = safe_cast<half> (data[i] * value);
}
break;
@ -1504,9 +1515,9 @@ template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixe
Z = ratio * ((Float) 1.0f - x - y);
/* Convert from XYZ tristimulus values to ITU-R Rec. BT.709 linear RGB */
data[0] = (T)( 3.240479f * X + -1.537150f * Y + -0.498535f * Z);
data[1] = (T)( -0.969256f * X + 1.875991f * Y + 0.041556f * Z);
data[2] = (T)( 0.055648f * X + -0.204043f * Y + 1.057311f * Z);
data[0] = safe_cast<T>( 3.240479f * X + -1.537150f * Y + -0.498535f * Z);
data[1] = safe_cast<T>( -0.969256f * X + 1.875991f * Y + 0.041556f * Z);
data[2] = safe_cast<T>( 0.055648f * X + -0.204043f * Y + 1.057311f * Z);
data += channels;
}
@ -1531,9 +1542,9 @@ template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixe
X = ratio * x;
Z = ratio * ((Float) 1.0f - x - y);
data[0] = (T) X;
data[1] = (T) Y;
data[2] = (T) Z;
data[0] = safe_cast<T>(X);
data[1] = safe_cast<T>(Y);
data[2] = safe_cast<T>(Z);
data += channels;
}
@ -1544,7 +1555,7 @@ template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixe
Float Lp = (Float) *data * scale;
/* Apply the tonemapping transformation */
*data = (T) (Lp * (1.0f + Lp*invWp2) / (1.0f + Lp));
*data = safe_cast<T> (Lp * (1.0f + Lp*invWp2) / (1.0f + Lp));
data += channels;
}
@ -1795,7 +1806,7 @@ template <typename Scalar> static void resample(ref<const ReconstructionFilter>
+ y * target->getWidth() * channels;
r.resampleAndClamp(srcPtr, 1, trgPtr, 1, channels,
(Scalar) minValue, (Scalar) maxValue);
safe_cast<Scalar>(minValue), safe_cast<Scalar>(maxValue));
}
/* Now, read from the temporary bitmap */
@ -1814,7 +1825,7 @@ template <typename Scalar> static void resample(ref<const ReconstructionFilter>
Scalar *trgPtr = (Scalar *) target->getUInt8Data() + x * channels;
r.resampleAndClamp(srcPtr, source->getWidth(), trgPtr, target->getWidth(),
channels, (Scalar) minValue, (Scalar) maxValue);
channels, safe_cast<Scalar>(minValue), safe_cast<Scalar>(maxValue));
}
}
}
@ -3228,7 +3239,7 @@ void Bitmap::readPFM(Stream *stream) {
}
stream->setByteOrder(backup);
Float scale = std::abs(scaleAndOrder);
const float scale = std::abs(scaleAndOrder);
if (scale != 1) {
for (size_t i=0; i<size; ++i)
data[i] *= scale;

View File

@ -68,13 +68,14 @@ namespace detail {
};
// Safely convert from size_t to other types, avoiding downcasting warning
template <typename T> inline T safe_cast(size_t a) {
template <typename T, typename S> inline T safe_cast(S a) {
return static_cast<T>(a);
}
template <> inline half safe_cast(size_t a) {
float tmp = static_cast<float>(a);
return static_cast<half>(tmp);
return static_cast<half>(static_cast<float>(a));
}
template <> inline half safe_cast(double a) {
return static_cast<half>(static_cast<float>(a));
}
}
@ -1140,10 +1141,10 @@ private:
value = applyGamma(value, invDestGamma);
if (format_traits<DestFmt>::is_float)
return (DestFmt) value;
return detail::safe_cast<DestFmt> (value);
else /* Round to nearest value and clamp to representable range */
return (DestFmt) std::min(static_cast<Float>(std::numeric_limits<DestFmt>::max()),
std::max((Float) 0, value * (Float) std::numeric_limits<DestFmt>::max() + (Float) 0.5f));
return detail::safe_cast<DestFmt> (std::min(static_cast<Float>(std::numeric_limits<DestFmt>::max()),
std::max((Float) 0, value * (Float) std::numeric_limits<DestFmt>::max() + (Float) 0.5f)));
}
};

View File

@ -115,8 +115,8 @@ public:
m_distortion = false;
} else if (kc_tokens.size() == 2) {
char *end_ptr0, *end_ptr1;
m_kc[0] = std::strtod(kc_tokens[0].c_str(), &end_ptr0);
m_kc[1] = std::strtod(kc_tokens[1].c_str(), &end_ptr1);
m_kc[0] = (Float) std::strtod(kc_tokens[0].c_str(), &end_ptr0);
m_kc[1] = (Float) std::strtod(kc_tokens[1].c_str(), &end_ptr1);
if (*end_ptr0 != '\0' || *end_ptr1 != 0)
Log(EError, "Invalid input to the 'kc' parameter!");
m_distortion = m_kc[0] != 0 || m_kc[1] != 0;

View File

@ -299,6 +299,10 @@ public:
value[0] = a; value[1] = b; value[2] = c;
}
inline explicit float3(double a, double b, double c) {
value[0] = (float) a; value[1] = (float) b; value[2] = (float) c;
}
inline float3 operator*(Float v) const {
return float3((float) (value[0]*v), (float) (value[1]*v), (float) (value[2]*v));
}