@@ -125,24 +125,36 @@ end
125
125
Base. widemul (x:: Integer , y:: FD ) = widemul (y, x)
126
126
127
127
"""
128
- _round_to_even(quotient, remainder, divisor)
129
-
130
- Round `quotient + remainder / divisor` to the nearest even integer, given that
131
- `0 ≤ remainder < divisor` or `0 ≥ remainder > divisor`. (This assumption is
132
- satisfied by the return value of `fldmod` in all cases, and the return value of
133
- `divrem` in cases where `divisor` is known to be positive.)
128
+ _round_to_even(quotient, remainder, divisor, ::RoundingMode{M})
129
+
130
+ Round `quotient + remainder / divisor` to the nearest even integer,
131
+ given that `0 ≤ remainder < divisor` or `0 ≥ remainder >
132
+ divisor`. (This assumption is satisfied by the return value of
133
+ `fldmod` in all cases, and the return value of `divrem` in cases where
134
+ `divisor` is known to be positive.) The tie is decided depending on
135
+ the `RoundingMode`.
134
136
"""
135
- function _round_to_even (quotient:: T , remainder:: T , divisor:: T ) where {T <: Integer }
137
+ function _round_to_even (quotient:: T , remainder:: T , divisor:: T , :: RoundingMode{M} = RoundNearest ) where {T <: Integer , M }
136
138
halfdivisor = divisor >> 1
137
139
if iseven (divisor) && remainder == halfdivisor
138
- ifelse (iseven (quotient), quotient, quotient + one (quotient))
140
+ # `:NearestTiesAway` will tie away from zero, e.g. -8.5 ->
141
+ # -9. `:NearestTiesUp` will always ties towards positive
142
+ # infinity. `:Nearest` will tie towards the nearest even
143
+ # integer.
144
+ if M == :NearestTiesAway && quotient < zero (quotient)
145
+ quotient
146
+ elseif M == :Nearest && iseven (quotient)
147
+ quotient
148
+ else
149
+ quotient + one (quotient)
150
+ end
139
151
elseif abs (remainder) > abs (halfdivisor)
140
152
quotient + one (quotient)
141
153
else
142
154
quotient
143
155
end
144
156
end
145
- _round_to_even (q, r, d) = _round_to_even (promote (q, r, d)... )
157
+ _round_to_even (q, r, d, m = RoundNearest ) = _round_to_even (promote (q, r, d)... , m )
146
158
147
159
# In many of our calls to fldmod, `y` is a constant (the coefficient, 10^f). However, since
148
160
# `fldmod` is sometimes not being inlined, that constant information is not available to the
@@ -188,11 +200,18 @@ end
188
200
Base. trunc (x:: FD{T, f} ) where {T, f} = FD {T, f} (div (x. i, coefficient (FD{T, f})))
189
201
Base. floor (x:: FD{T, f} ) where {T, f} = FD {T, f} (fld (x. i, coefficient (FD{T, f})))
190
202
203
+ Base. round (fd:: FD , :: RoundingMode{:Up} ) = ceil (fd)
204
+ Base. round (fd:: FD , :: RoundingMode{:Down} ) = floor (fd)
205
+ Base. round (fd:: FD , :: RoundingMode{:ToZero} ) = trunc (fd)
206
+
191
207
# TODO : round with number of digits; should be easy
192
- function Base. round (x:: FD{T, f} , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
208
+ function Base. round (x:: FD{T, f} ,
209
+ m:: Union {RoundingMode{:Nearest },
210
+ RoundingMode{:NearestTiesUp },
211
+ RoundingMode{:NearestTiesAway }}= RoundNearest) where {T, f}
193
212
powt = coefficient (FD{T, f})
194
213
quotient, remainder = fldmodinline (x. i, powt)
195
- FD {T, f} (_round_to_even (quotient, remainder, powt))
214
+ FD {T, f} (_round_to_even (quotient, remainder, powt, m ))
196
215
end
197
216
function Base. ceil (x:: FD{T, f} ) where {T, f}
198
217
powt = coefficient (FD{T, f})
@@ -247,8 +266,8 @@ for fn in [:trunc, :floor, :ceil]
247
266
reinterpret (FD{T, f}, val)
248
267
end
249
268
end
250
- function Base. round (:: Type{TI} , x:: FD , :: RoundingMode{:Nearest} = RoundNearest) where {TI <: Integer }
251
- convert (TI, round (x)):: TI
269
+ function Base. round (:: Type{TI} , x:: FD , m :: RoundingMode = RoundNearest) where {TI <: Integer }
270
+ convert (TI, round (x,m )):: TI
252
271
end
253
272
function Base. round (:: Type{FD{T, f}} , x:: Real , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
254
273
reinterpret (FD{T, f}, round (T, x * coefficient (FD{T, f})))
0 commit comments