@@ -843,7 +843,12 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
843
843
*
844
844
* @return `true` if the $coll contains no elements, `false` otherwise.
845
845
*/
846
- def isEmpty : Boolean = ! iterator.hasNext
846
+ def isEmpty : Boolean =
847
+ knownSize match {
848
+ case - 1 => ! iterator.hasNext
849
+ case 0 => true
850
+ case _ => false
851
+ }
847
852
848
853
/** Tests whether the $coll is not empty.
849
854
*
@@ -929,7 +934,13 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
929
934
i - start
930
935
}
931
936
932
- /** Sums up the elements of this collection.
937
+ /** Sums the elements of this collection.
938
+ *
939
+ * The default implementation uses `reduce` for a known non-empty collection,
940
+ * `foldLeft` otherwise.
941
+ *
942
+ * If `foldLeft` is used, this implementation works around pollution of the math context
943
+ * by ignoring the identity element.
933
944
*
934
945
* $willNotTerminateInf
935
946
*
@@ -940,12 +951,24 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
940
951
*/
941
952
def sum [B >: A ](implicit num : Numeric [B ]): B =
942
953
knownSize match {
943
- case - 1 => reduceLeftIterator[B ](num.zero)(num.plus)
954
+ case - 1 =>
955
+ val z = num.zero
956
+ if ((num eq Numeric .BigDecimalIsFractional ) || (num eq Numeric .BigDecimalAsIfIntegral )) {
957
+ def nonPollutingPlus (x : B , y : B ): B = if (x.asInstanceOf [AnyRef ] eq z.asInstanceOf [AnyRef ]) y else num.plus(x, y)
958
+ foldLeft(z)(nonPollutingPlus)
959
+ }
960
+ else foldLeft(z)(num.plus)
944
961
case 0 => num.zero
945
962
case _ => reduce(num.plus)
946
963
}
947
964
948
- /** Multiplies up the elements of this collection.
965
+ /** Multiplies together the elements of this collection.
966
+ *
967
+ * The default implementation uses `reduce` for a known non-empty collection,
968
+ * `foldLeft` otherwise.
969
+ *
970
+ * If `foldLeft` is used, this implementation works around pollution of the math context
971
+ * by ignoring the identity element.
949
972
*
950
973
* $willNotTerminateInf
951
974
*
@@ -956,7 +979,13 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
956
979
*/
957
980
def product [B >: A ](implicit num : Numeric [B ]): B =
958
981
knownSize match {
959
- case - 1 => reduceLeftIterator[B ](num.one)(num.times)
982
+ case - 1 =>
983
+ val u = num.one
984
+ if ((num eq Numeric .BigDecimalIsFractional ) || (num eq Numeric .BigDecimalAsIfIntegral )) {
985
+ def nonPollutingProd (x : B , y : B ): B = if (x.asInstanceOf [AnyRef ] eq u.asInstanceOf [AnyRef ]) y else num.times(x, y)
986
+ foldLeft(u)(nonPollutingProd)
987
+ }
988
+ else foldLeft(u)(num.times)
960
989
case 0 => num.one
961
990
case _ => reduce(num.times)
962
991
}
0 commit comments