From e2d3793e8c14056131c9a7b3223249c4d28cd0ab Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Mon, 23 Nov 2015 13:38:59 -0600 Subject: [PATCH] Add a file that contains ways to generate signaling NaNs. --- include/deal.II/base/signaling_nan.h | 213 +++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 include/deal.II/base/signaling_nan.h diff --git a/include/deal.II/base/signaling_nan.h b/include/deal.II/base/signaling_nan.h new file mode 100644 index 0000000000..d467381293 --- /dev/null +++ b/include/deal.II/base/signaling_nan.h @@ -0,0 +1,213 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2005 - 2015 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +#ifndef dealii__signaling_nan_h +#define dealii__signaling_nan_h + +#include +#include +#include +#include + +#include + + +DEAL_II_NAMESPACE_OPEN + +namespace numbers +{ + + namespace internal + { + /** + * A namespace for the implementation of functions that create + * signaling NaN objects. This is where the Utilities::signaling_nan() + * function calls into. + */ + namespace SignalingNaN + { + /** + * A general template for classes that know how to initialize + * objects of type @p T with signaling NaNs to denote invalid + * values. + * + * The real implementation of this class happens in (partial) + * specializations for particular values of the template + * argument @p T. + */ + template + struct NaNInitializer; + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a @p float value equal to + * the invalid signaling NaN. + */ + template <> + struct NaNInitializer + { + static float invalid_element () + { + return std::numeric_limits::signaling_NaN(); + } + }; + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a @p double value equal to + * the invalid signaling NaN. + */ + template <> + struct NaNInitializer + { + static double invalid_element () + { + return std::numeric_limits::signaling_NaN(); + } + }; + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a Tensor<1,dim> value whose + * components are invalid signaling NaN values. + */ + template + struct NaNInitializer > + { + static Tensor<1,dim,T> invalid_element () + { + Tensor<1,dim,T> nan_tensor; + + for (unsigned int i=0; i::invalid_element(); + + return nan_tensor; + } + }; + + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a Tensor value whose + * components are invalid signaling NaN values. + */ + template + struct NaNInitializer > + { + static Tensor invalid_element () + { + Tensor nan_tensor; + + // recursively initialize sub-tensors with invalid elements + for (unsigned int i=0; i >::invalid_element(); + + return nan_tensor; + } + }; + + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a SymmetricTensor + * value whose components are invalid signaling NaN values. + */ + template + struct NaNInitializer > + { + static SymmetricTensor invalid_element () + { + // initialize symmetric tensors via the unrolled list of elements + T initializers[SymmetricTensor::n_independent_components]; + for (unsigned int i=0; i::n_independent_components; ++i) + initializers[i] = NaNInitializer::invalid_element(); + + return SymmetricTensor(initializers); + } + }; + + + + /** + * A specialization of the general NaNInitializer class that + * provides a function that returns a + * DerivativeForm value whose components are + * invalid signaling NaN values. + */ + template + struct NaNInitializer > + { + static DerivativeForm invalid_element () + { + DerivativeForm form; + + // recursively initialize sub-tensors with invalid elements + for (unsigned int i=0; i >::invalid_element(); + + return form; + } + }; + } + } + + + + + /** + * Provide an object of type @p T filled with a signaling NaN that + * will cause an exception when used in a computation. The content + * of these objects is a "signaling NaN" ("NaN" stands for "not a + * number", and "signaling" implies that at least on platforms where + * this is supported, any arithmetic operation using them terminates + * the program). The purpose of such objects is to use them as + * markers for uninitialized objects and arrays that are required to + * be filled in other places, and to trigger an error when this + * later initialization does not happen before the first use. + * + * @tparam T The type of the returned invalid object. This type can either + * be a scalar, or of type Tensor, SymmetricTensor, or DerivativeForm. + * Other types may be supported if there is a corresponding + * specialization of the internal::SignalingNaN::NaNInitializer class + * for this type. + * + * @note Because the type @p T is not used as a function argument, the + * compiler cannot deduce it from the type of arguments. Consequently, + * you have to provide it explicitly. For example, the line + * @code + * Tensor<1,dim> tensor = Utilities::signaling_nan >(); + * @endcode + * initializes a tensor with invalid values. + */ + template + T + signaling_nan() + { + // dispatch to the classes in the internal namespace because there + // we can do partial specializations, which is not possible for + // template functions such as the current one + return internal::SignalingNaN::NaNInitializer::invalid_element (); + } +} + + +DEAL_II_NAMESPACE_CLOSE + +#endif -- 2.39.5