template <int dim, typename Number> class Point;
template <int rank_, int dim, typename Number = double> class Tensor;
template <typename Number> class Vector;
+template <typename Number> class VectorizedArray;
#ifndef DOXYGEN
// Overload invalid tensor types of negative rank that come up during
* Constructor, where the data is copied from a C-style array.
*/
template <typename OtherNumber>
- Tensor (const OtherNumber initializer);
+ Tensor (const OtherNumber &initializer);
/**
* Return a reference to the encapsulated Number object. Since rank-0
* @ingroup CUDAWrappers
*/
template <typename OtherNumber>
- DEAL_II_CUDA_HOST_DEV Tensor<0,dim,Number> &operator *= (const OtherNumber factor);
+ DEAL_II_CUDA_HOST_DEV Tensor<0,dim,Number> &operator *= (const OtherNumber &factor);
/**
* Divide the scalar by <tt>factor</tt>.
*/
template <typename OtherNumber>
- Tensor<0,dim,Number> &operator /= (const OtherNumber factor);
+ Tensor<0,dim,Number> &operator /= (const OtherNumber &factor);
/**
* Tensor with inverted entries.
* value allowed for <tt>d</tt>, allowing the intuitive notation
* <tt>t=0</tt> to reset all elements of the tensor to zero.
*/
- Tensor<rank_,dim,Number> &operator = (const Number d);
+ Tensor<rank_,dim,Number> &operator = (const Number &d);
/**
* Test for equality of two tensors.
* @ingroup CUDAWrappers
*/
template <typename OtherNumber>
- DEAL_II_CUDA_HOST_DEV Tensor<rank_,dim,Number> &operator *= (const OtherNumber factor);
+ DEAL_II_CUDA_HOST_DEV Tensor<rank_,dim,Number> &operator *= (const OtherNumber &factor);
/**
* Scale the vector by <tt>1/factor</tt>.
*/
template <typename OtherNumber>
- Tensor<rank_,dim,Number> &operator /= (const OtherNumber factor);
+ Tensor<rank_,dim,Number> &operator /= (const OtherNumber &factor);
/**
* Unary minus operator. Negate all entries of a tensor.
};
+namespace internal
+{
+ /**
+ * The structs below are needed since VectorizedArray<T1> is a POD-type without a constructor and
+ * can be a template argument for Tensor<...,T2> where T2 would equal Tensor<1, dim, VectorizedArray >.
+ * Internally, in previous versions of deal.II, Tensor<...,T2> would make use of the constructor
+ * of T2 leading to a compile-time error. However simply adding a constructor for VectorizedArray<T1>
+ * breaks the POD-idioms needed elsewhere. Calls to constructors of T2 subsequently got replaced by a
+ * call to internal::NumberType<T2> which then determines the right function to use by template deduction.
+ * A detailed discussion can be found at https://github.com/dealii/dealii/pull/3967 . Also see
+ * numbers.h for another specialization.
+ */
+ template <int rank, int dim, typename T>
+ struct NumberType<Tensor<rank,dim,T> >
+ {
+ static Tensor<rank,dim,T> value (const T &t)
+ {
+ Tensor<rank,dim,T> tmp;
+ tmp=t;
+ return tmp;
+ }
+ };
+
+ template <int rank, int dim, typename T>
+ struct NumberType<Tensor<rank,dim,VectorizedArray<T> > >
+ {
+ static Tensor<rank,dim,VectorizedArray<T> > value (const T &t)
+ {
+ Tensor<rank,dim,VectorizedArray<T> > tmp;
+ tmp=internal::NumberType<VectorizedArray<T> >::value(t);
+ return tmp;
+ }
+ };
+}
+
+
/*---------------------- Inline functions: Tensor<0,dim> ---------------------*/
template <int dim,typename Number>
inline
DEAL_II_CUDA_HOST_DEV Tensor<0,dim,Number>::Tensor ()
- : value()
+// Some auto-differentiable numbers need explicit
+// zero initialization.
+ : value(internal::NumberType<Number>::value(0.0))
{
}
template <int dim, typename Number>
template <typename OtherNumber>
inline
-Tensor<0,dim,Number>::Tensor (const OtherNumber initializer)
+Tensor<0,dim,Number>::Tensor (const OtherNumber &initializer)
{
value = initializer;
}
template <int dim, typename Number>
template <typename OtherNumber>
inline
-DEAL_II_CUDA_HOST_DEV Tensor<0,dim,Number> &Tensor<0,dim,Number>::operator *= (const OtherNumber s)
+DEAL_II_CUDA_HOST_DEV Tensor<0,dim,Number> &Tensor<0,dim,Number>::operator *= (const OtherNumber &s)
{
value *= s;
return *this;
template <int dim, typename Number>
template <typename OtherNumber>
inline
-Tensor<0,dim,Number> &Tensor<0,dim,Number>::operator /= (const OtherNumber s)
+Tensor<0,dim,Number> &Tensor<0,dim,Number>::operator /= (const OtherNumber &s)
{
value /= s;
return *this;
inline
void Tensor<0,dim,Number>::clear ()
{
- value = value_type();
+ // Some auto-differentiable numbers need explicit
+ // zero initialization.
+ value = internal::NumberType<Number>::value(0.0);
}
template <int rank_, int dim, typename Number>
inline
Tensor<rank_,dim,Number> &
-Tensor<rank_,dim,Number>::operator = (const Number d)
+Tensor<rank_,dim,Number>::operator = (const Number &d)
{
- Assert (d == Number(), ExcMessage ("Only assignment with zero is allowed"));
+ Assert (d == internal::NumberType<Number>::value(0.0),
+ ExcMessage ("Only assignment with zero is allowed"));
(void) d;
for (unsigned int i=0; i<dim; ++i)
- values[i] = Number();
+ values[i] = internal::NumberType<Number>::value(0.0);
return *this;
}
inline
DEAL_II_CUDA_HOST_DEV
Tensor<rank_,dim,Number> &
-Tensor<rank_,dim,Number>::operator *= (const OtherNumber s)
+Tensor<rank_,dim,Number>::operator *= (const OtherNumber &s)
{
for (unsigned int i=0; i<dim; ++i)
values[i] *= s;
template <typename OtherNumber>
inline
Tensor<rank_,dim,Number> &
-Tensor<rank_,dim,Number>::operator /= (const OtherNumber s)
+Tensor<rank_,dim,Number>::operator /= (const OtherNumber &s)
{
for (unsigned int i=0; i<dim; ++i)
values[i] /= s;
typename numbers::NumberTraits<Number>::real_type
Tensor<rank_,dim,Number>::norm_square () const
{
- typename numbers::NumberTraits<Number>::real_type s = typename numbers::NumberTraits<Number>::real_type();
+ typename numbers::NumberTraits<Number>::real_type s
+ = internal::NumberType<typename numbers::NumberTraits<Number>::real_type>::value(0.0);
for (unsigned int i=0; i<dim; ++i)
s += values[i].norm_square();
void Tensor<rank_,dim,Number>::clear ()
{
for (unsigned int i=0; i<dim; ++i)
- values[i] = value_type();
+ values[i] = internal::NumberType<Number>::value(0.0);
}
template <int dim, typename Number, typename Other>
inline
typename ProductType<Other, Number>::type
-operator * (const Other object,
+operator * (const Other &object,
const Tensor<0,dim,Number> &t)
{
return object * static_cast<const Number &>(t);
inline
typename ProductType<Number, Other>::type
operator * (const Tensor<0,dim,Number> &t,
- const Other object)
+ const Other &object)
{
return static_cast<const Number &>(t) * object;
}
inline
Tensor<0,dim,typename ProductType<Number, typename EnableIfScalar<OtherNumber>::type>::type>
operator / (const Tensor<0,dim,Number> &t,
- const OtherNumber factor)
+ const OtherNumber &factor)
{
- return static_cast<Number>(t) / factor;
+ return static_cast<const Number &>(t) / factor;
}
template <int dim, typename Number, typename OtherNumber>
inline
Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
-operator+ (const Tensor<0,dim,Number> &p, const Tensor<0,dim,OtherNumber> &q)
+operator+ (const Tensor<0,dim,Number> &p,
+ const Tensor<0,dim,OtherNumber> &q)
{
return static_cast<const Number &>(p) + static_cast<const OtherNumber &>(q);
}
template <int dim, typename Number, typename OtherNumber>
inline
Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
-operator- (const Tensor<0,dim,Number> &p, const Tensor<0,dim,OtherNumber> &q)
+operator- (const Tensor<0,dim,Number> &p,
+ const Tensor<0,dim,OtherNumber> &q)
{
return static_cast<const Number &>(p) - static_cast<const OtherNumber &>(q);
}
inline
Tensor<rank,dim,typename ProductType<Number, typename EnableIfScalar<OtherNumber>::type>::type>
operator * (const Tensor<rank,dim,Number> &t,
- const OtherNumber factor)
+ const OtherNumber &factor)
{
// recurse over the base objects
Tensor<rank,dim,typename ProductType<Number,OtherNumber>::type> tt;
typename OtherNumber>
inline
Tensor<rank,dim,typename ProductType<typename EnableIfScalar<Number>::type, OtherNumber>::type>
-operator * (const Number factor,
+operator * (const Number &factor,
const Tensor<rank,dim,OtherNumber> &t)
{
// simply forward to the operator above
inline
Tensor<rank,dim,typename ProductType<Number, typename EnableIfScalar<OtherNumber>::type>::type>
operator / (const Tensor<rank,dim,Number> &t,
- const OtherNumber factor)
+ const OtherNumber &factor)
{
// recurse over the base objects
Tensor<rank,dim,typename ProductType<Number,OtherNumber>::type> tt;
template <int rank, int dim, typename Number, typename OtherNumber>
inline
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
-operator+ (const Tensor<rank,dim,Number> &p, const Tensor<rank,dim,OtherNumber> &q)
+operator+ (const Tensor<rank,dim,Number> &p,
+ const Tensor<rank,dim,OtherNumber> &q)
{
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tmp (p);
template <int rank, int dim, typename Number, typename OtherNumber>
inline
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
-operator- (const Tensor<rank,dim,Number> &p, const Tensor<rank,dim,OtherNumber> &q)
+operator- (const Tensor<rank,dim,Number> &p,
+ const Tensor<rank,dim,OtherNumber> &q)
{
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tmp (p);
{
// Compute the determinant using the Laplace expansion of the
// determinant. We expand along the last row.
- Number det = Number();
+ Number det = internal::NumberType<Number>::value(0.0);
for (unsigned int k=0; k<dim; ++k)
{