<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 23, 2016, at 15:35, Max Moiseev <<a href="mailto:moiseev@apple.com" class="">moiseev@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="">Hi Jordan,<div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 23, 2016, at 1:50 PM, Jordan Rose <<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hey, standard library folks. Glad we're doing this one. :-)<div class=""><br class=""></div><div class="">- I remain unconvinced that defining an Arithmetic that includes both exact and floating-point numbers is a good idea. All of the arguments from Swift 1 and 2 about why we didn't include this still seem relevant. To phrase it in generic programming terms, what algorithm would be generic over Arithmetic?</div></div></div></blockquote><div class="">Steve, I don’t remember exactly why we chose to do it this time. Can you answer?</div><br class=""><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=""><br class=""></div><div class="">- What is Integer.init<T: FloatingPoint>(_:) supposed to do if the floating-point value is larger than the maximum representable integer? Smaller than the minimum? (As a special case, negative, when the integer type is unsigned?) Infinity? NaN?</div></div></div></blockquote>The same thing it does now — trap.</div></div></div></div></blockquote><div><br class=""></div><div>I think this is worth calling out as a precondition: the value must be within the bounds of the integer type. (The implementation may not trap for some values slightly outside the integer type, like 0.1 being converted to UInt, but it's still not defined.)</div><div><br class=""></div><br class=""><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=""><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=""><br class=""></div><div class="">- Integer.init<T: Integer>(_:) currently says "if it is representable". It should say something like "trapping if it is not representable”.</div></div></div></blockquote>There is a comment saying that this is the precondition that must be checked by the caller. The initializer will trap but this is the implementation detail, isn’t it?<br class=""></div></div></div></div></blockquote><div><br class=""></div><div>Ah, of course. My bad.</div><div><br class=""></div><br class=""><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=""><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=""><br class=""></div><div class="">- I find it odd that Integer.init(clamping:) privileges the bounds of fixed-width integers. I was going to suggest it should take a range to clamp to that <i class="">defaults</i> to the min and max, but that's not implementable for a BigInt.</div></div></div></blockquote>It is always possible to pass bounds as an optional value and default to min…max in .none case.</div><div class="">So you are suggesting something like `init<T : Integer>(clamping: T, within bounds: Optional<ClosedRange<Self>> = nil)` then?</div><div class="">I don’t disagree. Looks useful, but I cannot imagine a good real world use for it, except for:</div><div class=""><br class=""></div><div class="">extension Integer {</div><div class=""> public func findClosest(to: Self, within bounds: ClosedRange<Self>) {</div><div class=""> return Self(clamping: to, within: bounds)</div><div class=""> }</div><div class="">}</div></div></div></div></blockquote><div><br class=""></div><div>I don't find it any different from the existing requirement. If I'm going from a potentially large (absolute) value to a smaller one, it's <i class="">possible</i> I only care about representation, but it's also possible I have a smaller type here because of context.</div><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div>englishPluralIndex = items.count.clamped(to: 0...2)</div></div></blockquote><div><div><br class=""></div><div>Maybe I'd go the other way, and say that this isn't a useful requirement. Are there algorithms that need this that are generic over Integer? (rather than FixedWidthInteger)</div><div><br class=""></div><div><br class=""></div><br class=""><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=""><br class=""></div><div class=""><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=""><br class=""></div><div class="">- nthWord should count "from least-significant to most-significant" rather than "from the right”.</div></div></div></blockquote>Will this definition work fine with different endiannesses? It needs some thinking, but I see your point.<br class=""></div></div></div></div></blockquote><div><br class=""></div><div>Yes, "significant" always refers to place values, not to the representation in memory/registers.</div><div><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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="">- Why is bitWidth in bits but nthWord in words? (I know there's a good answer to this, but using them together seems like it will be common.)</div></div></div></blockquote>There is a derived property that will return the width in words based on bitWidth and word size.<br class=""></div></div></div></blockquote><div><br class=""></div><div>Got it. May be deserving of a SeeAlso.</div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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=""><br class=""></div><div class="">- Why are bitwise operations limited to fixed-width integers? I see "The only difference is that because shifting left truncates the high bits of fixed-width integers, it is hard to define what a left shift would mean to an arbitrary-precision integer" further down, but I would just assume it wouldn't truncate (i.e. it would be a pure multiplication by two).</div></div></div></blockquote>Exactly. It won’t truncate and we considered it to be a sufficient difference in behavior to not allow it to be used in the context over all integers.<br class=""></div></div></div></blockquote><div><br class=""></div><div>Hm. I guess that makes sense. My interpretation: the behavior on fixed-width integers is well-understood, the behavior on arbitrary-precision integers is easy to understand, but the behavior in an algorithm generic over both might be problematic. Thanks for the explanation.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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=""><br class=""></div><div class="">- Is there a requirement about left-shifting into the sign bit, for '<<' and for '&<<‘?</div></div></div></blockquote>The current behavior is to not do anything special about the sign bit. So that (64 as Int8) << 1 would result in a -128.</div><div class=""><br class=""></div><div class="">I should probably add a general note somewhere in the proposal that “unless specifically mentioned, the behavior will remain consistent with the existing implementation”.</div></div></div></blockquote><div><br class=""></div><div>Sure. In this case I was asking about the requirement, though. If I use something like llvm::APSInt, which has an arbitrary-but-fixed-at-creation number of words, does shifting into the sign bit of a signed integer <i class="">always</i> result in a negative number? It never traps or is assumed not to happen?</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""><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=""><br class=""></div><div class="">- What is the ArithmeticOverflow type?</div></div></div></div></blockquote>It is an enum with 2 cases, just like Optional<()>, but with more specific case name. If not for the explicitness, a simple Bool value could have been used.<br class=""></div></div></div></blockquote><div><br class=""></div><div>Please do include this in the proposal. :-)</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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=""><br class=""></div><div class="">- When does the remainder operation overflow? (I just can't remember.)</div></div></div></div></blockquote>Discussed in a separate email. The only case where it should trap is ‘division by zero’, so this part is subjected to changes.</div><div class=""><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=""><br class=""></div><div class="">- I feel a little weird having "someValue.and(mask)". Maybe bitwiseAnd or bitwiseAND to be more explicit?</div></div></div></div></blockquote>Doesn’t return type hint at the ‘bitwise' and not logical nature of these operations? Besides, I would expect operators to be used instead of actual protocol functions.<br class=""></div></div></div></blockquote><div><br class=""></div><div>I guess so. It just reads oddly to me.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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=""><br class=""></div></div><div class="">- maskingShiftLeft/Right seem underspecified in their doc comments. Why can't the protocol requirement just assume the shift amount has already been masked, instead of performing the masking themselves? Is it because we won't be able to optimize that away?</div></div></div></blockquote>There is a section about shifts: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md#a-note-on-bit-shifts" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md#a-note-on-bit-shifts</a></div><div class="">Let me know if you think it is insufficient.<br class=""></div></div></div></blockquote><div><br class=""></div><div>I did see this section, but that's about the operator-based interface, not the requirements on a model type. I'd like to hear a little more about what the expected input range of maskingShiftLeft is and why.</div><div><br class=""></div><div>Jordan</div></div></body></html>