deal.II version 9.7.0
\(\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: 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// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_numbers_h
16#define dealii_numbers_h
17
18
19#include <deal.II/base/config.h>
20
21#include <deal.II/base/types.h>
22
23#include <cmath>
24#include <complex>
25#include <cstddef>
26#include <type_traits>
27
28// Forward-declare the automatic differentiation types so we can add prototypes
29// for our own wrappers.
30#ifdef DEAL_II_WITH_ADOLC
31class adouble;
32namespace adtl
33{
34 class adouble;
35}
36#endif
37
39
40namespace internal
41{
58 template <typename Number>
60 {
64 constexpr static unsigned int max_width = 1;
65 };
66
73 template <>
75 {
79 constexpr static unsigned int max_width =
80#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512
81 8;
82#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256
83 4;
84#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128
85 2;
86#else
87 1;
88#endif
89 };
90
97 template <>
99 {
103 constexpr static unsigned int max_width =
104#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ALTIVEC__)
105 4;
106#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
107 16;
108#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
109 8;
110#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
111 4;
112#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
113 4;
114#else
115 1;
116#endif
117 };
118
119
120} // namespace internal
121
122// forward declarations to support abs or sqrt operations on VectorizedArray
123#ifndef DOXYGEN
124template <typename Number,
125 std::size_t width =
127class VectorizedArray;
128template <typename T>
129struct EnableIfScalar;
130#endif
131
132#ifdef DEAL_II_WITH_ADOLC
133# ifndef DOXYGEN
134// Prototype some inline functions present in adolc_math.h for use in
135// NumberTraits.
136//
137// ADOL-C uses fabs(), but for genericity we want to use abs(). Simultaneously,
138// though, we don't want to include ADOL-C headers in this header since
139// numbers.h is in everything. To get around this: use C++ rules which permit
140// the use of forward-declared classes in function prototypes to declare some
141// functions which are defined in adolc_math.h. This permits us to write "using
142// ::abs;" in NumberTraits which will allow us to select the correct
143// overload (the one in ::) when instantiating NumberTraits for ADOL-C
144// types.
145
146adouble
147abs(const adouble &x);
148
149adtl::adouble
150abs(const adtl::adouble &x);
151# endif
152#endif
153
154DEAL_II_NAMESPACE_CLOSE // Do not convert for module purposes
155
156 namespace std
157{
158 template <typename Number, std::size_t width>
159 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> sqrt(
160 const ::VectorizedArray<Number, width> &);
161 template <typename Number, std::size_t width>
162 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> abs(
163 const ::VectorizedArray<Number, width> &);
164 template <typename Number, std::size_t width>
165 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> max(
166 const ::VectorizedArray<Number, width> &,
167 const ::VectorizedArray<Number, width> &);
168 template <typename Number, std::size_t width>
169 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width> min(
170 const ::VectorizedArray<Number, width> &,
171 const ::VectorizedArray<Number, width> &);
172 template <typename Number, size_t width>
174 const ::VectorizedArray<Number, width> &, const Number p);
175 template <typename Number, size_t width>
177 const ::VectorizedArray<Number, width> &);
178 template <typename Number, size_t width>
180 const ::VectorizedArray<Number, width> &);
181 template <typename Number, size_t width>
183 const ::VectorizedArray<Number, width> &);
184 template <typename Number, size_t width>
186 const ::VectorizedArray<Number, width> &);
187 template <typename Number, size_t width>
189 const ::VectorizedArray<Number, width> &);
190} // namespace std
191
192DEAL_II_NAMESPACE_OPEN // Do not convert for module purposes
193
209 namespace numbers
210{
214 constexpr double E = 2.7182818284590452354;
215
219 constexpr double LOG2E = 1.4426950408889634074;
220
224 constexpr double LOG10E = 0.43429448190325182765;
225
229 constexpr double LN2 = 0.69314718055994530942;
230
234 constexpr double LN10 = 2.30258509299404568402;
235
239 constexpr double PI = 3.14159265358979323846;
240
244 constexpr double PI_2 = 1.57079632679489661923;
245
249 constexpr double PI_4 = 0.78539816339744830962;
250
254 constexpr double SQRT2 = 1.41421356237309504880;
255
259 constexpr double SQRT1_2 = 0.70710678118654752440;
260
270 bool is_finite(const double x);
271
276 bool is_finite(const std::complex<double> &x);
277
282 bool is_finite(const std::complex<float> &x);
283
292 bool is_finite(const std::complex<long double> &x);
293
304 template <typename Number1, typename Number2>
305 constexpr DEAL_II_HOST_DEVICE bool values_are_equal(const Number1 &value_1,
306 const Number2 &value_2);
307
318 template <typename Number1, typename Number2>
319 constexpr bool values_are_not_equal(const Number1 &value_1,
320 const Number2 &value_2);
321
329 template <typename Number>
330 constexpr DEAL_II_HOST_DEVICE bool value_is_zero(const Number &value);
331
342 template <typename Number1, typename Number2>
343 bool value_is_less_than(const Number1 &value_1, const Number2 &value_2);
344
355 template <typename Number1, typename Number2>
356 bool value_is_less_than_or_equal_to(const Number1 &value_1,
357 const Number2 &value_2);
358
359
360
371 template <typename Number1, typename Number2>
372 bool value_is_greater_than(const Number1 &value_1, const Number2 &value_2);
373
384 template <typename Number1, typename Number2>
385 bool value_is_greater_than_or_equal_to(const Number1 &value_1,
386 const Number2 &value_2);
387
396 template <typename number>
398 {
404 static constexpr bool is_complex = false;
405
412 using real_type = number;
413
417 using double_type = double;
418
426 static constexpr DEAL_II_HOST_DEVICE const number &
427 conjugate(const number &x);
428
437 static constexpr DEAL_II_HOST_DEVICE real_type
438 abs_square(const number &x);
439
443 static real_type
444 abs(const number &x);
445 };
446
447
452 template <typename number>
453 struct NumberTraits<std::complex<number>>
454 {
460 static constexpr bool is_complex = true;
461
468 using real_type = number;
469
473 using double_type = std::complex<double>;
474
478 static constexpr std::complex<number>
479 conjugate(const std::complex<number> &x);
480
487 static constexpr real_type
488 abs_square(const std::complex<number> &x);
489
490
494 static real_type
495 abs(const std::complex<number> &x);
496 };
497
498 // --------------- inline and template functions ---------------- //
499
500 inline bool is_nan(const double x)
501 {
502 return std::isnan(x);
503 }
504
505
506
507 inline bool is_finite(const double x)
508 {
509 return std::isfinite(x);
510 }
511
512
513
514 inline bool is_finite(const std::complex<double> &x)
515 {
516 // Check complex numbers for infinity
517 // by testing real and imaginary part
518 return (is_finite(x.real()) && is_finite(x.imag()));
519 }
520
521
522
523 inline bool is_finite(const std::complex<float> &x)
524 {
525 // Check complex numbers for infinity
526 // by testing real and imaginary part
527 return (is_finite(x.real()) && is_finite(x.imag()));
528 }
529
530
531
532 inline bool is_finite(const std::complex<long double> &x)
533 {
534 // Same for std::complex<long double>
535 return (is_finite(x.real()) && is_finite(x.imag()));
536 }
537
538
539 template <typename number>
541 const number &x)
542 {
543 return x;
544 }
545
546
547
548 template <typename number>
551 {
552 return x * x;
553 }
554
555
556
557 template <typename number>
559 const number &x)
560 {
561 // Make things work with AD types
562 using std::abs;
563#ifdef DEAL_II_WITH_ADOLC
564 // This one is a little tricky - we have our own abs function in ::,
565 // prototyped with forward-declared types in this file, but it only exists
566 // if we have ADOL-C: hence we only add this using statement in that
567 // situation
568 using ::abs;
569#endif
570 return abs(x);
571 }
572
573
574
575 template <typename number>
576 constexpr std::complex<number> NumberTraits<std::complex<number>>::conjugate(
577 const std::complex<number> &x)
578 {
579 return std::conj(x);
580 }
581
582
583
584 template <typename number>
585 typename NumberTraits<std::complex<number>>::real_type
586 NumberTraits<std::complex<number>>::abs(const std::complex<number> &x)
587 {
588 // Make things work with AD types
589 using std::abs;
590#ifdef DEAL_II_WITH_ADOLC
591 // Same comment as the non-complex case holds here
592 using ::abs;
593#endif
594 return abs(x);
595 }
596
597
598
599 template <typename number>
600 constexpr typename NumberTraits<std::complex<number>>::real_type
601 NumberTraits<std::complex<number>>::abs_square(const std::complex<number> &x)
602 {
603 return std::norm(x);
604 }
605
606} // namespace numbers
607
608
609// Forward declarations
611{
612 namespace AD
613 {
614 namespace internal
615 {
616 // Defined in differentiation/ad/ad_number_traits.h
617 template <typename T>
619 } // namespace internal
620
621 // Defined in differentiation/ad/ad_number_traits.h
622 template <typename NumberType>
624 } // namespace AD
625} // namespace Differentiation
626
627
628namespace internal
629{
634 template <typename From, typename To>
636 {
637 // Source: https://stackoverflow.com/a/16944130
638 private:
639 template <typename T>
640 static void f(T);
641
642 template <typename F, typename T>
643 static constexpr auto
644 test(int) -> decltype(f(static_cast<T>(std::declval<F>())), true)
645 {
646 return true;
647 }
648
649 template <typename F, typename T>
650 static constexpr auto
651 test(...) -> bool
652 {
653 return false;
654 }
655
656 public:
657 static const bool value = test<From, To>(0);
658 };
659
660 /*
661 * The structs below are needed to convert between some special number types.
662 * Also see tensor.h for another specialization.
663 */
664 template <typename T>
666 {
667 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T &
668 value(const T &t)
669 {
670 return t;
671 }
672
673 // Below are generic functions that allows an overload for any
674 // type U that is transformable to type T. This is particularly
675 // useful when needing to cast exotic number types
676 // (e.g. auto-differentiable or symbolic numbers) to a floating
677 // point one, such as might happen when converting between tensor
678 // types.
679
680 // Type T is constructible from F.
681 template <typename F>
682 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
683 value(const F &f,
684 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
685 std::is_constructible_v<T, F>> * = nullptr)
686 {
687 return T(f);
688 }
689
690 // Type T is explicitly convertible (but not constructible) from F.
691 template <typename F>
692 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
693 value(const F &f,
694 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
695 !std::is_constructible_v<T, F> &&
697 nullptr)
698 {
699 return static_cast<T>(f);
700 }
701
702 // Sacado doesn't provide any conversion operators, so we have
703 // to extract the value and perform further conversions from there.
704 // To be safe, we extend this to other possible AD numbers that
705 // might fall into the same category.
706 template <typename F>
707 static T
709 const F &f,
710 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
711 !std::is_constructible_v<T, F> &&
714 {
716 }
717 };
718
719 template <typename T>
720 struct NumberType<std::complex<T>>
721 {
722 static constexpr const std::complex<T> &
723 value(const std::complex<T> &t)
724 {
725 return t;
726 }
727
728 static constexpr std::complex<T>
729 value(const T &t)
730 {
731 return std::complex<T>(t);
732 }
733
734 // Facilitate cast from complex<double> to complex<float>
735 template <typename U>
736 static constexpr std::complex<T>
737 value(const std::complex<U> &t)
738 {
739 return std::complex<T>(NumberType<T>::value(t.real()),
740 NumberType<T>::value(t.imag()));
741 }
742 };
743
744} // namespace internal
745
746namespace numbers
747{
748#ifdef DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
749
760 // Defined in differentiation/ad/adolc_number_types.cc
761 bool
762 values_are_equal(const adouble &value_1, const adouble &value_2);
763
764
775 template <typename Number>
776 bool
777 values_are_equal(const adouble &value_1, const Number &value_2)
778 {
779 // Use the specialized definition for two ADOL-C taped types
780 return values_are_equal(
782 }
783
784
795 template <typename Number>
796 bool
797 values_are_equal(const Number &value_1, const adouble &value_2)
798 {
799 // Use the above definition
800 return values_are_equal(value_2, value_1);
801 }
802
814 // Defined in differentiation/ad/adolc_number_types.cc
815 bool
816 value_is_less_than(const adouble &value_1, const adouble &value_2);
817
818
830 template <typename Number>
831 bool
832 value_is_less_than(const adouble &value_1, const Number &value_2)
833 {
834 // Use the specialized definition for two ADOL-C taped types
835 return value_is_less_than(
837 }
838
839
851 template <typename Number>
852 bool
853 value_is_less_than(const Number &value_1, const adouble &value_2)
854 {
855 // Use the specialized definition for two ADOL-C taped types
856 return value_is_less_than(
858 }
859
860#endif
861
862
863 template <typename Number1, typename Number2>
864 constexpr DEAL_II_HOST_DEVICE bool
865 values_are_equal(const Number1 &value_1, const Number2 &value_2)
866 {
867 return (value_1 == ::internal::NumberType<Number1>::value(value_2));
868 }
869
870
871 template <typename Number1, typename Number2>
872 inline constexpr bool
873 values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
874 {
875 return !(values_are_equal(value_1, value_2));
876 }
877
878
879 template <typename Number>
880 constexpr DEAL_II_HOST_DEVICE bool
881 value_is_zero(const Number &value)
882 {
883 return values_are_equal(value, 0.0);
884 }
885
886
887 template <typename Number1, typename Number2>
888 inline bool
889 value_is_less_than(const Number1 &value_1, const Number2 &value_2)
890 {
891 return (value_1 < ::internal::NumberType<Number1>::value(value_2));
892 }
893
894
895 template <typename Number1, typename Number2>
896 inline bool
897 value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
898 {
899 return (value_is_less_than(value_1, value_2) ||
900 values_are_equal(value_1, value_2));
901 }
902
903
904 template <typename Number1, typename Number2>
905 bool
906 value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
907 {
908 return !(value_is_less_than_or_equal_to(value_1, value_2));
909 }
910
911
912 template <typename Number1, typename Number2>
913 inline bool
914 value_is_greater_than_or_equal_to(const Number1 &value_1,
915 const Number2 &value_2)
916 {
917 return !(value_is_less_than(value_1, value_2));
918 }
919} // namespace numbers
920
922
923#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_HOST_DEVICE
Definition config.h:171
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define DEAL_II_HOST_DEVICE_ALWAYS_INLINE
Definition config.h:172
const bool IsBlockVector< VectorType >::value
Definition numbers.h:33
constexpr double LOG10E
Definition numbers.h:224
constexpr double PI_2
Definition numbers.h:244
bool value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:897
constexpr double E
Definition numbers.h:214
constexpr double PI
Definition numbers.h:239
bool value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:906
constexpr bool values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:873
constexpr double SQRT2
Definition numbers.h:254
constexpr bool value_is_zero(const Number &value)
Definition numbers.h:881
constexpr double SQRT1_2
Definition numbers.h:259
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:865
constexpr double PI_4
Definition numbers.h:249
constexpr double LN10
Definition numbers.h:234
constexpr double LN2
Definition numbers.h:229
bool value_is_less_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:889
bool is_finite(const double x)
Definition numbers.h:507
constexpr double LOG2E
Definition numbers.h:219
bool value_is_greater_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:914
bool is_nan(const double x)
Definition numbers.h:500
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:737
static constexpr std::complex< T > value(const T &t)
Definition numbers.h:729
static constexpr const std::complex< T > & value(const std::complex< T > &t)
Definition numbers.h:723
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:683
static constexpr const T & value(const T &t)
Definition numbers.h:668
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 >::value > *=nullptr)
Definition numbers.h:693
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 >::value &&Differentiation::AD::is_ad_number< F >::value > *=nullptr)
Definition numbers.h:708
static constexpr unsigned int max_width
Definition numbers.h:79
static constexpr unsigned int max_width
Definition numbers.h:103
static constexpr unsigned int max_width
Definition numbers.h:64
static constexpr auto test(...) -> bool
Definition numbers.h:651
static constexpr auto test(int) -> decltype(f(static_cast< T >(std::declval< F >())), true)
Definition numbers.h:644
static constexpr std::complex< number > conjugate(const std::complex< number > &x)
Definition numbers.h:576
static real_type abs(const std::complex< number > &x)
Definition numbers.h:586
static constexpr real_type abs_square(const std::complex< number > &x)
Definition numbers.h:601
static constexpr const number & conjugate(const number &x)
Definition numbers.h:540
static constexpr bool is_complex
Definition numbers.h:404
static real_type abs(const number &x)
Definition numbers.h:558
static constexpr real_type abs_square(const number &x)
Definition numbers.h:550