Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/src/sage_setup/autogen/interpreters/internal/storage.py
4086 views
1
#*****************************************************************************
2
# Copyright (C) 2009 Carl Witty <[email protected]>
3
# Copyright (C) 2015 Jeroen Demeyer <[email protected]>
4
#
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, either version 2 of the License, or
8
# (at your option) any later version.
9
# http://www.gnu.org/licenses/
10
#*****************************************************************************
11
12
"""Implements different data storage types."""
13
14
from __future__ import print_function, absolute_import
15
16
from .utils import je, reindent_lines as ri
17
18
19
class StorageType(object):
20
r"""
21
A StorageType specifies the C types used to deal with values of a
22
given type.
23
24
We currently support three categories of types.
25
26
First are the "simple" types. These are types where: the
27
representation is small, functions expect arguments to be passed
28
by value, and the C/C++ assignment operator works. This would
29
include built-in C types (long, float, etc.) and small structs
30
(like gsl_complex).
31
32
Second is 'PyObject*'. This is just like a simple type, except
33
that we have to incref/decref at appropriate places.
34
35
Third is "auto-reference" types. This is how
36
GMP/MPIR/MPFR/MPFI/FLINT types work. For these types, functions
37
expect arguments to be passed by reference, and the C assignment
38
operator does not do what we want. In addition, they take
39
advantage of a quirk in C (where arrays are automatically
40
converted to pointers) to automatically pass arguments by
41
reference.
42
43
Support for further categories would not be difficult to add (such
44
as reference-counted types other than PyObject*, or
45
pass-by-reference types that don't use the GMP auto-reference
46
trick), if we ever run across a use for them.
47
"""
48
49
def __init__(self):
50
r"""
51
Initialize an instance of StorageType.
52
53
This sets several properties:
54
55
class_member_declarations:
56
A string giving variable declarations that must be members of any
57
wrapper class using this type.
58
59
class_member_initializations:
60
A string initializing the class_member_declarations; will be
61
inserted into the __init__ method of any wrapper class using this
62
type.
63
64
local_declarations:
65
A string giving variable declarations that must be local variables
66
in Cython methods using this storage type.
67
68
EXAMPLES::
69
70
sage: from sage_setup.autogen.interpreters.internal import *
71
sage: ty_double.class_member_declarations
72
''
73
sage: ty_double.class_member_initializations
74
''
75
sage: ty_double.local_declarations
76
''
77
sage: ty_mpfr.class_member_declarations
78
'cdef RealField_class domain\n'
79
sage: ty_mpfr.class_member_initializations
80
"self.domain = args['domain']\n"
81
sage: ty_mpfr.local_declarations
82
'cdef RealNumber rn\n'
83
"""
84
self.class_member_declarations = ''
85
self.class_member_initializations = ''
86
self.local_declarations = ''
87
88
def cheap_copies(self):
89
r"""
90
Returns True or False, depending on whether this StorageType
91
supports cheap copies -- whether it is cheap to copy values of
92
this type from one location to another. This is true for
93
primitive types, and for types like PyObject* (where you are only
94
copying a pointer, and possibly changing some reference counts).
95
It is false for types like mpz_t and mpfr_t, where copying values
96
can involve arbitrarily much work (including memory allocation).
97
98
The practical effect is that if cheap_copies is True,
99
instructions with outputs of this type write the results into
100
local variables, and the results are then copied to their
101
final locations. If cheap_copies is False, then the addresses
102
of output locations are passed into the instruction and the
103
instruction writes outputs directly in the final location.
104
105
EXAMPLES::
106
107
sage: from sage_setup.autogen.interpreters.internal import *
108
sage: ty_double.cheap_copies()
109
True
110
sage: ty_python.cheap_copies()
111
True
112
sage: ty_mpfr.cheap_copies()
113
False
114
"""
115
return False
116
117
def python_refcounted(self):
118
r"""
119
Says whether this storage type is a Python type, so we need to
120
use INCREF/DECREF.
121
122
(If we needed to support any non-Python refcounted types, it
123
might be better to make this object-oriented and have methods
124
like "generate an incref" and "generate a decref". But as
125
long as we only support Python, this way is probably simpler.)
126
127
EXAMPLES::
128
129
sage: from sage_setup.autogen.interpreters.internal import *
130
sage: ty_double.python_refcounted()
131
False
132
sage: ty_python.python_refcounted()
133
True
134
"""
135
return False
136
137
def cython_decl_type(self):
138
r"""
139
Give the Cython type for a single value of this type (as a string).
140
141
EXAMPLES::
142
143
sage: from sage_setup.autogen.interpreters.internal import *
144
sage: ty_double.cython_decl_type()
145
'double'
146
sage: ty_python.cython_decl_type()
147
'object'
148
sage: ty_mpfr.cython_decl_type()
149
'mpfr_t'
150
"""
151
return self.c_decl_type()
152
153
def cython_array_type(self):
154
r"""
155
Give the Cython type for referring to an array of values of
156
this type (as a string).
157
158
EXAMPLES::
159
160
sage: from sage_setup.autogen.interpreters.internal import *
161
sage: ty_double.cython_array_type()
162
'double*'
163
sage: ty_python.cython_array_type()
164
'PyObject**'
165
sage: ty_mpfr.cython_array_type()
166
'mpfr_t*'
167
"""
168
return self.c_ptr_type()
169
170
def needs_cython_init_clear(self):
171
r"""
172
Says whether values/arrays of this type need to be initialized
173
before use and cleared before the underlying memory is freed.
174
175
(We could remove this method, always call .cython_init() to
176
generate initialization code, and just let .cython_init()
177
generate empty code if no initialization is required; that would
178
generate empty loops, which are ugly and potentially might not
179
be optimized away.)
180
181
EXAMPLES::
182
183
sage: from sage_setup.autogen.interpreters.internal import *
184
sage: ty_double.needs_cython_init_clear()
185
False
186
sage: ty_mpfr.needs_cython_init_clear()
187
True
188
sage: ty_python.needs_cython_init_clear()
189
True
190
"""
191
return False
192
193
def c_decl_type(self):
194
r"""
195
Give the C type for a single value of this type (as a string).
196
197
EXAMPLES::
198
199
sage: from sage_setup.autogen.interpreters.internal import *
200
sage: ty_double.c_decl_type()
201
'double'
202
sage: ty_python.c_decl_type()
203
'PyObject*'
204
sage: ty_mpfr.c_decl_type()
205
'mpfr_t'
206
"""
207
raise NotImplementedError
208
209
def c_ptr_type(self):
210
r"""
211
Give the C type for a pointer to this type (as a reference to
212
either a single value or an array) (as a string).
213
214
EXAMPLES::
215
216
sage: from sage_setup.autogen.interpreters.internal import *
217
sage: ty_double.c_ptr_type()
218
'double*'
219
sage: ty_python.c_ptr_type()
220
'PyObject**'
221
sage: ty_mpfr.c_ptr_type()
222
'mpfr_t*'
223
"""
224
return self.c_decl_type() + '*'
225
226
def c_reference_type(self):
227
r"""
228
Give the C type which should be used for passing a reference
229
to a single value in a call. This is used as the type for the
230
return value.
231
232
EXAMPLES::
233
234
sage: from sage_setup.autogen.interpreters.internal import *
235
sage: ty_double.c_reference_type()
236
'double*'
237
sage: ty_python.c_reference_type()
238
'PyObject**'
239
"""
240
return self.c_ptr_type()
241
242
def c_local_type(self):
243
r"""
244
Give the C type used for a value of this type inside an
245
instruction. For assignable/cheap_copy types, this is the
246
same as c_decl_type; for auto-reference types, this is the
247
pointer type.
248
249
EXAMPLES::
250
251
sage: from sage_setup.autogen.interpreters.internal import *
252
sage: ty_double.c_local_type()
253
'double'
254
sage: ty_python.c_local_type()
255
'PyObject*'
256
sage: ty_mpfr.c_local_type()
257
'mpfr_ptr'
258
"""
259
raise NotImplementedError
260
261
def assign_c_from_py(self, c, py):
262
r"""
263
Given a Cython variable/array reference/etc. of this storage type,
264
and a Python expression, generate code to assign to the Cython
265
variable from the Python expression.
266
267
EXAMPLES::
268
269
sage: from sage_setup.autogen.interpreters.internal import *
270
sage: ty_double.assign_c_from_py('foo', 'bar')
271
'foo = bar'
272
sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')
273
'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'
274
sage: ty_mpfr.assign_c_from_py('foo', 'bar')
275
'rn = self.domain(bar)\nmpfr_set(foo, rn.value, MPFR_RNDN)'
276
"""
277
return je("{{ c }} = {{ py }}", c=c, py=py)
278
279
def declare_chunk_class_members(self, name):
280
r"""
281
Return a string giving the declarations of the class members
282
in a wrapper class for a memory chunk with this storage type
283
and the given name.
284
285
EXAMPLES::
286
287
sage: from sage_setup.autogen.interpreters.internal import *
288
sage: ty_mpfr.declare_chunk_class_members('args')
289
' cdef int _n_args\n cdef mpfr_t* _args\n'
290
"""
291
return je(ri(0,
292
"""
293
{# XXX Variables here (and everywhere, really) should actually be Py_ssize_t #}
294
cdef int _n_{{ name }}
295
cdef {{ myself.cython_array_type() }} _{{ name }}
296
"""), myself=self, name=name)
297
298
def alloc_chunk_data(self, name, len):
299
r"""
300
Return a string allocating the memory for the class members for
301
a memory chunk with this storage type and the given name.
302
303
EXAMPLES::
304
305
sage: from sage_setup.autogen.interpreters.internal import *
306
sage: print(ty_mpfr.alloc_chunk_data('args', 'MY_LENGTH'))
307
self._n_args = MY_LENGTH
308
self._args = <mpfr_t*>check_allocarray(self._n_args, sizeof(mpfr_t))
309
for i in range(MY_LENGTH):
310
mpfr_init2(self._args[i], self.domain.prec())
311
<BLANKLINE>
312
"""
313
return je(ri(0,
314
"""
315
self._n_{{ name }} = {{ len }}
316
self._{{ name }} = <{{ myself.c_ptr_type() }}>check_allocarray(self._n_{{ name }}, sizeof({{ myself.c_decl_type() }}))
317
{% if myself.needs_cython_init_clear() %}
318
for i in range({{ len }}):
319
{{ myself.cython_init('self._%s[i]' % name) }}
320
{% endif %}
321
"""), myself=self, name=name, len=len)
322
323
def dealloc_chunk_data(self, name):
324
r"""
325
Return a string to be put in the __dealloc__ method of a
326
wrapper class using a memory chunk with this storage type, to
327
deallocate the corresponding class members.
328
329
EXAMPLES::
330
331
sage: from sage_setup.autogen.interpreters.internal import *
332
sage: print(ty_double.dealloc_chunk_data('args'))
333
if self._args:
334
sig_free(self._args)
335
<BLANKLINE>
336
sage: print(ty_mpfr.dealloc_chunk_data('constants'))
337
if self._constants:
338
for i in range(self._n_constants):
339
mpfr_clear(self._constants[i])
340
sig_free(self._constants)
341
<BLANKLINE>
342
"""
343
return je(ri(0, """
344
if self._{{ name }}:
345
{% if myself.needs_cython_init_clear() %}
346
for i in range(self._n_{{ name }}):
347
{{ myself.cython_clear('self._%s[i]' % name) }}
348
{% endif %}
349
sig_free(self._{{ name }})
350
"""), myself=self, name=name)
351
352
353
class StorageTypeAssignable(StorageType):
354
r"""
355
StorageTypeAssignable is a subtype of StorageType that deals with
356
types with cheap copies, like primitive types and PyObject*.
357
"""
358
359
def __init__(self, ty):
360
r"""
361
Initializes the property type (the C/Cython name for this type),
362
as well as the properties described in the documentation for
363
StorageType.__init__.
364
365
EXAMPLES::
366
367
sage: from sage_setup.autogen.interpreters.internal import *
368
sage: ty_double.class_member_declarations
369
''
370
sage: ty_double.class_member_initializations
371
''
372
sage: ty_double.local_declarations
373
''
374
sage: ty_double.type
375
'double'
376
sage: ty_python.type
377
'PyObject*'
378
"""
379
StorageType.__init__(self)
380
self.type = ty
381
382
def cheap_copies(self):
383
r"""
384
Returns True or False, depending on whether this StorageType
385
supports cheap copies -- whether it is cheap to copy values of
386
this type from one location to another. (See StorageType.cheap_copies
387
for more on this property.)
388
389
Since having cheap copies is essentially the definition of
390
StorageTypeAssignable, this always returns True.
391
392
EXAMPLES::
393
394
sage: from sage_setup.autogen.interpreters.internal import *
395
sage: ty_double.cheap_copies()
396
True
397
sage: ty_python.cheap_copies()
398
True
399
"""
400
return True
401
402
def c_decl_type(self):
403
r"""
404
Give the C type for a single value of this type (as a string).
405
406
EXAMPLES::
407
408
sage: from sage_setup.autogen.interpreters.internal import *
409
sage: ty_double.c_decl_type()
410
'double'
411
sage: ty_python.c_decl_type()
412
'PyObject*'
413
"""
414
return self.type
415
416
def c_local_type(self):
417
r"""
418
Give the C type used for a value of this type inside an
419
instruction. For assignable/cheap_copy types, this is the
420
same as c_decl_type; for auto-reference types, this is the
421
pointer type.
422
423
EXAMPLES::
424
425
sage: from sage_setup.autogen.interpreters.internal import *
426
sage: ty_double.c_local_type()
427
'double'
428
sage: ty_python.c_local_type()
429
'PyObject*'
430
"""
431
return self.type
432
433
434
class StorageTypeSimple(StorageTypeAssignable):
435
r"""
436
StorageTypeSimple is a subtype of StorageTypeAssignable that deals
437
with non-reference-counted types with cheap copies, like primitive
438
types. As of yet, it has no functionality differences from
439
StorageTypeAssignable.
440
"""
441
pass
442
443
444
ty_int = StorageTypeSimple('int')
445
ty_double = StorageTypeSimple('double')
446
447
448
class StorageTypeDoubleComplex(StorageTypeSimple):
449
r"""
450
This is specific to the complex double type. It behaves exactly
451
like a StorageTypeSimple in C, but needs a little help to do
452
conversions in Cython.
453
454
This uses functions defined in CDFInterpreter, and is for use in
455
that context.
456
"""
457
def assign_c_from_py(self, c, py):
458
"""
459
sage: from sage_setup.autogen.interpreters.internal import ty_double_complex
460
sage: ty_double_complex.assign_c_from_py('z_c', 'z_py')
461
'z_c = CDE_to_dz(z_py)'
462
"""
463
return je("{{ c }} = CDE_to_dz({{ py }})", c=c, py=py)
464
465
466
ty_double_complex = StorageTypeDoubleComplex('double_complex')
467
468
469
class StorageTypePython(StorageTypeAssignable):
470
r"""
471
StorageTypePython is a subtype of StorageTypeAssignable that deals
472
with Python objects.
473
474
Just allocating an array full of PyObject* leads to problems,
475
because the Python garbage collector must be able to get to every
476
Python object, and it wouldn't know how to get to these arrays.
477
So we allocate the array as a Python list, but then we immediately
478
pull the ob_item out of it and deal only with that from then on.
479
480
We often leave these lists with NULL entries. This is safe for
481
the garbage collector and the deallocator, which is all we care
482
about; but it would be unsafe to provide Python-level access to
483
these lists.
484
485
There is one special thing about StorageTypePython: memory that is
486
used by the interpreter as scratch space (for example, the stack)
487
must be cleared after each call (so we don't hold on to
488
potentially-large objects and waste memory). Since we have to do
489
this anyway, the interpreter gains a tiny bit of speed by assuming
490
that the scratch space is cleared on entry; for example, when
491
pushing a value onto the stack, it doesn't bother to XDECREF the
492
previous value because it's always NULL.
493
"""
494
495
def __init__(self):
496
r"""
497
Initializes the properties described in the documentation
498
for StorageTypeAssignable.__init__. The type is always
499
'PyObject*'.
500
501
EXAMPLES::
502
503
sage: from sage_setup.autogen.interpreters.internal import *
504
sage: ty_python.class_member_declarations
505
''
506
sage: ty_python.class_member_initializations
507
''
508
sage: ty_python.local_declarations
509
''
510
sage: ty_python.type
511
'PyObject*'
512
"""
513
super(StorageTypePython, self).__init__('PyObject*')
514
515
def python_refcounted(self):
516
r"""
517
Says whether this storage type is a Python type, so we need to
518
use INCREF/DECREF.
519
520
Returns True.
521
522
EXAMPLES::
523
524
sage: from sage_setup.autogen.interpreters.internal import *
525
sage: ty_python.python_refcounted()
526
True
527
"""
528
return True
529
530
def cython_decl_type(self):
531
r"""
532
Give the Cython type for a single value of this type (as a string).
533
534
EXAMPLES::
535
536
sage: from sage_setup.autogen.interpreters.internal import *
537
sage: ty_python.cython_decl_type()
538
'object'
539
"""
540
return 'object'
541
542
def declare_chunk_class_members(self, name):
543
r"""
544
Return a string giving the declarations of the class members
545
in a wrapper class for a memory chunk with this storage type
546
and the given name.
547
548
EXAMPLES::
549
550
sage: from sage_setup.autogen.interpreters.internal import *
551
sage: ty_python.declare_chunk_class_members('args')
552
' cdef object _list_args\n cdef int _n_args\n cdef PyObject** _args\n'
553
"""
554
return je(ri(4,
555
"""
556
cdef object _list_{{ name }}
557
cdef int _n_{{ name }}
558
cdef {{ myself.cython_array_type() }} _{{ name }}
559
"""), myself=self, name=name)
560
561
def alloc_chunk_data(self, name, len):
562
r"""
563
Return a string allocating the memory for the class members for
564
a memory chunk with this storage type and the given name.
565
566
EXAMPLES::
567
568
sage: from sage_setup.autogen.interpreters.internal import *
569
sage: print(ty_python.alloc_chunk_data('args', 'MY_LENGTH'))
570
self._n_args = MY_LENGTH
571
self._list_args = PyList_New(self._n_args)
572
self._args = (<PyListObject *>self._list_args).ob_item
573
<BLANKLINE>
574
"""
575
return je(ri(8,
576
"""
577
self._n_{{ name }} = {{ len }}
578
self._list_{{ name }} = PyList_New(self._n_{{ name }})
579
self._{{ name }} = (<PyListObject *>self._list_{{ name }}).ob_item
580
"""), myself=self, name=name, len=len)
581
582
def dealloc_chunk_data(self, name):
583
r"""
584
Return a string to be put in the __dealloc__ method of a
585
wrapper class using a memory chunk with this storage type, to
586
deallocate the corresponding class members.
587
588
Our array was allocated as a Python list; this means we actually
589
don't need to do anything to deallocate it.
590
591
EXAMPLES::
592
593
sage: from sage_setup.autogen.interpreters.internal import *
594
sage: ty_python.dealloc_chunk_data('args')
595
''
596
"""
597
return ''
598
599
def needs_cython_init_clear(self):
600
r"""
601
Says whether values/arrays of this type need to be initialized
602
before use and cleared before the underlying memory is freed.
603
604
Returns True.
605
606
EXAMPLES::
607
608
sage: from sage_setup.autogen.interpreters.internal import *
609
sage: ty_python.needs_cython_init_clear()
610
True
611
"""
612
return True
613
614
def assign_c_from_py(self, c, py):
615
r"""
616
Given a Cython variable/array reference/etc. of this storage type,
617
and a Python expression, generate code to assign to the Cython
618
variable from the Python expression.
619
620
EXAMPLES::
621
622
sage: from sage_setup.autogen.interpreters.internal import *
623
sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')
624
'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'
625
"""
626
return je("""{{ c }} = <PyObject *>{{ py }}; Py_INCREF({{ c }})""",
627
c=c, py=py)
628
629
def cython_init(self, loc):
630
r"""
631
Generates code to initialize a variable (or array reference)
632
holding a PyObject*. Sets it to NULL.
633
634
EXAMPLES::
635
636
sage: from sage_setup.autogen.interpreters.internal import *
637
sage: ty_python.cython_init('foo[i]')
638
'foo[i] = NULL'
639
"""
640
return je("{{ loc }} = NULL", loc=loc)
641
642
def cython_clear(self, loc):
643
r"""
644
Generates code to clear a variable (or array reference) holding
645
a PyObject*.
646
647
EXAMPLES::
648
649
sage: from sage_setup.autogen.interpreters.internal import *
650
sage: ty_python.cython_clear('foo[i]')
651
'Py_CLEAR(foo[i])'
652
"""
653
return je("Py_CLEAR({{ loc }})", loc=loc)
654
655
656
ty_python = StorageTypePython()
657
658
659
class StorageTypeAutoReference(StorageType):
660
r"""
661
StorageTypeAutoReference is a subtype of StorageType that deals with
662
types in the style of GMP/MPIR/MPFR/MPFI/FLINT, where copies are
663
not cheap, functions expect arguments to be passed by reference,
664
and the API takes advantage of the C quirk where arrays are
665
automatically converted to pointers to automatically pass
666
arguments by reference.
667
"""
668
def __init__(self, decl_ty, ref_ty):
669
r"""
670
Initializes the properties decl_type and ref_type (the C type
671
names used when declaring variables and function parameters,
672
respectively), as well as the properties described in
673
the documentation for StorageType.__init__.
674
675
EXAMPLES::
676
677
sage: from sage_setup.autogen.interpreters.internal import *
678
sage: ty_mpfr.class_member_declarations
679
'cdef RealField_class domain\n'
680
sage: ty_mpfr.class_member_initializations
681
"self.domain = args['domain']\n"
682
sage: ty_mpfr.local_declarations
683
'cdef RealNumber rn\n'
684
sage: ty_mpfr.decl_type
685
'mpfr_t'
686
sage: ty_mpfr.ref_type
687
'mpfr_ptr'
688
"""
689
super(StorageTypeAutoReference, self).__init__()
690
self.decl_type = decl_ty
691
self.ref_type = ref_ty
692
693
def c_decl_type(self):
694
r"""
695
Give the C type for a single value of this type (as a string).
696
697
EXAMPLES::
698
699
sage: from sage_setup.autogen.interpreters.internal import *
700
sage: ty_mpfr.c_decl_type()
701
'mpfr_t'
702
"""
703
return self.decl_type
704
705
def c_local_type(self):
706
r"""
707
Give the C type used for a value of this type inside an
708
instruction. For assignable/cheap_copy types, this is the
709
same as c_decl_type; for auto-reference types, this is the
710
pointer type.
711
712
EXAMPLES::
713
714
sage: from sage_setup.autogen.interpreters.internal import *
715
sage: ty_mpfr.c_local_type()
716
'mpfr_ptr'
717
"""
718
return self.ref_type
719
720
def c_reference_type(self):
721
r"""
722
Give the C type which should be used for passing a reference
723
to a single value in a call. This is used as the type for the
724
return value.
725
726
EXAMPLES::
727
728
sage: from sage_setup.autogen.interpreters.internal import *
729
sage: ty_mpfr.c_reference_type()
730
'mpfr_t'
731
"""
732
return self.decl_type
733
734
def needs_cython_init_clear(self):
735
r"""
736
Says whether values/arrays of this type need to be initialized
737
before use and cleared before the underlying memory is freed.
738
739
All known examples of auto-reference types do need a special
740
initialization call, so this always returns True.
741
742
EXAMPLES::
743
744
sage: from sage_setup.autogen.interpreters.internal import *
745
sage: ty_mpfr.needs_cython_init_clear()
746
True
747
"""
748
return True
749
750
751
class StorageTypeMPFR(StorageTypeAutoReference):
752
r"""
753
StorageTypeMPFR is a subtype of StorageTypeAutoReference that deals
754
the MPFR's mpfr_t type.
755
756
For any given program that we're interpreting, ty_mpfr can only
757
refer to a single precision. An interpreter that needs to use
758
two precisions of mpfr_t in the same program should instantiate two
759
separate instances of StorageTypeMPFR. (Interpreters that need
760
to handle arbitrarily many precisions in the same program are not
761
handled at all.)
762
"""
763
764
def __init__(self, id=''):
765
r"""
766
Initializes the id property, as well as the properties described
767
in the documentation for StorageTypeAutoReference.__init__.
768
769
The id property is used if you want to have an interpreter
770
that handles two instances of StorageTypeMPFR (that is,
771
handles mpfr_t variables at two different precisions
772
simultaneously). It's a string that's used to generate
773
variable names that don't conflict. (The id system has
774
never actually been used, so bugs probably remain.)
775
776
EXAMPLES::
777
778
sage: from sage_setup.autogen.interpreters.internal import *
779
sage: ty_mpfr.class_member_declarations
780
'cdef RealField_class domain\n'
781
sage: ty_mpfr.class_member_initializations
782
"self.domain = args['domain']\n"
783
sage: ty_mpfr.local_declarations
784
'cdef RealNumber rn\n'
785
sage: ty_mpfr.decl_type
786
'mpfr_t'
787
sage: ty_mpfr.ref_type
788
'mpfr_ptr'
789
790
TESTS::
791
792
sage: ty_mpfr2 = StorageTypeMPFR(id='_the_second')
793
sage: ty_mpfr2.class_member_declarations
794
'cdef RealField_class domain_the_second\n'
795
sage: ty_mpfr2.class_member_initializations
796
"self.domain_the_second = args['domain_the_second']\n"
797
sage: ty_mpfr2.local_declarations
798
'cdef RealNumber rn_the_second\n'
799
"""
800
801
super(StorageTypeMPFR, self).__init__('mpfr_t', 'mpfr_ptr')
802
self.id = id
803
self.class_member_declarations = "cdef RealField_class domain%s\n" % self.id
804
self.class_member_initializations = \
805
"self.domain%s = args['domain%s']\n" % (self.id, self.id)
806
self.local_declarations = "cdef RealNumber rn%s\n" % self.id
807
808
def cython_init(self, loc):
809
r"""
810
Generates code to initialize an mpfr_t reference (a variable, an
811
array reference, etc.)
812
813
EXAMPLES::
814
815
sage: from sage_setup.autogen.interpreters.internal import *
816
sage: ty_mpfr.cython_init('foo[i]')
817
'mpfr_init2(foo[i], self.domain.prec())'
818
"""
819
return je("mpfr_init2({{ loc }}, self.domain{{ myself.id }}.prec())",
820
myself=self, loc=loc)
821
822
def cython_clear(self, loc):
823
r"""
824
Generates code to clear an mpfr_t reference (a variable, an
825
array reference, etc.)
826
827
EXAMPLES::
828
829
sage: from sage_setup.autogen.interpreters.internal import *
830
sage: ty_mpfr.cython_clear('foo[i]')
831
'mpfr_clear(foo[i])'
832
"""
833
return 'mpfr_clear(%s)' % loc
834
835
def assign_c_from_py(self, c, py):
836
r"""
837
Given a Cython variable/array reference/etc. of this storage type,
838
and a Python expression, generate code to assign to the Cython
839
variable from the Python expression.
840
841
EXAMPLES::
842
843
sage: from sage_setup.autogen.interpreters.internal import *
844
sage: ty_mpfr.assign_c_from_py('foo[i]', 'bar[j]')
845
'rn = self.domain(bar[j])\nmpfr_set(foo[i], rn.value, MPFR_RNDN)'
846
"""
847
return je(ri(0, """
848
rn{{ myself.id }} = self.domain({{ py }})
849
mpfr_set({{ c }}, rn.value, MPFR_RNDN)"""),
850
myself=self, c=c, py=py)
851
852
853
ty_mpfr = StorageTypeMPFR()
854
855
856
class StorageTypeMPC(StorageTypeAutoReference):
857
r"""
858
StorageTypeMPC is a subtype of StorageTypeAutoReference that deals
859
the MPC's mpc_t type.
860
861
For any given program that we're interpreting, ty_mpc can only
862
refer to a single precision. An interpreter that needs to use
863
two precisions of mpc_t in the same program should instantiate two
864
separate instances of StorageTypeMPC. (Interpreters that need
865
to handle arbitrarily many precisions in the same program are not
866
handled at all.)
867
"""
868
869
def __init__(self, id=''):
870
r"""
871
Initializes the id property, as well as the properties described
872
in the documentation for StorageTypeAutoReference.__init__.
873
874
The id property is used if you want to have an interpreter
875
that handles two instances of StorageTypeMPC (that is,
876
handles mpC_t variables at two different precisions
877
simultaneously). It's a string that's used to generate
878
variable names that don't conflict. (The id system has
879
never actually been used, so bugs probably remain.)
880
881
EXAMPLES::
882
883
sage: from sage_setup.autogen.interpreters.internal import *
884
sage: ty_mpc.class_member_declarations
885
'cdef object domain\ncdef ComplexNumber domain_element\n'
886
sage: ty_mpc.class_member_initializations
887
"self.domain = args['domain']\nself.domain_element = self.domain.zero()\n"
888
sage: ty_mpc.local_declarations
889
'cdef ComplexNumber cn\n'
890
sage: ty_mpc.decl_type
891
'mpc_t'
892
sage: ty_mpc.ref_type
893
'mpc_ptr'
894
895
TESTS::
896
897
sage: ty_mpfr2 = StorageTypeMPC(id='_the_second')
898
sage: ty_mpfr2.class_member_declarations
899
'cdef object domain_the_second\ncdef ComplexNumber domain_element_the_second\n'
900
sage: ty_mpfr2.class_member_initializations
901
"self.domain_the_second = args['domain_the_second']\nself.domain_element_the_second = self.domain.zero()\n"
902
sage: ty_mpfr2.local_declarations
903
'cdef ComplexNumber cn_the_second\n'
904
905
"""
906
StorageTypeAutoReference.__init__(self, 'mpc_t', 'mpc_ptr')
907
self.id = id
908
self.class_member_declarations = "cdef object domain%s\ncdef ComplexNumber domain_element%s\n" % (self.id, self.id)
909
self.class_member_initializations = \
910
"self.domain%s = args['domain%s']\nself.domain_element%s = self.domain.zero()\n" % (self.id, self.id, self.id)
911
self.local_declarations = "cdef ComplexNumber cn%s\n" % self.id
912
913
def cython_init(self, loc):
914
r"""
915
Generates code to initialize an mpc_t reference (a variable, an
916
array reference, etc.)
917
918
EXAMPLES::
919
920
sage: from sage_setup.autogen.interpreters.internal import *
921
sage: ty_mpc.cython_init('foo[i]')
922
'mpc_init2(foo[i], self.domain_element._prec)'
923
"""
924
return je("mpc_init2({{ loc }}, self.domain_element{{ myself.id }}._prec)",
925
myself=self, loc=loc)
926
927
def cython_clear(self, loc):
928
r"""
929
Generates code to clear an mpfr_t reference (a variable, an
930
array reference, etc.)
931
932
EXAMPLES::
933
934
sage: from sage_setup.autogen.interpreters.internal import *
935
sage: ty_mpc.cython_clear('foo[i]')
936
'mpc_clear(foo[i])'
937
"""
938
return 'mpc_clear(%s)' % loc
939
940
def assign_c_from_py(self, c, py):
941
r"""
942
Given a Cython variable/array reference/etc. of this storage type,
943
and a Python expression, generate code to assign to the Cython
944
variable from the Python expression.
945
946
EXAMPLES::
947
948
sage: from sage_setup.autogen.interpreters.internal import *
949
sage: ty_mpc.assign_c_from_py('foo[i]', 'bar[j]')
950
'cn = self.domain(bar[j])\nmpc_set_fr_fr(foo[i], cn.__re, cn.__im, MPC_RNDNN)'
951
"""
952
return je("""
953
cn{{ myself.id }} = self.domain({{ py }})
954
mpc_set_fr_fr({{ c }}, cn.__re, cn.__im, MPC_RNDNN)""", myself=self, c=c, py=py)
955
956
957
ty_mpc = StorageTypeMPC()
958
959