]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add a file that contains ways to generate signaling NaNs.
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Mon, 23 Nov 2015 19:38:59 +0000 (13:38 -0600)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Sat, 28 Nov 2015 22:00:21 +0000 (16:00 -0600)
include/deal.II/base/signaling_nan.h [new file with mode: 0644]

diff --git a/include/deal.II/base/signaling_nan.h b/include/deal.II/base/signaling_nan.h
new file mode 100644 (file)
index 0000000..d467381
--- /dev/null
@@ -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 <deal.II/base/config.h>
+#include <deal.II/base/tensor.h>
+#include <deal.II/base/symmetric_tensor.h>
+#include <deal.II/base/derivative_form.h>
+
+#include <limits>
+
+
+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 <typename T>
+      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<float>
+      {
+        static float invalid_element ()
+        {
+          return std::numeric_limits<float>::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<double>
+      {
+        static double invalid_element ()
+        {
+          return std::numeric_limits<double>::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 <int dim, typename T>
+      struct NaNInitializer<Tensor<1,dim,T> >
+      {
+        static Tensor<1,dim,T> invalid_element ()
+        {
+          Tensor<1,dim,T> nan_tensor;
+
+          for (unsigned int i=0; i<dim; ++i)
+            nan_tensor[i] = NaNInitializer<T>::invalid_element();
+
+          return nan_tensor;
+        }
+      };
+
+
+
+      /**
+       * A specialization of the general NaNInitializer class that
+       * provides a function that returns a Tensor<rank,dim> value whose
+       * components are invalid signaling NaN values.
+       */
+      template <int rank, int dim, typename T>
+      struct NaNInitializer<Tensor<rank,dim,T> >
+      {
+        static Tensor<rank,dim,T> invalid_element ()
+        {
+          Tensor<rank,dim,T> nan_tensor;
+
+          // recursively initialize sub-tensors with invalid elements
+          for (unsigned int i=0; i<dim; ++i)
+            nan_tensor[i] = NaNInitializer<Tensor<rank-1,dim,T> >::invalid_element();
+
+          return nan_tensor;
+        }
+      };
+
+
+
+      /**
+       * A specialization of the general NaNInitializer class that
+       * provides a function that returns a SymmetricTensor<rank,dim>
+       * value whose components are invalid signaling NaN values.
+       */
+      template <int rank, int dim, typename T>
+      struct NaNInitializer<SymmetricTensor<rank,dim,T> >
+      {
+        static SymmetricTensor<rank,dim,T> invalid_element ()
+        {
+          // initialize symmetric tensors via the unrolled list of elements
+          T initializers[SymmetricTensor<rank,dim,T>::n_independent_components];
+          for (unsigned int i=0; i<SymmetricTensor<rank,dim,T>::n_independent_components; ++i)
+            initializers[i] = NaNInitializer<T>::invalid_element();
+
+          return SymmetricTensor<rank,dim,T>(initializers);
+        }
+      };
+
+
+
+      /**
+       * A specialization of the general NaNInitializer class that
+       * provides a function that returns a
+       * DerivativeForm<order,dim,spacedim> value whose components are
+       * invalid signaling NaN values.
+       */
+      template <int order, int dim, int spacedim, typename T>
+      struct NaNInitializer<DerivativeForm<order,dim,spacedim,T> >
+      {
+        static DerivativeForm<order,dim,spacedim,T> invalid_element ()
+        {
+          DerivativeForm<order,dim,spacedim,T> form;
+
+          // recursively initialize sub-tensors with invalid elements
+          for (unsigned int i=0; i<spacedim; ++i)
+            form[i] = NaNInitializer<Tensor<order,dim,T> >::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<Tensor<1,dim> >();
+   *   @endcode
+   *   initializes a tensor with invalid values.
+   */
+  template <class T>
+  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<T>::invalid_element ();
+  }
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.