@@ -1229,9 +1229,16 @@ unittest
12291229/+ +
12301230Computes the median of `slice`.
12311231
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+
12321236Can also pass a boolean variable, `allowModify`, that allows the input slice to
12331237be modified. By default, a reference-counted copy is made.
12341238
1239+ Params:
1240+ F = output type
1241+ allowModify = Allows the input slice to be modified, default is false
12351242Returns:
12361243 the median of the slice
12371244
@@ -1240,8 +1247,16 @@ See_also:
12401247+/
12411248template median (F, bool allowModify = false )
12421249{
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)
12441255 {
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 );
12451260 size_t len = slice.elementCount;
12461261 assert (len > 0 , " median: slice must have length greater than zero" );
12471262
@@ -1253,9 +1268,9 @@ template median(F, bool allowModify = false)
12531268 if (len > 2 ) {
12541269 auto val = slice.rcslice.flattened;
12551270 auto temp = val.lightScope;
1256- return .median! (F , true )(temp);
1271+ return .median! (G , true )(temp);
12571272 } else {
1258- return mean! F (slice);
1273+ return mean! G (slice);
12591274 }
12601275 } else {
12611276 import mir.ndslice.sorting: partitionAt;
@@ -1266,26 +1281,31 @@ template median(F, bool allowModify = false)
12661281 size_t half_n = len / 2 ;
12671282 partitionAt(temp, half_n);
12681283 if (len % 2 == 1 ) {
1269- return cast (F ) temp[half_n];
1284+ return cast (G ) temp[half_n];
12701285 } else {
12711286 // move largest value in first half of slice to half_n - 1
12721287 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 ;
12741289 }
12751290 } else {
1276- return smallMedianImpl! (F )(temp);
1291+ return smallMedianImpl! (G )(temp);
12771292 }
12781293 }
12791294 }
12801295}
12811296
1282- // /
1297+ // / ditto
12831298template median (bool allowModify = false )
12841299{
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);
12891309 }
12901310}
12911311
@@ -1356,7 +1376,7 @@ unittest
13561376}
13571377
13581378/+ +
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
13601380type is correct
13611381+/
13621382version (mir_test)
@@ -1366,7 +1386,11 @@ unittest
13661386 import mir.ndslice.slice: sliced;
13671387
13681388 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 ));
13701394}
13711395
13721396version (mir_test)
0 commit comments