On Apr 21, 4:19 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> Keith H Duggar wrote:
> > On Apr 20, 5:06 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> >> Keith H Duggar wrote:
> >> > On Apr 19, 6:19 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> >> >> Keith H Duggar wrote:
> > I think we have to resolve the central issue of (-) above first.
>
> Right. I hope, what I wrote is comprehensible.
Yes, it was excellent. Thank you.
> >> >> This is too strong a claim. The interpretation of unsigned
> >> >> types as modeling a finite modular group works well for the
> >> >> three operators +, -, and *. It does not work for the operators
> >> >> /, %, <, and >.
....
> >> So, even though comparing unsigned values in C++ is meaningful, the
> >> meaning is not really well-aligned with the interpretation of unsigned
> >> values as representing values in a modular group.
>
> > I'm not getting this one. It seems C++ < > are well-aligned with
> > /finite/ modular groups.
>
> Actually, they are not aligned at all. The only connection of the order and
> the group structure is that the identity element of the group, i.e., 0 is
> also the minimum with respect to the order. Other than that, the order and
> the algebra are not related by any formula (like translation invariance).
> That's why I'd say they are not well-aligned.
>
> Of course, since there is no relation at all, the algebraic structure and
> the order also do not _conflict_ one another.
Ah ok, now I understand your point and I agree with you now on
this point. Operators < and > are neither well-aligned nor in
conflict with unsigned as implementing modular arithmetic. So
emphasizing the modular arithmetic does not do justice to the
other operations defined on unsigned. I agree.
What I took issue with earlier was the phrasing "does not work
for the operators [< >]" which to me implied a /conflict/ where
I saw none.
> > Now hold on. The definition of division above is an /equality/
> > not a /congruence/ (2) and that applies for both the modular and
> > "regular" versions of the definition. So there is no (mod 32)
> > in /this/ definition of division (1). So the unique solution is
> > (3,1). Or am I missing something fundamental?
>
> Well, the point under discussion is, which interpretation for the unsigned
> types is appropriate. Let me try to make this question precise by
> formalizing the two interpretations.
>
> Let N denote the set of non-negative integers: {0, 1, 2, ... }. Let N_k
> denote the subset {0, 1, 2, ..., 2^k-1 } of the first 2^k counting numbers.
> Let M_k denote the set { [0], [1], [2], ... } of congruence classes mod 2^k.
> Now let T be the set of admissible values of an unsigned type of bitlength
> k. There are two obvious maps
>
> f : T --> N_k
> g : T --> M_k
>
> The first map f corresponds to the _interpretation_ of the unsigned type T
> as modeling the first 2^k counting numbers, and the map g corresponds to the
> interpretation of the unsigned type T as modeling the finite modular group
> with 2^k elements. To say that a certain operator of C++ is better
> interpreted one way or the other can be made precise by saying that it
> corresponds via f or g to a mathematical notion in N_k or M_k. E.g., the
> operator + is best interpreted in the second way:
>
> g(a+b) = g(a) + g(b) for all a,b in T
> + on the left is C++
> + on the right is addition in M_k
>
> however, there are a,b in T such that f(a+b) != f(a)+f(b).
>
> Conversely, there is no mathematical notion of less-than in M_k, but there
> is a mathematical notion of less-than in N_k and:
>
> a < b if and only if f(a) less than f(b)
> < is C++
> less than is in N_k
>
> In this sense, the interpretation via f is more natural for operator<
>
> Now, for the question whether (-) defined / and %. Here are the relevant
> statements:
>
> 1) For any two numbers p, d in N_k with d != 0, there are unique numbers q
> and r in N_k satisfying
> (a) p = d * q + r
> (b) r < d
>
> 2) There are elements [p], [d] in M_k with [d] != [0] such that more than
> one pair ([q], [r]) exists, for which
> (a) [p] = [d] * [q] + [r]
> (b) r < d
>
> So, (-) defines division with remainder in N_k but not in M_k. Now, the C++
> operators / and % model division with remainder in N_k. Hence, they are best
> interpreted via the map f but not via the map g:
>
> f(a/b) and f(a%b) are the unique elements of N_k satisfying
> f(a) = f(b) * f(a/b) + f(a%b) and f(a%b) < f(b)
>
> Replacing f with g renders the statements false because uniqueness fails.
Hmm, yes this is a very clever formalization of the qualifer
"better interpreted". I'm forced to agree. unsigned is "better
interpreted" as a set of counting numbers for / and %. Thanks!
> > (1) There is a another common definition of "division" which /is/
> > based on congruence instead of equality and defines division by d
> > as multiplication by d^-1 the multiplicative inverse of d where
>
> > d * d^-1 =m= 1
>
> > with =m= representing congruence modulo m.
>
> > However, this definition is limited to d which are coprime to the
> > modulus and is more difficult to calculate so it would be rather
> > inconvenient for a programming language. Also the result merges
> > the quotient and remainder in an interesting way into a single
> > result even if the remainder is not 0. Finally, and importantly
> > for this context, the multiplicative inverse definition does
> > not apply at all to "regular" arithmetic on integers.
>
> True. This definition of division makes (partial) sense in M_k, but it does
> not correspond to any operator in C++.
Agreed.
> > (2) Meh while I was going back to respond to
>
> >> First, note that this definition hinges upon <, which in turn is not
> >> really a concept of modular arithmetic. This triggers some suspicion that
> >> / and % may also not be all that cool with regard to modular arithmetic.
>
> > I realized an unfortunate and careless s/integer/unsigned/g led
> > to this phrase "for unsigned * and +" in "Let p = d * q + r for
> > unsigned * and + and unsigned q and r". That is not intended to
> > imply the = is a congruence (it is not) nor that the itermediate
> > expressions in the definition are modulo something. "unsigned
> > p, d, q, r" just means they are members of the group.
>
> > Anyhow, the point is, in response to both the the snip above and
> > the bad substitution, definitions frequently involve "meta" sets,
> > functions, etc. So the pedantic full blown definition of modular
> > division would involve /integers/ proper along with /integer/
> > addition, multiplication, etc. So < does not trigger suspicion
> > for me because in the back of my mind I know there is the larger
> > precise definition that uses integer < if necessary.
>
> Pulling the integer interpretation in when necessary is precisely, what I
> advicate
It just so happens that I think, the integer interpretation is
> the _right one_ for /, %, and <.
Agreed.
> > > I don't deny what is in the standard. What I deny is that the catch phrase
> > > "unsigned means modular" captures the essence of unsigned types. It
> > > overemphasizes a particular aspect and does not do justice to _other_
> > > provisions in the standard that are hard to reconcile with modular
> > > arithmetic.
Now agreed.
> > > What I do agree on is that "unsigned means non-negative" is a misguided
> > > mantra, which has (also) no foundation in the standard. I also can see that
> > > following this slogan does lead to problems. I would suspect (although I am
> > > open to correction from experience) that the main benefit of the phrase
> > > "unsigned means modular" is to act as an antidote to "unsigned means non-
> > > negative".
Now agreed.
Thank you, Kai-Uwe, for this excellent demonstration. This has
been very instructive. I appreciate your patience and effort
KHD