Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move real/complex interval fields to new coercion model #24371

Closed
jdemeyer opened this issue Dec 12, 2017 · 77 comments
Closed

Move real/complex interval fields to new coercion model #24371

jdemeyer opened this issue Dec 12, 2017 · 77 comments

Comments

@jdemeyer
Copy link

Also fix the following:

sage: NF.<a> = QuadraticField(-2)
sage: CIF(a)
...
ValueError: can not convert complex algebraic number to real interval

We also deal with Python 3 compatibility regarding int/long and bytes/unicode.

Depends on #24423

CC: @tscrim

Component: coercion

Author: Jeroen Demeyer

Branch/Commit: 9ac1612

Reviewer: Travis Scrimshaw

Issue created by migration from https://trac.sagemath.org/ticket/24371

@jdemeyer jdemeyer added this to the sage-8.2 milestone Dec 12, 2017
@jdemeyer
Copy link
Author

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 14, 2017

Commit: db4611a

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 14, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

375e40fMap._extra_slots(): do not pass dict
db4611aMove real/complex interval fields to new coercion model

@jdemeyer
Copy link
Author

Author: Jeroen Demeyer

@jdemeyer
Copy link
Author

Dependencies: #24372

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 14, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

549bd7dMove real/complex interval fields to new coercion model

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 14, 2017

Changed commit from db4611a to 549bd7d

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 15, 2017

Changed commit from 549bd7d to fe4c823

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 15, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

fe4c823Move real/complex interval fields to new coercion model

@jdemeyer

This comment has been minimized.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 15, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

2cee3a4Move real/complex interval fields to new coercion model

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 15, 2017

Changed commit from fe4c823 to 2cee3a4

@tscrim
Copy link
Collaborator

tscrim commented Dec 15, 2017

comment:9

This will conflict with #23739, but note that #23739 is currently stalled.

@tscrim
Copy link
Collaborator

tscrim commented Dec 15, 2017

comment:10

Also, I imagine #24363 is a dependency from looking at the code.

@jdemeyer
Copy link
Author

comment:11

Replying to @tscrim:

Also, I imagine #24363 is a dependency from looking at the code.

I don't see why.

@jdemeyer

This comment has been minimized.

@jdemeyer
Copy link
Author

comment:13

Replying to @tscrim:

This will conflict with #23739, but note that #23739 is currently stalled.

I shouldn't be hard to fix #23739 in this ticket.

@koffie
Copy link

koffie commented Dec 16, 2017

comment:14

I also shortly want to note #15114 here and the discussion from which that ticket spawned at sage-devel. I am not saying it needs to get fixed here, but it is a good thing to have in the back of your mind while working on this ticket so that at least things do not get worse in that respect.

@tscrim
Copy link
Collaborator

tscrim commented Dec 16, 2017

comment:15

Replying to @jdemeyer:

Replying to @tscrim:

Also, I imagine #24363 is a dependency from looking at the code.

I don't see why.

I thought I saw a conflict, but that turns out to not be the case.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 17, 2017

Changed commit from 2cee3a4 to d66b54f

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 17, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

d66b54fMove real/complex interval fields to new coercion model

@jdemeyer
Copy link
Author

comment:17

Replying to @koffie:

I also shortly want to note #15114 here and the discussion from which that ticket spawned at sage-devel. I am not saying it needs to get fixed here, but it is a good thing to have in the back of your mind while working on this ticket so that at least things do not get worse in that respect.

OK. So with #15114 in mind, this should be a feature and not a bug:

sage: CC.one() + CIF.one()
...
TypeError: unsupported operand parent(s) for +: 'Complex Field with 53 bits of precision' and 'Complex Interval Field with 53 bits of precision'

@jdemeyer

This comment has been minimized.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 18, 2017

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

3eaf54fClean up MPFI declarations
4984485Move real/complex interval fields to new coercion model

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 18, 2017

Changed commit from d66b54f to 4984485

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Dec 19, 2017

Changed commit from 4984485 to 2448563

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 9, 2018

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

@jdemeyer
Copy link
Author

jdemeyer commented Feb 9, 2018

comment:37

I still need to implement the Python 3 compatibility that I promised.

@jdemeyer

This comment has been minimized.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 9, 2018

Changed commit from c74d8e7 to 1195b3a

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 9, 2018

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

