<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 27, 2016, at 12:34 PM, Karl <<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 27 Jun 2016, at 16:23, Stephen Canon <<a href="mailto:scanon@apple.com" class="">scanon@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div dir="auto" class=""><div class="">On Jun 25, 2016, at 05:06, Karl via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class="">Proposal: <a href="https://gist.github.com/karwa/273db66cd8a5fe2c388ccc7de9c4cf31" class="">https://gist.github.com/karwa/273db66cd8a5fe2c388ccc7de9c4cf31</a></div></blockquote></div></blockquote><div class=""><br class=""></div><div class="">Karl, thanks for writing this up. It should be extended to include not only floor( ) and ceiling( ), but also:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// Returns the integral value closest to `self` whose magnitude is not greater than that of `self`.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func truncate( ) -> Self</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// Returns the integral value closest to `self`. If two integrers are equally close, the even one</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// is returned.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// NOTE: The name of this function requires bike-shedding. I’ve chosen a deliberately poor</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// name as a straw-man.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func roundToNearestTiesToEven( ) -> Self</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>/// Returns the integral value closest to `self`. If two integrers are equally close, the one with</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// greater magnitude is returned.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// NOTE: The name of this function requires bike-shedding. I’ve chosen a deliberately poor</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// name as a straw-man.</div></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func roundToNearestTiesAway( ) -> Self</div><div class=""><br class=""></div><div class="">and mutating versions of those.</div><div class=""><br class=""></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I was trying to add these, but working out the names of the mutating functions is difficult. How is truncate different to floor if it returns an integral value and can never round up?</div></div></div></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">Perhaps for the other functions, we could have a general `round` function with a tiebreak-enum parameter (it would be great if we could embed enums in protocols, but I’m not sure if that’s even on the roadmap):</div><div class=""><br class=""></div><div class="">enum FloatingPointRoundingStrategy { // or something to that effect</div><div class=""> case preferEven</div><div class=""> case preferGreatest</div><div class="">}</div><div class=""><br class=""></div><div class="">func rounded(inTiebreak: FloatingPointRoundingStrategy) -> Self</div><div class=""><br class=""></div><div class="">I think `(4.5).rounded(inTiebreak: .preferGreatest) == 5.0` looks quite nice.</div></div></div></div></blockquote><br class=""></div><div>Yes, something along these lines might work, though `FloatingPointRoundingStrategy` isn’t quite right; after all, round-towards-infinity (aka ceiling) is also a rounding strategy.</div><div><br class=""></div><div>One option (which I don’t totally love, but which simplifies the API surface quite a bit, and avoids adding more formXXXX constructions) would be to fold all the rounding rules into a single member function (very strawman):</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/// Describes a rule for rounding to an integral value.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>enum RoundingRule {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// The result is the closest representable value greater than or equal to the source.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case upwards</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// The result is the closest representable value less than or equal to the source.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case downwards</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// The result is the closest representable value whose magnitude is less than or equal to that of the source.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case towardZero</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// The result is the closest representable value; if two values are equally close, the even one is chosen.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case toNearestTiesToEven</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// The result is the closest representable value; if two values are equally close, the one with greater magnitude is chosen.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case toNearestTiesAway</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/// Rounds to an integral value according to the specified rounding rule.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>mutating func round(_ rule: RoundingRule = toNearestTiesAway)</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>func rounded(_ rule: RoundingRule = toNearestTiesAway) -> Self</div><div><br class=""></div><div>That gives us e.g.:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>let x = -2.5</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>x.round(.upwards)<span class="Apple-tab-span" style="white-space:pre">        </span>// -2</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>x.round(.downwards)<span class="Apple-tab-span" style="white-space:pre">        </span>// -3</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>x.round(.towardZero)<span class="Apple-tab-span" style="white-space:pre">        </span>// -2</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>x.round(.toNearestTiesToEven)<span class="Apple-tab-span" style="white-space:pre">        </span>// -2</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>x.round()<span class="Apple-tab-span" style="white-space:pre">        </span>// -3</div><div><br class=""></div><div>We might also provide free functions that implement the most common operations under the familiar libc names (I realize that free-functions are not broadly considered “swifty”, but they may be appropriate here; we would effectively simply be moving these free functions from Darwin/Glibc into the stdlib, and making them available for all FloatingPoint types).</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>func ceil<T: FloatingPoint>(_ x: T) -> T {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>return x.rounded(.upwards)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>func floor<T: FloatingPoint>(_ x: T) -> T {</div><span class="Apple-tab-span" style="white-space: pre;">                </span>return x.rounded(.downwards)<div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>func trunc<T: FloatingPoint>(_ x: T) -> T {</div><span class="Apple-tab-span" style="white-space: pre;">                </span>return x.rounded(.towardZero)<div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><br class=""></div><div><br class=""></div></body></html>