- reimplementing the comparison of quadratic number field elements is a well defined unit of change itself. I suggest moving
floor()
and ceil()
implementations to a separate patch, even a different ticket.
left.D
is of type Integer
. Cython tries to do the right thing for <unsigned int> left.D
, but it would be better to use mpz_mul()
with left.D.value
.
Done and done.
- Do you really need to use rich comparisons? Working only with
__cmp__
should simplify the case comparisons before the return statements and avoid the new python_object.pxi
include.
We loose speed (~1 micro sec) by doing this. I quickly look at the code of comparison for Integer. The comparison is directly implemented inside richcmp and avoid as much as possible the coercion machinery (ie the type of the input is check with the cython function PY_TYPE_CHECK). Do you think we should proceed that way ?
- I guess speed could be further improved by using an approximation (with
double
s say) first and falling back to the exact computation if the results are too close.
What do you mean by too close ? How do I certify that my float comparison is accurate enough ?
Moreover, if we proceed that way we have to perform conversion from mpz_t to float (or double or real_mpfr). A way it may work is to look first if a,b, D and denom have reasonable values (recall that mpz_t have unlimited precision) and if yes, convert it to double and try to compare the arguments.
Last, I'm not sure the gain of speed would be terrific. Comparison requires only 7 integer operations.
mpz_sgn()
returns 0 if the argument is 0
. You don't seem to cover this case, though I couldn't find any example that returns wrong results.
Actually there is no problem since we compute the sign of an expression of the form a2 + b2 D where a and b are both integers (and one of them is non null) and D is a square free integer. Hence the sign is never 0.
- To avoid code duplication, it might be better change the if statement to:
if mpz_sgn(i)*mpz_sgn(j) == 1:
# both i and j are positive or negative
mpz_mul(i, i, i)
mpz_mul(j, j, j)
mpz_mul_ui(j, j, <unsigned int> left.D)
test = mpz_cmp(i, j)
if mpz_sgn(i) == -1:
# both i and j are negative
test *= -1
Sure but that way we call twice mpz_sgn(i)... I may change it if you prefer.
Actually, the part where a lot of time is lost is the check for embedding
if not RDF.has_coerce_map_from(left._parent):
...
By replacing it by
if left.D < 0:
...
I pass from 4 micro second to 2 micro seconds. That way comparison without embedding for positive discriminant will be equivalent to comparison with the standard embedding. This is in the last version of the patch. What do you think about that ?