1195b3aMove real/complex interval fields to new coercion model

@tscrim
Copy link
Collaborator

tscrim commented Feb 9, 2018

Reviewer: Travis Scrimshaw

@tscrim
Copy link
Collaborator

tscrim commented Feb 9, 2018

comment:40

Some comments:

  • I know this is slightly outside the purview of this ticket, but perhaps we can rename ComplexIntervalField_class to ComplexIntervalField and have it inherit from UniqueRepresentation in order to get rid of the custom caching. I can also do this if you want.

  • I would do the same for RealIntervalField_class except it is an extension class. Do you think there is a benefit for that? We don't even do that for Rationals.

  • Why not use @cached_method for real_field, middle_field, etc.? They to have UniqueRepresentation-like behavior, so do not strictly need to be cached. However, I am assuming they are cached for speed reasons, so doing @cached_method is the best for repeated use:

    sage: class Foo(object):
    ....:     def __init__(self):
    ....:         self._cache2 = None
    ....:     @cached_method
    ....:     def cm(self):
    ....:         return 5
    ....:     def c1(self):
    ....:         try:
    ....:             return self._cache1
    ....:         except AttributeError:
    ....:             self._cache1 = 5
    ....:             return self._cache1
    ....:     def c2(self):
    ....:         if self._cache2 is None:
    ....:             self._cache2 = 5
    ....:         return self._cache2
    sage: timeit('F = Foo(); F.cm()', number=10000, repeat=20)
    10000 loops, best of 20: 1.53 µs per loop
    sage: timeit('F = Foo(); F.c1()', number=10000, repeat=20)
    10000 loops, best of 20: 1.39 µs per loop
    sage: timeit('F = Foo(); F.c2()', number=10000, repeat=20)
    10000 loops, best of 20: 635 ns per loop
    sage: F = Foo()
    sage: timeit('F.cm()', number=10000, repeat=20)
    10000 loops, best of 20: 68.7 ns per loop
    sage: timeit('F.c1()', number=10000, repeat=20)
    10000 loops, best of 20: 121 ns per loop
    sage: timeit('F.c2()', number=10000, repeat=20)
    10000 loops, best of 20: 1.49 µs per loop
  • Is the _real_field = real_field leftover from testing? I think it should be removed altogether.

  • You should replace

          return complex_interval.ComplexIntervalFieldElement(self, x, im, **kwds)
          return self.element_class(self, x, im, **kwds)

    (in fact, if that is used elsewhere in the file, it should be replaced as well) to pick up the category contributions.

  • Same comment for returning RealIntervalFieldElement.

  • Similarly, I would also make this change:

         R = RealIntervalField(prec=max(bits+pad, min_prec))
         if upper is not None:
             s = (s, upper)
    -    return RealIntervalFieldElement(R, s, base)
    +    return R.element_class(R, s, base)

I think it looks good otherwise.

@jdemeyer
Copy link
Author

jdemeyer commented Feb 9, 2018

comment:41

I consider the proposed changes to unique representation outside the scope of this ticket. This ticket is already reasonably large, let's not add more things. I'll have a look at your other comments.

@tscrim
Copy link
Collaborator

tscrim commented Feb 9, 2018

comment:42

I guess the _real_field = real_field is to avoid #24695 as a dependency?

@tscrim
Copy link
Collaborator

tscrim commented Feb 9, 2018

comment:43

We should also do changes of the form in ComplexIntervalFieldElement:

-return ComplexIntervalFieldElement(self._parent, re, im)
+return type(self)(self._parent, re, im)

and similarly for RealIntervalFieldElement.

@jdemeyer
Copy link
Author

jdemeyer commented Feb 9, 2018

comment:44

Replying to @tscrim:

I guess the _real_field = real_field is to avoid #24695 as a dependency?

I wasn't actually aware of that, thanks for the pointer :-)

@jdemeyer
Copy link
Author

comment:45

I guess I kept _real_field for compatibility with other "complex number" implementations such as

sage: CC._real_field()
Real Field with 53 bits of precision

We should probably have a separate ticket to replace _real_field by real_field: this looks like a useful method, it should not be private.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 12, 2018

Changed commit from 1195b3a to 22d309c

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 12, 2018

Branch pushed to git repo; I updated commit sha1. New commits:

