#13213: Comparisons in real number field
-------------------------------------------------+--------------------------
Reporter: vdelecroix | Owner: vdelecroix
Type: enhancement | Status: new
Priority: major | Milestone: sage-5.2
Component: number fields | Resolution:
Keywords: real number field, comparison | Work issues:
Report Upstream: N/A | Reviewers: Burcin Erocal
Authors: Vincent Delecroix | Merged in:
Dependencies: | Stopgaps:
-------------------------------------------------+--------------------------
Old description:
> Provide the order from RR for number field embedded in RR as in
> {{{
> sage: K.<sqrt2> = NumberField(x^2 - 2, 'sqrt2', embedding=1.4142)
> sage: sqrt2 - 1 > 0
> True
> sage: sqrt2 < 2
> True
> sage: sqrt2.floor()
> 1
> }}}
>
> There is a patch for quadratic field. Another one is comming for general
> number fields. Note that this patch is partly a duplicate because of
> #7160.
>
> Timings with the patch
> {{{
> sage: K.<sqrt2> = QuadraticField(2,'sqrt2',embedding=1.4142)
> sage: b = (5*sqrt2 + 14)/5
> sage: a = (3*sqrt2 + 18)/7
> sage: %timeit a < b
> 625 loops, best of 3: 6.68 µs per loop
> }}}
> Timings without the patch
> {{{
> sage: sage: K.<sqrt2> = QuadraticField(2,'sqrt2',embedding=1.4142)
> sage: a = (3*sqrt2 + 18)/7
> sage: b = (5*sqrt2 + 14)/5
> sage: %timeit a < b
> 625 loops, best of 3: 478 ns per loop
> }}}
New description:
Provide the order from RR for real quadratic number field. The current
implementation does
{{{
sage: K.<sqrt2> = NumberField(x^2 - 2, 'sqrt2', embedding=1.4142)
sage: sqrt2 < 100
False
}}}
There is a patch for quadratic field. Another one is comming for general
number fields. Note that this patch is partly a duplicate because of
#7160.
The lost of speed is about x5 for positive discriminant and almost nothing
for negative ones
{{{
sage: K.<sqrt2> = QuadraticField(2,'sqrt2',embedding=1.4142)
sage: a = (3*sqrt2 + 18)/7
sage: b = (5*sqrt2 + 14)/5
sage: %timeit a < b
625 loops, best of 3: 2.36 µs per loop
sage: K.<s> = QuadraticField(-2)
sage: a=3*s+2/4
sage: b=5/7*s+1/3
sage: %timeit a < b
625 loops, best of 3: 600 ns per loop
}}}
Timings without the patch
{{{
sage: sage: K.<sqrt2> = QuadraticField(2,'sqrt2',embedding=1.4142)
sage: a = (3*sqrt2 + 18)/7
sage: b = (5*sqrt2 + 14)/5
sage: %timeit a < b
625 loops, best of 3: 491 ns per loop
sage: K.<s> = QuadraticField(-2)
sage: a=3*s+2/4
sage: b=5/7*s+1/3
sage: %timeit a < b
625 loops, best of 3: 488 ns per loop
}}}
--
Comment (by vdelecroix):
> * 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 a^2 + b^2 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 ?
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/13213#comment:6>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en.