Reference documentation for deal.II version 9.1.1
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
ad_number_traits.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_differentiation_ad_ad_number_traits_h
17 #define dealii_differentiation_ad_ad_number_traits_h
18 
19 #include <deal.II/base/exceptions.h>
20 #include <deal.II/base/numbers.h>
21 
22 #include <deal.II/differentiation/ad/ad_number_types.h>
23 
24 #include <boost/type_traits.hpp>
25 
26 #include <complex>
27 #include <type_traits>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 namespace Differentiation
32 {
33  namespace AD
34  {
48  template <typename ScalarType,
49  enum NumberTypes ADNumberTypeCode,
50  typename T = void>
51  struct NumberTraits;
52 
53 
54 
69  template <typename ADNumberType, typename T = void>
71 
72 
77  namespace internal
78  {
79  // The following three classes, namely ADNumberInfoFromEnum, Marking, and
80  // ExtractData, are those that need to be implemented for each new
81  // auto-differentiable number type. This information is then used by
82  // NumberTraits and ADNumberTraits to provide a uniform interface, as used
83  // by our drivers, to the underlying number types.
84 
85 
111  template <typename ScalarType,
112  enum NumberTypes ADNumberTypeCode,
113  typename = void>
115 
116 
148  template <typename ADNumberType, typename T = void>
149  struct Marking;
150 
151 
183  template <typename ADNumberType, typename T = void>
184  struct ExtractData;
185 
186 
201  template <typename ADNumberTrait, typename T = void>
203 
204 
221  template <typename T>
222  struct NumberType;
223 
224 
231  template <typename Number>
233 
234  } // namespace internal
235 
236 
245  template <typename NumberType>
246  struct is_ad_number;
247 
248 
257  template <typename NumberType, typename = void>
259 
260 
269  template <typename NumberType, typename = void>
271 
272 
281  template <typename NumberType, typename = void>
283 
284 
293  template <typename NumberType, typename = void>
295 
296  } // namespace AD
297 } // namespace Differentiation
298 
299 
300 /* ----------- inline and template functions and specializations ----------- */
301 
302 
303 #ifndef DOXYGEN
304 
305 
306 namespace Differentiation
307 {
308  namespace AD
309  {
310  namespace internal
311  {
312  template <typename ADNumberTrait, typename>
313  struct HasRequiredADInfo : std::false_type
314  {};
315 
316 
328  template <typename ADNumberTrait>
329  struct HasRequiredADInfo<
330  ADNumberTrait,
331  decltype((void)ADNumberTrait::type_code,
332  (void)ADNumberTrait::is_taped,
333  (void)std::declval<typename ADNumberTrait::real_type>(),
334  (void)std::declval<typename ADNumberTrait::derivative_type>(),
335  void())>
336  : std::conditional<
337  std::is_floating_point<typename ADNumberTrait::real_type>::value,
338  std::false_type,
339  std::true_type>::type
340  {};
341 
342 
347  template <typename ScalarType>
348  struct ADNumberInfoFromEnum<
349  ScalarType,
351  typename std::enable_if<
352  std::is_floating_point<ScalarType>::value>::type>
353  {
354  static const bool is_taped = false;
355  using real_type = ScalarType;
356  using derivative_type = ScalarType;
357  static const unsigned int n_supported_derivative_levels = 0;
358  };
359 
360 
366  template <typename ScalarType>
367  struct Marking<ScalarType,
368  typename std::enable_if<
369  std::is_floating_point<ScalarType>::value>::type>
370  {
378  template <typename ADNumberType>
379  static void
380  independent_variable(const ScalarType &in,
381  const unsigned int,
382  const unsigned int,
383  ADNumberType &out)
384  {
385  out = in;
386  }
387 
388  /*
389  * Initialize the state of a dependent variable.
390  */
391  template <typename ADNumberType>
392  static void
393  dependent_variable(ADNumberType &, const ScalarType &)
394  {
395  AssertThrow(
396  false,
397  ExcMessage(
398  "Floating point numbers cannot be marked as dependent variables."));
399  }
400  };
401 
402 
406  template <typename ADNumberType>
407  struct Marking<
408  ADNumberType,
409  typename std::enable_if<boost::is_complex<ADNumberType>::value>::type>
410  {
411  /*
412  * Initialize the state of an independent variable.
413  */
414  template <typename ScalarType>
415  static void
416  independent_variable(const ScalarType &in,
417  const unsigned int,
418  const unsigned int,
419  ADNumberType &out)
420  {
421  AssertThrow(
422  false,
423  ExcMessage(
424  "Marking for complex numbers has not yet been implemented."));
425  out = in;
426  }
427 
428  /*
429  * Initialize the state of a dependent variable.
430  */
431  template <typename ScalarType>
432  static void
433  dependent_variable(ADNumberType &, const ScalarType &)
434  {
435  AssertThrow(
436  false,
437  ExcMessage(
438  "Marking for complex numbers has not yet been implemented."));
439  }
440  };
441 
442  } // namespace internal
443 
444 
445  template <typename NumberType, typename>
446  struct is_taped_ad_number : std::false_type
447  {};
448 
449 
450  template <typename NumberType, typename>
451  struct is_tapeless_ad_number : std::false_type
452  {};
453 
454 
455  template <typename NumberType, typename>
456  struct is_real_valued_ad_number : std::false_type
457  {};
458 
459 
460  template <typename NumberType, typename>
461  struct is_complex_valued_ad_number : std::false_type
462  {};
463 
464 
470  template <typename NumberType>
471  struct is_ad_number
472  : internal::HasRequiredADInfo<
473  ADNumberTraits<typename std::decay<NumberType>::type>>
474  {};
475 
476 
481  template <typename NumberType>
482  struct is_taped_ad_number<
483  NumberType,
484  typename std::enable_if<
485  ADNumberTraits<typename std::decay<NumberType>::type>::is_taped>::type>
486  : std::true_type
487  {};
488 
489 
494  template <typename NumberType>
495  struct is_tapeless_ad_number<
496  NumberType,
497  typename std::enable_if<ADNumberTraits<
498  typename std::decay<NumberType>::type>::is_tapeless>::type>
499  : std::true_type
500  {};
501 
502 
508  template <typename NumberType>
509  struct is_real_valued_ad_number<
510  NumberType,
511  typename std::enable_if<ADNumberTraits<
512  typename std::decay<NumberType>::type>::is_real_valued>::type>
513  : std::true_type
514  {};
515 
516 
522  template <typename NumberType>
523  struct is_complex_valued_ad_number<
524  NumberType,
525  typename std::enable_if<ADNumberTraits<
526  typename std::decay<NumberType>::type>::is_complex_valued>::type>
527  : std::true_type
528  {};
529 
530 
531  namespace internal
532  {
537  template <typename Number>
538  struct RemoveComplexWrapper
539  {
540  using type = Number;
541  };
542 
543 
549  template <typename Number>
550  struct RemoveComplexWrapper<std::complex<Number>>
551  {
552  using type = typename RemoveComplexWrapper<Number>::type;
553  };
554 
555 
561  template <typename NumberType>
562  struct ExtractData<NumberType,
563  typename std::enable_if<
564  std::is_floating_point<NumberType>::value>::type>
565  {
569  static const NumberType &
570  value(const NumberType &x)
571  {
572  return x;
573  }
574 
575 
579  static unsigned int
580  n_directional_derivatives(const NumberType &)
581  {
582  return 0;
583  }
584 
585 
589  static NumberType
590  directional_derivative(const NumberType &, const unsigned int)
591  {
592  return 0.0;
593  }
594  };
595 
596 
597 
602  template <typename ADNumberType>
603  struct ExtractData<std::complex<ADNumberType>>
604  {
606  "Expected an auto-differentiable number.");
607 
608 
612  static std::complex<typename ADNumberTraits<ADNumberType>::scalar_type>
613  value(const std::complex<ADNumberType> &x)
614  {
615  return std::complex<
616  typename ADNumberTraits<ADNumberType>::scalar_type>(
617  ExtractData<ADNumberType>::value(x.real()),
618  ExtractData<ADNumberType>::value(x.imag()));
619  }
620 
621 
625  static unsigned int
626  n_directional_derivatives(const std::complex<ADNumberType> &x)
627  {
628  return ExtractData<ADNumberType>::n_directional_derivatives(x.real());
629  }
630 
631 
635  static std::complex<
636  typename ADNumberTraits<ADNumberType>::derivative_type>
637  directional_derivative(const std::complex<ADNumberType> &x,
638  const unsigned int direction)
639  {
640  return std::complex<
641  typename ADNumberTraits<ADNumberType>::derivative_type>(
642  ExtractData<ADNumberType>::directional_derivative(x.real(),
643  direction),
644  ExtractData<ADNumberType>::directional_derivative(x.imag(),
645  direction));
646  }
647  };
648 
649 
650  template <typename T>
651  struct NumberType
652  {
656  template <typename F>
657  static auto
658  value(const F &f,
659  typename std::enable_if<!is_ad_number<F>::value>::type * =
660  nullptr) -> decltype(::internal::NumberType<T>::value(f))
661  {
662  // We call the other function defined in the numbers
663  // header to take care of all of the usual cases.
664  return ::internal::NumberType<T>::value(f);
665  }
666 
673  template <typename F>
674  static T
675  value(const F &f,
676  typename std::enable_if<is_ad_number<F>::value &&
677  std::is_floating_point<T>::value>::type
678  * = nullptr)
679  {
680  // We recursively call this function in case the AD number is a
681  // nested one. The recursion ends when the extracted value is
682  // a floating point number.
683  return NumberType<T>::value(ExtractData<F>::value(f));
684  }
685 
692  template <typename F>
693  static T
694  value(const F &f,
695  typename std::enable_if<is_ad_number<F>::value &&
696  is_ad_number<T>::value>::type * = nullptr)
697  {
698  return T(f);
699  }
700  };
701 
702  template <typename T>
703  struct NumberType<std::complex<T>>
704  {
708  template <typename F>
709  static auto
710  value(
711  const F &f,
712  typename std::enable_if<!is_ad_number<F>::value>::type * = nullptr)
713  -> decltype(::internal::NumberType<std::complex<T>>::value(f))
714  {
715  // We call the other function defined in the numbers
716  // header to take care of all of the usual cases.
717  return ::internal::NumberType<std::complex<T>>::value(f);
718  }
719 
720 
725  template <typename F>
726  static std::complex<T>
727  value(const F &f,
728  typename std::enable_if<is_ad_number<F>::value &&
729  std::is_floating_point<T>::value>::type
730  * = nullptr)
731  {
732  // We recursively call this function in case the AD number is a
733  // nested one. The recursion ends when the extracted value is
734  // a floating point number.
735  return std::complex<T>(
736  NumberType<T>::value(ExtractData<F>::value(f)));
737  }
738 
739  template <typename F>
740  static std::complex<T>
741  value(const std::complex<F> &f)
742  {
743  // Deal with the two parts of the input complex
744  // number individually.
745  return std::complex<T>(NumberType<T>::value(f.real()),
746  NumberType<T>::value(f.imag()));
747  }
748  };
749 
750  } // namespace internal
751 
752 
753 
774  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
775  struct NumberTraits<
776  ScalarType,
777  ADNumberTypeCode,
778  typename std::enable_if<
779  std::is_floating_point<ScalarType>::value ||
780  (boost::is_complex<ScalarType>::value &&
781  std::is_floating_point<typename internal::RemoveComplexWrapper<
782  ScalarType>::type>::value)>::type>
783  {
787  static constexpr enum NumberTypes type_code = ADNumberTypeCode;
788 
789  // The clang compiler does not seem to like these
790  // variables being defined as constant expressions
791  // (the tests <adolc|sacado>/ad_number_traits_02 will
792  // fail with linking errors). However, GCC complains
793  // about the use of non-constant expressions in
794  // std::conditional.
795 # ifdef __clang__
796 
801  static const bool is_taped;
802 
803 
808  static const bool is_tapeless;
809 
810 
815  static const bool is_real_valued;
816 
817 
822  static const bool is_complex_valued;
823 
824 
829  static const unsigned int n_supported_derivative_levels;
830 
831 # else
832 
837  static constexpr bool is_taped = internal::ADNumberInfoFromEnum<
838  typename internal::RemoveComplexWrapper<ScalarType>::type,
839  ADNumberTypeCode>::is_taped;
840 
841 
846  static constexpr bool is_tapeless =
847  !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
848 
849 
854  static constexpr bool is_real_valued =
855  (!boost::is_complex<ScalarType>::value);
856 
857 
862  static constexpr bool is_complex_valued =
863  !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
864 
865 
870  static constexpr unsigned int n_supported_derivative_levels =
871  internal::ADNumberInfoFromEnum<
872  typename internal::RemoveComplexWrapper<ScalarType>::type,
873  ADNumberTypeCode>::n_supported_derivative_levels;
874 
875 # endif
876 
877 
882  using scalar_type = ScalarType;
883 
884 
888  using real_type = typename internal::ADNumberInfoFromEnum<
889  typename internal::RemoveComplexWrapper<ScalarType>::type,
890  ADNumberTypeCode>::real_type;
891 
892 
896  using complex_type = std::complex<real_type>;
897 
898 
902  using ad_type = typename std::
903  conditional<is_real_valued, real_type, complex_type>::type;
904 
908  using derivative_type = typename std::conditional<
909  is_real_valued,
910  typename internal::ADNumberInfoFromEnum<
911  typename internal::RemoveComplexWrapper<ScalarType>::type,
912  ADNumberTypeCode>::derivative_type,
913  std::complex<typename internal::ADNumberInfoFromEnum<
914  typename internal::RemoveComplexWrapper<ScalarType>::type,
915  ADNumberTypeCode>::derivative_type>>::type;
916 
917 
921  static scalar_type get_scalar_value(const ad_type &x)
922  {
923  // Some tricky conversion cases to consider here:
924  // - Nested AD numbers
925  // - std::complex<double> --> std::complex<float>
926  // e.g. when ScalarType = float and ADNumberTypeCode = adolc_taped
927  // Therefore, we use the internal casting mechanism
928  // provided by the internal::NumberType struct.
930  internal::ExtractData<ad_type>::value(x));
931  }
932 
933 
937  static derivative_type get_directional_derivative(
938  const ad_type &x, const unsigned int direction)
939  {
940  return internal::ExtractData<ad_type>::directional_derivative(
941  x, direction);
942  }
943 
944 
949  static unsigned int n_directional_derivatives(const ad_type &x)
950  {
951  return internal::ExtractData<ad_type>::n_directional_derivatives(x);
952  }
953 
954 
955  static_assert((is_real_valued == true ?
956  std::is_same<ad_type, real_type>::value :
957  std::is_same<ad_type, complex_type>::value),
958  "Incorrect template type selected for ad_type");
959 
960  static_assert((is_complex_valued == true ?
961  boost::is_complex<scalar_type>::value :
962  true),
963  "Expected a complex float_type");
964 
965  static_assert((is_complex_valued == true ?
966  boost::is_complex<ad_type>::value :
967  true),
968  "Expected a complex ad_type");
969  };
970 
971 # ifdef __clang__
972 
973  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
974  const bool NumberTraits<
975  ScalarType,
976  ADNumberTypeCode,
977  typename std::enable_if<
978  std::is_floating_point<ScalarType>::value ||
979  (boost::is_complex<ScalarType>::value &&
980  std::is_floating_point<typename internal::RemoveComplexWrapper<
981  ScalarType>::type>::value)>::type>::is_taped =
982  internal::ADNumberInfoFromEnum<
983  typename internal::RemoveComplexWrapper<ScalarType>::type,
984  ADNumberTypeCode>::is_taped;
985 
986 
987  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
988  const bool NumberTraits<
989  ScalarType,
990  ADNumberTypeCode,
991  typename std::enable_if<
992  std::is_floating_point<ScalarType>::value ||
993  (boost::is_complex<ScalarType>::value &&
994  std::is_floating_point<typename internal::RemoveComplexWrapper<
995  ScalarType>::type>::value)>::type>::is_tapeless =
996  !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
997 
998 
999  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1000  const bool NumberTraits<
1001  ScalarType,
1002  ADNumberTypeCode,
1003  typename std::enable_if<
1004  std::is_floating_point<ScalarType>::value ||
1005  (boost::is_complex<ScalarType>::value &&
1006  std::is_floating_point<typename internal::RemoveComplexWrapper<
1007  ScalarType>::type>::value)>::type>::is_real_valued =
1008  (!boost::is_complex<ScalarType>::value);
1009 
1010 
1011  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1012  const bool NumberTraits<
1013  ScalarType,
1014  ADNumberTypeCode,
1015  typename std::enable_if<
1016  std::is_floating_point<ScalarType>::value ||
1017  (boost::is_complex<ScalarType>::value &&
1018  std::is_floating_point<typename internal::RemoveComplexWrapper<
1019  ScalarType>::type>::value)>::type>::is_complex_valued =
1020  !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
1021 
1022 
1023  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1024  const unsigned int NumberTraits<
1025  ScalarType,
1026  ADNumberTypeCode,
1027  typename std::enable_if<
1028  std::is_floating_point<ScalarType>::value ||
1029  (boost::is_complex<ScalarType>::value &&
1030  std::is_floating_point<typename internal::RemoveComplexWrapper<
1031  ScalarType>::type>::value)>::type>::n_supported_derivative_levels =
1032  internal::ADNumberInfoFromEnum<
1033  typename internal::RemoveComplexWrapper<ScalarType>::type,
1034  ADNumberTypeCode>::n_supported_derivative_levels;
1035 
1036 # else
1037 
1038  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1039  constexpr bool NumberTraits<
1040  ScalarType,
1041  ADNumberTypeCode,
1042  typename std::enable_if<
1043  std::is_floating_point<ScalarType>::value ||
1044  (boost::is_complex<ScalarType>::value &&
1045  std::is_floating_point<typename internal::RemoveComplexWrapper<
1046  ScalarType>::type>::value)>::type>::is_taped;
1047 
1048 
1049  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1050  constexpr bool NumberTraits<
1051  ScalarType,
1052  ADNumberTypeCode,
1053  typename std::enable_if<
1054  std::is_floating_point<ScalarType>::value ||
1055  (boost::is_complex<ScalarType>::value &&
1056  std::is_floating_point<typename internal::RemoveComplexWrapper<
1057  ScalarType>::type>::value)>::type>::is_tapeless;
1058 
1059 
1060  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1061  constexpr bool NumberTraits<
1062  ScalarType,
1063  ADNumberTypeCode,
1064  typename std::enable_if<
1065  std::is_floating_point<ScalarType>::value ||
1066  (boost::is_complex<ScalarType>::value &&
1067  std::is_floating_point<typename internal::RemoveComplexWrapper<
1068  ScalarType>::type>::value)>::type>::is_real_valued;
1069 
1070 
1071  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1072  constexpr bool NumberTraits<
1073  ScalarType,
1074  ADNumberTypeCode,
1075  typename std::enable_if<
1076  std::is_floating_point<ScalarType>::value ||
1077  (boost::is_complex<ScalarType>::value &&
1078  std::is_floating_point<typename internal::RemoveComplexWrapper<
1079  ScalarType>::type>::value)>::type>::is_complex_valued;
1080 
1081 
1082  template <typename ScalarType, enum NumberTypes ADNumberTypeCode>
1083  constexpr unsigned int NumberTraits<
1084  ScalarType,
1085  ADNumberTypeCode,
1086  typename std::enable_if<
1087  std::is_floating_point<ScalarType>::value ||
1088  (boost::is_complex<ScalarType>::value &&
1089  std::is_floating_point<typename internal::RemoveComplexWrapper<
1090  ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1091 
1092 # endif
1093 
1094 
1095 
1105  template <typename ScalarType>
1106  struct NumberTraits<
1107  ScalarType,
1108  NumberTypes::none,
1109  typename std::enable_if<
1110  std::is_floating_point<ScalarType>::value ||
1111  (boost::is_complex<ScalarType>::value &&
1112  std::is_floating_point<typename internal::RemoveComplexWrapper<
1113  ScalarType>::type>::value)>::type>
1114  {
1118  static constexpr enum NumberTypes type_code = NumberTypes::none;
1119 
1120  // The clang compiler does not seem to like these
1121  // variables being defined as constant expressions
1122  // (the tests <adolc|sacado>/ad_number_traits_02 will
1123  // fail with linking errors). However, GCC complains
1124  // about the use of non-constant expressions in
1125  // std::conditional.
1126 # ifdef __clang__
1127 
1132  static const bool is_taped;
1133 
1134 
1139  static const bool is_tapeless;
1140 
1141 
1146  static const bool is_real_valued;
1147 
1148 
1153  static const bool is_complex_valued;
1154 
1155 
1160  static const unsigned int n_supported_derivative_levels;
1161 
1162 # else
1163 
1168  static constexpr bool is_taped = false;
1169 
1170 
1175  static constexpr bool is_tapeless = false;
1176 
1177 
1182  static constexpr bool is_real_valued =
1183  (!boost::is_complex<ScalarType>::value);
1184 
1185 
1190  static constexpr bool is_complex_valued = !is_real_valued;
1191 
1192 
1197  static constexpr unsigned int n_supported_derivative_levels = 0;
1198 
1199 # endif
1200 
1201 
1206  using scalar_type = ScalarType;
1207 
1208 
1212  using real_type =
1213  typename ::numbers::NumberTraits<scalar_type>::real_type;
1214 
1215 
1219  using complex_type = std::complex<real_type>;
1220 
1221 
1225  using ad_type = ScalarType;
1226 
1230  using derivative_type = ScalarType;
1231 
1232 
1236  static scalar_type
1237  get_scalar_value(const ad_type &x)
1238  {
1239  return x;
1240  }
1241 
1242 
1246  static derivative_type
1247  get_directional_derivative(const ad_type &, const unsigned int)
1248  {
1249  Assert(
1250  false,
1251  ExcMessage(
1252  "Floating point/arithmetic numbers have no directional derivatives."));
1253  return derivative_type();
1254  }
1255 
1256 
1261  static unsigned int
1262  n_directional_derivatives(const ad_type &)
1263  {
1264  Assert(
1265  false,
1266  ExcMessage(
1267  "Floating point/arithmetic numbers have no directional derivatives."));
1268  return 0;
1269  }
1270  };
1271 
1272 # ifdef __clang__
1273 
1274  template <typename ScalarType>
1275  const bool NumberTraits<
1276  ScalarType,
1278  typename std::enable_if<
1279  std::is_floating_point<ScalarType>::value ||
1280  (boost::is_complex<ScalarType>::value &&
1281  std::is_floating_point<typename internal::RemoveComplexWrapper<
1282  ScalarType>::type>::value)>::type>::is_taped = false;
1283 
1284 
1285  template <typename ScalarType>
1286  const bool NumberTraits<
1287  ScalarType,
1289  typename std::enable_if<
1290  std::is_floating_point<ScalarType>::value ||
1291  (boost::is_complex<ScalarType>::value &&
1292  std::is_floating_point<typename internal::RemoveComplexWrapper<
1293  ScalarType>::type>::value)>::type>::is_tapeless = false;
1294 
1295 
1296  template <typename ScalarType>
1297  const bool NumberTraits<
1298  ScalarType,
1300  typename std::enable_if<
1301  std::is_floating_point<ScalarType>::value ||
1302  (boost::is_complex<ScalarType>::value &&
1303  std::is_floating_point<typename internal::RemoveComplexWrapper<
1304  ScalarType>::type>::value)>::type>::is_real_valued =
1305  (!boost::is_complex<ScalarType>::value);
1306 
1307 
1308  template <typename ScalarType>
1309  const bool NumberTraits<
1310  ScalarType,
1312  typename std::enable_if<
1313  std::is_floating_point<ScalarType>::value ||
1314  (boost::is_complex<ScalarType>::value &&
1315  std::is_floating_point<typename internal::RemoveComplexWrapper<
1316  ScalarType>::type>::value)>::type>::is_complex_valued =
1317  !(NumberTraits<ScalarType, NumberTypes::none>::is_real_valued);
1318 
1319 
1320  template <typename ScalarType>
1321  const unsigned int NumberTraits<
1322  ScalarType,
1324  typename std::enable_if<
1325  std::is_floating_point<ScalarType>::value ||
1326  (boost::is_complex<ScalarType>::value &&
1327  std::is_floating_point<typename internal::RemoveComplexWrapper<
1328  ScalarType>::type>::value)>::type>::n_supported_derivative_levels =
1329  0;
1330 
1331 # else
1332 
1333  template <typename ScalarType>
1334  constexpr bool NumberTraits<
1335  ScalarType,
1337  typename std::enable_if<
1338  std::is_floating_point<ScalarType>::value ||
1339  (boost::is_complex<ScalarType>::value &&
1340  std::is_floating_point<typename internal::RemoveComplexWrapper<
1341  ScalarType>::type>::value)>::type>::is_taped;
1342 
1343 
1344  template <typename ScalarType>
1345  constexpr bool NumberTraits<
1346  ScalarType,
1348  typename std::enable_if<
1349  std::is_floating_point<ScalarType>::value ||
1350  (boost::is_complex<ScalarType>::value &&
1351  std::is_floating_point<typename internal::RemoveComplexWrapper<
1352  ScalarType>::type>::value)>::type>::is_tapeless;
1353 
1354 
1355  template <typename ScalarType>
1356  constexpr bool NumberTraits<
1357  ScalarType,
1359  typename std::enable_if<
1360  std::is_floating_point<ScalarType>::value ||
1361  (boost::is_complex<ScalarType>::value &&
1362  std::is_floating_point<typename internal::RemoveComplexWrapper<
1363  ScalarType>::type>::value)>::type>::is_real_valued;
1364 
1365 
1366  template <typename ScalarType>
1367  constexpr bool NumberTraits<
1368  ScalarType,
1370  typename std::enable_if<
1371  std::is_floating_point<ScalarType>::value ||
1372  (boost::is_complex<ScalarType>::value &&
1373  std::is_floating_point<typename internal::RemoveComplexWrapper<
1374  ScalarType>::type>::value)>::type>::is_complex_valued;
1375 
1376 
1377  template <typename ScalarType>
1378  constexpr unsigned int NumberTraits<
1379  ScalarType,
1381  typename std::enable_if<
1382  std::is_floating_point<ScalarType>::value ||
1383  (boost::is_complex<ScalarType>::value &&
1384  std::is_floating_point<typename internal::RemoveComplexWrapper<
1385  ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1386 
1387 # endif
1388 
1389 
1408  template <typename ScalarType>
1409  struct ADNumberTraits<
1410  ScalarType,
1411  typename std::enable_if<std::is_floating_point<ScalarType>::value>::type>
1412  : NumberTraits<ScalarType, NumberTypes::none>
1413  {};
1414 
1418  template <typename ComplexScalarType>
1419  struct ADNumberTraits<
1420  ComplexScalarType,
1421  typename std::enable_if<
1422  boost::is_complex<ComplexScalarType>::value &&
1423  std::is_floating_point<typename ComplexScalarType::value_type>::value>::
1424  type> : NumberTraits<ComplexScalarType, NumberTypes::none>
1425  {};
1426 
1427  } // namespace AD
1428 } // namespace Differentiation
1429 
1430 #endif // DOXYGEN
1431 
1432 
1433 namespace numbers
1434 {
1435  template <typename ADNumberType>
1436  bool
1437  is_nan(const typename std::enable_if<
1439  ADNumberType>::type &x)
1440  {
1441  return is_nan(
1443  }
1444 
1445 } // namespace numbers
1446 
1447 
1448 DEAL_II_NAMESPACE_CLOSE
1449 
1450 #endif
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:1519
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1407
bool is_nan(const double x)
Definition: numbers.h:455