<div dir="ltr">[ proposal link: <a href="https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c" target="_blank">https://gist.github.com/<wbr>moiseev/<wbr>62ffe3c91b66866fdebf6f3fcc7cad<wbr>8c</a> ]<br><div class="gmail_extra"><div><div class="m_-7385509867756785065gmail_signature"><div dir="ltr"><div><br></div></div></div></div>
<br><div class="gmail_quote">On Sat, Jan 14, 2017 at 4:55 PM, Dave Abrahams via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Responding to both Jacob and Xiaodi here; thanks very much for your<br>
feedback!<br>
<span class="m_-7385509867756785065gmail-"><br>
on Sat Jan 14 2017, Xiaodi Wu &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</span><span class="m_-7385509867756785065gmail-"><br>
&gt; I think, in the end, it&#39;s the _name_ that could use improvement here. As<br>
&gt; the doc comments say, `Arithmetic` is supposed to provide a &quot;suitable basis<br>
&gt; for arithmetic on scalars&quot;--perhaps `ScalarArithmetic` might be more<br>
&gt; appropriate? It would make it clear that `CGVector` is not meant to be a<br>
&gt; conforming type.<br>
<br>
</span>We want Arithmetic to be able to handle complex numbers.  Whether Scalar<br>
would be appropriate in that case sort of depends on what the implied<br>
field is, right?<br></blockquote><div><br></div><div>I think &quot;scalar&quot; is an appropriate term for any field. The scalar-ness usually comes into play when it&#39;s used in a vector space, but using the term alone doesn&#39;t bother me.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">It&#39;s true that CGPoint and CGVector have no obvious sensible<br>
interpretation of &quot;42&quot;, and that&#39;s unfortunate.  The problem with<br>
protocols for algebraic structures is that there&#39;s an incredibly<br>
complicated lattice (see figures 3.1, 3.2 in<br>
<a href="ftp://jcmc.indiana.edu/pub/techreports/TR638.pdf" rel="noreferrer" target="_blank">ftp://jcmc.indiana.edu/pub/tec<wbr>hreports/TR638.pdf</a>) and we don&#39;t want to<br>
shove all of those protocols into the standard library (especially not<br>
prematurely) but each requirement you add to a more-coarsely aggregated<br>
protocol like Arithmetic will make it ineligible for representing some<br>
important type.<br></blockquote><div><br></div><div>Yep, it is quite complicated, and I understand not wanting to address all that right now; calling it ScalarArithmetic seems appropriate to clarify the limitations. FieldArithmetic might also be appropriate, but is less clear (+ see below about quaternions).</div><div><br></div><div>Daves Sweeris and Abrahams wrote:</div><div><br></div><div>&gt; &gt; I was under the impression that complex numbers are scalar numbers... although maybe not since once you get past, I think quaternions, you start losing division and eventually multiplication, IIRC. (I hate it when two of my recollections try to conflict with each other.) </div><div>&gt;</div><div>&gt; Well, you can view them as 2d vectors, so I&#39;m not sure.  We need more of a numerics expert than I am to weigh in here.</div><div> </div><div>But complex numbers have multiplication and division operations defined (they form a field), unlike regular vectors in R². Meaning you can have a vector space over the field of complex numbers.</div><div><br></div><div>You still have multiplication and division past quaternions, but the quaternions are <b>not commutative</b>. This isn&#39;t really a problem in Swift, since the compiler never allows you to write an expression where the order of arguments to an operator is ambiguous. This means they are <b>not a field</b>, just a <a href="https://en.wikipedia.org/wiki/Division_ring" target="_blank">division ring</a> (a field is a commutative division ring). (I believe you can&#39;t technically have a vector space over a non-commutative ring; the generalization would be a <a href="https://en.wikipedia.org/wiki/Module_%28mathematics%29" target="_blank">module</a>. That&#39;s probably an argument for the name ScalarArithmetic over FieldArithmetic.)</div><div><br></div><div>Octonions are furthermore <b>not associative</b>, which is more of a problem since the standard library arithmetic operators are given an associativity. We can&#39;t give that up for regular numeric types, so someone working with octonions would just have to define their own non-associative operators (since there&#39;s no way for the protocol requirement to specify the operator associativity).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
That said, the ability to interpret integer literals as an arbitrary<br>
Arithmetic isn&#39;t used anywhere in the standard library, so I&#39;d like to<br>
consider undoing<br>
<a href="https://github.com/apple/swift/commit/de5b03ddc41be9c5ca5e15d5709eb2be069286c1" rel="noreferrer" target="_blank">https://github.com/apple/swift<wbr>/commit/de5b03ddc41be9c5ca5e15<wbr>d5709eb2be069286c1</a><br>
and moving ExpressibleByIntegerLiteral down the protocol hierarchy to<br>
BinaryInteger.<br></blockquote><div><br></div><div>+1</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
&gt;&gt; *## BinaryInteger*<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt;<br>
&gt;&gt; I&#39;m a little confused by the presence of init(extendingOrTruncating:) for<br>
</span>&gt;&gt; *all* binary integers. Why does it make sense to be able to write<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt; UInt16(extendingOrTruncating: (-21 as Int8)) ? In my mind, sign-extension<br>
&gt;&gt; only has meaning when the source and destination types are both signed.<br>
&gt;&gt;<br>
&gt;<br>
&gt; Here (just IMHO), I disagree. Since any binary integer can be truncated and<br>
&gt; any can be right-shifted, it makes sense for `init(extendingOrTruncating:)`<br>
&gt; to be available for all of them. If I understand the proposal correctly,<br>
&gt; `Int(extendingOrTruncating: (-1 as Int8))` would give you a different<br>
&gt; result than `Int(extendingOrTruncating: (255 as UInt8)`.<br>
<br>
</span>Yes it would.  But the real justification for this operation is generic<br>
programming with integers.  It isn&#39;t possible, today, to define:<br>
<br>
  init&lt;T:BinaryInteger&gt;(extendin<wbr>g:T) where T.isNarrowerThan(Self)<br>
  init&lt;T:BinaryInteger&gt;(truncati<wbr>ng:T) where T.isWiderThan(Self)<br>
<div><div class="m_-7385509867756785065gmail-h5"><br>
&gt;&gt; Although I would not be against a clamp() function in the standard library,<br>
&gt;&gt; &quot;init(clamping:)&quot; sounds strange to me. What about calling it<br>
&gt;&gt; &quot;init(nearestTo:)&quot;?  One could also define a FloatingPoint version of<br>
&gt;&gt; init(nearestTo:), i.e. lround(). For maximum annoyance and explicitness,<br>
&gt;&gt; you could even rename the existing init(_:) to init(truncating:) to make it<br>
&gt;&gt; clear that truncation, not regular rounding, occurs when converting from<br>
&gt;&gt; floating-point.<br>
&gt;&gt;<br>
&gt;<br>
&gt; I would disagree with that as well; the existing `init(_:)` truncates the<br>
&gt; fractional part but errors if that value is outside the representable<br>
&gt; range, while the word &quot;truncating&quot; makes it sound like something is done to<br>
&gt; make any possible source value give you a destination value (a la<br>
&gt; &quot;extendingOrTruncating&quot; for integers).<br>
&gt;<br>
&gt; Meanwhile, &quot;nearest to&quot; is problematic for me because either 127 and 129 is<br>
&gt; &quot;nearest to&quot; 128, and neither integer is &quot;nearest to&quot; 500, yet<br>
&gt; `Int8(clamping: 128)` and `Int8(clamping: 500)` both give you 127. This<br>
&gt; operation is very different from lround() for floating point, which in<br>
&gt; Swift is `rounded(.toNearestOrAwayFromZ<wbr>ero)` (or just `rounded()`).<br></div></div></blockquote><div><br></div><div>127 and 129 are both nearest to 128, but both of them are not Int8s. The &quot;Int8(nearestTo: 128)&quot; would be 127.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div class="m_-7385509867756785065gmail-h5">
&gt;<br>
&gt; In both these cases, I think it&#39;s important to use spellings that<br>
&gt; distinguish doing things to the fractional part of floating point values<br>
&gt; and doing things to the binary representation of integer values. I think<br>
&gt; there&#39;s great value in using the term &quot;clamp&quot;, which is very different from<br>
&gt; &quot;nearest&quot;; and in using an unlabeled `init(_:)` for initializing from FP<br>
&gt; values, which is most similar to the unlabeled `init(_:)` for initializing<br>
&gt; from integer values, as opposed to your suggested `init(truncating:)` which<br>
&gt; connotes some similarity to `init(extendingOrTruncating:)` for integer<br>
&gt; values.<br>
<br>
</div></div>+1<br>
<br>
&gt; *... masking shifts*<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt;<br>
&gt;&gt; The example claims that &quot;(30 as UInt8) &amp;&gt;&gt; 11&quot; produces 3, because it<br>
&gt;&gt; right-shifts 30 by 3. But isn&#39;t the bitWidth of UInt8 always 8 since it&#39;s a<br>
&gt;&gt; fixed-width type?<br>
<br>
</span>Yes.<br>
<span class="m_-7385509867756785065gmail-"><br>
&gt;&gt; Why should 11 get masked to 3 before the shift?<br>
<br>
</span>Because those are the semantics of masking shift?<br></blockquote><div><br></div><div>Ah, I see why I was confused (the point is that  2³ = 8 = bitWidth). Does this mean that masking shifts only work when the bitWidth is a power of two? Otherwise, there&#39;d be no way to reduce the shift range to exactly 0..&lt;bitWidth using a mask.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
You can think of masking shift as an optimization akin to using &amp;+ to<br>
add signed numbers when you know it can&#39;t overflow.  It&#39;s an expert&#39;s<br>
tool.  If you want semantics that always make sense, use regular shift.<br>
<span class="m_-7385509867756785065gmail-"><br>
&gt;&gt; (Also, it might be a good idea to choose examples with numbers whose<br>
&gt;&gt; base-ten representations don&#39;t look like valid binary. 😉)<br>
<br>
</span>Good point.<br>
<span class="m_-7385509867756785065gmail-"><br>
&gt;&gt; What use cases are there for masking shifts? I was under the<br>
&gt;&gt; impression that &quot;smart shifts&quot; were pretty much how the usual shift<br>
&gt;&gt; instructions already behaved.<br>
<br>
</span>No, sadly not!  The way the usual shift instructions behave is that if<br>
you shift by a negative amount or you overshift, you get undefined<br>
behavior, which gets expressed in various fun ways at runtime!<br>
<span class="m_-7385509867756785065gmail-"><br>
&gt;&gt; (Minor: were the smart shift operators supposed to be included as<br>
&gt;&gt; BinaryInteger protocol requirements? I only see them in the &quot;heterogeneous<br>
&gt;&gt; shifts&quot; extension.)<br>
<br>
</span>They don&#39;t need to be requirements, as they&#39;re defined entirely in terms<br>
of other (required) operations.  I&#39;d be interested in any arguments you<br>
might have for making them requirements, though.<br>
<br>
&gt;&gt; *... init&lt;T: BinaryInteger&gt;(_ source: T)*<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt;<br>
&gt;&gt; Now a thought experiment: suppose you wanted to write an<br>
&gt;&gt; arbitrary-precision BigInt, or any binary integer such as Int256. The<br>
&gt;&gt; BinaryInteger protocol requires you to provide init&lt;T:BinaryInteger&gt;(_<br>
&gt;&gt; source: T). Given the source of type T, how do you access its bits? Is<br>
&gt;&gt; repeated use of word(at:) the recommended way?<br>
<br>
</span>Yes.<br>
<span class="m_-7385509867756785065gmail-"><br>
&gt;&gt; If so, it might be nice to include a &quot;wordCount&quot; returning the number<br>
&gt;&gt; of available words; otherwise I suppose the user has to use something<br>
&gt;&gt; like bitWidth/(8*MemoryLayout&lt;Int&gt;.<wbr>size), which is pretty ugly.<br>
<br>
</span>good catch; countRepresentedWords is in the prototype<br>
(<a href="https://github.com/apple/swift/blob/new-integer-protocols/stdlib/public/core/Integers.swift.gyb#L1521" rel="noreferrer" target="_blank">https://github.com/apple/swif<wbr>t/blob/new-integer-protocols/<wbr>stdlib/public/core/Integers.<wbr>swift.gyb#L1521</a>),<br>
and it should be in the proposal.<br>
<br>
&gt;&gt; *## FixedWidthInteger*<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt;<br>
&gt;&gt; Why is popcount restricted to FixedWidthInteger? It seems like it could<br>
&gt;&gt; theoretically apply to any UnsignedInteger.<br>
&gt;&gt;<br>
&gt;<br>
&gt; You can perfectly legitimately get a popcount for a signed integer. It&#39;s<br>
&gt; just looking at the binary representation and counting the ones. But then<br>
&gt; with two&#39;s complement, it&#39;d have to be restricted to FixedWidthInteger and<br>
&gt; not BinaryInteger, because the same negative value would have a different<br>
&gt; popcount depending on the type&#39;s bitwidth.<br>
<br>
</span>Right, or to put it differently, the popcount of a negative BigInt would<br>
always be inifinite.<br></blockquote><div><br></div><div>Makes sense, but infinity has no representation in Int, so what would the popcount be?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<span class="m_-7385509867756785065gmail-"><br></span>&gt;&gt; *## Masking arithmetic*<br>
<span class="m_-7385509867756785065gmail-">&gt;&gt;<br>
&gt;&gt; Do &amp;* and &amp;+ and &amp;- need their operands to have the same type, or could<br>
&gt;&gt; these be heterogeneous too (at least &amp;+ and &amp;-)?<br>
<br>
</span>I don&#39;t know what semantics you&#39;re imagining for heterogeneous &amp;+.  What<br>
type would it return?  What mask would it use? </blockquote><div><br></div><div>I was thinking of these as overflow rather than masking operators; i.e. the lhs type would be allowed to overflow if the rhs value were too large. </div></div></div></div>