DEAL_II_NAMESPACE_OPEN
+/**
+ * Helper struct to tell us if we can use SIMD instructions for the given @p
+ * Number type.
+ */
+template <typename Number>
+struct EnableOpenMPSimdFor
+{
+ static const bool value = true;
+};
+
+#ifdef __INTEL_COMPILER
+// Disable long double SIMD instructions on ICC. This is to work around a bug
+// that generates wrong code at least up to intel 15 (see
+// tests/lac/vector-vector, tests/lac/intel-15-bug, and the discussion at
+// https://github.com/dealii/dealii/issues/598).
+template <>
+struct EnableOpenMPSimdFor<long double>
+{
+ static const bool value = false;
+};
+#endif
+
namespace internal
{
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] *= factor;
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] *= factor;
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] *= factor;
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] += factor*v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] += factor*v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] += factor*v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = x*val[i] + a*v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + a*v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + a*v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] -= v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] -= v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] -= v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] += factor;
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] += factor;
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] += factor;
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] += v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] += v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] += v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = val[i] + a*v_val[i] + b*w_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = val[i] + a*v_val[i] + b*w_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = val[i] + a*v_val[i] + b*w_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = x*val[i] + v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = x*val[i] + a*v_val[i] + b*w_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + a*v_val[i] + b*w_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = x*val[i] + a*v_val[i] + b*w_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] *= v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] *= v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] *= v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = a*u_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = a*u_val[i] + b*v_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i] + b*v_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i] + b*v_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = a*u_val[i] + b*v_val[i] + c*w_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i] + b*v_val[i] + c*w_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a*u_val[i] + b*v_val[i] + c*w_val[i];
+ }
}
};
void operator() (const size_type begin, const size_type end) const
{
- DEAL_II_OPENMP_SIMD_PRAGMA
- for (size_type i=begin; i<end; ++i)
- val[i] = a_val[i]/b_val[i];
+ if (EnableOpenMPSimdFor<Number>::value)
+ {
+ DEAL_II_OPENMP_SIMD_PRAGMA
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a_val[i]/b_val[i];
+ }
+ else
+ {
+ for (size_type i=begin; i<end; ++i)
+ val[i] = a_val[i]/b_val[i];
+ }
}
};