Path: blob/develop/src/sage_setup/autogen/interpreters/internal/storage.py
4086 views
#*****************************************************************************1# Copyright (C) 2009 Carl Witty <[email protected]>2# Copyright (C) 2015 Jeroen Demeyer <[email protected]>3#4# This program is free software: you can redistribute it and/or modify5# it under the terms of the GNU General Public License as published by6# the Free Software Foundation, either version 2 of the License, or7# (at your option) any later version.8# http://www.gnu.org/licenses/9#*****************************************************************************1011"""Implements different data storage types."""1213from __future__ import print_function, absolute_import1415from .utils import je, reindent_lines as ri161718class StorageType(object):19r"""20A StorageType specifies the C types used to deal with values of a21given type.2223We currently support three categories of types.2425First are the "simple" types. These are types where: the26representation is small, functions expect arguments to be passed27by value, and the C/C++ assignment operator works. This would28include built-in C types (long, float, etc.) and small structs29(like gsl_complex).3031Second is 'PyObject*'. This is just like a simple type, except32that we have to incref/decref at appropriate places.3334Third is "auto-reference" types. This is how35GMP/MPIR/MPFR/MPFI/FLINT types work. For these types, functions36expect arguments to be passed by reference, and the C assignment37operator does not do what we want. In addition, they take38advantage of a quirk in C (where arrays are automatically39converted to pointers) to automatically pass arguments by40reference.4142Support for further categories would not be difficult to add (such43as reference-counted types other than PyObject*, or44pass-by-reference types that don't use the GMP auto-reference45trick), if we ever run across a use for them.46"""4748def __init__(self):49r"""50Initialize an instance of StorageType.5152This sets several properties:5354class_member_declarations:55A string giving variable declarations that must be members of any56wrapper class using this type.5758class_member_initializations:59A string initializing the class_member_declarations; will be60inserted into the __init__ method of any wrapper class using this61type.6263local_declarations:64A string giving variable declarations that must be local variables65in Cython methods using this storage type.6667EXAMPLES::6869sage: from sage_setup.autogen.interpreters.internal import *70sage: ty_double.class_member_declarations71''72sage: ty_double.class_member_initializations73''74sage: ty_double.local_declarations75''76sage: ty_mpfr.class_member_declarations77'cdef RealField_class domain\n'78sage: ty_mpfr.class_member_initializations79"self.domain = args['domain']\n"80sage: ty_mpfr.local_declarations81'cdef RealNumber rn\n'82"""83self.class_member_declarations = ''84self.class_member_initializations = ''85self.local_declarations = ''8687def cheap_copies(self):88r"""89Returns True or False, depending on whether this StorageType90supports cheap copies -- whether it is cheap to copy values of91this type from one location to another. This is true for92primitive types, and for types like PyObject* (where you are only93copying a pointer, and possibly changing some reference counts).94It is false for types like mpz_t and mpfr_t, where copying values95can involve arbitrarily much work (including memory allocation).9697The practical effect is that if cheap_copies is True,98instructions with outputs of this type write the results into99local variables, and the results are then copied to their100final locations. If cheap_copies is False, then the addresses101of output locations are passed into the instruction and the102instruction writes outputs directly in the final location.103104EXAMPLES::105106sage: from sage_setup.autogen.interpreters.internal import *107sage: ty_double.cheap_copies()108True109sage: ty_python.cheap_copies()110True111sage: ty_mpfr.cheap_copies()112False113"""114return False115116def python_refcounted(self):117r"""118Says whether this storage type is a Python type, so we need to119use INCREF/DECREF.120121(If we needed to support any non-Python refcounted types, it122might be better to make this object-oriented and have methods123like "generate an incref" and "generate a decref". But as124long as we only support Python, this way is probably simpler.)125126EXAMPLES::127128sage: from sage_setup.autogen.interpreters.internal import *129sage: ty_double.python_refcounted()130False131sage: ty_python.python_refcounted()132True133"""134return False135136def cython_decl_type(self):137r"""138Give the Cython type for a single value of this type (as a string).139140EXAMPLES::141142sage: from sage_setup.autogen.interpreters.internal import *143sage: ty_double.cython_decl_type()144'double'145sage: ty_python.cython_decl_type()146'object'147sage: ty_mpfr.cython_decl_type()148'mpfr_t'149"""150return self.c_decl_type()151152def cython_array_type(self):153r"""154Give the Cython type for referring to an array of values of155this type (as a string).156157EXAMPLES::158159sage: from sage_setup.autogen.interpreters.internal import *160sage: ty_double.cython_array_type()161'double*'162sage: ty_python.cython_array_type()163'PyObject**'164sage: ty_mpfr.cython_array_type()165'mpfr_t*'166"""167return self.c_ptr_type()168169def needs_cython_init_clear(self):170r"""171Says whether values/arrays of this type need to be initialized172before use and cleared before the underlying memory is freed.173174(We could remove this method, always call .cython_init() to175generate initialization code, and just let .cython_init()176generate empty code if no initialization is required; that would177generate empty loops, which are ugly and potentially might not178be optimized away.)179180EXAMPLES::181182sage: from sage_setup.autogen.interpreters.internal import *183sage: ty_double.needs_cython_init_clear()184False185sage: ty_mpfr.needs_cython_init_clear()186True187sage: ty_python.needs_cython_init_clear()188True189"""190return False191192def c_decl_type(self):193r"""194Give the C type for a single value of this type (as a string).195196EXAMPLES::197198sage: from sage_setup.autogen.interpreters.internal import *199sage: ty_double.c_decl_type()200'double'201sage: ty_python.c_decl_type()202'PyObject*'203sage: ty_mpfr.c_decl_type()204'mpfr_t'205"""206raise NotImplementedError207208def c_ptr_type(self):209r"""210Give the C type for a pointer to this type (as a reference to211either a single value or an array) (as a string).212213EXAMPLES::214215sage: from sage_setup.autogen.interpreters.internal import *216sage: ty_double.c_ptr_type()217'double*'218sage: ty_python.c_ptr_type()219'PyObject**'220sage: ty_mpfr.c_ptr_type()221'mpfr_t*'222"""223return self.c_decl_type() + '*'224225def c_reference_type(self):226r"""227Give the C type which should be used for passing a reference228to a single value in a call. This is used as the type for the229return value.230231EXAMPLES::232233sage: from sage_setup.autogen.interpreters.internal import *234sage: ty_double.c_reference_type()235'double*'236sage: ty_python.c_reference_type()237'PyObject**'238"""239return self.c_ptr_type()240241def c_local_type(self):242r"""243Give the C type used for a value of this type inside an244instruction. For assignable/cheap_copy types, this is the245same as c_decl_type; for auto-reference types, this is the246pointer type.247248EXAMPLES::249250sage: from sage_setup.autogen.interpreters.internal import *251sage: ty_double.c_local_type()252'double'253sage: ty_python.c_local_type()254'PyObject*'255sage: ty_mpfr.c_local_type()256'mpfr_ptr'257"""258raise NotImplementedError259260def assign_c_from_py(self, c, py):261r"""262Given a Cython variable/array reference/etc. of this storage type,263and a Python expression, generate code to assign to the Cython264variable from the Python expression.265266EXAMPLES::267268sage: from sage_setup.autogen.interpreters.internal import *269sage: ty_double.assign_c_from_py('foo', 'bar')270'foo = bar'271sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')272'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'273sage: ty_mpfr.assign_c_from_py('foo', 'bar')274'rn = self.domain(bar)\nmpfr_set(foo, rn.value, MPFR_RNDN)'275"""276return je("{{ c }} = {{ py }}", c=c, py=py)277278def declare_chunk_class_members(self, name):279r"""280Return a string giving the declarations of the class members281in a wrapper class for a memory chunk with this storage type282and the given name.283284EXAMPLES::285286sage: from sage_setup.autogen.interpreters.internal import *287sage: ty_mpfr.declare_chunk_class_members('args')288' cdef int _n_args\n cdef mpfr_t* _args\n'289"""290return je(ri(0,291"""292{# XXX Variables here (and everywhere, really) should actually be Py_ssize_t #}293cdef int _n_{{ name }}294cdef {{ myself.cython_array_type() }} _{{ name }}295"""), myself=self, name=name)296297def alloc_chunk_data(self, name, len):298r"""299Return a string allocating the memory for the class members for300a memory chunk with this storage type and the given name.301302EXAMPLES::303304sage: from sage_setup.autogen.interpreters.internal import *305sage: print(ty_mpfr.alloc_chunk_data('args', 'MY_LENGTH'))306self._n_args = MY_LENGTH307self._args = <mpfr_t*>check_allocarray(self._n_args, sizeof(mpfr_t))308for i in range(MY_LENGTH):309mpfr_init2(self._args[i], self.domain.prec())310<BLANKLINE>311"""312return je(ri(0,313"""314self._n_{{ name }} = {{ len }}315self._{{ name }} = <{{ myself.c_ptr_type() }}>check_allocarray(self._n_{{ name }}, sizeof({{ myself.c_decl_type() }}))316{% if myself.needs_cython_init_clear() %}317for i in range({{ len }}):318{{ myself.cython_init('self._%s[i]' % name) }}319{% endif %}320"""), myself=self, name=name, len=len)321322def dealloc_chunk_data(self, name):323r"""324Return a string to be put in the __dealloc__ method of a325wrapper class using a memory chunk with this storage type, to326deallocate the corresponding class members.327328EXAMPLES::329330sage: from sage_setup.autogen.interpreters.internal import *331sage: print(ty_double.dealloc_chunk_data('args'))332if self._args:333sig_free(self._args)334<BLANKLINE>335sage: print(ty_mpfr.dealloc_chunk_data('constants'))336if self._constants:337for i in range(self._n_constants):338mpfr_clear(self._constants[i])339sig_free(self._constants)340<BLANKLINE>341"""342return je(ri(0, """343if self._{{ name }}:344{% if myself.needs_cython_init_clear() %}345for i in range(self._n_{{ name }}):346{{ myself.cython_clear('self._%s[i]' % name) }}347{% endif %}348sig_free(self._{{ name }})349"""), myself=self, name=name)350351352class StorageTypeAssignable(StorageType):353r"""354StorageTypeAssignable is a subtype of StorageType that deals with355types with cheap copies, like primitive types and PyObject*.356"""357358def __init__(self, ty):359r"""360Initializes the property type (the C/Cython name for this type),361as well as the properties described in the documentation for362StorageType.__init__.363364EXAMPLES::365366sage: from sage_setup.autogen.interpreters.internal import *367sage: ty_double.class_member_declarations368''369sage: ty_double.class_member_initializations370''371sage: ty_double.local_declarations372''373sage: ty_double.type374'double'375sage: ty_python.type376'PyObject*'377"""378StorageType.__init__(self)379self.type = ty380381def cheap_copies(self):382r"""383Returns True or False, depending on whether this StorageType384supports cheap copies -- whether it is cheap to copy values of385this type from one location to another. (See StorageType.cheap_copies386for more on this property.)387388Since having cheap copies is essentially the definition of389StorageTypeAssignable, this always returns True.390391EXAMPLES::392393sage: from sage_setup.autogen.interpreters.internal import *394sage: ty_double.cheap_copies()395True396sage: ty_python.cheap_copies()397True398"""399return True400401def c_decl_type(self):402r"""403Give the C type for a single value of this type (as a string).404405EXAMPLES::406407sage: from sage_setup.autogen.interpreters.internal import *408sage: ty_double.c_decl_type()409'double'410sage: ty_python.c_decl_type()411'PyObject*'412"""413return self.type414415def c_local_type(self):416r"""417Give the C type used for a value of this type inside an418instruction. For assignable/cheap_copy types, this is the419same as c_decl_type; for auto-reference types, this is the420pointer type.421422EXAMPLES::423424sage: from sage_setup.autogen.interpreters.internal import *425sage: ty_double.c_local_type()426'double'427sage: ty_python.c_local_type()428'PyObject*'429"""430return self.type431432433class StorageTypeSimple(StorageTypeAssignable):434r"""435StorageTypeSimple is a subtype of StorageTypeAssignable that deals436with non-reference-counted types with cheap copies, like primitive437types. As of yet, it has no functionality differences from438StorageTypeAssignable.439"""440pass441442443ty_int = StorageTypeSimple('int')444ty_double = StorageTypeSimple('double')445446447class StorageTypeDoubleComplex(StorageTypeSimple):448r"""449This is specific to the complex double type. It behaves exactly450like a StorageTypeSimple in C, but needs a little help to do451conversions in Cython.452453This uses functions defined in CDFInterpreter, and is for use in454that context.455"""456def assign_c_from_py(self, c, py):457"""458sage: from sage_setup.autogen.interpreters.internal import ty_double_complex459sage: ty_double_complex.assign_c_from_py('z_c', 'z_py')460'z_c = CDE_to_dz(z_py)'461"""462return je("{{ c }} = CDE_to_dz({{ py }})", c=c, py=py)463464465ty_double_complex = StorageTypeDoubleComplex('double_complex')466467468class StorageTypePython(StorageTypeAssignable):469r"""470StorageTypePython is a subtype of StorageTypeAssignable that deals471with Python objects.472473Just allocating an array full of PyObject* leads to problems,474because the Python garbage collector must be able to get to every475Python object, and it wouldn't know how to get to these arrays.476So we allocate the array as a Python list, but then we immediately477pull the ob_item out of it and deal only with that from then on.478479We often leave these lists with NULL entries. This is safe for480the garbage collector and the deallocator, which is all we care481about; but it would be unsafe to provide Python-level access to482these lists.483484There is one special thing about StorageTypePython: memory that is485used by the interpreter as scratch space (for example, the stack)486must be cleared after each call (so we don't hold on to487potentially-large objects and waste memory). Since we have to do488this anyway, the interpreter gains a tiny bit of speed by assuming489that the scratch space is cleared on entry; for example, when490pushing a value onto the stack, it doesn't bother to XDECREF the491previous value because it's always NULL.492"""493494def __init__(self):495r"""496Initializes the properties described in the documentation497for StorageTypeAssignable.__init__. The type is always498'PyObject*'.499500EXAMPLES::501502sage: from sage_setup.autogen.interpreters.internal import *503sage: ty_python.class_member_declarations504''505sage: ty_python.class_member_initializations506''507sage: ty_python.local_declarations508''509sage: ty_python.type510'PyObject*'511"""512super(StorageTypePython, self).__init__('PyObject*')513514def python_refcounted(self):515r"""516Says whether this storage type is a Python type, so we need to517use INCREF/DECREF.518519Returns True.520521EXAMPLES::522523sage: from sage_setup.autogen.interpreters.internal import *524sage: ty_python.python_refcounted()525True526"""527return True528529def cython_decl_type(self):530r"""531Give the Cython type for a single value of this type (as a string).532533EXAMPLES::534535sage: from sage_setup.autogen.interpreters.internal import *536sage: ty_python.cython_decl_type()537'object'538"""539return 'object'540541def declare_chunk_class_members(self, name):542r"""543Return a string giving the declarations of the class members544in a wrapper class for a memory chunk with this storage type545and the given name.546547EXAMPLES::548549sage: from sage_setup.autogen.interpreters.internal import *550sage: ty_python.declare_chunk_class_members('args')551' cdef object _list_args\n cdef int _n_args\n cdef PyObject** _args\n'552"""553return je(ri(4,554"""555cdef object _list_{{ name }}556cdef int _n_{{ name }}557cdef {{ myself.cython_array_type() }} _{{ name }}558"""), myself=self, name=name)559560def alloc_chunk_data(self, name, len):561r"""562Return a string allocating the memory for the class members for563a memory chunk with this storage type and the given name.564565EXAMPLES::566567sage: from sage_setup.autogen.interpreters.internal import *568sage: print(ty_python.alloc_chunk_data('args', 'MY_LENGTH'))569self._n_args = MY_LENGTH570self._list_args = PyList_New(self._n_args)571self._args = (<PyListObject *>self._list_args).ob_item572<BLANKLINE>573"""574return je(ri(8,575"""576self._n_{{ name }} = {{ len }}577self._list_{{ name }} = PyList_New(self._n_{{ name }})578self._{{ name }} = (<PyListObject *>self._list_{{ name }}).ob_item579"""), myself=self, name=name, len=len)580581def dealloc_chunk_data(self, name):582r"""583Return a string to be put in the __dealloc__ method of a584wrapper class using a memory chunk with this storage type, to585deallocate the corresponding class members.586587Our array was allocated as a Python list; this means we actually588don't need to do anything to deallocate it.589590EXAMPLES::591592sage: from sage_setup.autogen.interpreters.internal import *593sage: ty_python.dealloc_chunk_data('args')594''595"""596return ''597598def needs_cython_init_clear(self):599r"""600Says whether values/arrays of this type need to be initialized601before use and cleared before the underlying memory is freed.602603Returns True.604605EXAMPLES::606607sage: from sage_setup.autogen.interpreters.internal import *608sage: ty_python.needs_cython_init_clear()609True610"""611return True612613def assign_c_from_py(self, c, py):614r"""615Given a Cython variable/array reference/etc. of this storage type,616and a Python expression, generate code to assign to the Cython617variable from the Python expression.618619EXAMPLES::620621sage: from sage_setup.autogen.interpreters.internal import *622sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')623'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'624"""625return je("""{{ c }} = <PyObject *>{{ py }}; Py_INCREF({{ c }})""",626c=c, py=py)627628def cython_init(self, loc):629r"""630Generates code to initialize a variable (or array reference)631holding a PyObject*. Sets it to NULL.632633EXAMPLES::634635sage: from sage_setup.autogen.interpreters.internal import *636sage: ty_python.cython_init('foo[i]')637'foo[i] = NULL'638"""639return je("{{ loc }} = NULL", loc=loc)640641def cython_clear(self, loc):642r"""643Generates code to clear a variable (or array reference) holding644a PyObject*.645646EXAMPLES::647648sage: from sage_setup.autogen.interpreters.internal import *649sage: ty_python.cython_clear('foo[i]')650'Py_CLEAR(foo[i])'651"""652return je("Py_CLEAR({{ loc }})", loc=loc)653654655ty_python = StorageTypePython()656657658class StorageTypeAutoReference(StorageType):659r"""660StorageTypeAutoReference is a subtype of StorageType that deals with661types in the style of GMP/MPIR/MPFR/MPFI/FLINT, where copies are662not cheap, functions expect arguments to be passed by reference,663and the API takes advantage of the C quirk where arrays are664automatically converted to pointers to automatically pass665arguments by reference.666"""667def __init__(self, decl_ty, ref_ty):668r"""669Initializes the properties decl_type and ref_type (the C type670names used when declaring variables and function parameters,671respectively), as well as the properties described in672the documentation for StorageType.__init__.673674EXAMPLES::675676sage: from sage_setup.autogen.interpreters.internal import *677sage: ty_mpfr.class_member_declarations678'cdef RealField_class domain\n'679sage: ty_mpfr.class_member_initializations680"self.domain = args['domain']\n"681sage: ty_mpfr.local_declarations682'cdef RealNumber rn\n'683sage: ty_mpfr.decl_type684'mpfr_t'685sage: ty_mpfr.ref_type686'mpfr_ptr'687"""688super(StorageTypeAutoReference, self).__init__()689self.decl_type = decl_ty690self.ref_type = ref_ty691692def c_decl_type(self):693r"""694Give the C type for a single value of this type (as a string).695696EXAMPLES::697698sage: from sage_setup.autogen.interpreters.internal import *699sage: ty_mpfr.c_decl_type()700'mpfr_t'701"""702return self.decl_type703704def c_local_type(self):705r"""706Give the C type used for a value of this type inside an707instruction. For assignable/cheap_copy types, this is the708same as c_decl_type; for auto-reference types, this is the709pointer type.710711EXAMPLES::712713sage: from sage_setup.autogen.interpreters.internal import *714sage: ty_mpfr.c_local_type()715'mpfr_ptr'716"""717return self.ref_type718719def c_reference_type(self):720r"""721Give the C type which should be used for passing a reference722to a single value in a call. This is used as the type for the723return value.724725EXAMPLES::726727sage: from sage_setup.autogen.interpreters.internal import *728sage: ty_mpfr.c_reference_type()729'mpfr_t'730"""731return self.decl_type732733def needs_cython_init_clear(self):734r"""735Says whether values/arrays of this type need to be initialized736before use and cleared before the underlying memory is freed.737738All known examples of auto-reference types do need a special739initialization call, so this always returns True.740741EXAMPLES::742743sage: from sage_setup.autogen.interpreters.internal import *744sage: ty_mpfr.needs_cython_init_clear()745True746"""747return True748749750class StorageTypeMPFR(StorageTypeAutoReference):751r"""752StorageTypeMPFR is a subtype of StorageTypeAutoReference that deals753the MPFR's mpfr_t type.754755For any given program that we're interpreting, ty_mpfr can only756refer to a single precision. An interpreter that needs to use757two precisions of mpfr_t in the same program should instantiate two758separate instances of StorageTypeMPFR. (Interpreters that need759to handle arbitrarily many precisions in the same program are not760handled at all.)761"""762763def __init__(self, id=''):764r"""765Initializes the id property, as well as the properties described766in the documentation for StorageTypeAutoReference.__init__.767768The id property is used if you want to have an interpreter769that handles two instances of StorageTypeMPFR (that is,770handles mpfr_t variables at two different precisions771simultaneously). It's a string that's used to generate772variable names that don't conflict. (The id system has773never actually been used, so bugs probably remain.)774775EXAMPLES::776777sage: from sage_setup.autogen.interpreters.internal import *778sage: ty_mpfr.class_member_declarations779'cdef RealField_class domain\n'780sage: ty_mpfr.class_member_initializations781"self.domain = args['domain']\n"782sage: ty_mpfr.local_declarations783'cdef RealNumber rn\n'784sage: ty_mpfr.decl_type785'mpfr_t'786sage: ty_mpfr.ref_type787'mpfr_ptr'788789TESTS::790791sage: ty_mpfr2 = StorageTypeMPFR(id='_the_second')792sage: ty_mpfr2.class_member_declarations793'cdef RealField_class domain_the_second\n'794sage: ty_mpfr2.class_member_initializations795"self.domain_the_second = args['domain_the_second']\n"796sage: ty_mpfr2.local_declarations797'cdef RealNumber rn_the_second\n'798"""799800super(StorageTypeMPFR, self).__init__('mpfr_t', 'mpfr_ptr')801self.id = id802self.class_member_declarations = "cdef RealField_class domain%s\n" % self.id803self.class_member_initializations = \804"self.domain%s = args['domain%s']\n" % (self.id, self.id)805self.local_declarations = "cdef RealNumber rn%s\n" % self.id806807def cython_init(self, loc):808r"""809Generates code to initialize an mpfr_t reference (a variable, an810array reference, etc.)811812EXAMPLES::813814sage: from sage_setup.autogen.interpreters.internal import *815sage: ty_mpfr.cython_init('foo[i]')816'mpfr_init2(foo[i], self.domain.prec())'817"""818return je("mpfr_init2({{ loc }}, self.domain{{ myself.id }}.prec())",819myself=self, loc=loc)820821def cython_clear(self, loc):822r"""823Generates code to clear an mpfr_t reference (a variable, an824array reference, etc.)825826EXAMPLES::827828sage: from sage_setup.autogen.interpreters.internal import *829sage: ty_mpfr.cython_clear('foo[i]')830'mpfr_clear(foo[i])'831"""832return 'mpfr_clear(%s)' % loc833834def assign_c_from_py(self, c, py):835r"""836Given a Cython variable/array reference/etc. of this storage type,837and a Python expression, generate code to assign to the Cython838variable from the Python expression.839840EXAMPLES::841842sage: from sage_setup.autogen.interpreters.internal import *843sage: ty_mpfr.assign_c_from_py('foo[i]', 'bar[j]')844'rn = self.domain(bar[j])\nmpfr_set(foo[i], rn.value, MPFR_RNDN)'845"""846return je(ri(0, """847rn{{ myself.id }} = self.domain({{ py }})848mpfr_set({{ c }}, rn.value, MPFR_RNDN)"""),849myself=self, c=c, py=py)850851852ty_mpfr = StorageTypeMPFR()853854855class StorageTypeMPC(StorageTypeAutoReference):856r"""857StorageTypeMPC is a subtype of StorageTypeAutoReference that deals858the MPC's mpc_t type.859860For any given program that we're interpreting, ty_mpc can only861refer to a single precision. An interpreter that needs to use862two precisions of mpc_t in the same program should instantiate two863separate instances of StorageTypeMPC. (Interpreters that need864to handle arbitrarily many precisions in the same program are not865handled at all.)866"""867868def __init__(self, id=''):869r"""870Initializes the id property, as well as the properties described871in the documentation for StorageTypeAutoReference.__init__.872873The id property is used if you want to have an interpreter874that handles two instances of StorageTypeMPC (that is,875handles mpC_t variables at two different precisions876simultaneously). It's a string that's used to generate877variable names that don't conflict. (The id system has878never actually been used, so bugs probably remain.)879880EXAMPLES::881882sage: from sage_setup.autogen.interpreters.internal import *883sage: ty_mpc.class_member_declarations884'cdef object domain\ncdef ComplexNumber domain_element\n'885sage: ty_mpc.class_member_initializations886"self.domain = args['domain']\nself.domain_element = self.domain.zero()\n"887sage: ty_mpc.local_declarations888'cdef ComplexNumber cn\n'889sage: ty_mpc.decl_type890'mpc_t'891sage: ty_mpc.ref_type892'mpc_ptr'893894TESTS::895896sage: ty_mpfr2 = StorageTypeMPC(id='_the_second')897sage: ty_mpfr2.class_member_declarations898'cdef object domain_the_second\ncdef ComplexNumber domain_element_the_second\n'899sage: ty_mpfr2.class_member_initializations900"self.domain_the_second = args['domain_the_second']\nself.domain_element_the_second = self.domain.zero()\n"901sage: ty_mpfr2.local_declarations902'cdef ComplexNumber cn_the_second\n'903904"""905StorageTypeAutoReference.__init__(self, 'mpc_t', 'mpc_ptr')906self.id = id907self.class_member_declarations = "cdef object domain%s\ncdef ComplexNumber domain_element%s\n" % (self.id, self.id)908self.class_member_initializations = \909"self.domain%s = args['domain%s']\nself.domain_element%s = self.domain.zero()\n" % (self.id, self.id, self.id)910self.local_declarations = "cdef ComplexNumber cn%s\n" % self.id911912def cython_init(self, loc):913r"""914Generates code to initialize an mpc_t reference (a variable, an915array reference, etc.)916917EXAMPLES::918919sage: from sage_setup.autogen.interpreters.internal import *920sage: ty_mpc.cython_init('foo[i]')921'mpc_init2(foo[i], self.domain_element._prec)'922"""923return je("mpc_init2({{ loc }}, self.domain_element{{ myself.id }}._prec)",924myself=self, loc=loc)925926def cython_clear(self, loc):927r"""928Generates code to clear an mpfr_t reference (a variable, an929array reference, etc.)930931EXAMPLES::932933sage: from sage_setup.autogen.interpreters.internal import *934sage: ty_mpc.cython_clear('foo[i]')935'mpc_clear(foo[i])'936"""937return 'mpc_clear(%s)' % loc938939def assign_c_from_py(self, c, py):940r"""941Given a Cython variable/array reference/etc. of this storage type,942and a Python expression, generate code to assign to the Cython943variable from the Python expression.944945EXAMPLES::946947sage: from sage_setup.autogen.interpreters.internal import *948sage: ty_mpc.assign_c_from_py('foo[i]', 'bar[j]')949'cn = self.domain(bar[j])\nmpc_set_fr_fr(foo[i], cn.__re, cn.__im, MPC_RNDNN)'950"""951return je("""952cn{{ myself.id }} = self.domain({{ py }})953mpc_set_fr_fr({{ c }}, cn.__re, cn.__im, MPC_RNDNN)""", myself=self, c=c, py=py)954955956ty_mpc = StorageTypeMPC()957958959