deal.II version GIT relicensing-2165-gc91f007519 2024-11-20 01:40:00+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: LGPL-2.1-or-later
4// Copyright (C) 2006 - 2024 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 <Kokkos_Macros.hpp>
24
25#include <cmath>
26#include <complex>
27#include <cstddef>
28#include <type_traits>
29
30#define DEAL_II_HOST_DEVICE KOKKOS_FUNCTION
31#define DEAL_II_HOST_DEVICE_ALWAYS_INLINE KOKKOS_FORCEINLINE_FUNCTION
32
33// clang++ assumes that all constexpr functions are __host__ __device__ when
34// Kokkos was configured with CUDA or HIP support. This is problematic
35// when calling non-constexpr functions in constexpr functions. Hence, we
36// need a way to annotate functions explicitly as host-only.
37#if (defined(__clang__) && defined(__CUDA__)) || defined(KOKKOS_ENABLE_HIP)
38# define DEAL_II_HOST __host__
39#else
40# define DEAL_II_HOST
41#endif
42
43// Forward-declare the automatic differentiation types so we can add prototypes
44// for our own wrappers.
45#ifdef DEAL_II_WITH_ADOLC
46class adouble;
47namespace adtl
48{
49 class adouble;
50}
51#endif
52
54
55namespace internal
56{
73 template <typename Number>
75 {
79 constexpr static unsigned int max_width = 1;
80 };
81
88 template <>
90 {
94 constexpr static unsigned int max_width =
95#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512
96 8;
97#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256
98 4;
99#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128
100 2;
101#else
102 1;
103#endif
104 };
105
112 template <>
114 {
118 constexpr static unsigned int max_width =
119#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ALTIVEC__)
120 4;
121#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
122 16;
123#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
124 8;
125#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
126 4;
127#elif DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
128 4;
129#else
130 1;
131#endif
132 };
133
134
135} // namespace internal
136
137// forward declarations to support abs or sqrt operations on VectorizedArray
138#ifndef DOXYGEN
139template <typename Number,
140 std::size_t width =
142class VectorizedArray;
143template <typename T>
144struct EnableIfScalar;
145#endif
146
147#ifdef DEAL_II_WITH_ADOLC
148# ifndef DOXYGEN
149// Prototype some inline functions present in adolc_math.h for use in
150// NumberTraits.
151//
152// ADOL-C uses fabs(), but for genericity we want to use abs(). Simultaneously,
153// though, we don't want to include ADOL-C headers in this header since
154// numbers.h is in everything. To get around this: use C++ rules which permit
155// the use of forward-declared classes in function prototypes to declare some
156// functions which are defined in adolc_math.h. This permits us to write "using
157// ::abs;" in NumberTraits which will allow us to select the correct
158// overload (the one in ::) when instantiating NumberTraits for ADOL-C
159// types.
160
161adouble
162abs(const adouble &x);
163
164adtl::adouble
165abs(const adtl::adouble &x);
166# endif
167#endif
168
170
171namespace std
172{
173 template <typename Number, std::size_t width>
174 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width>
175 sqrt(const ::VectorizedArray<Number, width> &);
176 template <typename Number, std::size_t width>
177 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width>
178 abs(const ::VectorizedArray<Number, width> &);
179 template <typename Number, std::size_t width>
180 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width>
181 max(const ::VectorizedArray<Number, width> &,
182 const ::VectorizedArray<Number, width> &);
183 template <typename Number, std::size_t width>
184 DEAL_II_ALWAYS_INLINE ::VectorizedArray<Number, width>
185 min(const ::VectorizedArray<Number, width> &,
186 const ::VectorizedArray<Number, width> &);
187 template <typename Number, size_t width>
189 pow(const ::VectorizedArray<Number, width> &, const Number p);
190 template <typename Number, size_t width>
192 sin(const ::VectorizedArray<Number, width> &);
193 template <typename Number, size_t width>
195 cos(const ::VectorizedArray<Number, width> &);
196 template <typename Number, size_t width>
198 tan(const ::VectorizedArray<Number, width> &);
199 template <typename Number, size_t width>
201 exp(const ::VectorizedArray<Number, width> &);
202 template <typename Number, size_t width>
204 log(const ::VectorizedArray<Number, width> &);
205} // namespace std
206
208
224namespace numbers
225{
229 static constexpr double E = 2.7182818284590452354;
230
234 static constexpr double LOG2E = 1.4426950408889634074;
235
239 static constexpr double LOG10E = 0.43429448190325182765;
240
244 static constexpr double LN2 = 0.69314718055994530942;
245
249 static constexpr double LN10 = 2.30258509299404568402;
250
254 static constexpr double PI = 3.14159265358979323846;
255
259 static constexpr double PI_2 = 1.57079632679489661923;
260
264 static constexpr double PI_4 = 0.78539816339744830962;
265
269 static constexpr double SQRT2 = 1.41421356237309504880;
270
274 static constexpr double SQRT1_2 = 0.70710678118654752440;
275
285 bool
286 is_finite(const double x);
287
292 bool
293 is_finite(const std::complex<double> &x);
294
299 bool
300 is_finite(const std::complex<float> &x);
301
310 bool
311 is_finite(const std::complex<long double> &x);
312
323 template <typename Number1, typename Number2>
324 constexpr DEAL_II_HOST_DEVICE bool
325 values_are_equal(const Number1 &value_1, const Number2 &value_2);
326
337 template <typename Number1, typename Number2>
338 constexpr bool
339 values_are_not_equal(const Number1 &value_1, const Number2 &value_2);
340
348 template <typename Number>
349 constexpr DEAL_II_HOST_DEVICE bool
350 value_is_zero(const Number &value);
351
362 template <typename Number1, typename Number2>
363 bool
364 value_is_less_than(const Number1 &value_1, const Number2 &value_2);
365
376 template <typename Number1, typename Number2>
377 bool
378 value_is_less_than_or_equal_to(const Number1 &value_1,
379 const Number2 &value_2);
380
381
382
393 template <typename Number1, typename Number2>
394 bool
395 value_is_greater_than(const Number1 &value_1, const Number2 &value_2);
396
407 template <typename Number1, typename Number2>
408 bool
409 value_is_greater_than_or_equal_to(const Number1 &value_1,
410 const Number2 &value_2);
411
420 template <typename number>
422 {
428 static constexpr bool is_complex = false;
429
436 using real_type = number;
437
441 using double_type = double;
442
450 static constexpr DEAL_II_HOST_DEVICE const number &
451 conjugate(const number &x);
452
461 static constexpr DEAL_II_HOST_DEVICE real_type
462 abs_square(const number &x);
463
467 static real_type
468 abs(const number &x);
469 };
470
471
476 template <typename number>
477 struct NumberTraits<std::complex<number>>
478 {
484 static constexpr bool is_complex = true;
485
492 using real_type = number;
493
497 using double_type = std::complex<double>;
498
502 static constexpr std::complex<number>
503 conjugate(const std::complex<number> &x);
504
511 static constexpr real_type
512 abs_square(const std::complex<number> &x);
513
514
518 static real_type
519 abs(const std::complex<number> &x);
520 };
521
522 // --------------- inline and template functions ---------------- //
523
524 inline bool
525 is_nan(const double x)
526 {
527 return std::isnan(x);
528 }
529
530
531
532 inline bool
533 is_finite(const double x)
534 {
535 return std::isfinite(x);
536 }
537
538
539
540 inline bool
541 is_finite(const std::complex<double> &x)
542 {
543 // Check complex numbers for infinity
544 // by testing real and imaginary part
545 return (is_finite(x.real()) && is_finite(x.imag()));
546 }
547
548
549
550 inline bool
551 is_finite(const std::complex<float> &x)
552 {
553 // Check complex numbers for infinity
554 // by testing real and imaginary part
555 return (is_finite(x.real()) && is_finite(x.imag()));
556 }
557
558
559
560 inline bool
561 is_finite(const std::complex<long double> &x)
562 {
563 // Same for std::complex<long double>
564 return (is_finite(x.real()) && is_finite(x.imag()));
565 }
566
567
568 template <typename number>
569 constexpr DEAL_II_HOST_DEVICE const number &
571 {
572 return x;
573 }
574
575
576
577 template <typename number>
580 {
581 return x * x;
582 }
583
584
585
586 template <typename number>
589 {
590 // Make things work with AD types
591 using std::abs;
592#ifdef DEAL_II_WITH_ADOLC
593 // This one is a little tricky - we have our own abs function in ::,
594 // prototyped with forward-declared types in this file, but it only exists
595 // if we have ADOL-C: hence we only add this using statement in that
596 // situation
597 using ::abs;
598#endif
599 return abs(x);
600 }
601
602
603
604 template <typename number>
605 constexpr std::complex<number>
606 NumberTraits<std::complex<number>>::conjugate(const std::complex<number> &x)
607 {
608 return std::conj(x);
609 }
610
611
612
613 template <typename number>
614 typename NumberTraits<std::complex<number>>::real_type
615 NumberTraits<std::complex<number>>::abs(const std::complex<number> &x)
616 {
617 // Make things work with AD types
618 using std::abs;
619#ifdef DEAL_II_WITH_ADOLC
620 // Same comment as the non-complex case holds here
621 using ::abs;
622#endif
623 return abs(x);
624 }
625
626
627
628 template <typename number>
629 constexpr typename NumberTraits<std::complex<number>>::real_type
630 NumberTraits<std::complex<number>>::abs_square(const std::complex<number> &x)
631 {
632 return std::norm(x);
633 }
634
635} // namespace numbers
636
637
638// Forward declarations
640{
641 namespace AD
642 {
643 namespace internal
644 {
645 // Defined in differentiation/ad/ad_number_traits.h
646 template <typename T>
648 } // namespace internal
649
650 // Defined in differentiation/ad/ad_number_traits.h
651 template <typename NumberType>
653 } // namespace AD
654} // namespace Differentiation
655
656
657namespace internal
658{
663 template <typename From, typename To>
665 {
666 // Source: https://stackoverflow.com/a/16944130
667 private:
668 template <typename T>
669 static void f(T);
670
671 template <typename F, typename T>
672 static constexpr auto
673 test(int) -> decltype(f(static_cast<T>(std::declval<F>())), true)
674 {
675 return true;
676 }
677
678 template <typename F, typename T>
679 static constexpr auto
680 test(...) -> bool
681 {
682 return false;
683 }
684
685 public:
686 static const bool value = test<From, To>(0);
687 };
688
689 /*
690 * The structs below are needed to convert between some special number types.
691 * Also see tensor.h for another specialization.
692 */
693 template <typename T>
695 {
696 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T &
697 value(const T &t)
698 {
699 return t;
700 }
701
702 // Below are generic functions that allows an overload for any
703 // type U that is transformable to type T. This is particularly
704 // useful when needing to cast exotic number types
705 // (e.g. auto-differentiable or symbolic numbers) to a floating
706 // point one, such as might happen when converting between tensor
707 // types.
708
709 // Type T is constructible from F.
710 template <typename F>
711 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
712 value(const F &f,
713 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
714 std::is_constructible_v<T, F>> * = nullptr)
715 {
716 return T(f);
717 }
718
719 // Type T is explicitly convertible (but not constructible) from F.
720 template <typename F>
721 static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
722 value(const F &f,
723 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
724 !std::is_constructible_v<T, F> &&
726 nullptr)
727 {
728 return static_cast<T>(f);
729 }
730
731 // Sacado doesn't provide any conversion operators, so we have
732 // to extract the value and perform further conversions from there.
733 // To be safe, we extend this to other possible AD numbers that
734 // might fall into the same category.
735 template <typename F>
736 static T
738 const F &f,
739 std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::decay_t<F>> &&
740 !std::is_constructible_v<T, F> &&
743 {
745 }
746 };
747
748 template <typename T>
749 struct NumberType<std::complex<T>>
750 {
751 static constexpr const std::complex<T> &
752 value(const std::complex<T> &t)
753 {
754 return t;
755 }
756
757 static constexpr std::complex<T>
758 value(const T &t)
759 {
760 return std::complex<T>(t);
761 }
762
763 // Facilitate cast from complex<double> to complex<float>
764 template <typename U>
765 static constexpr std::complex<T>
766 value(const std::complex<U> &t)
767 {
768 return std::complex<T>(NumberType<T>::value(t.real()),
769 NumberType<T>::value(t.imag()));
770 }
771 };
772
773} // namespace internal
774
775namespace numbers
776{
777#ifdef DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
778
789 // Defined in differentiation/ad/adolc_number_types.cc
790 bool
791 values_are_equal(const adouble &value_1, const adouble &value_2);
792
793
804 template <typename Number>
805 bool
806 values_are_equal(const adouble &value_1, const Number &value_2)
807 {
808 // Use the specialized definition for two ADOL-C taped types
809 return values_are_equal(
811 }
812
813
824 template <typename Number>
825 bool
826 values_are_equal(const Number &value_1, const adouble &value_2)
827 {
828 // Use the above definition
829 return values_are_equal(value_2, value_1);
830 }
831
843 // Defined in differentiation/ad/adolc_number_types.cc
844 bool
845 value_is_less_than(const adouble &value_1, const adouble &value_2);
846
847
859 template <typename Number>
860 bool
861 value_is_less_than(const adouble &value_1, const Number &value_2)
862 {
863 // Use the specialized definition for two ADOL-C taped types
864 return value_is_less_than(
866 }
867
868
880 template <typename Number>
881 bool
882 value_is_less_than(const Number &value_1, const adouble &value_2)
883 {
884 // Use the specialized definition for two ADOL-C taped types
885 return value_is_less_than(
887 }
888
889#endif
890
891
892 template <typename Number1, typename Number2>
893 constexpr DEAL_II_HOST_DEVICE bool
894 values_are_equal(const Number1 &value_1, const Number2 &value_2)
895 {
896 return (value_1 == ::internal::NumberType<Number1>::value(value_2));
897 }
898
899
900 template <typename Number1, typename Number2>
901 inline constexpr bool
902 values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
903 {
904 return !(values_are_equal(value_1, value_2));
905 }
906
907
908 template <typename Number>
909 constexpr DEAL_II_HOST_DEVICE bool
910 value_is_zero(const Number &value)
911 {
912 return values_are_equal(value, 0.0);
913 }
914
915
916 template <typename Number1, typename Number2>
917 inline bool
918 value_is_less_than(const Number1 &value_1, const Number2 &value_2)
919 {
920 return (value_1 < ::internal::NumberType<Number1>::value(value_2));
921 }
922
923
924 template <typename Number1, typename Number2>
925 inline bool
926 value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
927 {
928 return (value_is_less_than(value_1, value_2) ||
929 values_are_equal(value_1, value_2));
930 }
931
932
933 template <typename Number1, typename Number2>
934 bool
935 value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
936 {
937 return !(value_is_less_than_or_equal_to(value_1, value_2));
938 }
939
940
941 template <typename Number1, typename Number2>
942 inline bool
943 value_is_greater_than_or_equal_to(const Number1 &value_1,
944 const Number2 &value_2)
945 {
946 return !(value_is_less_than(value_1, value_2));
947 }
948} // namespace numbers
949
951
952#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
Definition numbers.h:48
static constexpr double LOG10E
Definition numbers.h:239
static constexpr double PI_2
Definition numbers.h:259
bool value_is_less_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:926
static constexpr double E
Definition numbers.h:229
static constexpr double PI
Definition numbers.h:254
bool value_is_greater_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:935
constexpr bool values_are_not_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:902
static constexpr double SQRT2
Definition numbers.h:269
constexpr bool value_is_zero(const Number &value)
Definition numbers.h:910
static constexpr double SQRT1_2
Definition numbers.h:274
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:894
static constexpr double PI_4
Definition numbers.h:264
static constexpr double LN10
Definition numbers.h:249
static constexpr double LN2
Definition numbers.h:244
bool value_is_less_than(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:918
bool is_finite(const double x)
Definition numbers.h:533
static constexpr double LOG2E
Definition numbers.h:234
bool value_is_greater_than_or_equal_to(const Number1 &value_1, const Number2 &value_2)
Definition numbers.h:943
bool is_nan(const double x)
Definition numbers.h:525
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 > &)
#define DEAL_II_HOST_DEVICE
Definition numbers.h:30
#define DEAL_II_HOST_DEVICE_ALWAYS_INLINE
Definition numbers.h:31
static constexpr std::complex< T > value(const std::complex< U > &t)
Definition numbers.h:766
static constexpr std::complex< T > value(const T &t)
Definition numbers.h:758
static constexpr const std::complex< T > & value(const std::complex< T > &t)
Definition numbers.h:752
static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE 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:712
static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE 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:722
static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T & value(const T &t)
Definition numbers.h:697
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:737
static constexpr unsigned int max_width
Definition numbers.h:79
static constexpr auto test(...) -> bool
Definition numbers.h:680
static constexpr auto test(int) -> decltype(f(static_cast< T >(std::declval< F >())), true)
Definition numbers.h:673
static constexpr const number & conjugate(const number &x)
Definition numbers.h:570
static constexpr bool is_complex
Definition numbers.h:428
static real_type abs(const number &x)
Definition numbers.h:588
static constexpr real_type abs_square(const number &x)
Definition numbers.h:579