LCOV - code coverage report
Current view: top level - src - mo_moment.f90 (source / functions) Hit Total Coverage
Test: forces coverage Lines: 560 564 99.3 %
Date: 2024-03-13 19:03:28 Functions: 28 28 100.0 %

          Line data    Source code
       1             : !> \file    mo_moment.f90
       2             : !> \brief \copybrief mo_moment
       3             : !> \details \copydetails mo_moment
       4             : 
       5             : !> \brief   Statistical moments.
       6             : !> \details This module contains routines for the masked calculation of
       7             : !! statistical properties such as moments and mixed moments of input vectors
       8             : !! \note all except variance and standard deviation are population and not sample moments,
       9             : !!       i.e. they are normally divided by n and not (n-1)
      10             : !> \par Literature
      11             : !!   Central moments and error variances
      12             : !!       LH Benedict & RD Gould, Towards better uncertainty estimates for turbulence statistics,
      13             : !!           Experiments in Fluids 22, 129-136, 1996
      14             : !> \changelog
      15             : !! - Matthias Cuntz, Nov 2011
      16             : !!   - written
      17             : !! - Matthias Cuntz, Dec 2011
      18             : !!   - mod. correlation, covariance
      19             : !! - M. Schroen, Sep 2015
      20             : !!   - average/mean for single value
      21             : !! - S. Mueller, Dec 2019
      22             : !!   - remove citations for common sence
      23             : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
      24             : !! FORCES is released under the LGPLv3+ license \license_note
      25             : MODULE mo_moment
      26             : 
      27             :   USE mo_kind, ONLY : i4, sp, dp
      28             : 
      29             :   IMPLICIT NONE
      30             : 
      31             :   PUBLIC :: absdev                        ! Mean absolute deviation from mean of an array
      32             :   PUBLIC :: average                       ! 1st moment of an array (same as mean)
      33             :   PUBLIC :: central_moment                ! Arbitrary central moment of an array
      34             :   PUBLIC :: central_moment_var            ! Central moment error variance
      35             :   PUBLIC :: correlation                   ! Correlation between two arrays
      36             :   PUBLIC :: covariance                    ! Covariance between two arrays
      37             :   PUBLIC :: kurtosis                      ! 4th moment of an array
      38             :   PUBLIC :: mean                          ! 1st moment of an array
      39             :   PUBLIC :: mixed_central_moment          ! Arbitrary mixed central moment
      40             :   PUBLIC :: mixed_central_moment_var      ! Arbitrary mixed central moment error variance
      41             :   PUBLIC :: moment                        ! 1st to 4th moments of an array
      42             :   PUBLIC :: skewness                      ! 3rd moment of an array
      43             :   PUBLIC :: stddev                        ! Sqrt of 2nd moment of an array
      44             :   PUBLIC :: variance                      ! 2nd moment of an array
      45             : 
      46             :   ! ------------------------------------------------------------------
      47             : 
      48             :   !>    \brief Mean absolute deviation from mean.
      49             : 
      50             :   !>    \details
      51             :   !!    Calculates the mean absolute deviations from the mean
      52             :   !!
      53             :   !!    \f[ ABSDEV = \sum_i\frac{|x_i-\bar x|}{N} \f]
      54             :   !!
      55             :   !!    If an optinal mask is given, the calculations are over those locations that correspond to true values in the mask.
      56             :   !!    \f$ x\f$ can be single or double precision. The result will have the same numerical precision.\n
      57             :   !!
      58             :   !!    \b Example
      59             :   !!
      60             :   !!        vec = (/ 1., 2, 3., -999., 5., 6. /)
      61             :   !!        m   = absdev(vec, mask=(vec >= 0.))
      62             :   !!
      63             :   !!    See also example in pf_tests directory.
      64             : 
      65             : 
      66             :   !>    \param[in]  "real(sp/dp) :: dat(:)"               1D-array with input numbers.
      67             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with `size(dat)`.
      68             :   !!                                                      If present, only those locations in `vec`
      69             :   !!                                                      corresponding to the true values in mask are used.
      70             :   !>    \retval     "real(sp/dp) :: absdev"               Mean absolute deviations from average.
      71             : 
      72             :   !>    \note Input values must be floating points.
      73             : 
      74             :   !>    \author Matthias Cuntz
      75             :   !>    \date Nov 2011
      76             : 
      77             :   ! ------------------------------------------------------------------
      78             : 
      79             :   INTERFACE absdev
      80             :     MODULE PROCEDURE absdev_sp, absdev_dp
      81             :   END INTERFACE absdev
      82             : 
      83             :   ! ------------------------------------------------------------------
      84             : 
      85             :   !>    \brief Mean of vector.
      86             : 
      87             :   !>    \details
      88             :   !!    Calculates the average value of a vector, i.e. the first moment of a series of numbers:
      89             :   !!
      90             :   !!    \f[ AVE = \sum_i \frac{x_i}{N} \f]
      91             :   !!
      92             :   !!    If an optional mask is given, the average is only over those locations that correspond to true values in the mask.
      93             :   !!    \f$ x\f$ can be single or double precision. The result will have the same numerical precision.
      94             :   !!
      95             :   !!    \b Example
      96             :   !!
      97             :   !!        vec = (/ 1., 2, 3., -999., 5., 6. /)
      98             :   !!        m   = average(vec, mask=(vec >= 0.))
      99             :   !!        --> m = 3.4
     100             :   !!
     101             :   !!    See also example in pf_tests directory.
     102             : 
     103             :   !>    \param[in]  "real(sp/dp) :: dat(:)"         1D-array with input numbers
     104             : 
     105             :   !>    \retval     "real(sp/dp) :: average"        Average of all elements in dat
     106             : 
     107             : 
     108             :   !>    \param[in]  "logical, optional :: mask(:)"  1D-array of logical values with `size(dat)`.
     109             :   !!                                                If present, only those locations in dat
     110             :   !!                                                corresponding to the true values in mask are used.
     111             : 
     112             :   !>    \note Input values must be floating points.
     113             : 
     114             :   !>    \author Matthias Cuntz
     115             :   !>    \date Nov 2011
     116             : 
     117             :   ! ------------------------------------------------------------------
     118             : 
     119             :   INTERFACE average
     120             :     MODULE PROCEDURE average_sp, average_dp
     121             :   END INTERFACE average
     122             : 
     123             :   ! ------------------------------------------------------------------
     124             : 
     125             :   !>    \brief R-central moment
     126             : 
     127             :   !>    \details
     128             :   !!    Calculates the central moment of a vector, i.e. the r-central moment of a series of numbers:
     129             :   !!
     130             :   !!    \f[ \mu_r = \sum_i\frac{(x_i-\bar x)^r}{N} \f]
     131             :   !!
     132             :   !!    Note that the variance is the second central moment: `variance(x) = central_moment(x,2)`\n
     133             :   !!
     134             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     135             :   !!    x can be single or double precision. The result will have the same numerical precision.
     136             :   !!
     137             :   !!    \b Example
     138             :   !!
     139             :   !!        vec = (/ 1., 2, 3., 4., 5., 6. /)
     140             :   !!        m   = central_moment(vec, 2, mask=(vec >= 0.))
     141             :   !!        --> m = 2.91666
     142             :   !!
     143             :   !!    See also example in pf_tests directory.
     144             :   !!
     145             :   !>    \b Literature
     146             :   !!    1.  LH Benedict & RD Gould, _Towards better uncertainty estimates for turbulence statistics_.
     147             :   !!        Experiments in Fluids 22, 129-136, 1996
     148             :   !!
     149             :   !>    \param[in]  "real(sp/dp) :: dat(:)"         1D-array with input numbers.
     150             :   !>    \param[in]  "integer(i4) :: r"              Order of the central moment, i.e. r=2 is variance.
     151             :   !>    \param[in]  "logical, optional :: mask(:)"  1D-array of logical values with size(dat).
     152             :   !!                                                If present, only those locations in `dat`
     153             :   !!                                                corresponding to the true values in mask are used.
     154             :   !>    \retval "real(sp/dp) :: central_moment"     R-th central moment of elements in `dat`.
     155             : 
     156             :   !>    \note Input values must be floating points.
     157             : 
     158             :   !>    \author Matthias Cuntz
     159             :   !>    \date Nov 2011
     160             : 
     161             :   ! ------------------------------------------------------------------
     162             :   INTERFACE central_moment
     163             :     MODULE PROCEDURE central_moment_sp, central_moment_dp
     164             :   END INTERFACE central_moment
     165             : 
     166             :   ! ------------------------------------------------------------------
     167             : 
     168             :   !>    \brief R-central moment variance
     169             : 
     170             :   !>    \details
     171             :   !!    Calculates the sampling variance of the central moment of a vector.
     172             :   !!    `central_moment_var` is something like the "error variance" of the r-th order central moment sampling statistic.\n
     173             :   !!
     174             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     175             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.\n
     176             :   !!
     177             :   !!    \b Example
     178             :   !!
     179             :   !!        vec = (/ 1., 2, 3., -999., 5., 6. /)
     180             :   !!        m   = central_moment(vec, 2, mask=(vec >= 0.))
     181             :   !!        em  = central_moment_var(vec, 2, mask=(vec >= 0.))
     182             :   !!
     183             :   !!    See also example in pf_tests directory.
     184             :   !!
     185             :   !!    \b Literature
     186             :   !!    1.  LH Benedict & RD Gould, _Towards better uncertainty estimates for turbulence statistics_,
     187             :   !!        Experiments in Fluids 22, 129-136, 1996
     188             :   !!
     189             :   !>    \param[in]  "real(sp/dp) :: dat(:)"                 1D-array with input numbers.
     190             :   !>    \param[in]  "integer(i4) :: r"                      Order of the central moment, i.e. r=2 is variance.
     191             :   !>    \param[in]  "logical, optional :: mask(:)"          1D-array of logical values with `size(dat)`.
     192             :   !!                                                        If present, only those locations in dat
     193             :   !!                                                        corresponding to the true values in mask are used.
     194             :   !>    \retval     "real(sp/dp) :: central_moment_var"     Sampling variance of r-th central moment of elements in dat
     195             : 
     196             :   !>    \note  Input values must be floating points.
     197             : 
     198             :   !>    \author Matthias Cuntz
     199             :   !>    \date Nov 2011
     200             :   INTERFACE central_moment_var
     201             :     MODULE PROCEDURE central_moment_var_sp, central_moment_var_dp
     202             :   END INTERFACE central_moment_var
     203             : 
     204             :   ! ------------------------------------------------------------------
     205             : 
     206             :   !>    \brief Correlation between two vectors.
     207             : 
     208             :   !>    \details
     209             :   !!    Calculates the correlation between two input vectors, i.e. the covariance divided by the standard deviations:\n
     210             :   !!
     211             :   !!    \f[\langle x y\rangle = \sum_i\frac{(x_i-\bar x)(y_i-\bar y)}{N\sqrt{\mu_2(x)\mu_2(y)}}\f]
     212             :   !!
     213             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     214             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     215             :   !!
     216             :   !!    \b Example
     217             :   !!
     218             :   !!        vec1 = (/ 1., 2, 3., -999., 5., 6. /)
     219             :   !!        vec2 = (/ 1.3, 2.7, 3.9, 5.1, 6., 8. /)
     220             :   !!        m   = correlation(vec1, vec2, mask=((vec1 >= 0.) .and. (vec2 >= 0.)))
     221             :   !!
     222             :   !!    See also example in pf_tests directory.
     223             : 
     224             :   !>    \param[in]  "real(sp/dp) :: x(:)"           First 1D-array with input numbers.
     225             :   !>    \param[in]  "real(sp/dp) :: y(:)"           Second 1D-array with input numbers.
     226             :   !>    \retval     "real(sp/dp) :: correlation"    Correlation between \f$x\f$ and \f$y\f$.
     227             :   !>    \param[in]  "logical, optional :: mask(:)"  1D-array of logical values with `size(x)`.
     228             :   !!                                                If present, only those locations in dat
     229             :   !!                                                corresponding to the true values in mask are used.
     230             : 
     231             :   !>    \note Input values must be floating points.
     232             : 
     233             :   !>    \author Matthias Cuntz
     234             :   !>    \date Nov 2011
     235             :   !>    \date Dec 2011
     236             :   !!        - covariance as <(x-<x>)(y-<y>)> instead of <xy>-<x><y>
     237             : 
     238             :   ! ------------------------------------------------------------------
     239             : 
     240             :   INTERFACE correlation
     241             :     MODULE PROCEDURE correlation_sp, correlation_dp
     242             :   END INTERFACE correlation
     243             : 
     244             :   ! ------------------------------------------------------------------
     245             : 
     246             :   !>    \brief Covariance between vectors
     247             : 
     248             :   !>    \details
     249             :   !!    Calculates the covariance between two input vectors:\n
     250             :   !!
     251             :   !!    \f[Cov(x,y) = \sum_i\frac{(x_i-\bar x)(y_i-\bar y)}{N}\f]
     252             :   !!
     253             :   !!    If an optional mask is given, the average is only over those locations that correspond to true values in the mask.
     254             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     255             :   !!
     256             :   !!    \b Example
     257             :   !!
     258             :   !!         vec1 = (/ 1., 2, 3., -999., 5., 6. /)
     259             :   !!         vec2 = (/ 1.3, 2.7, 3.9, 5.1, 6., 8. /)
     260             :   !!         m   = covariance(vec1, vec2, mask=((vec1 >= 0.) .and. (vec2 >= 0.)))
     261             :   !!
     262             :   !!    See also example in test directory.
     263             : 
     264             :   !>    \param[in]  "real(sp/dp) :: x(:)"           First 1D-array with input numbers.
     265             :   !>    \param[in]  "real(sp/dp) :: y(:)"           Second 1D-array with input numbers.
     266             :   !>    \param[in]  "logical, optional :: mask(:)"  1D-array of logical values with size(x).
     267             :   !!                                                If present, only those locations in dat
     268             :   !!                                                corresponding to the true values in mask are used.
     269             :   !>    \retval     "real(sp/dp) :: covariance"     Covariance between x and y.
     270             : 
     271             :   !>    \note Input values must be floating points.
     272             : 
     273             :   !>    \author Matthias Cuntz
     274             :   !>    \date Nov 2011
     275             :   !>    \date Dec 2011
     276             :   !!        - covariance as <(x-<x>)(y-<y>)> instead of <xy>-<x><y>
     277             : 
     278             :   ! ------------------------------------------------------------------
     279             : 
     280             :   INTERFACE covariance
     281             :     MODULE PROCEDURE covariance_sp, covariance_dp
     282             :   END INTERFACE covariance
     283             : 
     284             :   ! ------------------------------------------------------------------
     285             : 
     286             :   !>    \brief Kurtosis of a vector.
     287             : 
     288             :   !>    \details
     289             :   !!    Calculates the kurtosis of a vector, also called excess kurtosis:
     290             :   !!
     291             :   !!    \f[ Kurt(x) = \verb|central_moment(x,4) / variance(x)**2 - 3|
     292             :   !!    = \sum_i\frac{1}{N}\left(\frac{(x_i-\bar x)^2}{\mu_2(x)}\right)^2 - 3\f]
     293             :   !!
     294             :   !!    If an optional mask is given, the average is only over those locations that correspond to true values in the mask.
     295             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     296             :   !!
     297             :   !!    \b Example
     298             :   !!
     299             :   !!         vec = (/ 1., 2, 3., -999., 5., 6. /)
     300             :   !!         m   = kurtosis(vec, mask=(vec >= 0.))
     301             :   !!
     302             :   !!    See also example in test directory.
     303             : 
     304             : 
     305             :   !>    \param[in]  "real(sp/dp) :: dat(:)"         1D-array with input numbers.
     306             :   !>    \param[in]  "logical, optional :: mask(:)"  1D-array of logical values with `size(dat)`.
     307             :   !!                                                If present, only those locations in dat
     308             :   !!                                                corresponding to the true values in mask are used.
     309             :   !>    \retval     "real(sp/dp) :: kurtosis"       Kurtosis of all elements in dat.
     310             : 
     311             :   !>    \note  Input values must be floating points.
     312             : 
     313             :   !>    \authors Matthias Cuntz
     314             :   !>    \date Nov 2011
     315             : 
     316             :   ! ------------------------------------------------------------------
     317             : 
     318             :   INTERFACE kurtosis
     319             :     MODULE PROCEDURE kurtosis_sp, kurtosis_dp
     320             :   END INTERFACE kurtosis
     321             : 
     322             :   ! ------------------------------------------------------------------
     323             : 
     324             :   !>    \brief Mean of a vector.
     325             : 
     326             :   !>    \details
     327             :   !!    Calculates the average value of a vector, i.e. the first moment of a series of numbers:
     328             :   !!
     329             :   !!    \f[\bar x = sum_i \frac{x_i}{N}
     330             :   !!
     331             :   !!    If an optional mask is given, the mean is only over those locations that correspond to true values in the mask.
     332             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     333             :   !!
     334             :   !!    \b Example
     335             :   !!    \code{.f90}
     336             :   !!    vec = (/ 1., 2, 3., -999., 5., 6. /)
     337             :   !!    m   = mean(vec, mask=(vec >= 0.))
     338             :   !!    \endcode
     339             :   !!    See also example in test directory.
     340             :   !!
     341             :   !>    \param[in]  "real(sp/dp) :: dat(:)"           1D-array with input numbers.
     342             :   !>    \param[in]  "logical, optional :: mask(:)"    1D-array of logical values with `size(dat)`.
     343             :   !!                                                  If present, only those locations in dat
     344             :   !!                                                  corresponding to the true values in mask are used.
     345             :   !>    \retval     "real(sp/dp) :: mean"             Average of all elements in dat.
     346             : 
     347             :   !>    \note  Input values must be floating points.
     348             : 
     349             :   !>    \author Matthias Cuntz
     350             :   !>    \date Nov 2011
     351             : 
     352             :   ! ------------------------------------------------------------------
     353             : 
     354             :   INTERFACE mean
     355             :     MODULE PROCEDURE mean_sp, mean_dp
     356             :   END INTERFACE mean
     357             : 
     358             :   ! ------------------------------------------------------------------
     359             : 
     360             :   !>    \brief R-s mixed central moment between vectors.
     361             : 
     362             :   !>    \details
     363             :   !!    Calculates the r,s-th mixed central moment between two vectors:
     364             :   !!
     365             :   !!    \f[\mu_{r-s} = \sum_i\frac{(x_i-\bar{x})^r(y_i-\bar{y})^s}{N}\f]
     366             :   !!
     367             :   !!    Note that covariace(x,y) = mixed_central_moment(x,y,1,1)
     368             :   !!
     369             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     370             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     371             :   !!
     372             :   !!    \b Example
     373             :   !!
     374             :   !!         vec1 = (/ 1., 2, 3., -999., 5., 6. /)
     375             :   !!         vec2 = (/ 1.3, 2.7, 3.9, 5.1, 6., 8. /)
     376             :   !!         m   = mixed_central_moment(vec1, vec2, 2, 2, mask=((vec1 >= 0.) .and. (vec2 >= 0.)))
     377             :   !!
     378             :   !!    See also example in test directory.
     379             :   !!
     380             :   !!    \b Literature
     381             :   !!
     382             :   !!    1. LH Benedict & RD Gould, _Towards better uncertainty estimates for turbulence statistics_,
     383             :   !!            Experiments in Fluids 22, 129-136, 1996
     384             :   !!
     385             :   !>    \param[in]  "real(sp/dp) :: x(:)"                 First 1D-array
     386             :   !>    \param[in]  "real(sp/dp) :: y(:)"                 Second 1D-array
     387             :   !>    \param[in]  "integer(i4) :: r"                    Order of x
     388             :   !>    \param[in]  "integer(i4) :: s"                    Order of y
     389             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with size(x).
     390             :   !!                                                      If present, only those locations in dat
     391             :   !!                                                      corresponding to the true values in mask are used.
     392             :   !>    \retval     "real(sp/dp) :: mixed_central_moment" r,s-th mixed central moment between x and y
     393             : 
     394             :   !>    \note Input values must be floating points.
     395             : 
     396             :   !>    \author Matthias Cuntz
     397             :   !>    \date Nov 2011
     398             : 
     399             :   ! ------------------------------------------------------------------
     400             : 
     401             :   INTERFACE mixed_central_moment
     402             :     MODULE PROCEDURE mixed_central_moment_sp, mixed_central_moment_dp
     403             :   END INTERFACE mixed_central_moment
     404             : 
     405             :   ! ------------------------------------------------------------------
     406             : 
     407             :   !>    \brief Mixed central moment variance.
     408             : 
     409             :   !>    \details
     410             :   !!    Calculates the sample variance of r,s-th mixed central moment between two vectors.
     411             :   !!    `mixed_central_moment_var` is something like the "error variance" of
     412             :   !!    the r,s-th order mixed central moment sampling statistic.
     413             :   !!
     414             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     415             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     416             :   !!
     417             :   !!    \b Example
     418             :   !!
     419             :   !!         vec1 = (/ 1., 2, 3., -999., 5., 6. /)
     420             :   !!         vec2 = (/ 1.3, 2.7, 3.9, 5.1, 6., 8. /)
     421             :   !!         em   = mixed_central_moment_var(vec1, vec2, 2, 2, mask=((vec1 >= 0.) .and. (vec2 >= 0.)))
     422             :   !!
     423             :   !!    See also example in test directory.
     424             :   !!
     425             :   !!    \b Literature
     426             :   !!
     427             :   !!    1. LH Benedict & RD Gould, _Towards better uncertainty estimates for turbulence statistics_,
     428             :   !!            Experiments in Fluids 22, 129-136, 1996
     429             :   !!
     430             :   !>    \param[in]  "real(sp/dp) :: x(:)"                       First 1D-array
     431             :   !>    \param[in]  "real(sp/dp) :: y(:)"                       Second 1D-array
     432             :   !>    \param[in]  "integer(i4) :: r"                          Order of x
     433             :   !>    \param[in]  "integer(i4) :: s"                          Order of y
     434             :   !>    \param[in]  "logical, optional :: mask(:)"              1D-array of logical values with size(x).
     435             :   !!                                                            If present, only those locations in dat
     436             :   !!                                                            corresponding to the true values in mask are used.
     437             :   !>    \retval     "real(sp/dp) :: mixed_central_moment_var"   Sampling variance of r,s-th mixed central moment between x and y
     438             : 
     439             :   !>    \note  Input values must be floating points.
     440             : 
     441             :   !>    \author Matthias Cuntz
     442             :   !>    \date Nov 2011
     443             : 
     444             :   INTERFACE mixed_central_moment_var
     445             :     MODULE PROCEDURE mixed_central_moment_var_sp, mixed_central_moment_var_dp
     446             :   END INTERFACE mixed_central_moment_var
     447             : 
     448             :   ! ------------------------------------------------------------------
     449             : 
     450             :   !>    \brief First four moments, stddev and mean absolute devation.
     451             : 
     452             :   !>    \details
     453             :   !!    Calculates the first four sample/population moments of a vector, i.e. mean, variance, skewness, and kurtosis,
     454             :   !!    as well as standard deviation and mean absolute devation.\n
     455             :   !!
     456             :   !!    All output is optional.
     457             :   !!
     458             :   !!    If an optinal mask is given, the calculations are over those locations that correspond to true values in the mask.
     459             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     460             :   !!
     461             :   !!    \b Example
     462             :   !!
     463             :   !!         vec = (/ 1., 2, 3., 4., 5., 6. /)
     464             :   !!         call moment(vec, average=average, variance=variance, skewness=skewness, kurtosis=kurtosis, &
     465             :   !!                    mean=mean, stddev=stddev, absdev=absdev, mask=mask, sample=sample)
     466             :   !!         --> average = 3.5
     467             : 
     468             :   !>    \param[in]  "real(sp/dp) :: dat(:)"               1D-array with input numbers.
     469             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with `size(dat)`.
     470             :   !!                                                      If present, only those locations in vec
     471             :   !!                                                      corresponding to the true values in mask are used.
     472             :   !>    \param[in]  "logical, optional :: sample"         Logical value.
     473             :   !!                                                      If present and False, the population variance and
     474             :   !!                                                      std-dev will be calculated (divide by n).
     475             : 
     476             :   !>    \param[out] "real(sp/dp), optional :: average"    Average of input vector.
     477             :   !>    \param[out] "real(sp/dp), optional :: variance"   Sample variance of input vector (either a sample or pupulation moment).
     478             :   !>    \param[out] "real(sp/dp), optional :: skewness"   Skewness of input vector.
     479             :   !>    \param[out] "real(sp/dp), optional :: kurtosis"   Excess kurtosis of input vector.
     480             :   !>    \param[out] "real(sp/dp), optional :: mean"       Same as average.
     481             :   !>    \param[out] "real(sp/dp), optional :: stddev"     Sqaure root of variance (either a sample or pupulation moment).
     482             :   !>    \param[out] "real(sp/dp), optional :: absdev"     Mean absolute deviations from average.
     483             : 
     484             :   !>    \note  Input values must be floating points. Inpt and all optional outputs must have same kind.
     485             : 
     486             :   !>    \author Matthias Cuntz
     487             :   !>    \date Nov 2011
     488             :   !>    \author Sebastian Mueller
     489             :   !>    \date Dec 2019
     490             :   !!        -   added optional sample input-para to switch sample to population variance and std-dev.
     491             : 
     492             :   ! ------------------------------------------------------------------
     493             : 
     494             :   INTERFACE moment
     495             :     MODULE PROCEDURE moment_sp, moment_dp
     496             :   END INTERFACE moment
     497             : 
     498             :   ! ------------------------------------------------------------------
     499             : 
     500             :   !>    \brief Skewness of a vector
     501             : 
     502             :   !>    \details
     503             :   !!    Calculates the skewness of a vector, i.e. the third standardised moment:
     504             :   !!
     505             :   !!    \f[\tilde \mu_3 = \sum_i\left(\frac{(x-\bar x)}{\sigma_x}\right)^3\f]
     506             :   !!
     507             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     508             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     509             :   !!
     510             :   !!    \b Example
     511             :   !!
     512             :   !!         vec = (/ 1., 2, 3., -999., 5., 6. /)
     513             :   !!         m   = skewness(vec, mask=(vec >= 0.))
     514             :   !!
     515             :   !!    See also example in test directory.
     516             : 
     517             : 
     518             :   !>    \param[in]  "real(sp/dp) :: dat(:)"               1D-array with input numbers.
     519             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with `size(dat)`.
     520             :   !!                                                      If present, only those locations in vec
     521             :   !!                                                      corresponding to the true values in mask are used.
     522             :   !>    \retval     "real(sp/dp) :: skewness"             Skewness of all elements in dat.
     523             : 
     524             :   !>    \note   Input values must be floating points.
     525             : 
     526             :   !>    \author Matthias Cuntz
     527             :   !>    \date Nov 2011
     528             :   INTERFACE skewness
     529             :     MODULE PROCEDURE skewness_sp, skewness_dp
     530             :   END INTERFACE skewness
     531             : 
     532             :   ! ------------------------------------------------------------------
     533             : 
     534             :   !>    \brief  Standard deviation of a vector.
     535             : 
     536             :   !>    \details
     537             :   !!    Calculates the sample standard deviation of a vector, i.e. the square root of the second moment
     538             :   !!
     539             :   !!    \f[\sigma_x = \sqrt{\sum_i\frac{(x_i-\bar x)^2}{N-1}}\f]
     540             :   !!
     541             :   !!    If an optinal mask is given, the average is only over those locations that correspond to true values in the mask.
     542             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     543             :   !!
     544             :   !!    \b Example
     545             :   !!
     546             :   !!         vec = (/ 1., 2, 3., -999., 5., 6. /)
     547             :   !!         m   = stddev(vec, mask=(vec >= 0.))
     548             :   !!
     549             :   !!    See also example in test directory
     550             : 
     551             :   !>    \param[in]  "real(sp/dp) :: dat(:)"               1D-array with input numbers.
     552             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with `size(dat)`.
     553             :   !!                                                      If present, only those locations in vec
     554             :   !!                                                      corresponding to the true values in mask are used.
     555             :   !>    \retval     "real(sp/dp) :: stddev"               Sample standard deviation of all elements in dat.
     556             : 
     557             :   !>    \note
     558             :   !!    Input values must be floating points.\n
     559             :   !!    This is the sample standard deviation. The population standard deviation is:
     560             :   !!            `popstddev = stddev * sqrt((n-1)/n)`
     561             : 
     562             :   !>    \author Matthias Cuntz
     563             :   !>    \date Nov 2011
     564             : 
     565             :   ! ------------------------------------------------------------------
     566             : 
     567             :   INTERFACE stddev
     568             :     MODULE PROCEDURE stddev_sp, stddev_dp
     569             :   END INTERFACE stddev
     570             : 
     571             :   ! ------------------------------------------------------------------
     572             : 
     573             :   !>    \brief  Standard deviation of a vector.
     574             : 
     575             :   !>    \details
     576             :   !!    Calculates the sample variance of a vector, i.e. the second moment
     577             :   !!
     578             :   !!    \f[\sigma_x^2 = \sum_i\frac{(x_i-\bar x)^2}{N-1}\f]
     579             :   !!
     580             :   !!    If an optional mask is given, the average is only over those locations that correspond to true values in the mask.
     581             :   !!    \f$x\f$ can be single or double precision. The result will have the same numerical precision.
     582             : 
     583             :    !!
     584             :   !!    \b Example
     585             :   !!
     586             :   !!         vec = (/ 1., 2, 3., -999., 5., 6. /)
     587             :   !!         m   = variance(vec, mask=(vec >= 0.))
     588             :   !!
     589             :   !!    See also example in test directory
     590             : 
     591             :   !>    \param[in]  "real(sp/dp) :: dat(:)"               1D-array with input numbers.
     592             :   !>    \param[in]  "logical, optional :: mask(:)"        1D-array of logical values with `size(dat)`.
     593             :   !!                                                      If present, only those locations in vec
     594             :   !!                                                      corresponding to the true values in mask are used.
     595             :   !>    \retval     "real(sp/dp) :: variance"             Sample variance of all elements in dat.
     596             : 
     597             :   !>    \note
     598             :   !!    Input values must be floating points.\n
     599             :   !!    This is the sample variance. The population variance is:
     600             :   !!             `var = variance * (n-1)/n`
     601             : 
     602             :   !>    \author Matthias Cuntz
     603             :   !>    \date Nov 2011
     604             :   INTERFACE variance
     605             :     MODULE PROCEDURE variance_sp, variance_dp
     606             :   END INTERFACE variance
     607             : 
     608             :   ! ------------------------------------------------------------------
     609             : 
     610             :   PRIVATE
     611             : 
     612             :   ! ------------------------------------------------------------------
     613             : 
     614             : CONTAINS
     615             : 
     616             :   ! ------------------------------------------------------------------
     617             : 
     618           6 :   FUNCTION absdev_dp(dat, mask)
     619             : 
     620             :     IMPLICIT NONE
     621             : 
     622             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
     623             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     624             :     REAL(dp) :: absdev_dp
     625             : 
     626           3 :     REAL(dp) :: n
     627             : 
     628           3 :     REAL(dp) :: ave
     629           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
     630             : 
     631           3 :     if (present(mask)) then
     632           1 :       if (size(mask) .ne. size(dat)) stop 'Error absdev_dp: size(mask) .ne. size(dat)'
     633          12 :       maske = mask
     634          11 :       n = real(count(maske), dp)
     635             :     else
     636          21 :       maske(:) = .true.
     637           2 :       n = real(size(dat), dp)
     638             :     end if
     639           3 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'absdev_dp: n must be at least 2'
     640             : 
     641             :     ! Average
     642          35 :     ave = sum(dat(:), mask = maske) / n
     643             :     ! Sum of absolute deviation
     644          32 :     absdev_dp = sum(abs(dat(:) - ave), mask = maske) / n
     645             : 
     646           3 :   END FUNCTION absdev_dp
     647             : 
     648             : 
     649           6 :   FUNCTION absdev_sp(dat, mask)
     650             : 
     651             :     IMPLICIT NONE
     652             : 
     653             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
     654             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     655             :     REAL(sp) :: absdev_sp
     656             : 
     657           3 :     REAL(sp) :: n
     658             : 
     659           3 :     REAL(sp) :: ave
     660           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
     661             : 
     662           3 :     if (present(mask)) then
     663           1 :       if (size(mask) .ne. size(dat)) stop 'Error absdev_sp: size(mask) .ne. size(dat)'
     664          12 :       maske = mask
     665          11 :       n = real(count(maske), sp)
     666             :     else
     667          21 :       maske(:) = .true.
     668           2 :       n = real(size(dat), sp)
     669             :     end if
     670           3 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'absdev_sp: n must be at least 2'
     671             : 
     672             :     ! Average
     673          35 :     ave = sum(dat(:), mask = maske) / n
     674             :     ! Sum of absolute deviation
     675          32 :     absdev_sp = sum(abs(dat(:) - ave), mask = maske) / n
     676             : 
     677           3 :   END FUNCTION absdev_sp
     678             : 
     679             :   ! ------------------------------------------------------------------
     680             : 
     681         130 :   FUNCTION average_dp(dat, mask)
     682             : 
     683             :     IMPLICIT NONE
     684             : 
     685             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
     686             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     687             :     REAL(dp) :: average_dp
     688             : 
     689          65 :     REAL(dp) :: n
     690          65 :     LOGICAL, DIMENSION(size(dat)) :: maske
     691             : 
     692          65 :     if (present(mask)) then
     693          59 :       if (size(mask) .ne. size(dat)) stop 'Error average_dp: size(mask) .ne. size(dat)'
     694        8948 :       maske = mask
     695        8889 :       n = real(count(maske), dp)
     696             :     else
     697         762 :       maske(:) = .true.
     698           6 :       n = real(size(dat), dp)
     699             :     end if
     700             : 
     701             :     ! Average
     702        9716 :     average_dp = sum(dat(:), mask = maske) / n
     703             : 
     704           3 :   END FUNCTION average_dp
     705             : 
     706             : 
     707         130 :   FUNCTION average_sp(dat, mask)
     708             : 
     709             :     IMPLICIT NONE
     710             : 
     711             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
     712             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     713             :     REAL(sp) :: average_sp
     714             : 
     715          65 :     REAL(sp) :: n
     716          65 :     LOGICAL, DIMENSION(size(dat)) :: maske
     717             : 
     718          65 :     if (present(mask)) then
     719          59 :       if (size(mask) .ne. size(dat)) stop 'Error average_sp: size(mask) .ne. size(dat)'
     720        8948 :       maske = mask
     721        8889 :       n = real(count(maske), sp)
     722             :     else
     723         762 :       maske(:) = .true.
     724           6 :       n = real(size(dat), sp)
     725             :     end if
     726             : 
     727             :     ! Average
     728        9716 :     average_sp = sum(dat(:), mask = maske) / n
     729             : 
     730          65 :   END FUNCTION average_sp
     731             : 
     732             :   ! ------------------------------------------------------------------
     733             : 
     734          36 :   FUNCTION central_moment_dp(x, r, mask)
     735             : 
     736             :     IMPLICIT NONE
     737             : 
     738             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
     739             :     INTEGER(i4), INTENT(IN) :: r
     740             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     741             :     REAL(dp) :: central_moment_dp
     742             : 
     743          18 :     REAL(dp) :: n, mx
     744          18 :     LOGICAL, DIMENSION(size(x)) :: maske
     745             : 
     746          18 :     if (r .lt. 0) then
     747          18 :       central_moment_dp = 0.0_dp
     748             :       return
     749             :     end if
     750          18 :     if (r .eq. 0) then
     751          18 :       central_moment_dp = 1.0_dp
     752             :       return
     753             :     end if
     754             : 
     755          18 :     if (present(mask)) then
     756          16 :       if (size(mask) .ne. size(x)) stop 'Error central_moment_dp: size(mask) .ne. size(x)'
     757         171 :       maske = mask
     758         171 :       n = real(count(maske), dp)
     759             :     else
     760          21 :       maske(:) = .true.
     761           2 :       n = real(size(x), dp)
     762             :     end if
     763          18 :     if (n .le. (2.0_dp + tiny(2.0_dp))) stop 'central_moment_dp: n must be at least 3'
     764             : 
     765             :     ! average
     766         192 :     mx = sum(x, mask = maske) / n
     767             :     ! central moment
     768         192 :     central_moment_dp = sum((x - mx)**r, mask = maske) / n
     769             : 
     770          83 :   END FUNCTION central_moment_dp
     771             : 
     772             : 
     773          36 :   FUNCTION central_moment_sp(x, r, mask)
     774             : 
     775             :     IMPLICIT NONE
     776             : 
     777             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
     778             :     INTEGER(i4), INTENT(IN) :: r
     779             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     780             :     REAL(sp) :: central_moment_sp
     781             : 
     782          18 :     REAL(sp) :: n, mx
     783          18 :     LOGICAL, DIMENSION(size(x)) :: maske
     784             : 
     785          18 :     if (r .lt. 0) then
     786          18 :       central_moment_sp = 0.0_sp
     787             :       return
     788             :     end if
     789          18 :     if (r .eq. 0) then
     790          18 :       central_moment_sp = 1.0_sp
     791             :       return
     792             :     end if
     793             : 
     794          18 :     if (present(mask)) then
     795          16 :       if (size(mask) .ne. size(x)) stop 'Error central_moment_sp: size(mask) .ne. size(x)'
     796         171 :       maske = mask
     797         171 :       n = real(count(maske), sp)
     798             :     else
     799          21 :       maske(:) = .true.
     800           2 :       n = real(size(x), sp)
     801             :     end if
     802          18 :     if (n .le. (2.0_sp + tiny(2.0_sp))) stop 'central_moment_sp: n must be at least 3'
     803             : 
     804             :     ! average
     805         192 :     mx = sum(x, mask = maske) / n
     806             :     ! central moment
     807         192 :     central_moment_sp = sum((x - mx)**r, mask = maske) / n
     808             : 
     809          36 :   END FUNCTION central_moment_sp
     810             : 
     811             :   ! ------------------------------------------------------------------
     812             : 
     813           6 :   FUNCTION central_moment_var_dp(x, r, mask)
     814             : 
     815             :     IMPLICIT NONE
     816             : 
     817             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
     818             :     INTEGER(i4), INTENT(IN) :: r
     819             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     820             :     REAL(dp) :: central_moment_var_dp
     821             : 
     822           3 :     REAL(dp) :: n, rr, u2r, ur, urm1, urp1, u2
     823           3 :     LOGICAL, DIMENSION(size(x)) :: maske
     824             : 
     825           3 :     if (r.le.1) then
     826           3 :       central_moment_var_dp = 0.0_dp
     827             :       return
     828             :     end if
     829             : 
     830           3 :     if (present(mask)) then
     831           1 :       if (size(mask) .ne. size(x)) stop 'Error central_moment_var_dp: size(mask) .ne. size(x)'
     832          11 :       maske = mask
     833          11 :       n = real(count(maske), dp)
     834             :     else
     835          21 :       maske(:) = .true.
     836           2 :       n = real(size(x), dp)
     837             :     end if
     838           3 :     if (n .le. (2.0_dp + tiny(2.0_dp))) stop 'central_moment_var_dp: n must be at least 3'
     839             : 
     840           3 :     u2r = central_moment(x, 2 * r, mask = maske)
     841           3 :     ur = central_moment(x, r, mask = maske)
     842           3 :     urm1 = central_moment(x, r - 1, mask = maske)
     843           3 :     u2 = central_moment(x, 2, mask = maske)
     844           3 :     urp1 = central_moment(x, r + 1, mask = maske)
     845           3 :     rr = real(r, dp)
     846           3 :     central_moment_var_dp = (u2r - ur * ur + rr * rr * urm1 * urm1 * u2 - 2.0_dp * rr * urp1 * urm1) / n
     847             : 
     848          21 :   END FUNCTION central_moment_var_dp
     849             : 
     850             : 
     851           6 :   FUNCTION central_moment_var_sp(x, r, mask)
     852             : 
     853             :     IMPLICIT NONE
     854             : 
     855             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
     856             :     INTEGER(i4), INTENT(IN) :: r
     857             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     858             :     REAL(sp) :: central_moment_var_sp
     859             : 
     860           3 :     REAL(sp) :: n, rr, u2r, ur, urm1, urp1, u2
     861           3 :     LOGICAL, DIMENSION(size(x)) :: maske
     862             : 
     863           3 :     if (r.le.1) then
     864           3 :       central_moment_var_sp = 0.0_sp
     865             :       return
     866             :     end if
     867             : 
     868           3 :     if (present(mask)) then
     869           1 :       if (size(mask) .ne. size(x)) stop 'Error central_moment_var_sp: size(mask) .ne. size(x)'
     870          11 :       maske = mask
     871          11 :       n = real(count(maske), sp)
     872             :     else
     873          21 :       maske(:) = .true.
     874           2 :       n = real(size(x), sp)
     875             :     end if
     876           3 :     if (n .le. (2.0_sp + tiny(2.0_sp))) stop 'central_moment_var_sp: n must be at least 3'
     877             : 
     878           3 :     u2r = central_moment(x, 2 * r, mask = maske)
     879           3 :     ur = central_moment(x, r, mask = maske)
     880           3 :     urm1 = central_moment(x, r - 1, mask = maske)
     881           3 :     u2 = central_moment(x, 2, mask = maske)
     882           3 :     urp1 = central_moment(x, r + 1, mask = maske)
     883           3 :     rr = real(r, sp)
     884           3 :     central_moment_var_sp = (u2r - ur * ur + rr * rr * urm1 * urm1 * u2 - 2.0_sp * rr * urp1 * urm1) / n
     885             : 
     886           6 :   END FUNCTION central_moment_var_sp
     887             : 
     888             :   ! ------------------------------------------------------------------
     889             : 
     890          18 :   FUNCTION correlation_dp(x, y, mask)
     891             : 
     892             :     IMPLICIT NONE
     893             : 
     894             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
     895             :     REAL(dp), DIMENSION(:), INTENT(IN) :: y
     896             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     897             :     REAL(dp) :: correlation_dp
     898             : 
     899           9 :     REAL(dp) :: n
     900           9 :     REAL(dp) :: mx, my
     901           9 :     REAL(dp) :: sx, sy, covar
     902           9 :     LOGICAL, DIMENSION(size(x)) :: maske
     903             : 
     904           9 :     if (size(x) .ne. size(y)) stop 'Error correlation_dp: size(x) .ne. size(y)'
     905           9 :     if (present(mask)) then
     906           7 :       if (size(mask) .ne. size(x)) stop 'Error correlation_dp: size(mask) .ne. size(x)'
     907        1104 :       maske = mask
     908        1097 :       n = real(count(maske), dp)
     909             :     else
     910          21 :       maske(:) = .true.
     911           2 :       n = real(size(x), dp)
     912             :     end if
     913           9 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'correlation_dp: n must be at least 2'
     914             : 
     915             :     ! Mean and Stddev of x and y
     916           9 :     call moment(x, mx, stddev = sx, mask = maske)
     917           9 :     call moment(y, my, stddev = sy, mask = maske)
     918        1118 :     covar = sum((x - mx) * (y - my), mask = maske) / n
     919             :     ! correlation
     920           9 :     correlation_dp = covar / (sx * sy)
     921             : 
     922           3 :   END FUNCTION correlation_dp
     923             : 
     924             : 
     925          18 :   FUNCTION correlation_sp(x, y, mask)
     926             : 
     927             :     IMPLICIT NONE
     928             : 
     929             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
     930             :     REAL(sp), DIMENSION(:), INTENT(IN) :: y
     931             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     932             :     REAL(sp) :: correlation_sp
     933             : 
     934           9 :     REAL(sp) :: n
     935           9 :     REAL(sp) :: mx, my
     936           9 :     REAL(sp) :: sx, sy, covar
     937           9 :     LOGICAL, DIMENSION(size(x)) :: maske
     938             : 
     939           9 :     if (size(x) .ne. size(y)) stop 'Error correlation_sp: size(x) .ne. size(y)'
     940           9 :     if (present(mask)) then
     941           7 :       if (size(mask) .ne. size(x)) stop 'Error correlation_sp: size(mask) .ne. size(x)'
     942        1104 :       maske = mask
     943        1097 :       n = real(count(maske), sp)
     944             :     else
     945          21 :       maske(:) = .true.
     946           2 :       n = real(size(x), sp)
     947             :     end if
     948           9 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'correlation_sp: n must be at least 2'
     949             : 
     950             :     ! Mean and Stddev of x and y
     951           9 :     call moment(x, mx, stddev = sx, mask = maske)
     952           9 :     call moment(y, my, stddev = sy, mask = maske)
     953        1118 :     covar = sum((x - mx) * (y - my), mask = maske) / n
     954             :     ! correlation
     955           9 :     correlation_sp = covar / (sx * sy)
     956             : 
     957           9 :   END FUNCTION correlation_sp
     958             : 
     959             :   ! ------------------------------------------------------------------
     960             : 
     961           6 :   FUNCTION covariance_dp(x, y, mask)
     962             : 
     963             :     IMPLICIT NONE
     964             : 
     965             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
     966             :     REAL(dp), DIMENSION(:), INTENT(IN) :: y
     967             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
     968             :     REAL(dp) :: covariance_dp
     969             : 
     970           3 :     REAL(dp) :: n
     971           3 :     REAL(dp) :: mx, my
     972           3 :     LOGICAL, DIMENSION(size(x)) :: maske
     973             : 
     974           3 :     if (size(x) .ne. size(y)) stop 'Error covariance_dp: size(x) .ne. size(y)'
     975           3 :     if (present(mask)) then
     976           1 :       if (size(mask) .ne. size(x)) stop 'Error covariance_dp: size(mask) .ne. size(x)'
     977          12 :       maske = mask
     978          11 :       n = real(count(maske), dp)
     979             :     else
     980          21 :       maske(:) = .true.
     981           2 :       n = real(size(x), dp)
     982             :     end if
     983           3 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'covariance_dp: n must be at least 2'
     984             : 
     985             :     ! Mean of x and y
     986           3 :     mx = mean(x, mask = maske)
     987           3 :     my = mean(y, mask = maske)
     988          35 :     covariance_dp = sum((x - mx) * (y - my), mask = maske) / n
     989             : 
     990           9 :   END FUNCTION covariance_dp
     991             : 
     992             : 
     993           6 :   FUNCTION covariance_sp(x, y, mask)
     994             : 
     995             :     IMPLICIT NONE
     996             : 
     997             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
     998             :     REAL(sp), DIMENSION(:), INTENT(IN) :: y
     999             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1000             :     REAL(sp) :: covariance_sp
    1001             : 
    1002           3 :     REAL(sp) :: n
    1003           3 :     REAL(sp) :: mx, my
    1004           3 :     LOGICAL, DIMENSION(size(x)) :: maske
    1005             : 
    1006           3 :     if (size(x) .ne. size(y)) stop 'Error covariance_sp: size(x) .ne. size(y)'
    1007           3 :     if (present(mask)) then
    1008           1 :       if (size(mask) .ne. size(x)) stop 'Error covariance_sp: size(mask) .ne. size(x)'
    1009          12 :       maske = mask
    1010          11 :       n = real(count(maske), sp)
    1011             :     else
    1012          21 :       maske(:) = .true.
    1013           2 :       n = real(size(x), sp)
    1014             :     end if
    1015           3 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'covariance_sp: n must be at least 2'
    1016             : 
    1017             :     ! Mean of x and y
    1018           3 :     mx = mean(x, mask = maske)
    1019           3 :     my = mean(y, mask = maske)
    1020          35 :     covariance_sp = sum((x - mx) * (y - my), mask = maske) / n
    1021             : 
    1022           3 :   END FUNCTION covariance_sp
    1023             : 
    1024             :   ! ------------------------------------------------------------------
    1025             : 
    1026           6 :   FUNCTION kurtosis_dp(dat, mask)
    1027             : 
    1028             :     IMPLICIT NONE
    1029             : 
    1030             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1031             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1032             :     REAL(dp) :: kurtosis_dp
    1033             : 
    1034           3 :     REAL(dp) :: n
    1035             : 
    1036          35 :     REAL(dp) :: ep, ave, var
    1037          67 :     REAL(dp), DIMENSION(size(dat)) :: p, s
    1038           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1039             : 
    1040           3 :     if (present(mask)) then
    1041           1 :       if (size(mask) .ne. size(dat)) stop 'Error kurtosis_dp: size(mask) .ne. size(dat)'
    1042          12 :       maske = mask
    1043          11 :       n = real(count(maske), dp)
    1044             :     else
    1045          21 :       maske(:) = .true.
    1046           2 :       n = real(size(dat), dp)
    1047             :     end if
    1048           3 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'kurtosis_dp: n must be at least 2'
    1049             : 
    1050             :     ! Average
    1051          35 :     ave = sum(dat(:), mask = maske) / n
    1052          32 :     s(:) = dat(:) - ave
    1053             :     ! Variance / Standard deviation
    1054          32 :     ep = sum(s(:), mask = maske)
    1055          32 :     p(:) = s(:) * s(:)
    1056          32 :     var = sum(p(:), mask = maske)
    1057           3 :     var = (var - ep * ep / n) / (n - 1.0_dp)
    1058           3 :     if (abs(var) .lt. tiny(0.0_dp)) stop 'kurtosis_dp: no kurtosis when zero variance'
    1059             :     ! Kurtosis
    1060          32 :     p(:) = p(:) * s(:) * s(:)
    1061          32 :     kurtosis_dp = sum(p(:), mask = maske)
    1062           3 :     kurtosis_dp = kurtosis_dp / (n * var * var) - 3.0_dp
    1063             : 
    1064           3 :   END FUNCTION kurtosis_dp
    1065             : 
    1066             : 
    1067           6 :   FUNCTION kurtosis_sp(dat, mask)
    1068             : 
    1069             :     IMPLICIT NONE
    1070             : 
    1071             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1072             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1073             :     REAL(sp) :: kurtosis_sp
    1074             : 
    1075           3 :     REAL(sp) :: n
    1076             : 
    1077          35 :     REAL(sp) :: ep, ave, var
    1078          67 :     REAL(sp), DIMENSION(size(dat)) :: p, s
    1079           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1080             : 
    1081           3 :     if (present(mask)) then
    1082           1 :       if (size(mask) .ne. size(dat)) stop 'Error kurtosis_sp: size(mask) .ne. size(dat)'
    1083          12 :       maske = mask
    1084          11 :       n = real(count(maske), sp)
    1085             :     else
    1086          21 :       maske(:) = .true.
    1087           2 :       n = real(size(dat), sp)
    1088             :     end if
    1089           3 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'kurtosis_sp: n must be at least 2'
    1090             : 
    1091             :     ! Average
    1092          35 :     ave = sum(dat(:), mask = maske) / n
    1093          32 :     s(:) = dat(:) - ave
    1094             :     ! Variance / Standard deviation
    1095          32 :     ep = sum(s(:), mask = maske)
    1096          32 :     p(:) = s(:) * s(:)
    1097          32 :     var = sum(p(:), mask = maske)
    1098           3 :     var = (var - ep * ep / n) / (n - 1.0_sp)
    1099           3 :     if (abs(var) .lt. tiny(0.0_sp)) stop 'kurtosis_sp: no kurtosis when zero variance'
    1100             :     ! Kurtosis
    1101          32 :     p(:) = p(:) * s(:) * s(:)
    1102          32 :     kurtosis_sp = sum(p(:), mask = maske)
    1103           3 :     kurtosis_sp = kurtosis_sp / (n * var * var) - 3.0_sp
    1104             : 
    1105           3 :   END FUNCTION kurtosis_sp
    1106             : 
    1107             :   ! ------------------------------------------------------------------
    1108             : 
    1109     9084348 :   FUNCTION mean_dp(dat, mask)
    1110             : 
    1111             :     IMPLICIT NONE
    1112             : 
    1113             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1114             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1115             :     REAL(dp) :: mean_dp
    1116             : 
    1117     4542174 :     REAL(dp) :: n
    1118             : 
    1119     4542174 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1120             : 
    1121     4542174 :     if (present(mask)) then
    1122     4542163 :       if (size(mask) .ne. size(dat)) stop 'Error mean_dp: size(mask) .ne. size(dat)'
    1123    46356358 :       maske = mask
    1124    41814195 :       n = real(count(maske), dp)
    1125             :     else
    1126      225030 :       maske(:) = .true.
    1127          11 :       n = real(size(dat), dp)
    1128             :     end if
    1129             : 
    1130             :     ! Mean
    1131    46581399 :     mean_dp = sum(dat(:), mask = maske) / n
    1132             : 
    1133           3 :   END FUNCTION mean_dp
    1134             : 
    1135             :   !> \copydoc mean
    1136          18 :   FUNCTION mean_sp(dat, mask)
    1137             : 
    1138             :     IMPLICIT NONE
    1139             : 
    1140             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1141             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1142             :     REAL(sp) :: mean_sp
    1143             : 
    1144           9 :     REAL(sp) :: n
    1145             : 
    1146           9 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1147             : 
    1148           9 :     if (present(mask)) then
    1149           7 :       if (size(mask) .ne. size(dat)) stop 'Error mean_sp: size(mask) .ne. size(dat)'
    1150          82 :       maske = mask
    1151          75 :       n = real(count(maske), sp)
    1152             :     else
    1153          21 :       maske(:) = .true.
    1154           2 :       n = real(size(dat), sp)
    1155             :     end if
    1156             : 
    1157             :     ! Mean
    1158         105 :     mean_sp = sum(dat(:), mask = maske) / n
    1159             : 
    1160     4542174 :   END FUNCTION mean_sp
    1161             : 
    1162             :   ! ------------------------------------------------------------------
    1163             : 
    1164          60 :   FUNCTION mixed_central_moment_dp(x, y, r, s, mask)
    1165             : 
    1166             :     IMPLICIT NONE
    1167             : 
    1168             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
    1169             :     REAL(dp), DIMENSION(:), INTENT(IN) :: y
    1170             :     INTEGER(i4), INTENT(IN) :: r
    1171             :     INTEGER(i4), INTENT(IN) :: s
    1172             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1173             :     REAL(dp) :: mixed_central_moment_dp
    1174             : 
    1175          30 :     REAL(dp) :: n, mx, my
    1176         610 :     REAL(dp), DIMENSION(size(x)) :: xx, yy
    1177          30 :     LOGICAL, DIMENSION(size(x)) :: maske
    1178             : 
    1179          30 :     if (r.lt.0 .or. s.lt.0) then
    1180          30 :       mixed_central_moment_dp = 0.0_dp
    1181             :       return
    1182             :     end if
    1183             : 
    1184          30 :     if (size(x) .ne. size(y)) stop 'Error mixed_central_moment_dp: size(x) .ne. size(y)'
    1185          30 :     if (present(mask)) then
    1186          28 :       if (size(mask) .ne. size(x)) stop 'Error mixed_central_moment_dp: size(mask) .ne. size(x)'
    1187         299 :       maske = mask
    1188         299 :       n = real(count(maske), dp)
    1189             :     else
    1190          21 :       maske(:) = .true.
    1191           2 :       n = real(size(x), dp)
    1192             :     end if
    1193          30 :     if (n .le. (2.0_dp + tiny(2.0_dp))) stop 'mixed_central_moment_dp: n must be at least 3'
    1194             : 
    1195             :     ! Averages of x and y
    1196         320 :     mx = sum(x, mask = maske) / n
    1197         320 :     my = sum(y, mask = maske) / n
    1198             :     ! Mixed central moment
    1199          30 :     if (r>0) then
    1200         256 :       xx = (x - mx)**r
    1201             :     else
    1202          64 :       xx = 1._dp
    1203             :     end if
    1204          30 :     if (s>0) then
    1205         256 :       yy = (y - my)**s
    1206             :     else
    1207          64 :       yy = 1._dp
    1208             :     end if
    1209         320 :     mixed_central_moment_dp = sum(xx * yy, mask = maske) / n
    1210             : 
    1211          39 :   END FUNCTION mixed_central_moment_dp
    1212             : 
    1213             : 
    1214          60 :   FUNCTION mixed_central_moment_sp(x, y, r, s, mask)
    1215             : 
    1216             :     IMPLICIT NONE
    1217             : 
    1218             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
    1219             :     REAL(sp), DIMENSION(:), INTENT(IN) :: y
    1220             :     INTEGER(i4), INTENT(IN) :: r
    1221             :     INTEGER(i4), INTENT(IN) :: s
    1222             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1223             :     REAL(sp) :: mixed_central_moment_sp
    1224             : 
    1225          30 :     REAL(sp) :: n, mx, my
    1226         610 :     REAL(sp), DIMENSION(size(x)) :: xx, yy
    1227          30 :     LOGICAL, DIMENSION(size(x)) :: maske
    1228             : 
    1229          30 :     if (r.lt.0 .or. s.lt.0) then
    1230          30 :       mixed_central_moment_sp = 0.0_sp
    1231             :       return
    1232             :     end if
    1233             : 
    1234          30 :     if (size(x) .ne. size(y)) stop 'Error mixed_central_moment_sp: size(x) .ne. size(y)'
    1235          30 :     if (present(mask)) then
    1236          28 :       if (size(mask) .ne. size(x)) stop 'Error mixed_central_moment_sp: size(mask) .ne. size(x)'
    1237         299 :       maske = mask
    1238         299 :       n = real(count(maske), sp)
    1239             :     else
    1240          21 :       maske(:) = .true.
    1241           2 :       n = real(size(x), sp)
    1242             :     end if
    1243          30 :     if (n .le. (2.0_sp + tiny(2.0_sp))) stop 'mixed_central_moment_sp: n must be at least 3'
    1244             : 
    1245             :     ! Averages of x and y
    1246         320 :     mx = sum(x, mask = maske) / n
    1247         320 :     my = sum(y, mask = maske) / n
    1248             :     ! Mixed central moment
    1249          30 :     if (r>0) then
    1250         256 :       xx = (x - mx)**r
    1251             :     else
    1252          64 :       xx = 1._sp
    1253             :     end if
    1254          30 :     if (s>0) then
    1255         256 :       yy = (y - my)**s
    1256             :     else
    1257          64 :       yy = 1._sp
    1258             :     end if
    1259         320 :     mixed_central_moment_sp = sum(xx * yy, mask = maske) / n
    1260             : 
    1261          60 :   END FUNCTION mixed_central_moment_sp
    1262             : 
    1263             :   ! ------------------------------------------------------------------
    1264             : 
    1265           6 :   FUNCTION mixed_central_moment_var_dp(x, y, r, s, mask)
    1266             :     ! Error variance of mixed central moment (Benedict & Gould 1996)
    1267             :     IMPLICIT NONE
    1268             : 
    1269             :     REAL(dp), DIMENSION(:), INTENT(IN) :: x
    1270             :     REAL(dp), DIMENSION(:), INTENT(IN) :: y
    1271             :     INTEGER(i4), INTENT(IN) :: r
    1272             :     INTEGER(i4), INTENT(IN) :: s
    1273             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1274             :     REAL(dp) :: mixed_central_moment_var_dp
    1275             : 
    1276           3 :     REAL(dp) :: u2r2s, urs, urm1s, u20, urp1s, ursm1, u02, ursp1, u11
    1277           3 :     REAL(dp) :: n, rr, ss
    1278           3 :     LOGICAL, DIMENSION(size(x)) :: maske
    1279             : 
    1280           3 :     if (size(x) .ne. size(y)) stop 'Error mixed_central_moment_var_dp: size(x) .ne. size(y)'
    1281           3 :     if (present(mask)) then
    1282           1 :       if (size(mask) .ne. size(x)) stop 'Error mixed_central_moment_var_dp: size(mask) .ne. size(x)'
    1283          11 :       maske = mask
    1284          11 :       n = real(count(maske), dp)
    1285             :     else
    1286          21 :       maske(:) = .true.
    1287           2 :       n = real(size(x), dp)
    1288             :     end if
    1289           3 :     if (n .le. (2.0_dp + tiny(2.0_dp))) stop 'mixed_central_moment_var_dp: n must be at least 3'
    1290             : 
    1291           3 :     u2r2s = mixed_central_moment(x, y, 2 * r, 2 * s, mask = maske)
    1292           3 :     urs = mixed_central_moment(x, y, r, s, mask = maske)
    1293           3 :     urm1s = mixed_central_moment(x, y, r - 1, s, mask = maske)
    1294           3 :     u20 = mixed_central_moment(x, y, 2, 0, mask = maske)
    1295           3 :     urp1s = mixed_central_moment(x, y, r + 1, s, mask = maske)
    1296           3 :     ursm1 = mixed_central_moment(x, y, r, s - 1, mask = maske)
    1297           3 :     u02 = mixed_central_moment(x, y, 0, 2, mask = maske)
    1298           3 :     ursp1 = mixed_central_moment(x, y, r, s + 1, mask = maske)
    1299           3 :     u11 = mixed_central_moment(x, y, 1, 1, mask = maske)
    1300           3 :     rr = real(r, dp)
    1301           3 :     ss = real(s, dp)
    1302             : 
    1303             :     mixed_central_moment_var_dp = (u2r2s - urs * urs &
    1304             :             + rr * rr**u20 * urm1s * urm1s + ss * ss * u02 * ursm1 * ursm1 &
    1305             :             + 2.0_dp * rr * ss * u11 * urm1s * ursm1 &
    1306           3 :             - 2.0_dp * rr * urp1s * urm1s - 2.0_dp * ss * ursp1 * ursm1) / n
    1307             : 
    1308          30 :   END FUNCTION mixed_central_moment_var_dp
    1309             : 
    1310             : 
    1311           6 :   FUNCTION mixed_central_moment_var_sp(x, y, r, s, mask)
    1312             :     ! Error variance of mixed central moment (Benedict & Gould 1996)
    1313             :     IMPLICIT NONE
    1314             : 
    1315             :     REAL(sp), DIMENSION(:), INTENT(IN) :: x
    1316             :     REAL(sp), DIMENSION(:), INTENT(IN) :: y
    1317             :     INTEGER(i4), INTENT(IN) :: r
    1318             :     INTEGER(i4), INTENT(IN) :: s
    1319             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1320             :     REAL(sp) :: mixed_central_moment_var_sp
    1321             : 
    1322           3 :     REAL(sp) :: u2r2s, urs, urm1s, u20, urp1s, ursm1, u02, ursp1, u11
    1323           3 :     REAL(sp) :: n, rr, ss
    1324           3 :     LOGICAL, DIMENSION(size(x)) :: maske
    1325             : 
    1326           3 :     if (size(x) .ne. size(y)) stop 'Error mixed_central_moment_var_sp: size(x) .ne. size(y)'
    1327           3 :     if (present(mask)) then
    1328           1 :       if (size(mask) .ne. size(x)) stop 'Error mixed_central_moment_var_sp: size(mask) .ne. size(x)'
    1329          11 :       maske = mask
    1330          11 :       n = real(count(maske), sp)
    1331             :     else
    1332          21 :       maske(:) = .true.
    1333           2 :       n = real(size(x), sp)
    1334             :     end if
    1335           3 :     if (n .le. (2.0_sp + tiny(2.0_sp))) stop 'mixed_central_moment_var_sp: n must be at least 3'
    1336             : 
    1337           3 :     u2r2s = mixed_central_moment(x, y, 2 * r, 2 * s, mask = maske)
    1338           3 :     urs = mixed_central_moment(x, y, r, s, mask = maske)
    1339           3 :     urm1s = mixed_central_moment(x, y, r - 1, s, mask = maske)
    1340           3 :     u20 = mixed_central_moment(x, y, 2, 0, mask = maske)
    1341           3 :     urp1s = mixed_central_moment(x, y, r + 1, s, mask = maske)
    1342           3 :     ursm1 = mixed_central_moment(x, y, r, s - 1, mask = maske)
    1343           3 :     u02 = mixed_central_moment(x, y, 0, 2, mask = maske)
    1344           3 :     ursp1 = mixed_central_moment(x, y, r, s + 1, mask = maske)
    1345           3 :     u11 = mixed_central_moment(x, y, 1, 1, mask = maske)
    1346           3 :     rr = real(r, sp)
    1347           3 :     ss = real(s, sp)
    1348             : 
    1349             :     mixed_central_moment_var_sp = (u2r2s - urs * urs &
    1350             :             + rr * rr**u20 * urm1s * urm1s + ss * ss * u02 * ursm1 * ursm1 &
    1351             :             + 2.0_sp * rr * ss * u11 * urm1s * ursm1 &
    1352           3 :             - 2.0_sp * rr * urp1s * urm1s - 2.0_sp * ss * ursp1 * ursm1) / n
    1353             : 
    1354           3 :   END FUNCTION mixed_central_moment_var_sp
    1355             : 
    1356             :   ! ------------------------------------------------------------------
    1357             : 
    1358          48 :   SUBROUTINE moment_dp(dat, average, variance, skewness, kurtosis, mean, stddev, absdev, mask, sample)
    1359             : 
    1360             :     IMPLICIT NONE
    1361             : 
    1362             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1363             :     REAL(dp), OPTIONAL, INTENT(OUT) :: average
    1364             :     REAL(dp), OPTIONAL, INTENT(OUT) :: variance
    1365             :     REAL(dp), OPTIONAL, INTENT(OUT) :: skewness
    1366             :     REAL(dp), OPTIONAL, INTENT(OUT) :: kurtosis
    1367             :     REAL(dp), OPTIONAL, INTENT(OUT) :: mean
    1368             :     REAL(dp), OPTIONAL, INTENT(OUT) :: stddev
    1369             :     REAL(dp), OPTIONAL, INTENT(OUT) :: absdev
    1370             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1371             :     LOGICAL, OPTIONAL, INTENT(IN) :: sample
    1372             : 
    1373          24 :     REAL(dp) :: n, div_n  ! divisor depending if sample or population moments
    1374             : 
    1375        9776 :     REAL(dp) :: ep, ave, var
    1376       19480 :     REAL(dp), DIMENSION(size(dat)) :: p, s
    1377          24 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1378             : 
    1379          24 :     if (present(mask)) then
    1380          24 :       if (size(mask) .ne. size(dat)) stop 'Error moment_dp: size(mask) .ne. size(dat)'
    1381        9752 :       maske = mask
    1382        9752 :       n = real(count(maske), sp)
    1383             :     else
    1384           0 :       maske(:) = .true.
    1385           0 :       n = real(size(dat), sp)
    1386             :     end if
    1387          24 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'moment_dp: n must be at least 2'
    1388             : 
    1389             :     ! set divisor for population (n) or sample (n-1) variance
    1390          24 :     div_n = n - 1.0_dp
    1391          24 :     if (present(sample)) then
    1392           5 :       if (.not. sample) div_n = n
    1393             :     end if
    1394             : 
    1395             :     ! Any optional argument
    1396          24 :     if (.not. (present(average) .or. present(variance) .or. present(skewness) .or. &
    1397             :             present(kurtosis) .or. present(mean) .or. present(stddev) .or. present(absdev))) return
    1398             :     ! Average
    1399        9752 :     ave = sum(dat(:), mask = maske) / n
    1400          24 :     if (present(average)) average = ave
    1401          24 :     if (present(mean))    mean = ave
    1402          24 :     if (.not. (present(variance) .or. present(skewness) .or. &
    1403             :             present(kurtosis) .or. present(stddev) .or. present(absdev))) return
    1404             :     ! Absolute deviation
    1405        9752 :     s(:) = dat(:) - ave
    1406          34 :     if (present(absdev)) absdev = sum(abs(s(:)), mask = maske) / n
    1407             :     ! Variance / Standard deviation
    1408          24 :     if (.not. (present(variance) .or. present(skewness) .or. &
    1409             :             present(kurtosis) .or. present(stddev))) return
    1410        9752 :     ep = sum(s(:), mask = maske)
    1411        9752 :     p(:) = s(:) * s(:)
    1412        9752 :     var = sum(p(:), mask = maske)
    1413          24 :     var = (var - ep * ep / n) / div_n
    1414          24 :     if (present(variance)) variance = var
    1415             :     ! Standard deviation
    1416          24 :     if (present(stddev))   stddev = sqrt(var)
    1417          24 :     if (.not. (present(skewness) .or. present(kurtosis))) return
    1418             :     ! Skewness
    1419           1 :     if (abs(var) .lt. tiny(0.0_dp)) stop 'moment_dp: no skewness or kurtosis when zero variance'
    1420          11 :     p(:) = p(:) * s(:)
    1421           1 :     if (present(skewness)) then
    1422          11 :       skewness = sum(p(:), mask = maske)
    1423           1 :       skewness = skewness / (n * stddev * stddev * stddev)
    1424             :     end if
    1425             :     ! Kurtosis
    1426           1 :     if (present(kurtosis)) then
    1427          11 :       p(:) = p(:) * s(:)
    1428          11 :       kurtosis = sum(p(:), mask = maske)
    1429           1 :       kurtosis = kurtosis / (n * variance * variance) - 3.0_dp
    1430             :     end if
    1431             : 
    1432          27 :   END SUBROUTINE moment_dp
    1433             : 
    1434             : 
    1435          48 :   SUBROUTINE moment_sp(dat, average, variance, skewness, kurtosis, mean, stddev, absdev, mask, sample)
    1436             : 
    1437             :     IMPLICIT NONE
    1438             : 
    1439             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1440             :     REAL(sp), OPTIONAL, INTENT(OUT) :: average
    1441             :     REAL(sp), OPTIONAL, INTENT(OUT) :: variance
    1442             :     REAL(sp), OPTIONAL, INTENT(OUT) :: skewness
    1443             :     REAL(sp), OPTIONAL, INTENT(OUT) :: kurtosis
    1444             :     REAL(sp), OPTIONAL, INTENT(OUT) :: mean
    1445             :     REAL(sp), OPTIONAL, INTENT(OUT) :: stddev
    1446             :     REAL(sp), OPTIONAL, INTENT(OUT) :: absdev
    1447             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1448             :     LOGICAL, OPTIONAL, INTENT(IN) :: sample
    1449             : 
    1450          24 :     REAL(sp) :: n, div_n  ! divisor depending if sample or population moments
    1451             : 
    1452        9776 :     REAL(sp) :: ep, ave, var
    1453       19480 :     REAL(sp), DIMENSION(size(dat)) :: p, s
    1454          24 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1455             : 
    1456          24 :     if (present(mask)) then
    1457          24 :       if (size(mask) .ne. size(dat)) stop 'Error moment_sp: size(mask) .ne. size(dat)'
    1458        9752 :       maske = mask
    1459        9752 :       n = real(count(maske), sp)
    1460             :     else
    1461           0 :       maske(:) = .true.
    1462           0 :       n = real(size(dat), sp)
    1463             :     end if
    1464          24 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'moment_sp: n must be at least 2'
    1465             : 
    1466             :     ! set divisor for population (n) or sample (n-1) variance
    1467          24 :     div_n = n - 1.0_sp
    1468          24 :     if (present(sample)) then
    1469           5 :       if (.not. sample) div_n = n
    1470             :     end if
    1471             : 
    1472             :     ! Any optional argument
    1473          24 :     if (.not. (present(average) .or. present(variance) .or. present(skewness) .or. &
    1474             :             present(kurtosis) .or. present(mean) .or. present(stddev) .or. present(absdev))) return
    1475             :     ! Average
    1476        9752 :     ave = sum(dat(:), mask = maske) / n
    1477          24 :     if (present(average)) average = ave
    1478          24 :     if (present(mean))    mean = ave
    1479          24 :     if (.not. (present(variance) .or. present(skewness) .or. &
    1480             :             present(kurtosis) .or. present(stddev) .or. present(absdev))) return
    1481             :     ! Absolute deviation
    1482        9752 :     s(:) = dat(:) - ave
    1483          34 :     if (present(absdev)) absdev = sum(abs(s(:)), mask = maske) / n
    1484             :     ! Variance / Standard deviation
    1485          24 :     if (.not. (present(variance) .or. present(skewness) .or. &
    1486             :             present(kurtosis) .or. present(stddev))) return
    1487        9752 :     ep = sum(s(:), mask = maske)
    1488        9752 :     p(:) = s(:) * s(:)
    1489        9752 :     var = sum(p(:), mask = maske)
    1490          24 :     var = (var - ep * ep / n) / div_n
    1491          24 :     if (present(variance)) variance = var
    1492             :     ! Standard deviation
    1493          24 :     if (present(stddev))   stddev = sqrt(var)
    1494          24 :     if (.not. (present(skewness) .or. present(kurtosis))) return
    1495             :     ! Skewness
    1496           1 :     if (abs(var) .lt. tiny(0.0_sp)) stop 'moment_sp: no skewness or kurtosis when zero variance'
    1497          11 :     p(:) = p(:) * s(:)
    1498           1 :     if (present(skewness)) then
    1499          11 :       skewness = sum(p(:), mask = maske)
    1500           1 :       skewness = skewness / (n * stddev * stddev * stddev)
    1501             :     end if
    1502             :     ! Kurtosis
    1503           1 :     if (present(kurtosis)) then
    1504          11 :       p(:) = p(:) * s(:)
    1505          11 :       kurtosis = sum(p(:), mask = maske)
    1506           1 :       kurtosis = kurtosis / (n * variance * variance) - 3.0_sp
    1507             :     end if
    1508             : 
    1509          48 :   END SUBROUTINE moment_sp
    1510             : 
    1511             :   ! ------------------------------------------------------------------
    1512             : 
    1513      364574 :   FUNCTION stddev_dp(dat, mask)
    1514             : 
    1515             :     IMPLICIT NONE
    1516             : 
    1517             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1518             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1519             :     REAL(dp) :: stddev_dp
    1520             : 
    1521      182287 :     REAL(dp) :: n
    1522             : 
    1523    19036075 :     REAL(dp) :: ep, ave, var
    1524    37525289 :     REAL(dp), DIMENSION(size(dat)) :: p, s
    1525      182287 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1526             : 
    1527      182287 :     if (present(mask)) then
    1528          33 :       if (size(mask) .ne. size(dat)) stop 'Error stddev_dp: size(mask) .ne. size(dat)'
    1529        4435 :       maske = mask
    1530        4435 :       n = real(count(maske), dp)
    1531             :     else
    1532    18849353 :       maske(:) = .true.
    1533      182254 :       n = real(size(dat), dp)
    1534             :     end if
    1535      182287 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'stddev_dp: n must be at least 2'
    1536             : 
    1537             :     ! Average
    1538    18853788 :     ave = sum(dat(:), mask = maske) / n
    1539    18853788 :     s(:) = dat(:) - ave
    1540             :     ! Variance / Standard deviation
    1541    18853788 :     ep = sum(s(:), mask = maske)
    1542    18853788 :     p(:) = s(:) * s(:)
    1543    18853788 :     var = sum(p(:), mask = maske)
    1544      182287 :     var = (var - ep * ep / n) / (n - 1.0_dp)
    1545      182287 :     stddev_dp = sqrt(var)
    1546             : 
    1547          24 :   END FUNCTION stddev_dp
    1548             : 
    1549             : 
    1550          70 :   FUNCTION stddev_sp(dat, mask)
    1551             : 
    1552             :     IMPLICIT NONE
    1553             : 
    1554             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1555             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1556             :     REAL(sp) :: stddev_sp
    1557             : 
    1558          35 :     REAL(sp) :: n
    1559             : 
    1560        4491 :     REAL(sp) :: ep, ave, var
    1561        8877 :     REAL(sp), DIMENSION(size(dat)) :: p, s
    1562          35 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1563             : 
    1564          35 :     if (present(mask)) then
    1565          33 :       if (size(mask) .ne. size(dat)) stop 'Error stddev_sp: size(mask) .ne. size(dat)'
    1566        4435 :       maske = mask
    1567        4435 :       n = real(count(maske), sp)
    1568             :     else
    1569          21 :       maske(:) = .true.
    1570           2 :       n = real(size(dat), sp)
    1571             :     end if
    1572          35 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'stddev_sp: n must be at least 2'
    1573             : 
    1574             :     ! Average
    1575        4456 :     ave = sum(dat(:), mask = maske) / n
    1576        4456 :     s(:) = dat(:) - ave
    1577             :     ! Variance / Standard deviation
    1578        4456 :     ep = sum(s(:), mask = maske)
    1579        4456 :     p(:) = s(:) * s(:)
    1580        4456 :     var = sum(p(:), mask = maske)
    1581          35 :     var = (var - ep * ep / n) / (n - 1.0_sp)
    1582          35 :     stddev_sp = sqrt(var)
    1583             : 
    1584      182287 :   END FUNCTION stddev_sp
    1585             : 
    1586             :   ! ------------------------------------------------------------------
    1587             : 
    1588           6 :   FUNCTION skewness_dp(dat, mask)
    1589             : 
    1590             :     IMPLICIT NONE
    1591             : 
    1592             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1593             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1594             :     REAL(dp) :: skewness_dp
    1595             : 
    1596           3 :     REAL(dp) :: n
    1597             : 
    1598          35 :     REAL(dp) :: ep, ave, var, stddev
    1599          61 :     REAL(dp), DIMENSION(size(dat)) :: p, s
    1600           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1601             : 
    1602           3 :     if (present(mask)) then
    1603           1 :       if (size(mask) .ne. size(dat)) stop 'Error skewness_dp: size(mask) .ne. size(dat)'
    1604          11 :       maske = mask
    1605          11 :       n = real(count(maske), dp)
    1606             :     else
    1607          21 :       maske(:) = .true.
    1608           2 :       n = real(size(dat), dp)
    1609             :     end if
    1610           3 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'skewness_dp: n must be at least 2'
    1611             : 
    1612             :     ! Average
    1613          32 :     ave = sum(dat(:), mask = maske) / n
    1614          32 :     s(:) = dat(:) - ave
    1615             :     ! Variance / Standard deviation
    1616          32 :     ep = sum(s(:), mask = maske)
    1617          32 :     p(:) = s(:) * s(:)
    1618          32 :     var = sum(p(:), mask = maske)
    1619           3 :     var = (var - ep * ep / n) / (n - 1.0_dp)
    1620           3 :     stddev = sqrt(var)
    1621             :     ! Skewness
    1622           3 :     if (abs(var) .lt. tiny(0.0_dp)) stop 'skewness_dp: no skewness when zero variance'
    1623          32 :     p(:) = p(:) * s(:)
    1624          32 :     skewness_dp = sum(p(:), mask = maske)
    1625           3 :     skewness_dp = skewness_dp / (n * stddev * stddev * stddev)
    1626             : 
    1627          35 :   END FUNCTION skewness_dp
    1628             : 
    1629             : 
    1630           6 :   FUNCTION skewness_sp(dat, mask)
    1631             : 
    1632             :     IMPLICIT NONE
    1633             : 
    1634             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1635             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1636             :     REAL(sp) :: skewness_sp
    1637             : 
    1638           3 :     REAL(sp) :: n
    1639             : 
    1640          35 :     REAL(sp) :: ep, ave, var, stddev
    1641          61 :     REAL(sp), DIMENSION(size(dat)) :: p, s
    1642           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1643             : 
    1644           3 :     if (present(mask)) then
    1645           1 :       if (size(mask) .ne. size(dat)) stop 'Error skewness_sp: size(mask) .ne. size(dat)'
    1646          11 :       maske = mask
    1647          11 :       n = real(count(maske), sp)
    1648             :     else
    1649          21 :       maske(:) = .true.
    1650           2 :       n = real(size(dat), sp)
    1651             :     end if
    1652           3 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'skewness_sp: n must be at least 2'
    1653             : 
    1654             :     ! Average
    1655          32 :     ave = sum(dat(:), mask = maske) / n
    1656          32 :     s(:) = dat(:) - ave
    1657             :     ! Variance / Standard deviation
    1658          32 :     ep = sum(s(:), mask = maske)
    1659          32 :     p(:) = s(:) * s(:)
    1660          32 :     var = sum(p(:), mask = maske)
    1661           3 :     var = (var - ep * ep / n) / (n - 1.0_sp)
    1662           3 :     stddev = sqrt(var)
    1663             :     ! Skewness
    1664           3 :     if (abs(var) .lt. tiny(0.0_sp)) stop 'skewness_sp: no skewness when zero variance'
    1665          32 :     p(:) = p(:) * s(:)
    1666          32 :     skewness_sp = sum(p(:), mask = maske)
    1667           3 :     skewness_sp = skewness_sp / (n * stddev * stddev * stddev)
    1668             : 
    1669           3 :   END FUNCTION skewness_sp
    1670             : 
    1671             :   ! ------------------------------------------------------------------
    1672             : 
    1673           6 :   FUNCTION variance_dp(dat, mask)
    1674             : 
    1675             :     IMPLICIT NONE
    1676             : 
    1677             :     REAL(dp), DIMENSION(:), INTENT(IN) :: dat
    1678             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1679             :     REAL(dp) :: variance_dp
    1680             : 
    1681           3 :     REAL(dp) :: n
    1682             : 
    1683          35 :     REAL(dp) :: ep, ave, var
    1684          67 :     REAL(dp), DIMENSION(size(dat)) :: p, s
    1685           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1686             : 
    1687           3 :     if (present(mask)) then
    1688           1 :       if (size(mask) .ne. size(dat)) stop 'Error variance_dp: size(mask) .ne. size(dat)'
    1689          12 :       maske = mask
    1690          11 :       n = real(count(maske), dp)
    1691             :     else
    1692          21 :       maske(:) = .true.
    1693           2 :       n = real(size(dat), dp)
    1694             :     end if
    1695           3 :     if (n .le. (1.0_dp + tiny(1.0_dp))) stop 'variance_dp: n must be at least 2'
    1696             : 
    1697             :     ! Average
    1698          35 :     ave = sum(dat(:), mask = maske) / n
    1699          32 :     s(:) = dat(:) - ave
    1700             :     ! Variance / Standard deviation
    1701          32 :     ep = sum(s(:), mask = maske)
    1702          32 :     p(:) = s(:) * s(:)
    1703          32 :     var = sum(p(:), mask = maske)
    1704           3 :     variance_dp = (var - ep * ep / n) / (n - 1.0_dp)
    1705             : 
    1706           3 :   END FUNCTION variance_dp
    1707             : 
    1708             : 
    1709           3 :   FUNCTION variance_sp(dat, mask)
    1710             : 
    1711             :     IMPLICIT NONE
    1712             : 
    1713             :     REAL(sp), DIMENSION(:), INTENT(IN) :: dat
    1714             :     LOGICAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: mask
    1715             :     REAL(sp) :: variance_sp
    1716             : 
    1717           3 :     REAL(sp) :: n
    1718             : 
    1719          35 :     REAL(sp) :: ep, ave, var
    1720          67 :     REAL(sp), DIMENSION(size(dat)) :: p, s
    1721           3 :     LOGICAL, DIMENSION(size(dat)) :: maske
    1722             : 
    1723           3 :     if (present(mask)) then
    1724           1 :       if (size(mask) .ne. size(dat)) stop 'Error variance_sp: size(mask) .ne. size(dat)'
    1725          12 :       maske = mask
    1726          11 :       n = real(count(maske), sp)
    1727             :     else
    1728          21 :       maske(:) = .true.
    1729           2 :       n = real(size(dat), sp)
    1730             :     end if
    1731           3 :     if (n .le. (1.0_sp + tiny(1.0_sp))) stop 'variance_sp: n must be at least 2'
    1732             : 
    1733             :     ! Average
    1734          35 :     ave = sum(dat(:), mask = maske) / n
    1735          32 :     s(:) = dat(:) - ave
    1736             :     ! Variance / Standard deviation
    1737          32 :     ep = sum(s(:), mask = maske)
    1738          32 :     p(:) = s(:) * s(:)
    1739          32 :     var = sum(p(:), mask = maske)
    1740           3 :     variance_sp = (var - ep * ep / n) / (n - 1.0_sp)
    1741             : 
    1742           3 :   END FUNCTION variance_sp
    1743             : 
    1744             :   ! ------------------------------------------------------------------
    1745             : 
    1746             : END MODULE mo_moment

Generated by: LCOV version 1.16