Hi, The following example from q_analogues.py happens to work for a number of questionable reasons:
sage: q_binomial(6,1,I) 1 + I I'm working on a patch that breaks (or fixes, depending how you look at it) one of the behaviors it relies on, and I'd like advice on how to handle the situation. Here is my understanding of what is going on. Please correct me if I'm missing something. The implementation of q_binomial(n, k, q) in this case essentially amounts to: from sage.rings.polynomial.cyclotomic import cyclotomic_value return prod(cyclotomic_value(d,q) for d in range(2,n+1) if floor(n/d) != floor(k/d) + floor((n-k)/d)) and that cyclotomic_value(n, x) to if n < 3: if n == 1: return x - 1 if n == 2: return x + 1 raise ValueError("n must be positive") try: return x.parent()(pari.polcyclo_eval(n, x)) ... Now recall that I is an element of SR that wraps an element of a quadratic number field equipped with a complex embedding: sage: I.parent() Symbolic Ring sage: I.pyobject().parent() Number Field in I with defining polynomial x^2 + 1 sage: I.pyobject().parent().coerce_embedding() Generic morphism: From: Number Field in I with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: I -> 1*I At first cyclotomic_value() appears to work well when called with q=I: sage: cyclotomic_value(1, I) I - 1 sage: cyclotomic_value(3, I) I The call to polcyclo_eval() succeeds "thanks" to the fact that essentially anything can be converted (and even coerced) to a Pari object based, ultimately, on its string representation. (This happens through a maze of calls to _pari_, _pari_init_, _interface_init_, PariInstance.__call__ and objtogen. By the way, can anyone explain the interplay between the *two* places where the conversion falls back to using the string representation, namely in SageObject._interface_init_ and pari.gen.objtogen?) As cyclotomic_value() is careful to convert back the result to the parent of x, we have: sage: cyclotomic_value(1, I).parent() Symbolic Ring sage: cyclotomic_value(3, I).parent() Symbolic Ring But depending on the value of the first parameter, the true numeric object wrapped by the symbolic result will not have the same parent: sage: cyclotomic_value(1, I).pyobject().parent() Number Field in I with defining polynomial x^2 + 1 sage: cyclotomic_value(3, I).pyobject().parent() Interface to the PARI C library Not very nice, but hopefully the coercion system should be able to handle this, right? As it turns out, number fields have a properly implemented conversion to Pari (one that doesn't just take the string representation and hope for the best). This conversion, however, ignores the embedding: sage: pari(I.pyobject()) Mod(y, y^2 + 1) Thus: sage: pari(I)*pari(I.pyobject()) Mod(I*y, y^2 + 1) and yet: sage: pari(I)*I.pyobject() -1 sage: (pari(I)*I.pyobject()).parent() Interface to the PARI C library The trick is that the coercion discovery system currently prefers sage: pari.coerce_map_from(I.pyobject().parent()) Composite map: From: Number Field in I with defining polynomial x^2 + 1 To: Interface to the PARI C library Defn: Generic morphism: From: Number Field in I with defining polynomial x^2 + 1 To: Complex Lazy Field Defn: I -> 1*I then Call morphism: From: Complex Lazy Field To: Interface to the PARI C library to the direct conversion (which, as already mentioned, is also marked as a coercion). Of course, the coercion diagram is supposed to be commutative, but we all know this is currently far from true. This indirect coercion has the benefit of taking the embedding into account, and turns out to give the correct result in our particular example. In general, however, it is much worse than the direct one. Indeed, the CLF -> pari step is the fall-back conversion based on the string representation: sage: pari(1)*(I.pyobject()/3) *** Warning: unused characters: ?*I. 0.333333333333333 Now to my questions. A side effect of the patches I'm working on at #14982 to fix another coercion problem is that the direct conversion NF -> pari would be preferred to the indirect one, leading to: sage: q_binomial(6,1,I) Mod(y + 1, y^2 + 1) So: (1) What would be an acceptable workaround for the regression in q_binomial() that would allow me to move forward with the ticket I was originally working on? (2) In the longer term, how do we deal with that mess? Thanks, -- Marc -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at http://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.