deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
numbers.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2006 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_numbers_h
14#define dealii_numbers_h
15
16
17#include <deal.II/base/config.h>
18
20#include <deal.II/base/types.h>
21
22#include <Kokkos_MathematicalFunctions.hpp>
23
24#include <cmath>
25#include <complex>
26#include <cstddef>
27#include <type_traits>
28
29// Forward-declare the automatic differentiation types so we can add prototypes
30// for our own wrappers.
31#ifdef DEAL_II_WITH_ADOLC
32class adouble;
33namespace adtl
34{
35 class adouble;
36}
37#endif
38
40
41namespace internal
42{
59 template <typename Number>
61 {
65 constexpr static unsigned int max_width = 1;
66 };
67
74 template <>
76 {
80 constexpr static unsigned int max_width =
81#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512
82 8;
83#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256
84 4;
85#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128
86 2;
87#else
88 1;
89#endif
90 };
91
98 template <>
100 {
104 constexpr static unsigned int max_width =
105#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ALTIVEC__)
106 4;
107#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
108 16;
109#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
110 8;
111#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
112 4;
113#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
114 4;
115#else
116 1;
117#endif
118 };
119
120
121} // namespace internal
122
123// forward declarations to support abs or sqrt operations on VectorizedArray
124#ifndef DOXYGEN
125template <typename Number,
126 std::size_t width =
128class VectorizedArray;
129template <typename T>
130struct EnableIfScalar;
131#endif
132
133#ifdef DEAL_II_WITH_ADOLC
134# ifndef DOXYGEN
135// Prototype some inline functions present in adolc_math.h for use in
136// NumberTraits.
137//
138// ADOL-C uses fabs(), but for genericity we want to use abs(). Simultaneously,
139// though, we don't want to include ADOL-C headers in this header since
140// numbers.h is in everything. To get around this: use C++ rules which permit
141// the use of forward-declared classes in function prototypes to declare some
142// functions which are defined in adolc_math.h. This permits us to write "using
143// ::abs;" in NumberTraits which will allow us to select the correct
144// overload (the one in ::) when instantiating NumberTraits for ADOL-C
145// types.
146
147adouble
148abs(const adouble &x);
149
150adtl::adouble
151abs(const adtl::adouble &x);
152# endif
153#endif
154
155DEAL_II_NAMESPACE_CLOSE // Do not convert for module purposes
156
157 namespace std
158{
159 template <typename Number, std::size_t width>
160 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> sqrt(
161 const ::VectorizedArray<Number, width> &);
162 template <typename Number, std::size_t width>
163 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> abs(
164 const ::VectorizedArray<Number, width> &);
165 template <typename Number, std::size_t width>
166 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> max(
167 const ::VectorizedArray<Number, width> &,
168 const ::VectorizedArray<Number, width> &);
169 template <typename Number, std::size_t width>
170 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> min(
171 const ::VectorizedArray<Number, width> &,
172 const ::VectorizedArray<Number, width> &);
173 template <typename Number, size_t width>
175 const ::VectorizedArray<Number, width> &, const Number p);
176 template <typename Number, size_t width>
178 const ::VectorizedArray<Number, width> &);
179 template <typename Number, size_t width>
181 const ::VectorizedArray<Number, width> &);
182 template <typename Number, size_t width>
184 const ::VectorizedArray<Number, width> &);
185 template <typename Number, size_t width>
187 const ::VectorizedArray<Number, width> &);
188 template <typename Number, size_t width>
190 const ::VectorizedArray<Number, width> &);
191} // namespace std
192
193DEAL_II_NAMESPACE_OPEN // Do not convert for module purposes
194
210 namespace numbers
211{
215 constexpr double E = 2.7182818284590452354;
216
220 constexpr double LOG2E = 1.4426950408889634074;
221
225 constexpr double LOG10E = 0.43429448190325182765;
226
230 constexpr double LN2 = 0.69314718055994530942;
231
235 constexpr double LN10 = 2.30258509299404568402;
236
240 constexpr double PI = 3.14159265358979323846;
241
245 constexpr double PI_2 = 1.57079632679489661923;
246
250 constexpr double PI_4 = 0.78539816339744830962;
251
255 constexpr double SQRT2 = 1.41421356237309504880;
256
260 constexpr double SQRT1_2 = 0.70710678118654752440;
261
271 bool is_finite(const double x);
272
277 bool is_finite(const std::complex<double> &x);
278
283 bool is_finite(const std::complex<float> &x);
284
293 bool is_finite(const std::complex<long double> &x);
294
305 template <typename Number1, typename Number2>
306 constexpr DEAL_II_HOST_DEVICE bool values_are_equal(const Number1 &value_1,
307 const Number2 &value_2);
308
319 template <typename Number1, typename Number2>
320 constexpr bool values_are_not_equal(const Number1 &value_1,
321 const Number2 &value_2);
322
330 template <typename Number>
331 constexpr DEAL_II_HOST_DEVICE bool value_is_zero(const Number &value);
332
343 template <typename Number1, typename Number2>
344 bool value_is_less_than(const Number1 &value_1, const Number2 &value_2);
345
356 template <typename Number1, typename Number2>
357 bool value_is_less_than_or_equal_to(const Number1 &value_1,
358 const Number2 &value_2);
359
360
361
372 template <typename Number1, typename Number2>
373 bool value_is_greater_than(const Number1 &value_1, const Number2 &value_2);
374
385 template <typename Number1, typename Number2>
386 bool value_is_greater_than_or_equal_to(const Number1 &value_1,
387 const Number2 &value_2);
388
397 template <typename number>
399 {
405 static constexpr bool is_complex = false;
406
413 using real_type = number;
414
418 using double_type = double;
419
427 static constexpr DEAL_II_HOST_DEVICE const number &
428 conjugate(const number &x);
429
438 static constexpr DEAL_II_HOST_DEVICE real_type
439 abs_square(const number &x);
440
445 abs(const number &x);
446 };
447
448
453 template <typename number>
454 struct NumberTraits<std::complex<number>>
455 {
461 static constexpr bool is_complex = true;
462
469 using real_type = number;
470
474 using double_type = std::complex<double>;
475
479 static constexpr std::complex<number>
480 conjugate(const std::complex<number> &x);
481
488 static constexpr real_type
489 abs_square(const std::complex<number> &x);
490
491
495 static real_type
496 abs(const std::complex<number> &x);
497 };
498
499 // --------------- inline and template functions ---------------- //
500
501 inline bool is_nan(const double x)
502 {
503 return std::isnan(x);
504 }
505
506
507
508 inline bool is_finite(const double x)
509 {
510 return std::isfinite(x);
511 }
512
513
514
515 inline bool is_finite(const std::complex<double> &x)
516 {
517 // Check complex numbers for infinity
518 // by testing real and imaginary part
519 return (is_finite(x.real()) && is_finite(x.imag()));
520 }
521
522
523
524 inline bool is_finite(const std::complex<float> &x)
525 {
526 // Check complex numbers for infinity
527 // by testing real and imaginary part
528 return (is_finite(x.real()) && is_finite(x.imag()));
529 }
530
531
532
533 inline bool is_finite(const std::complex<long double> &x)
534 {
535 // Same for std::complex<long double>
536 return (is_finite(x.real()) && is_finite(x.imag()));
537 }
538
539
540 template <typename number>
542 const number &x)
543 {
544 return x;
545 }
546
547
548
549 template <typename number>
552 {
553 return x * x;
554 }
555
556
557
558 template <typename number>
561 {
562 // Make things work with AD types and device code
563
564#if DEAL_II_KOKKOS_VERSION_GTE(3, 7, 0)
565 if constexpr (std::is_same_v<number, double> ||
566 std::is_same_v<number, float>)
567 {
568 // Supported since Kokkos 3.7 and required for device support
569 // with SYCL.
570 return Kokkos::abs(x);
571 }
572#endif
573
574 using std::abs;
575
576#ifdef DEAL_II_WITH_ADOLC
577 // This one is a little tricky - we have our own abs function in
578 // ::, prototyped with forward-declared types in this file, but it
579 // only exists if we have ADOL-C: hence we only add this using statement
580 // in that situation
581 using ::abs;
582#endif
583 return abs(x);
584 }
585
586
587
588 template <typename number>
589 constexpr std::complex<number> NumberTraits<std::complex<number>>::conjugate(
590 const std::complex<number> &x)
591 {
592 return std::conj(x);
593 }
594
595
596
597 template <typename number>
598 typename NumberTraits<std::complex<number>>::real_type
599 NumberTraits<std::complex<number>>::abs(const std::complex<number> &x)
600 {
601 // Make things work with AD types
602 using std::abs;
603#ifdef DEAL_II_WITH_ADOLC
604 // Same comment as the non-complex case holds here
605 using ::abs;
606#endif
607 return abs(x);
608 }
609
610
611
612 template <typename number>
613 constexpr typename NumberTraits<std::complex<number>>::real_type
614 NumberTraits<std::complex<number>>::abs_square(const std::complex<number> &x)
615 {
616 return std::norm(x);
617 }
618
619} // namespace numbers
620
621
622// Forward declarations
624{
625 namespace AD
626 {
627 namespace internal
628 {
629 // Defined in differentiation/ad/ad_number_traits.h
630 template <typename T>
632 } // namespace internal
633
634 // Defined in differentiation/ad/ad_number_traits.h
635 template <typename NumberType>
637 } // namespace AD
638} // namespace Differentiation
639
640
641namespace internal
642{
647 template <typename From, typename To>
649 decltype(static_cast<To>(std::declval<From>()));
650 template <typename From, typename To>
652 internal::is_supported_operation<get_is_explicitly_convertible, From, To>;
653
654 /*
655 * The structs below are needed to convert between some special number types.
656 * Also see tensor.h for another specialization.
657 */
658 template <typename T>
660 {
661 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T &
662 value(const T &t)
663 {
664 return t;
665 }
666
667 // Below are generic functions that allows an overload for any
668 // type U that is transformable to type T. This is particularly
669 // useful when needing to cast exotic number types
670 // (e.g. auto-differentiable or symbolic numbers) to a floating
671 // point one, such as might happen when converting between tensor
672 // types.
673
674 // Type T is constructible from F.
675 template <typename F>
676 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
677 value(const F &f,
678 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
679 std::is_constructible_v<T, F>> * = nullptr)
680 {
681 return T(f);
682 }
683
684 // Type T is explicitly convertible (but not constructible) from F.
685 template <typename F>
686 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
687 value(const F &f,
688 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
689 !std::is_constructible_v<T, F> &&
690 is_explicitly_convertible<const F, T>> * = nullptr)
691 {
692 return static_cast<T>(f);
693 }
694
695 // Sacado doesn't provide any conversion operators, so we have
696 // to extract the value and perform further conversions from there.
697 // To be safe, we extend this to other possible AD numbers that
698 // might fall into the same category.
699 template <typename F>
700 static T
702 const F &f,
703 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
704 !std::is_constructible_v<T, F> &&
705 !is_explicitly_convertible<const F, T> &&
707 {
709 }
710 };
711
712 template <typename T>
713 struct NumberType<std::complex<T>>
714 {
715 static constexpr const std::complex<T> &
716 value(const std::complex<T> &t)
717 {
718 return t;
719 }
720
721 static constexpr std::complex<T>
722 value(const T &t)
723 {
724 return std::complex<T>(t);
725 }
726
727 // Facilitate cast from complex<double> to complex<float>
728 template <typename U>
729 static constexpr std::complex<T>
730 value(const std::complex<U> &t)
731 {
732 return std::complex<T>(NumberType<T>::value(t.real()),
733 NumberType<T>::value(t.imag()));
734 }
735 };
736
737} // namespace internal
738
739namespace numbers
740{
741#ifdef DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
742
753 // Defined in differentiation/ad/adolc_number_types.cc
754 bool
755 values_are_equal(const adouble &value_1, const adouble &value_2);
756
757
768 template <typename Number>
769 bool
770 values_are_equal(const adouble &value_1, const Number &value_2)
771 {
772 // Use the specialized definition for two ADOL-C taped types
773 return values_are_equal(
775 }
776
777
788 template <typename Number>
789 bool
790 values_are_equal(const Number &value_1, const adouble &value_2)
791 {
792 // Use the above definition
793 return values_are_equal(value_2, value_1);
794 }
795
807 // Defined in differentiation/ad/adolc_number_types.cc
808 bool
809 value_is_less_than(const adouble &value_1, const adouble &value_2);
810
811
823 template <typename Number>
824 bool
825 value_is_less_than(const adouble &value_1, const Number &value_2)
826 {
827 // Use the specialized definition for two ADOL-C taped types
828 return value_is_less_than(
830 }
831
832
844 template <typename Number>
845 bool
846 value_is_less_than(const Number &value_1, const adouble &value_2)
847 {
848 // Use the specialized definition for two ADOL-C taped types
849 return value_is_less_than(
851 }
852
853#endif
854
855
856 template <typename Number1, typename Number2>
857 constexpr DEAL_II_HOST_DEVICE bool
858 values_are_equal(const Number1 &value_1, const Number2 &value_2)
859 {
860 return (value_1 == ::internal::NumberType<Number1>::value(value_2));
861 }
862
863
864 template <typename Number1, typename Number2>
865 inline constexpr bool
866 values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
867 {
868 return !(values_are_equal(value_1, value_2));
869 }
870
871
872 template <typename Number>
873 constexpr DEAL_II_HOST_DEVICE bool
874 value_is_zero(const Number &value)
875 {
876 return values_are_equal(value, 0.0);
877 }
878
879
880 template <typename Number1, typename Number2>
881 inline bool
882 value_is_less_than(const Number1 &value_1, const Number2 &value_2)
883 {
884 return (value_1 < ::internal::NumberType<Number1>::value(value_2));
885 }
886
887
888 template <typename Number1, typename Number2>
889 inline bool
890 value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
891 {
892 return (value_is_less_than(value_1, value_2) ||
893 values_are_equal(value_1, value_2));
894 }
895
896
897 template <typename Number1, typename Number2>
898 bool
899 value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
900 {
901 return !(value_is_less_than_or_equal_to(value_1, value_2));
902 }
903
904
905 template <typename Number1, typename Number2>
906 inline bool
907 value_is_greater_than_or_equal_to(const Number1 &value_1,
908 const Number2 &value_2)
909 {
910 return !(value_is_less_than(value_1, value_2));
911 }
912} // namespace numbers
913
915
916#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_HOST_DEVICE
Definition config.h:171
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_HOST_DEVICE_ALWAYS_INLINE
Definition config.h:172
Definition numbers.h:34
decltype(static_cast< To >(std::declval< From >())) get_is_explicitly_convertible
Definition numbers.h:649
constexpr bool is_explicitly_convertible
Definition numbers.h:651
constexpr double LOG10E
Definition numbers.h:225
constexpr double PI_2
Definition numbers.h:245
bool value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:890
constexpr double E
Definition numbers.h:215
constexpr double PI
Definition numbers.h:240
bool value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:899
constexpr bool values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:866
constexpr double SQRT2
Definition numbers.h:255
constexpr bool value_is_zero(const Number &value)
Definition numbers.h:874
constexpr double SQRT1_2
Definition numbers.h:260
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:858
constexpr double PI_4
Definition numbers.h:250
constexpr double LN10
Definition numbers.h:235
constexpr double LN2
Definition numbers.h:230
bool value_is_less_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:882
bool is_finite(const double x)
Definition numbers.h:508
constexpr double LOG2E
Definition numbers.h:220
bool value_is_greater_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:907
bool is_nan(const double x)
Definition numbers.h:501
STL namespace.
::VectorizedArray< Number, width > log(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > exp(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > tan(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
static constexpr std::complex< T > value(const std::complex< U > &t)
Definition numbers.h:730
static constexpr std::complex< T > value(const T &t)
Definition numbers.h:722
static constexpr const std::complex< T > & value(const std::complex< T > &t)
Definition numbers.h:716
static T value(const F &f, std::enable_if_t<!std::is_same_v< std::decay_t< T >, std::decay_t< F > > &&!std::is_constructible_v< T, F > &&!is_explicitly_convertible< const F, T > &&Differentiation::AD::is_ad_number< F >::value > *=nullptr)
Definition numbers.h:701
static constexpr T value(const F &f, std::enable_if_t<!std::is_same_v< std::decay_t< T >, std::decay_t< F > > &&std::is_constructible_v< T, F > > *=nullptr)
Definition numbers.h:677
static constexpr const T & value(const T &t)
Definition numbers.h:662
static constexpr T value(const F &f, std::enable_if_t<!std::is_same_v< std::decay_t< T >, std::decay_t< F > > &&!std::is_constructible_v< T, F > &&is_explicitly_convertible< const F, T > > *=nullptr)
Definition numbers.h:687
static constexpr unsigned int max_width
Definition numbers.h:65
static constexpr const number & conjugate(const number &x)
Definition numbers.h:541
static constexpr bool is_complex
Definition numbers.h:405
static real_type abs(const number &x)
Definition numbers.h:560
static constexpr real_type abs_square(const number &x)
Definition numbers.h:551