…rather, the remainder will fit in width min(X, Y)<div><br></div><div>Nevin<br><br>On Tuesday, January 31, 2017, Nevin Brackett-Rozinsky <<a href="mailto:nevin.brackettrozinsky@gmail.com">nevin.brackettrozinsky@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">What, exactly, is the intended purpose of doubleWidthDivide?<br><br>I ask because, outside of degenerate cases, a quotient and remainder will fit in the same size type as the operands.<div><br></div><div>So widthX / widthY will have quotient that fits in width X, and remainder that fits in width Y.</div><div><br></div><div>In general, we cannot assume either one would be any smaller than that.</div><div><br></div><div>Nevin<br><br><br>On Monday, January 30, 2017, Brent Royal-Gordon via swift-evolution <<a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank">swift-evolution@swift.org</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> On Jan 30, 2017, at 11:31 AM, Max Moiseev <<a>moiseev@apple.com</a>> wrote:<br>
><br>
> doubleWidthDivide should not return a DoubleWidth<T> for two reasons:<br>
> 1. The components of it’s return type are not high and low, but are quotient and remainder instead.<br>
> 2. In DoubleWidth<T> high is T and low is T.Magnitude, which is not the case for quotient and remainder.<br>
<br>
You're right about the return value; for `doubleWidthDivide(_:_:)`, I was thinking about changing the dividend. Specifically, I'm thinking we should change these to:<br>
<br>
static func doubleWidthMultiply(_ lhs: Self, _ rhs: Self) -> DoubleWidth<Self><br>
static func doubleWidthDivide(_ lhs: DoubleWidth<Self>, _ rhs: Self) -> (quotient: Self, remainder: Self)<br>
<br>
I'm also thinking a little bit about spelling of these operations. I'd *love* to be able to call them `*` and `/` and let the type system sort things out, but that would cause problems, especially for multiply (since the return value is the only thing different from a normal `*`). We could invent a new operator, but that would be a bit much. Could these be simply `multiply` and `divide`, and we'll permit the `DoubleWidth` parameter/return type to explain itself?<br>
<br>
I'm also thinking the second parameter should be labeled `by`, since that's the way people talk about these operations. Applying both of these suggestions, we'd get:<br>
<br>
static func multiply(_ lhs: Self, by rhs: Self) -> DoubleWidth<Self><br>
static func divide(_ lhs: DoubleWidth<Self>, by rhs: Self) -> (quotient: Self, remainder: Self)<br>
<br>
let x = Int.multiply(a, by: b)<br>
let (aʹ, r) = Int.divide(x, by: b)<br>
assert(a == aʹ)<br>
assert(r == 0)<br>
<br>
Should the standard library provide extensions automatic definitions of multiplication and division in terms of their double-width equivalents?<br>
<br>
extension FixedWidthInteger {<br>
func multipliedWithOverflow(by other: Self) -> (partialValue: Self, overflow: ArithmeticOverflow) {<br>
let doubledResult = Self.multiply(self, by: other)<br>
let overflowed = doubledResult.high != (doubledResult < 0 ? -1 : 0)<br>
return (Self(bitPattern: doubledResult.lowerValue), overflowed ? .overflowed : .none)<br>
}<br>
<br>
func quotientAndRemainder(dividingB<wbr>y other: Self) -> (quotient: Self, remainder: Self) {<br>
precondition(other != 0, "Divide by zero")<br>
return Self.divide(DoubleWidth(self), by: other)<br>
}<br>
<br>
func dividedWithOverflow(by other: Self) -> (partialValue: Self, overflow: ArithmeticOverflow) {<br>
guard other != 0 else { return (self, .overflowed) }<br>
<br>
let result = Self.divide(self, by: other)<br>
return (result.quotient, .none)<br>
}<br>
<br>
static func * (lhs: Self, rhs: Self) -> Self {<br>
let result = lhs.dividedWithOverflow(by: rhs)<br>
precondition(result.overflow == .none, "Multiplication overflowed")<br>
return result.partialValue<br>
}<br>
<br>
static func / (lhs: Self, rhs: Self) -> Self {<br>
let result = lhs.quotientAndRemainder(divid<wbr>ingBy: rhs)<br>
return result.quotient<br>
}<br>
<br>
static func % (lhs: Self, rhs: Self) -> Self {<br>
let result = lhs.quotientAndRemainder(divid<wbr>ingBy: rhs)<br>
return result.remainder<br>
}<br>
}<br>
<br>
Hmm...having actually written this out, I now have a couple of concerns:<br>
<br>
1. There's a lot of jumping back and forth between instance methods and static methods. Can we standardize on just static methods? Or make sure that the user-facing interfaces are all either operators or instance methods?<br>
<br>
2. There is no quotient-and-remainder-with-ov<wbr>erflow, either regular or double-width. Can we do that?<br>
<br>
3. "Overflow" is not really a good description of what's happening in division; the value is undefined, not overflowing. Is there a better way to express this?<br>
<br>
4. For that matter, even non-fixed-width division can "overflow"; should that concept be hoisted higher up the protocol hierarchy?<br>
<br>
5. For *that* matter, should we simply make these operations throw instead of returning a flag?<br>
<br>
enum ArithmeticError<NumberType: Arithmetic>: Error {<br>
// Are generic errors permitted?<br>
case overflow(partialValue: NumberType)<br>
case undefined<br>
}<br>
<br>
// Should these throwing definitions be higher up so that, when working with `Arithmetic`<br>
// or similar types, you have an opportunity to handle errors instead of always trapping?<br>
protocol FixedWidthInteger: BinaryInteger {<br>
...<br>
func adding(_ other: Self) throws -> Self<br>
func subtracting(_ other: Self) throws -> Self<br>
func multiplied(by other: Self) throws -> Self<br>
func divided(by other: Self) throws -> Self<br>
...<br>
}<br>
<br>
I'm *really* tempted to suggest adding throwing variants of the actual operators (strawman example: `^+`, `^-`, `^*`, `^/`, `^%`), but they may be too specialized to really justify that.<br>
<br>
> Having said that, there is a solution for doubleWidthMultiply, that I think is worth trying:<br>
><br>
> enum DoubleWidth<T> {<br>
> case .parts(high: T, low: T.Magnitude)<br>
><br>
> var high: T { switch self { case .parts(let high, _): return high } }<br>
> var low: T.Magnitude { switch self { case .parts(_, let low): return low } }<br>
> }<br>
><br>
> This way it will be possible to both do pattern-matching on the result of doubleWidthMultiply, and use it as a whole, accessing r.high and r.low when needed.<br>
<br>
This sounds like a good idea to me. (Unless we want to create a protocol for destructuring, but I assume that's out of scope.)<br>
<br>
--<br>
Brent Royal-Gordon<br>
Architechies<br>
<br>
______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a>swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
</blockquote></div>
</blockquote></div>