22d309cCleanup for real/complex interval fields

@jdemeyer
Copy link
Author

comment:47

I ended up doing a lot of cleanup. I think I'm using element_class everywhere, but don't shoot me if I'm wrong.

Note that currently the category stuff won't be used anyway because the elements are extension types.

@tscrim
Copy link
Collaborator

tscrim commented Feb 13, 2018

comment:48

Thank you for doing the cleanup.

For changes such as

-        cdef ComplexIntervalFieldElement res = self._new()
+        res = self._new()

aren't we loosing some efficiency? I would think because they are still subclasses of ComplexIntervalFieldElement, that Cython would be able to optimize their attribute lookups by not treating them as Python objects? (Of course, we would have to explicitly cast <ComplexIntervalFieldElement> to avoid the type-checking-safety-penalty.)

This goes through the __call__ (which in this case, bypasses the coercion framework, but normally it wouldn't):

-        return complex_interval.ComplexIntervalFieldElement(self, 0, 1)
+        return self(0, 1)

I think we are better making a direct call to self.element_class(self, 0, 1) since this is not user input.

@jdemeyer
Copy link
Author

comment:49

Replying to @tscrim:

Thank you for doing the cleanup.

For changes such as

-        cdef ComplexIntervalFieldElement res = self._new()
+        res = self._new()

aren't we loosing some efficiency?

No, Cython has type inference. Since _new is declared as returning a ComplexIntervalFieldElement, the declaration cdef ComplexIntervalFieldElement res is just redundant.

This goes through the __call__ (which in this case, bypasses the coercion framework, but normally it wouldn't):

-        return complex_interval.ComplexIntervalFieldElement(self, 0, 1)
+        return self(0, 1)

I think we are better making a direct call to self.element_class(self, 0, 1) since this is not user input.

I don't see the problem with using __call__ here but I can make that change.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 13, 2018

Changed commit from 22d309c to 9ac1612

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Feb 13, 2018

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

9ac1612Cleanup for real/complex interval fields

@jdemeyer
Copy link
Author

comment:51

Replying to @tscrim:

Cython would be able to optimize their attribute lookups by not treating them as Python objects?

Actually, the relevant attributes are cdef attributes, so they cannot even be accessed from Python! So the fact that the code works proves that Cython must be doing type inference.

I changed some self(...) calls to self.element_class(self, ...)

@tscrim
Copy link
Collaborator

tscrim commented Feb 13, 2018

comment:52

Replying to @jdemeyer:

Replying to @tscrim:

Cython would be able to optimize their attribute lookups by not treating them as Python objects?

Actually, the relevant attributes are cdef attributes, so they cannot even be accessed from Python! So the fact that the code works proves that Cython must be doing type inference.

That is what is happening, e.g.:

  __pyx_t_1 = ((PyObject *)__pyx_f_4sage_5rings_16complex_interval_27ComplexIntervalFieldE
lement__new(__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 325, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_a00 = ((struct __pyx_obj_4sage_5rings_16complex_interval_ComplexIntervalFieldEle
ment *)__pyx_t_1);
  __pyx_t_1 = 0;

I didn't realize that Cython was that smart. :)

I changed some self(...) calls to self.element_class(self, ...)

Thank you. LGTM. (If I wanted to be really picky, I would say self.element_class(self, 1) should instead use the cached self.one(), but zeta(1) is almost certainly never called.)

@jdemeyer
Copy link
Author

comment:53

Thanks!

@vbraun
Copy link
Member

vbraun commented Feb 15, 2018

@vbraun vbraun closed this as completed in 8a64691 Feb 15, 2018
mkoeppe added a commit to mkoeppe/sage that referenced this issue Sep 21, 2023
vbraun pushed a commit to vbraun/sage that referenced this issue Sep 23, 2023
, sagemath#24483, sagemath#24371, sagemath#24511, sagemath#25848, sagemath#26105, sagemath#28481, sagemath#29010, sagemath#29412, sagemath#30332, sagemath#30372, sagemath#31345, sagemath#32375, sagemath#32606, sagemath#32610, sagemath#32612, sagemath#32641, sagemath#32660, sagemath#32750, sagemath#32869, sagemath#33602

    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#36307
Reported by: Matthias Köppe
Reviewer(s):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants