@@ -517,6 +517,13 @@ struct Limits {
517
517
template <typename Iterator> Double_t Mean (Iterator first, Iterator last);
518
518
template <typename Iterator, typename WeightIterator> Double_t Mean (Iterator first, Iterator last, WeightIterator wfirst);
519
519
520
+ template <typename T>
521
+ T *MovMedian (const Long64_t n, T *a, const Long64_t k, Double_t *w = nullptr , Long64_t *work = nullptr );
522
+ template <typename T>
523
+ T *MovMean (const Long64_t n, T *a, const Long64_t k, Double_t *w = nullptr );
524
+ template <typename T>
525
+ Double_t Mode (const Long64_t n, T *a);
526
+
520
527
template <typename T> Double_t GeomMean (Long64_t n, const T *a);
521
528
template <typename Iterator> Double_t GeomMean (Iterator first, Iterator last);
522
529
@@ -1083,7 +1090,7 @@ Double_t TMath::Mean(Iterator first, Iterator last, WeightIterator w)
1083
1090
}
1084
1091
1085
1092
// //////////////////////////////////////////////////////////////////////////////
1086
- // / Returns the weighted mean of an array a with length n.
1093
+ // / Returns the weighted mean of an array with a length n.
1087
1094
1088
1095
template <typename T>
1089
1096
Double_t TMath::Mean (Long64_t n, const T *a, const Double_t *w)
@@ -1095,6 +1102,220 @@ Double_t TMath::Mean(Long64_t n, const T *a, const Double_t *w)
1095
1102
}
1096
1103
}
1097
1104
1105
+ // //////////////////////////////////////////////////////////////////////////////
1106
+ // / Returns the moving mean of an array.
1107
+ // /
1108
+ // / \param[in] n number of array elements
1109
+ // / \param[in] *a array
1110
+ // / \param[in] k window size
1111
+ // / \param[in] *w weight of the array values
1112
+ // /
1113
+ // / The mean values will be calculated over the window value
1114
+ // / for each entry a[i] of the array. The function will return
1115
+ // / weighted moving mean if the weight argument is provided.
1116
+
1117
+ template <typename T>
1118
+ class Moving {
1119
+ public:
1120
+ T *a0;
1121
+ Double_t *w0;
1122
+ Long64_t *work0;
1123
+ Long64_t k0;
1124
+ Long64_t n0;
1125
+
1126
+ virtual Double_t GetValue (const Long64_t n, T *a, Double_t *w = nullptr , Long64_t *work = nullptr ) = 0;
1127
+ virtual ~Moving (){};
1128
+
1129
+ Moving (const Long64_t n, T *a, const Long64_t k, Double_t *w = nullptr , Long64_t *work = nullptr )
1130
+ {
1131
+ n0 = n;
1132
+ a0 = a;
1133
+ k0 = k;
1134
+ w0 = w;
1135
+ work0 = work;
1136
+ }
1137
+
1138
+ template <typename U>
1139
+ void SplitArray (const U *v, U *v1, Long64_t first, const Long64_t last)
1140
+ {
1141
+ Long64_t i = 0 ;
1142
+
1143
+ while (first <= last) {
1144
+ v1[i] = v[first];
1145
+ i++;
1146
+ first++;
1147
+ }
1148
+ }
1149
+
1150
+ Double_t GetMoving (const Long64_t n, const Long64_t first, const Long64_t last, Moving *sp)
1151
+ {
1152
+ Double_t result;
1153
+ T *a1 = new T[n + 1 ];
1154
+ SplitArray (a0, a1, first, last);
1155
+
1156
+ if (w0 != nullptr ) {
1157
+ Double_t *w1 = new Double_t[n + 1 ];
1158
+ SplitArray (w0, w1, first, last);
1159
+
1160
+ if (work0 != nullptr ) {
1161
+ Long64_t *wrk1 = new Long64_t[n + 1 ];
1162
+ SplitArray (work0, wrk1, first, last);
1163
+ result = sp->GetValue (n, a1, w1, wrk1);
1164
+ delete[] wrk1;
1165
+ } else {
1166
+ result = sp->GetValue (n, a1, w1);
1167
+ }
1168
+ delete[] w1;
1169
+ } else {
1170
+ result = sp->GetValue (n, a1);
1171
+ }
1172
+ delete[] a1;
1173
+ return result;
1174
+ }
1175
+
1176
+ T *GetResult (Moving *sp)
1177
+ {
1178
+ Long64_t kl = k0 / 2 ;
1179
+ Long64_t kr = (k0 % 2 ) ? k0 / 2 : k0 / 2 - 1 ;
1180
+ T *mov = new T[n0 + 1 ];
1181
+
1182
+ for (Long64_t i = 0 ; i != n0; i++) {
1183
+ kl = (i < k0 / 2 and i > 0 ) ? i : k0 / 2 ;
1184
+ if (i + kr > n0 - 1 ) {
1185
+ kr--;
1186
+ }
1187
+
1188
+ if (i == 0 ) {
1189
+ if (k0 > 2 ) {
1190
+ mov[i] = sp->GetMoving (kr + 1 , 0 , kr + 1 , sp);
1191
+ } else {
1192
+ mov[i] = sp->GetMoving (1 , 0 , 1 , sp);
1193
+ }
1194
+ } else if (i == n0 - 1 ) {
1195
+ mov[i] = sp->GetMoving (kl + 1 , i - kl, i, sp);
1196
+ } else {
1197
+ mov[i] = sp->GetMoving (kl + kr + 1 , i - kl, i + kr, sp);
1198
+ }
1199
+ }
1200
+ return mov;
1201
+ }
1202
+ };
1203
+
1204
+ template <typename T>
1205
+ class MovingMean : public Moving <T> {
1206
+ public:
1207
+ MovingMean (const Long64_t n, T *a, const Long64_t k, Double_t *w) : Moving<T>(n, a, k, w) {}
1208
+
1209
+ Double_t GetValue (const Long64_t n, T *a, Double_t *w = nullptr , Long64_t *work = nullptr )
1210
+ {
1211
+ (void )work;
1212
+ Double_t mean = TMath::Mean (n, a, w);
1213
+ return mean;
1214
+ }
1215
+ };
1216
+
1217
+ template <typename T>
1218
+ T *TMath::MovMean (const Long64_t n, T *a, const Long64_t k, Double_t *w)
1219
+ {
1220
+ if (!a) {
1221
+ Fatal (" MovMean" , " the array is empty" );
1222
+ }
1223
+ if (n <= 1 ) {
1224
+ Fatal (" MovMean" , " the length of the array must be >1" );
1225
+ }
1226
+ if (k > n) {
1227
+ Fatal (" MovMean" , " the window length k is larger than the length of the array" );
1228
+ }
1229
+ if (k == 1 ) {
1230
+ Fatal (" MovMean" , " the window length k must be >1" );
1231
+ }
1232
+
1233
+ MovingMean<T> *movmean = new MovingMean (n, a, k, w);
1234
+ T *result = movmean->GetResult (movmean);
1235
+ delete movmean;
1236
+ return result;
1237
+ }
1238
+
1239
+ // //////////////////////////////////////////////////////////////////////////////
1240
+ // / Returns the moving median of an array.
1241
+ // /
1242
+ // / \param[in] n number of array elements
1243
+ // / \param[in] *a array
1244
+ // / \param[in] k window size
1245
+ // / \param[in] *w weight of the array values
1246
+ // / \param[in] *work work
1247
+ // /
1248
+ // / The median values will be calculated over the window
1249
+ // / value for each entry a[i] of the array. The function will
1250
+ // / return weighted moving median if the weight argument
1251
+ // / is provided.
1252
+
1253
+ template <typename T>
1254
+ class MovingMedian : public Moving <T> {
1255
+ public:
1256
+ MovingMedian (const Long64_t n, T *a, const Long64_t k, Double_t *w, Long64_t *work) : Moving<T>(n, a, k, w, work) {}
1257
+
1258
+ Double_t GetValue (const Long64_t n, T *a, Double_t *w, Long64_t *work)
1259
+ {
1260
+ Double_t median = TMath::Median (n, a, w, work);
1261
+ return median;
1262
+ }
1263
+ };
1264
+
1265
+ template <typename T>
1266
+ T *TMath::MovMedian (const Long64_t n, T *a, const Long64_t k, Double_t *w, Long64_t *work)
1267
+ {
1268
+ if (!a) {
1269
+ Fatal (" MovMedian" , " the array is empty" );
1270
+ }
1271
+ if (n <= 1 ) {
1272
+ Fatal (" MovMedian" , " the length of the array must be >1" );
1273
+ }
1274
+ if (k > n) {
1275
+ Fatal (" MovMedian" , " the window length k is larger than the length of the array" );
1276
+ }
1277
+ if (k == 1 ) {
1278
+ Fatal (" MovMedian" , " the window length k must be >1" );
1279
+ }
1280
+
1281
+ MovingMedian<T> *movmedian = new MovingMedian (n, a, k, w, work);
1282
+ T *result = movmedian->GetResult (movmedian);
1283
+ delete movmedian;
1284
+ return result;
1285
+ }
1286
+
1287
+ // //////////////////////////////////////////////////////////////////////////////
1288
+ // / Returns the mode of an array. If there are an equal amount of
1289
+ // / different values, the smallest value will be returned.
1290
+ // /
1291
+ // / \param[in] n number of array elements
1292
+ // / \param[in] *a array
1293
+
1294
+ template <typename T>
1295
+ Double_t TMath::Mode (const Long64_t n, T *a)
1296
+ {
1297
+ if (!a) {
1298
+ Fatal (" Mode" , " the array is empty" );
1299
+ }
1300
+ if (n < 1 ) {
1301
+ Fatal (" Mode" , " the length of the array must be >0" );
1302
+ }
1303
+
1304
+ Long64_t N1 = 0 ;
1305
+ Long64_t N2 = 0 ;
1306
+ Double_t mode = 0 ;
1307
+ std::sort (a, a + n);
1308
+
1309
+ for (Long64_t i = 0 ; i < n; i++) {
1310
+ N2 = std::count (a, a + n, a[i]);
1311
+ if (N2 > N1 && mode != a[i]) {
1312
+ mode = a[i];
1313
+ }
1314
+ N1 = N2;
1315
+ }
1316
+ return mode;
1317
+ }
1318
+
1098
1319
// //////////////////////////////////////////////////////////////////////////////
1099
1320
// / Returns the geometric mean of an array defined by the iterators.
1100
1321
// / \f[ GeomMean = (\prod_{i=0}^{n-1} |a[i]|)^{1/n} \f]
0 commit comments