Feature #221
Better RingElems
Description
- allow default ctor for
RingElem
(value could be 0 inZZ
) - allow assignment of
RingElem
to change rings (no technical objections)
JAA estimates: both changes should be simple to achieve, and will probably not introduce any technical problems.
Note that my suggestion for the default value of a RingElem
should work well if/when we introduce automatic mapping of RingElem
values
Related issues
History
#1 Updated by John Abbott over 11 years ago
At the moment JAA sees no advantage to the current "restrictive" regime for RingElem
values.
JAA is not sure if he recalls why we introduced the restriction that a RingElem
is eternally associated with a single specific ring. He thinks it may have been vaguely "for reasons of safety".
If we really want to preserve the current restrictions, then JAA notes that it would be technically fairly simple to use a global flag to say whether to be restrictive or permissive.
Since CoCoA-5 does not impose restrictions about "changing ring", it seems hard to justify saying that we need such a restriction in CoCoALib.
#2 Updated by Anna Maria Bigatti over 11 years ago
- Category set to Various
The "safety" in assigning only RingElems in the same ring was (probably) to prevent mixing rings in one algorithm.
Anyway I see no strong problem in allowing the change of ring in an assignment.
The only problem I see here is in this example:
RingElem f(Qxy); f = 3;
Is now f in ZZ or Qxy?
Of course one could say: "Simple, put it in ZZ and allow mixed arithmetics!" (i.e. between different rings), but that's like opening a can of worms...
#3 Updated by John Abbott over 11 years ago
What should the following code excerpts do?
Case (A)
RingElem r; // by default an element of RingZZ r = BigRat(2,1);
Case (B)
RingElem r; // by default an element of RingZZ r = BigRat(2,3);
Assignment from a BigRat
is allowed, and JAA believes it would be inconvenient to forbid it.
Case (A) should surely work; the only question is to which ring r
belongs after the assignment (namely ZZ
or QQ
).
Case (B) might work or might give an error; if it works then after the assignment x
can no longer belong to RingZZ
, so would presumably belong to RingQQ
.
We can make the ring evident by using an explicit constructor like this:
x = RingElem(RingQQ(), BigRat(2,3));
NB we cannot mimic CoCoA-5 because there the type of the value changes from RINGELEM
to RAT
.
#4 Updated by John Abbott over 11 years ago
This may not be the correct place, but I wanted to note that until we have automatic conversions (if ever), an equality test between elements of different rings will produce an error!
Here is an example scenario (which is not too far-fetched).
RingElem x(R); RingElem y(R); if (x == y) ... // no error here x = 1; // to which ring does x belong now? Either R or ZZ if (x == y) ... // this will give error if RingOf(x) is not R
This makes me think that (the details of) the current issue are closely related to whether we intend implementing automatic "promotion" of ring elements.
I suggest the following rule/guideline:- assignment changes the ring if and only if the assigned value indicates explicitly the ring to use
(i.e. in practice the only possibility currently is when the RHS is itself a RingElem).
#5 Updated by John Abbott over 11 years ago
- the default ctor for
RingElem
produces 0 inZZ
- the rule/guideline in note-4 is good.
We propose implementing in the near future.
#6 Updated by John Abbott over 11 years ago
- Status changed from New to In Progress
- Assignee set to John Abbott
- Priority changed from Normal to High
- Target version set to CoCoALib-0.9952
- % Done changed from 0 to 50
#7 Updated by John Abbott over 11 years ago
If we allow "mixed ring" assignment then we should also allow "mixed ring" swap
.
JAA would expect swap
to work as if it were implemented like this:
void swap(A,B) { tmp = A; A = B; B = tmp; }
#8 Updated by Anna Maria Bigatti over 11 years ago
John Abbott wrote:
If we allow "mixed ring" assignment then we should also allow "mixed ring"
swap
.
I agree
#9 Updated by John Abbott over 11 years ago
Case (A) We have decided that this code:
RingElem r;
initializes r
as being the zero of ZZ
Case (B) What should this code do?
RingElem r = 3;
Case (C) And what about this?
RingElem r(3);
If I recall well, the rules of C++ say that cases (B) and (C) either both fail to compile or both succeed (since they trigger effectively the same ctor).
#10 Updated by John Abbott over 11 years ago
To implement assignment of RingElem
which can change the ring, I need to allow ring
to be assigned -- currently assignment is disabled.
Any objections to allowing assignment of values of type ring
?
JAA does not anticipate any nasty surprises suddenly appearing.
#11 Updated by Anna Maria Bigatti over 11 years ago
John Abbott wrote:
Any objections to allowing assignment of values of type
ring
?
ok for me: in fact I had to do use auto-prt tricks to delay initialization somewhere.
I could clean them up :-)
#12 Updated by John Abbott over 11 years ago
Note that assignment to a RefRingElem
cannot change the ring to which it belongs because it may well be a reference to a value inside some other homogeneous structure (e.g. a matrix). Perhaps the choice of name RefRingElem
is not ideal any more?
#13 Updated by John Abbott over 11 years ago
Non homogeneous assignment of RingElem
is trickier than I thought (because of the inheritance from RefRingElem
).
Currently I'm stuck.
#14 Updated by John Abbott over 11 years ago
- % Done changed from 50 to 70
I've solved yesterday's problem (but still have not understood what caused it).
I was about to update the documentation but then noticed that it is not clear what the following should do:
RingElem x0; // this *is* defined RingElem x1(2); RingElem x2 = 2; RingElem x3 = BigRat(2,1); RingElem x4 = BigRat(2,3);
We now have that
x0
will be initialized to 0 in ZZ
; all the others will not currently compile.
When no ring is specified in the default ctor, the system automatically chooses ZZ
. So should it automatically choose ZZ
whenever no ring is explicitly given to a ctor? If we adopt this rule then the line with x4
will compile but produce a run-time error.
We could also allow QQ
to be chosen automatically, so that the x4
line would work. Though if QQ
may also be chosen, it is not clear to me in which ring x3
will lie. Its initial value happens to be in ZZ
, but it was a value of type BigRat
.
Opinions? Ideas?
2013-02-18: DECISION according to the code and doc, I decided to KISS: if no ring is specified then the ring used is ZZ
(so the x4
line above will cause a run-time error).
#15 Updated by John Abbott over 11 years ago
2013-02-18: The problem presented in this post has been resolved by removing the class RefRingElem
(see #261)
There is a potential problem with "ring changing" assignment/swap
and RefRingElem
. The difficulty is highlighted by the following two examples:
(A) This example has been valid for some time, and will print 2
RingElem x(R,1); RingElem y(R,2); RefRingElem z(x); x = y; cout << "z=" << z << endl;
(B) We get DANGEROUS behaviour if the rings of x
and y
are different:
RingElem x(R1,1); RingElem y(R2,2); RefRingElem z(x); x = y; cout << "z=" << z << endl;
The assignment to
x
deletes the old value contained, so z
subsequently contains a dangling reference/pointer to the space where the original value of x
was stored!
Recall that the ring to which z
belongs cannot be changed, and it would require a significant redesign to produce a mechanism for informing z
(and any other references) that it is now dangling.
What to do???
#16 Updated by John Abbott over 11 years ago
- Status changed from In Progress to Resolved
- % Done changed from 70 to 90
Updated the doc for RingElem.
Might be necessary to revise the example progs?
#17 Updated by John Abbott about 11 years ago
- Status changed from Resolved to Closed
No problems have surfaced in 4 months; the doc seems to be correct too.
So I'm closing this issue.
#18 Updated by John Abbott about 11 years ago
- % Done changed from 90 to 100