File indexing completed on 2024-04-28 03:42:27

0001 /*
0002     SPDX-FileCopyrightText: 2022 Sophie Taylor <sophie@spacekitteh.moe>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <memory>
0010 #include <gsl/gsl_vector.h>
0011 #include <gsl/gsl_sort.h>
0012 #include <gsl/gsl_statistics.h>
0013 
0014 // gslhelpers is used to provide utility routines to access GNU Science Library (GSL) routines
0015 // iterators to access strided arrays are supported and these routines help to access the correct
0016 // GSL rotines (C based) for the datatype of the input data.
0017 //
0018 // gslheklpers is currently used by robuststatistics.h/cpp to access GSL robust statistics routines but
0019 // could be extended in future to access other GSL functions.
0020 
0021 namespace Mathematics
0022 {
0023 
0024 namespace GSLHelpers
0025 {
0026 
0027 // int64 code is currently deactiovated by GSLHELPERS_INT64. It doesn't compile on Mac becuase it
0028 // won't cast a long long * to a long * even though they are both 64bit pointers.
0029 // On 32bit systems this would be an issue because they are not the same.
0030 // If the int64 versions are required in future then this "problem" will need to
0031 // be resolved.
0032 #undef GSLHELPERS_INT64
0033 
0034 /**
0035  * @short creates a new shared pointer to a GSL vector which gets automatically freed.
0036  * The vector is initialised to 0.
0037  *
0038  * @param n the size of the vector.
0039  */
0040 std::shared_ptr<gsl_vector> NewGSLVector(size_t n);
0041 
0042 template<class Iter_T>
0043 class stride_iter
0044 {
0045     public:
0046         // public typedefs
0047         typedef typename std::iterator_traits<Iter_T>::value_type value_type;
0048         typedef typename std::iterator_traits<Iter_T>::reference reference;
0049         typedef typename std::iterator_traits<Iter_T>::difference_type
0050         difference_type;
0051         typedef typename std::iterator_traits<Iter_T>::pointer pointer;
0052         typedef std::random_access_iterator_tag iterator_category;
0053         typedef stride_iter self;
0054 
0055         // constructors
0056         constexpr stride_iter( ) : iter(nullptr), step(0) { }
0057         constexpr stride_iter(const self &x) : iter(x.iter), step(x.step) { }
0058         constexpr stride_iter(Iter_T x, difference_type n) : iter(x), step(n) { }
0059 
0060         // operators
0061         constexpr self &operator++( )
0062         {
0063             iter += step;
0064             return *this;
0065         }
0066         constexpr self operator++(int)
0067         {
0068             self tmp = *this;
0069             iter += step;
0070             return tmp;
0071         }
0072         constexpr self &operator+=(difference_type x)
0073         {
0074             iter += x * step;
0075             return *this;
0076         }
0077         constexpr self &operator--( )
0078         {
0079             iter -= step;
0080             return *this;
0081         }
0082         constexpr self operator--(int)
0083         {
0084             self tmp = *this;
0085             iter -= step;
0086             return tmp;
0087         }
0088         constexpr self &operator-=(difference_type x)
0089         {
0090             iter -= x * step;
0091             return *this;
0092         }
0093         constexpr reference operator[](difference_type n)
0094         {
0095             return iter[n * step];
0096         }
0097         reference operator*( ) const
0098         {
0099             return *iter;
0100         }
0101 
0102         // friend operators
0103         constexpr friend bool operator==(const self &x, const self &y)
0104         {
0105             assert(x.step == y.step);
0106             return x.iter == y.iter;
0107         }
0108         constexpr friend bool operator!=(const self &x, const self &y)
0109         {
0110             assert(x.step == y.step);
0111             return x.iter != y.iter;
0112         }
0113         constexpr friend bool operator<(const self &x, const self &y)
0114         {
0115             assert(x.step == y.step);
0116             return x.iter < y.iter;
0117         }
0118         constexpr friend difference_type operator-(const self &x, const self &y)
0119         {
0120             assert(x.step == y.step);
0121             return (x.iter - y.iter) / x.step;
0122         }
0123         constexpr friend self operator+(const self &x, difference_type y)
0124         {
0125             assert(x.step == y.step);
0126             return x += y * x.step;
0127         }
0128         constexpr friend self operator+(difference_type x, const self &y)
0129         {
0130             assert(x.step == y.step);
0131             return y += x * x.step;
0132         }
0133     private:
0134         Iter_T iter;
0135         difference_type step;
0136 };
0137 
0138 template< class Iter_T >
0139 constexpr static stride_iter<Iter_T> make_strided_iter(Iter_T i, typename stride_iter<Iter_T>::difference_type stride)
0140 {
0141     return stride_iter<Iter_T>(i, stride);
0142 }
0143 
0144 
0145 
0146 
0147 inline void gslSort(uint8_t data[], const size_t stride, const size_t n)
0148 {
0149     gsl_sort_uchar(data, stride, n);
0150 }
0151 inline void gslSort(double data[], const size_t stride, const size_t n)
0152 {
0153     gsl_sort(data, stride, n);
0154 }
0155 inline void gslSort(float data[], const size_t stride, const size_t n)
0156 {
0157     gsl_sort_float(data, stride, n);
0158 }
0159 inline void gslSort(uint16_t data[], const size_t stride, const size_t n)
0160 {
0161     gsl_sort_ushort(data, stride, n);
0162 }
0163 inline void gslSort(int16_t data[], const size_t stride, const size_t n)
0164 {
0165     gsl_sort_short(data, stride, n);
0166 }
0167 inline void gslSort(uint32_t data[], const size_t stride, const size_t n)
0168 {
0169     gsl_sort_uint(data, stride, n);
0170 }
0171 inline void gslSort(int32_t data[], const size_t stride, const size_t n)
0172 {
0173     gsl_sort_int(data, stride, n);
0174 }
0175 #ifdef GSLHELPERS_INT64
0176 inline void gslSort(int64_t data[], const size_t stride, const size_t n)
0177 {
0178     gsl_sort_long(data, stride, n);
0179 }
0180 #endif
0181 
0182 
0183 
0184 
0185 
0186 
0187 
0188 inline double gslMean(const uint8_t data[], const size_t stride, const size_t n)
0189 {
0190     return gsl_stats_uchar_mean(data, stride, n);
0191 }
0192 inline double gslMean(const double data[], const size_t stride, const size_t n)
0193 {
0194     return gsl_stats_mean(data, stride, n);
0195 }
0196 inline double gslMean(const float data[], const size_t stride, const size_t n)
0197 {
0198     return gsl_stats_float_mean(data, stride, n);
0199 }
0200 inline double gslMean(const uint16_t data[], const size_t stride, const size_t n)
0201 {
0202     return gsl_stats_ushort_mean(data, stride, n);
0203 }
0204 inline double gslMean(const int16_t data[], const size_t stride, const size_t n)
0205 {
0206     return gsl_stats_short_mean(data, stride, n);
0207 }
0208 inline double gslMean(const uint32_t data[], const size_t stride, const size_t n)
0209 {
0210     return gsl_stats_uint_mean(data, stride, n);
0211 }
0212 inline double gslMean(const int32_t data[], const size_t stride, const size_t n)
0213 {
0214     return gsl_stats_int_mean(data, stride, n);
0215 }
0216 #ifdef GSLHELPERS_INT64
0217 inline double gslMean(const int64_t data[], const size_t stride, const size_t n)
0218 {
0219     return gsl_stats_long_mean(data, stride, n);
0220 }
0221 #endif
0222 
0223 
0224 inline double gslGastwirthMeanFromSortedData(const uint8_t data[], const size_t stride, const size_t n)
0225 {
0226     return gsl_stats_uchar_gastwirth_from_sorted_data(data, stride, n);
0227 }
0228 inline double gslGastwirthMeanFromSortedData(const double data[], const size_t stride, const size_t n)
0229 {
0230     return gsl_stats_gastwirth_from_sorted_data(data, stride, n);
0231 }
0232 inline double gslGastwirthMeanFromSortedData(const float data[], const size_t stride, const size_t n)
0233 {
0234     return gsl_stats_float_gastwirth_from_sorted_data(data, stride, n);
0235 }
0236 inline double gslGastwirthMeanFromSortedData(const uint16_t data[], const size_t stride, const size_t n)
0237 {
0238     return gsl_stats_ushort_gastwirth_from_sorted_data(data, stride, n);
0239 }
0240 inline double gslGastwirthMeanFromSortedData(const int16_t data[], const size_t stride, const size_t n)
0241 {
0242     return gsl_stats_short_gastwirth_from_sorted_data(data, stride, n);
0243 }
0244 inline double gslGastwirthMeanFromSortedData(const uint32_t data[], const size_t stride, const size_t n)
0245 {
0246     return gsl_stats_uint_gastwirth_from_sorted_data(data, stride, n);
0247 }
0248 inline double gslGastwirthMeanFromSortedData(const int32_t data[], const size_t stride, const size_t n)
0249 {
0250     return gsl_stats_int_gastwirth_from_sorted_data(data, stride, n);
0251 }
0252 #ifdef GSLHELPERS_INT64
0253 inline double gslGastwirthMeanFromSortedData(const int64_t data[], const size_t stride, const size_t n)
0254 {
0255     return gsl_stats_long_gastwirth_from_sorted_data(data, stride, n);
0256 }
0257 #endif
0258 
0259 
0260 inline double gslTrimmedMeanFromSortedData(const double trim, const uint8_t data[], const size_t stride, const size_t n)
0261 {
0262     return gsl_stats_uchar_trmean_from_sorted_data(trim, data, stride, n);
0263 }
0264 inline double gslTrimmedMeanFromSortedData(const double trim, const double data[], const size_t stride, const size_t n)
0265 {
0266     return gsl_stats_trmean_from_sorted_data(trim, data, stride, n);
0267 }
0268 inline double gslTrimmedMeanFromSortedData(const double trim, const float data[], const size_t stride, const size_t n)
0269 {
0270     return gsl_stats_float_trmean_from_sorted_data(trim, data, stride, n);
0271 }
0272 inline double gslTrimmedMeanFromSortedData(const double trim, const uint16_t data[], const size_t stride,
0273         const size_t n)
0274 {
0275     return gsl_stats_ushort_trmean_from_sorted_data(trim, data, stride, n);
0276 }
0277 inline double gslTrimmedMeanFromSortedData(const double trim, const int16_t data[], const size_t stride, const size_t n)
0278 {
0279     return gsl_stats_short_trmean_from_sorted_data(trim, data, stride, n);
0280 }
0281 inline double gslTrimmedMeanFromSortedData(const double trim, const uint32_t data[], const size_t stride,
0282         const size_t n)
0283 {
0284     return gsl_stats_uint_trmean_from_sorted_data(trim, data, stride, n);
0285 }
0286 inline double gslTrimmedMeanFromSortedData(const double trim, const int32_t data[], const size_t stride, const size_t n)
0287 {
0288     return gsl_stats_int_trmean_from_sorted_data(trim, data, stride, n);
0289 }
0290 #ifdef GSLHELPERS_INT64
0291 inline double gslTrimmedMeanFromSortedData(const double trim, const int64_t data[], const size_t stride, const size_t n)
0292 {
0293     return gsl_stats_long_trmean_from_sorted_data(trim, data, stride, n);
0294 }
0295 #endif
0296 
0297 
0298 
0299 
0300 inline double gslMedianFromSortedData(const uint8_t data[], const size_t stride, const size_t n)
0301 {
0302     return gsl_stats_uchar_median_from_sorted_data(data, stride, n);
0303 }
0304 inline double gslMedianFromSortedData(const double data[], const size_t stride, const size_t n)
0305 {
0306     return gsl_stats_median_from_sorted_data(data, stride, n);
0307 }
0308 inline double gslMedianFromSortedData(const float data[], const size_t stride, const size_t n)
0309 {
0310     return gsl_stats_float_median_from_sorted_data(data, stride, n);
0311 }
0312 inline double gslMedianFromSortedData(const uint16_t data[], const size_t stride, const size_t n)
0313 {
0314     return gsl_stats_ushort_median_from_sorted_data(data, stride, n);
0315 }
0316 inline double gslMedianFromSortedData(const int16_t data[], const size_t stride, const size_t n)
0317 {
0318     return gsl_stats_short_median_from_sorted_data(data, stride, n);
0319 }
0320 inline double gslMedianFromSortedData(const uint32_t data[], const size_t stride, const size_t n)
0321 {
0322     return gsl_stats_uint_median_from_sorted_data(data, stride, n);
0323 }
0324 inline double gslMedianFromSortedData(const int32_t data[], const size_t stride, const size_t n)
0325 {
0326     return gsl_stats_int_median_from_sorted_data(data, stride, n);
0327 }
0328 #ifdef GSLHELPERS_INT64
0329 inline double gslMedianFromSortedData(const int64_t data[], const size_t stride, const size_t n)
0330 {
0331     return gsl_stats_long_median_from_sorted_data(data, stride, n);
0332 }
0333 #endif
0334 
0335 
0336 inline double gslVariance(const uint8_t data[], const size_t stride, const size_t n)
0337 {
0338     return gsl_stats_uchar_variance(data, stride, n);
0339 }
0340 inline double gslVariance(const double data[], const size_t stride, const size_t n)
0341 {
0342     return gsl_stats_variance(data, stride, n);
0343 }
0344 inline double gslVariance(const float data[], const size_t stride, const size_t n)
0345 {
0346     return gsl_stats_float_variance(data, stride, n);
0347 }
0348 inline double gslVariance(const uint16_t data[], const size_t stride, const size_t n)
0349 {
0350     return gsl_stats_ushort_variance(data, stride, n);
0351 }
0352 inline double gslVariance(const int16_t data[], const size_t stride, const size_t n)
0353 {
0354     return gsl_stats_short_variance(data, stride, n);
0355 }
0356 inline double gslVariance(const uint32_t data[], const size_t stride, const size_t n)
0357 {
0358     return gsl_stats_uint_variance(data, stride, n);
0359 }
0360 inline double gslVariance(const int32_t data[], const size_t stride, const size_t n)
0361 {
0362     return gsl_stats_int_variance(data, stride, n);
0363 }
0364 #ifdef GSLHELPERS_INT64
0365 inline double gslVariance(const int64_t data[], const size_t stride, const size_t n)
0366 {
0367     return gsl_stats_long_variance(data, stride, n);
0368 }
0369 #endif
0370 
0371 
0372 
0373 inline double gslStandardDeviation(const uint8_t data[], const size_t stride, const size_t n)
0374 {
0375     return gsl_stats_uchar_sd(data, stride, n);
0376 }
0377 inline double gslStandardDeviation(const double data[], const size_t stride, const size_t n)
0378 {
0379     return gsl_stats_sd(data, stride, n);
0380 }
0381 inline double gslStandardDeviation(const float data[], const size_t stride, const size_t n)
0382 {
0383     return gsl_stats_float_sd(data, stride, n);
0384 }
0385 inline double gslStandardDeviation(const uint16_t data[], const size_t stride, const size_t n)
0386 {
0387     return gsl_stats_ushort_sd(data, stride, n);
0388 }
0389 inline double gslStandardDeviation(const int16_t data[], const size_t stride, const size_t n)
0390 {
0391     return gsl_stats_short_sd(data, stride, n);
0392 }
0393 inline double gslStandardDeviation(const uint32_t data[], const size_t stride, const size_t n)
0394 {
0395     return gsl_stats_uint_sd(data, stride, n);
0396 }
0397 inline double gslStandardDeviation(const int32_t data[], const size_t stride, const size_t n)
0398 {
0399     return gsl_stats_int_sd(data, stride, n);
0400 }
0401 #ifdef GSLHELPERS_INT64
0402 inline double gslStandardDeviation(const int64_t data[], const size_t stride, const size_t n)
0403 {
0404     return gsl_stats_long_sd(data, stride, n);
0405 }
0406 #endif
0407 
0408 
0409 
0410 inline double gslMAD(const uint8_t data[], const size_t stride, const size_t n, double work[])
0411 {
0412     return gsl_stats_uchar_mad(data, stride, n, work);
0413 }
0414 inline double gslMAD(const double data[], const size_t stride, const size_t n, double work[])
0415 {
0416     return gsl_stats_mad(data, stride, n, work);
0417 }
0418 inline double gslMAD(const float data[], const size_t stride, const size_t n, double work[])
0419 {
0420     return gsl_stats_float_mad(data, stride, n, work);
0421 }
0422 inline double gslMAD(const uint16_t data[], const size_t stride, const size_t n, double work[])
0423 {
0424     return gsl_stats_ushort_mad(data, stride, n, work);
0425 }
0426 inline double gslMAD(const int16_t data[], const size_t stride, const size_t n, double work[])
0427 {
0428     return gsl_stats_short_mad(data, stride, n, work);
0429 }
0430 inline double gslMAD(const uint32_t data[], const size_t stride, const size_t n, double work[])
0431 {
0432     return gsl_stats_uint_mad(data, stride, n, work);
0433 }
0434 inline double gslMAD(const int32_t data[], const size_t stride, const size_t n, double work[])
0435 {
0436     return gsl_stats_int_mad(data, stride, n, work);
0437 }
0438 #ifdef GSLHELPERS_INT64
0439 inline double gslMAD(const int64_t data[], const size_t stride, const size_t n, double work[])
0440 {
0441     return gsl_stats_long_mad(data, stride, n, work);
0442 }
0443 #endif
0444 
0445 
0446 inline double gslSnFromSortedData(const uint8_t data[], const size_t stride, const size_t n, uint8_t work[])
0447 {
0448     return gsl_stats_uchar_Sn_from_sorted_data(data, stride, n, work);
0449 }
0450 inline double gslSnFromSortedData(const double data[], const size_t stride, const size_t n, double work[])
0451 {
0452     return gsl_stats_Sn_from_sorted_data(data, stride, n, work);
0453 }
0454 inline double gslSnFromSortedData(const float data[], const size_t stride, const size_t n, float work[])
0455 {
0456     return gsl_stats_float_Sn_from_sorted_data(data, stride, n, work);
0457 }
0458 inline double gslSnFromSortedData(const uint16_t data[], const size_t stride, const size_t n, uint16_t work[])
0459 {
0460     return gsl_stats_ushort_Sn_from_sorted_data(data, stride, n, work);
0461 }
0462 inline double gslSnFromSortedData(const int16_t data[], const size_t stride, const size_t n, int16_t work[])
0463 {
0464     return gsl_stats_short_Sn_from_sorted_data(data, stride, n, work);
0465 }
0466 inline double gslSnFromSortedData(const uint32_t data[], const size_t stride, const size_t n, uint32_t work[])
0467 {
0468     return gsl_stats_uint_Sn_from_sorted_data(data, stride, n, work);
0469 }
0470 inline double gslSnFromSortedData(const int32_t data[], const size_t stride, const size_t n, int32_t work[])
0471 {
0472     return gsl_stats_int_Sn_from_sorted_data(data, stride, n, work);
0473 }
0474 #ifdef GSLHELPERS_INT64
0475 inline double gslSnFromSortedData(const int64_t data[], const size_t stride, const size_t n, int64_t work[])
0476 {
0477     return gsl_stats_long_Sn_from_sorted_data(data, stride, n, work);
0478 }
0479 #endif
0480 
0481 inline double gslQnFromSortedData(const uint8_t data[], const size_t stride, const size_t n, uint8_t work[],
0482                                   int work_int[])
0483 {
0484     return gsl_stats_uchar_Qn_from_sorted_data(data, stride, n, work, work_int);
0485 }
0486 inline double gslQnFromSortedData(const double data[], const size_t stride, const size_t n, double work[],
0487                                   int work_int[])
0488 {
0489     return gsl_stats_Qn_from_sorted_data(data, stride, n, work, work_int);
0490 }
0491 inline double gslQnFromSortedData(const float data[], const size_t stride, const size_t n, float work[], int work_int[])
0492 {
0493     return gsl_stats_float_Qn_from_sorted_data(data, stride, n, work, work_int);
0494 }
0495 inline double gslQnFromSortedData(const uint16_t data[], const size_t stride, const size_t n, uint16_t work[],
0496                                   int work_int[])
0497 {
0498     return gsl_stats_ushort_Qn_from_sorted_data(data, stride, n, work, work_int);
0499 }
0500 inline double gslQnFromSortedData(const int16_t data[], const size_t stride, const size_t n, int16_t work[],
0501                                   int work_int[])
0502 {
0503     return gsl_stats_short_Qn_from_sorted_data(data, stride, n, work, work_int);
0504 }
0505 inline double gslQnFromSortedData(const uint32_t data[], const size_t stride, const size_t n, uint32_t work[],
0506                                   int work_int[])
0507 {
0508     return gsl_stats_uint_Qn_from_sorted_data(data, stride, n, work, work_int);
0509 }
0510 inline double gslQnFromSortedData(const int32_t data[], const size_t stride, const size_t n, int32_t work[],
0511                                   int work_int[])
0512 {
0513     return gsl_stats_int_Qn_from_sorted_data(data, stride, n, work, work_int);
0514 }
0515 #ifdef GSLHELPERS_INT64
0516 inline double gslQnFromSortedData(const int64_t data[], const size_t stride, const size_t n, int64_t work[],
0517                                   int work_int[])
0518 {
0519     return gsl_stats_long_Qn_from_sorted_data(data, stride, n, work, work_int);
0520 }
0521 #endif
0522 
0523 }
0524 } // namespace Mathematics