@@ -528,35 +528,6 @@ inline RT_API_ATTRS CppTypeFor<CAT, KIND> TotalNumericMaxOrMin(
528
528
NumericExtremumAccumulator<CAT, KIND, IS_MAXVAL>{x}, intrinsic);
529
529
}
530
530
531
- template <TypeCategory CAT, int KIND, typename ACCUMULATOR>
532
- static RT_API_ATTRS void DoMaxMinNorm2 (Descriptor &result, const Descriptor &x,
533
- int dim, const Descriptor *mask, const char *intrinsic,
534
- Terminator &terminator) {
535
- using Type = CppTypeFor<CAT, KIND>;
536
- ACCUMULATOR accumulator{x};
537
- if (dim == 0 || x.rank () == 1 ) {
538
- // Total reduction
539
-
540
- // Element size of the destination descriptor is the same
541
- // as the element size of the source.
542
- result.Establish (x.type (), x.ElementBytes (), nullptr , 0 , nullptr ,
543
- CFI_attribute_allocatable);
544
- if (int stat{result.Allocate ()}) {
545
- terminator.Crash (
546
- " %s: could not allocate memory for result; STAT=%d" , intrinsic, stat);
547
- }
548
- DoTotalReduction<Type>(x, dim, mask, accumulator, intrinsic, terminator);
549
- accumulator.GetResult (result.OffsetElement <Type>());
550
- } else {
551
- // Partial reduction
552
-
553
- // Element size of the destination descriptor is the same
554
- // as the element size of the source.
555
- PartialReduction<ACCUMULATOR, CAT, KIND>(result, x, x.ElementBytes (), dim,
556
- mask, terminator, intrinsic, accumulator);
557
- }
558
- }
559
-
560
531
template <TypeCategory CAT, bool IS_MAXVAL> struct MaxOrMinHelper {
561
532
template <int KIND> struct Functor {
562
533
RT_API_ATTRS void operator ()(Descriptor &result, const Descriptor &x,
@@ -802,66 +773,11 @@ RT_EXT_API_GROUP_END
802
773
803
774
// NORM2
804
775
805
- RT_VAR_GROUP_BEGIN
806
-
807
- // Use at least double precision for accumulators.
808
- // Don't use __float128, it doesn't work with abs() or sqrt() yet.
809
- static constexpr RT_CONST_VAR_ATTRS int largestLDKind {
810
- #if LDBL_MANT_DIG == 113
811
- 16
812
- #elif LDBL_MANT_DIG == 64
813
- 10
814
- #else
815
- 8
816
- #endif
817
- };
818
-
819
- RT_VAR_GROUP_END
820
-
821
- template <int KIND> class Norm2Accumulator {
822
- public:
823
- using Type = CppTypeFor<TypeCategory::Real, KIND>;
824
- using AccumType =
825
- CppTypeFor<TypeCategory::Real, std::clamp(KIND, 8 , largestLDKind)>;
826
- explicit RT_API_ATTRS Norm2Accumulator (const Descriptor &array)
827
- : array_{array} {}
828
- RT_API_ATTRS void Reinitialize () { max_ = sum_ = 0 ; }
829
- template <typename A>
830
- RT_API_ATTRS void GetResult (A *p, int /* zeroBasedDim*/ = -1 ) const {
831
- // m * sqrt(1 + sum((others(:)/m)**2))
832
- *p = static_cast <Type>(max_ * std::sqrt (1 + sum_));
833
- }
834
- RT_API_ATTRS bool Accumulate (Type x) {
835
- auto absX{std::abs (static_cast <AccumType>(x))};
836
- if (!max_) {
837
- max_ = absX;
838
- } else if (absX > max_) {
839
- auto t{max_ / absX}; // < 1.0
840
- auto tsq{t * t};
841
- sum_ *= tsq; // scale sum to reflect change to the max
842
- sum_ += tsq; // include a term for the previous max
843
- max_ = absX;
844
- } else { // absX <= max_
845
- auto t{absX / max_};
846
- sum_ += t * t;
847
- }
848
- return true ;
849
- }
850
- template <typename A>
851
- RT_API_ATTRS bool AccumulateAt (const SubscriptValue at[]) {
852
- return Accumulate (*array_.Element <A>(at));
853
- }
854
-
855
- private:
856
- const Descriptor &array_;
857
- AccumType max_{0 }; // value (m) with largest magnitude
858
- AccumType sum_{0 }; // sum((others(:)/m)**2)
859
- };
860
-
861
776
template <int KIND> struct Norm2Helper {
862
777
RT_API_ATTRS void operator ()(Descriptor &result, const Descriptor &x, int dim,
863
778
const Descriptor *mask, Terminator &terminator) const {
864
- DoMaxMinNorm2<TypeCategory::Real, KIND, Norm2Accumulator<KIND>>(
779
+ DoMaxMinNorm2<TypeCategory::Real, KIND,
780
+ typename Norm2AccumulatorGetter<KIND>::Type>(
865
781
result, x, dim, mask, " NORM2" , terminator);
866
782
}
867
783
};
@@ -872,26 +788,27 @@ RT_EXT_API_GROUP_BEGIN
872
788
// TODO: REAL(2 & 3)
873
789
CppTypeFor<TypeCategory::Real, 4 > RTDEF (Norm2_4)(
874
790
const Descriptor &x, const char *source, int line, int dim) {
875
- return GetTotalReduction<TypeCategory::Real, 4 >(
876
- x, source, line, dim, nullptr , Norm2Accumulator <4 >{x} , " NORM2" );
791
+ return GetTotalReduction<TypeCategory::Real, 4 >(x, source, line, dim, nullptr ,
792
+ Norm2AccumulatorGetter <4 >:: create (x) , " NORM2" );
877
793
}
878
794
CppTypeFor<TypeCategory::Real, 8 > RTDEF (Norm2_8)(
879
795
const Descriptor &x, const char *source, int line, int dim) {
880
- return GetTotalReduction<TypeCategory::Real, 8 >(
881
- x, source, line, dim, nullptr , Norm2Accumulator <8 >{x} , " NORM2" );
796
+ return GetTotalReduction<TypeCategory::Real, 8 >(x, source, line, dim, nullptr ,
797
+ Norm2AccumulatorGetter <8 >:: create (x) , " NORM2" );
882
798
}
883
799
#if LDBL_MANT_DIG == 64
884
800
CppTypeFor<TypeCategory::Real, 10 > RTDEF (Norm2_10)(
885
801
const Descriptor &x, const char *source, int line, int dim) {
886
- return GetTotalReduction<TypeCategory::Real, 10 >(
887
- x, source, line, dim, nullptr , Norm2Accumulator <10 >{x} , " NORM2" );
802
+ return GetTotalReduction<TypeCategory::Real, 10 >(x, source, line, dim,
803
+ nullptr , Norm2AccumulatorGetter <10 >:: create (x) , " NORM2" );
888
804
}
889
805
#endif
890
806
#if LDBL_MANT_DIG == 113
807
+ // The __float128 implementation resides in FortranFloat128Math library.
891
808
CppTypeFor<TypeCategory::Real, 16 > RTDEF (Norm2_16)(
892
809
const Descriptor &x, const char *source, int line, int dim) {
893
- return GetTotalReduction<TypeCategory::Real, 16 >(
894
- x, source, line, dim, nullptr , Norm2Accumulator <16 >{x} , " NORM2" );
810
+ return GetTotalReduction<TypeCategory::Real, 16 >(x, source, line, dim,
811
+ nullptr , Norm2AccumulatorGetter <16 >:: create (x) , " NORM2" );
895
812
}
896
813
#endif
897
814
@@ -901,7 +818,7 @@ void RTDEF(Norm2Dim)(Descriptor &result, const Descriptor &x, int dim,
901
818
auto type{x.type ().GetCategoryAndKind ()};
902
819
RUNTIME_CHECK (terminator, type);
903
820
if (type->first == TypeCategory::Real) {
904
- ApplyFloatingPointKind<Norm2Helper, void >(
821
+ ApplyFloatingPointKind<Norm2Helper, void , true >(
905
822
type->second , terminator, result, x, dim, nullptr , terminator);
906
823
} else {
907
824
terminator.Crash (" NORM2: bad type code %d" , x.type ().raw ());
0 commit comments