@@ -1229,9 +1229,16 @@ unittest
1229
1229
/+ +
1230
1230
Computes the median of `slice`.
1231
1231
1232
+ By default, if `F` is not floating point type or complex type, then the result
1233
+ will have a `double` type if `F` is implicitly convertible to a floating point
1234
+ type or have a `cdouble` type if `F` is implicitly convertible to a complex type.
1235
+
1232
1236
Can also pass a boolean variable, `allowModify`, that allows the input slice to
1233
1237
be modified. By default, a reference-counted copy is made.
1234
1238
1239
+ Params:
1240
+ F = output type
1241
+ allowModify = Allows the input slice to be modified, default is false
1235
1242
Returns:
1236
1243
the median of the slice
1237
1244
@@ -1240,8 +1247,16 @@ See_also:
1240
1247
+/
1241
1248
template median (F, bool allowModify = false )
1242
1249
{
1243
- F median (Iterator, size_t N, SliceKind kind)(Slice! (Iterator, N, kind) slice)
1250
+ /+ +
1251
+ Params:
1252
+ slice = slice
1253
+ +/
1254
+ meanType! F median (Iterator, size_t N, SliceKind kind)(Slice! (Iterator, N, kind) slice)
1244
1255
{
1256
+ static assert (! allowModify ||
1257
+ isMutable! (DeepElementType! (Slice! (Iterator, N, kind))),
1258
+ " allowModify must be false or the input must be mutable" );
1259
+ alias G = typeof (return );
1245
1260
size_t len = slice.elementCount;
1246
1261
assert (len > 0 , " median: slice must have length greater than zero" );
1247
1262
@@ -1253,9 +1268,9 @@ template median(F, bool allowModify = false)
1253
1268
if (len > 2 ) {
1254
1269
auto val = slice.rcslice.flattened;
1255
1270
auto temp = val.lightScope;
1256
- return .median! (F , true )(temp);
1271
+ return .median! (G , true )(temp);
1257
1272
} else {
1258
- return mean! F (slice);
1273
+ return mean! G (slice);
1259
1274
}
1260
1275
} else {
1261
1276
import mir.ndslice.sorting: partitionAt;
@@ -1266,26 +1281,31 @@ template median(F, bool allowModify = false)
1266
1281
size_t half_n = len / 2 ;
1267
1282
partitionAt(temp, half_n);
1268
1283
if (len % 2 == 1 ) {
1269
- return cast (F ) temp[half_n];
1284
+ return cast (G ) temp[half_n];
1270
1285
} else {
1271
1286
// move largest value in first half of slice to half_n - 1
1272
1287
partitionAt(temp[0 .. half_n], half_n - 1 );
1273
- return (temp[half_n - 1 ] + temp[half_n]) / cast (F ) 2 ;
1288
+ return (temp[half_n - 1 ] + temp[half_n]) / cast (G ) 2 ;
1274
1289
}
1275
1290
} else {
1276
- return smallMedianImpl! (F )(temp);
1291
+ return smallMedianImpl! (G )(temp);
1277
1292
}
1278
1293
}
1279
1294
}
1280
1295
}
1281
1296
1282
- // /
1297
+ // / ditto
1283
1298
template median (bool allowModify = false )
1284
1299
{
1285
- sumType! (Slice! (Iterator, N, kind))
1286
- median
1287
- (Iterator, size_t N, SliceKind kind)(Slice! (Iterator, N, kind) slice) {
1288
- return .median! (sumType! (Slice! (Iterator, N, kind)), allowModify)(slice.move);
1300
+ // / ditto
1301
+ meanType! (Slice! (Iterator, N, kind))
1302
+ median(Iterator, size_t N, SliceKind kind)(Slice! (Iterator, N, kind) slice)
1303
+ {
1304
+ static assert (! allowModify ||
1305
+ isMutable! (DeepElementType! (Slice! (Iterator, N, kind))),
1306
+ " allowModify must be false or the input must be mutable" );
1307
+ alias F = typeof (return );
1308
+ return .median! (F, allowModify)(slice.move);
1289
1309
}
1290
1310
}
1291
1311
@@ -1356,7 +1376,7 @@ unittest
1356
1376
}
1357
1377
1358
1378
/+ +
1359
- For integral slices, pass output type as template parameter to ensure output
1379
+ For integral slices, can pass output type as template parameter to ensure output
1360
1380
type is correct
1361
1381
+/
1362
1382
version (mir_test)
@@ -1366,7 +1386,11 @@ unittest
1366
1386
import mir.ndslice.slice: sliced;
1367
1387
1368
1388
auto x = [9 , 1 , 0 , 2 , 3 , 4 , 6 , 8 , 7 , 10 ].sliced;
1369
- assert (x.median! float == 5 );
1389
+ assert (x.median! float == 5f );
1390
+
1391
+ auto y = x.median;
1392
+ assert (y == 5.0 );
1393
+ static assert (is (typeof (y) == double ));
1370
1394
}
1371
1395
1372
1396
version (mir_test)
0 commit comments