Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/ext/gen_interpreters.py
4057 views
1
r"""
2
Generate interpreters for fast_callable
3
4
AUTHORS:
5
6
- Carl Witty
7
8
This file is part of the Sage support for "planned" computations;
9
that is, computations that are separated into a planning stage and
10
a plan-execution stage. Here, we generate fast interpreters for plan
11
executions.
12
13
There are at least two kinds of computations that are often planned in
14
this fashion. First is arithmetic expression evaluation, where we
15
take an arbitrary user-specified arithmetic expression and compile it
16
into a bytecode form for fast interpretation. Second is things like
17
FFTs and large multiplications, where large problems are split into
18
multiple smaller problems... we can do the logical "splitting" for a
19
given size only once, producing a plan which can be reused as often as
20
we want for different problems of the same size. Currently only
21
arithmetic expression evaluation is implemented, but other kinds of
22
planned computations should be easy to add.
23
24
Typically, for arithmetic expressions, we want the storage of
25
intermediate results to be handled automatically (on a stack); for
26
FFTs/multiplications/etc., the planner will keep track of intermediate
27
results itself.
28
29
For arithmetic expression evaluation, we want to have lots of
30
interpreters (at least one, and possibly several, per
31
specially-handled type). Also, for any given type, we have many
32
possible variants of instruction encoding, etc.; some of these could
33
be handled with conditional compilation, but some are more
34
complicated. So we end up writing an interpreter generator.
35
36
We want to share as much code as possible across all of these
37
interpreters, while still maintaining the freedom to make drastic
38
changes in the interpretation strategy (which may change the
39
generated code, the calling convention for the interpreter, etc.)
40
41
To make this work, the interpreter back-end is divided into three
42
parts:
43
44
1. The interpreter itself, in C or C++.
45
46
2. The wrapper, which is a Cython object holding the
47
constants, code, etc., and which actually calls the interpreter.
48
49
3. The code generator.
50
51
We generate parts 1 and 2. The code generator is table-driven,
52
and we generate the tables for the code generator.
53
54
There are a lot of techniques for fast interpreters that we do not yet
55
use; hopefully at least some of these will eventually be implemented:
56
57
- using gcc's "labels as values" extension where available
58
59
- top-of-stack caching
60
61
- superinstructions and/or superoperators
62
63
- static stack caching
64
65
- context threading/subrouting threading
66
67
- selective inlining/dynamic superinstructions
68
69
- automatic replication
70
71
Interpreters may be stack-based or register-based. Recent research
72
suggests that register-based interpreters are better, but the
73
researchers are investigating interpreters for entire programming
74
languages, rather than interpreters for expressions. I suspect
75
that stack-based expression interpreters may be better. However,
76
we'll implement both varieties and see what's best.
77
78
The relative costs of stack- and register-based interpreters will
79
depend on the costs of moving values. For complicated types (like
80
mpz_t), a register-based interpreter will quite likely be better,
81
since it will avoid moving values.
82
83
We will NOT support any sort of storage of bytecode; instead, the
84
code must be re-generated from expression trees in every Sage run.
85
This means that we can trivially experiment with different styles of
86
interpreter, or even use quite different interpreters depending on
87
the architecture, without having to worry about forward and backward
88
compatibility.
89
"""
90
#*****************************************************************************
91
# Copyright (C) 2009 Carl Witty <[email protected]>
92
#
93
# Distributed under the terms of the GNU General Public License (GPL)
94
# http://www.gnu.org/licenses/
95
#*****************************************************************************
96
97
from __future__ import with_statement
98
99
import os
100
import re
101
from jinja2 import Environment
102
from jinja2.runtime import StrictUndefined
103
from collections import defaultdict
104
from distutils.extension import Extension
105
106
##############################
107
# This module is used during the Sage build process, so it should not
108
# use any other Sage modules. (In particular, it MUST NOT use any
109
# Cython modules -- they won't be built yet!)
110
# Also, we have some trivial dependency tracking, where we don't
111
# rebuild the interpreters if this file hasn't changed; if
112
# interpreter configuration is split out into a separate file,
113
# that will have to be changed.
114
##############################
115
116
117
# We share a single jinja2 environment among all templating in this
118
# file. We use trim_blocks=True (which means that we ignore white
119
# space after "%}" jinja2 command endings), and set undefined to
120
# complain if we use an undefined variable.
121
jinja_env = Environment(trim_blocks=True, undefined=StrictUndefined)
122
123
# Allow 'i' as a shorter alias for the built-in 'indent' filter.
124
jinja_env.filters['i'] = jinja_env.filters['indent']
125
126
def indent_lines(n, text):
127
r"""
128
INPUTS:
129
n -- indentation amount
130
text -- text to indent
131
132
Indents each line in text by n spaces.
133
134
EXAMPLES:
135
sage: from sage.ext.gen_interpreters import indent_lines
136
sage: indent_lines(3, "foo")
137
' foo'
138
sage: indent_lines(3, "foo\nbar")
139
' foo\n bar'
140
sage: indent_lines(3, "foo\nbar\n")
141
' foo\n bar\n'
142
"""
143
lines = text.splitlines(True)
144
spaces = ' ' * n
145
return ''.join(spaces + line for line in lines)
146
147
def je(template, **kwargs):
148
r"""
149
A convenience method for creating strings with Jinja templates.
150
The name je stands for "Jinja evaluate".
151
152
The first argument is the template string; remaining keyword
153
arguments define Jinja variables.
154
155
If the first character in the template string is a newline, it is
156
removed (this feature is useful when using multi-line templates defined
157
with triple-quoted strings -- the first line doesn't have to be on
158
the same line as the quotes, which would screw up the indentation).
159
160
(This is very inefficient, because it recompiles the Jinja
161
template on each call; don't use it in situations where
162
performance is important.)
163
164
EXAMPLES:
165
sage: from sage.ext.gen_interpreters import je
166
sage: je("{{ a }} > {{ b }} * {{ c }}", a='"a suffusion of yellow"', b=3, c=7)
167
u'"a suffusion of yellow" > 3 * 7'
168
"""
169
if len(template) > 0 and template[0] == '\n':
170
template = template[1:]
171
172
# It looks like Jinja2 automatically removes one trailing newline?
173
if len(template) > 0 and template[-1] == '\n':
174
template = template + '\n'
175
176
tmpl = jinja_env.from_string(template)
177
return tmpl.render(kwargs)
178
179
class StorageType(object):
180
r"""
181
A StorageType specifies the C types used to deal with values of a
182
given type.
183
184
We currently support three categories of types.
185
186
First are the "simple" types. These are types where: the
187
representation is small, functions expect arguments to be passed
188
by value, and the C/C++ assignment operator works. This would
189
include built-in C types (long, float, etc.) and small structs
190
(like gsl_complex).
191
192
Second is 'PyObject*'. This is just like a simple type, except
193
that we have to incref/decref at appropriate places.
194
195
Third is "auto-reference" types. This is how
196
GMP/MPIR/MPFR/MPFI/FLINT types work. For these types, functions
197
expect arguments to be passed by reference, and the C assignment
198
operator does not do what we want. In addition, they take
199
advantage of a quirk in C (where arrays are automatically
200
converted to pointers) to automatically pass arguments by
201
reference.
202
203
Support for further categories would not be difficult to add (such
204
as reference-counted types other than PyObject*, or
205
pass-by-reference types that don't use the GMP auto-reference
206
trick), if we ever run across a use for them.
207
"""
208
209
def __init__(self):
210
r"""
211
Initialize an instance of StorageType.
212
213
This sets several properties:
214
215
class_member_declarations:
216
A string giving variable declarations that must be members of any
217
wrapper class using this type.
218
219
class_member_initializations:
220
A string initializing the class_member_declarations; will be
221
inserted into the __init__ method of any wrapper class using this
222
type.
223
224
local_declarations:
225
A string giving variable declarations that must be local variables
226
in Cython methods using this storage type.
227
228
EXAMPLES:
229
sage: from sage.ext.gen_interpreters import *
230
sage: ty_double.class_member_declarations
231
''
232
sage: ty_double.class_member_initializations
233
''
234
sage: ty_double.local_declarations
235
''
236
sage: ty_mpfr.class_member_declarations
237
'cdef RealField_class domain\n'
238
sage: ty_mpfr.class_member_initializations
239
"self.domain = args['domain']\n"
240
sage: ty_mpfr.local_declarations
241
'cdef RealNumber rn\n'
242
"""
243
self.class_member_declarations = ''
244
self.class_member_initializations = ''
245
self.local_declarations = ''
246
247
def cheap_copies(self):
248
r"""
249
Returns True or False, depending on whether this StorageType
250
supports cheap copies -- whether it is cheap to copy values of
251
this type from one location to another. This is true for
252
primitive types, and for types like PyObject* (where you're only
253
copying a pointer, and possibly changing some reference counts).
254
It is false for types like mpz_t and mpfr_t, where copying values
255
can involve arbitrarily much work (including memory allocation).
256
257
The practical effect is that if cheap_copies is True,
258
instructions with outputs of this type write the results into
259
local variables, and the results are then copied to their
260
final locations. If cheap_copies is False, then the addresses
261
of output locations are passed into the instruction and the
262
instruction writes outputs directly in the final location.
263
264
EXAMPLES:
265
sage: from sage.ext.gen_interpreters import *
266
sage: ty_double.cheap_copies()
267
True
268
sage: ty_python.cheap_copies()
269
True
270
sage: ty_mpfr.cheap_copies()
271
False
272
"""
273
return False
274
275
def python_refcounted(self):
276
r"""
277
Says whether this storage type is a Python type, so we need to
278
use INCREF/DECREF.
279
280
(If we needed to support any non-Python refcounted types, it
281
might be better to make this object-oriented and have methods
282
like "generate an incref" and "generate a decref". But as
283
long as we only support Python, this way is probably simpler.)
284
285
EXAMPLES:
286
sage: from sage.ext.gen_interpreters import *
287
sage: ty_double.python_refcounted()
288
False
289
sage: ty_python.python_refcounted()
290
True
291
"""
292
return False
293
294
def cython_decl_type(self):
295
r"""
296
Gives the Cython type for a single value of this type (as a string).
297
298
EXAMPLES:
299
sage: from sage.ext.gen_interpreters import *
300
sage: ty_double.cython_decl_type()
301
'double'
302
sage: ty_python.cython_decl_type()
303
'object'
304
sage: ty_mpfr.cython_decl_type()
305
'mpfr_t'
306
"""
307
return self.c_decl_type()
308
309
def cython_array_type(self):
310
r"""
311
Gives the Cython type for referring to an array of values of
312
this type (as a string).
313
314
EXAMPLES:
315
sage: from sage.ext.gen_interpreters import *
316
sage: ty_double.cython_array_type()
317
'double*'
318
sage: ty_python.cython_array_type()
319
'PyObject**'
320
sage: ty_mpfr.cython_array_type()
321
'mpfr_t*'
322
"""
323
return self.c_ptr_type()
324
325
def needs_cython_init_clear(self):
326
r"""
327
Says whether values/arrays of this type need to be initialized
328
before use and cleared before the underlying memory is freed.
329
330
(We could remove this method, always call .cython_init() to
331
generate initialization code, and just let .cython_init()
332
generate empty code if no initialization is required; that would
333
generate empty loops, which are ugly and potentially might not
334
be optimized away.)
335
336
EXAMPLES:
337
sage: from sage.ext.gen_interpreters import *
338
sage: ty_double.needs_cython_init_clear()
339
False
340
sage: ty_mpfr.needs_cython_init_clear()
341
True
342
sage: ty_python.needs_cython_init_clear()
343
True
344
"""
345
return False
346
347
def c_decl_type(self):
348
r"""
349
Gives the C type for a single value of this type (as a string).
350
351
EXAMPLES:
352
sage: from sage.ext.gen_interpreters import *
353
sage: ty_double.c_decl_type()
354
'double'
355
sage: ty_python.c_decl_type()
356
'PyObject*'
357
sage: ty_mpfr.c_decl_type()
358
'mpfr_t'
359
"""
360
raise NotImplementedError
361
362
def c_ptr_type(self):
363
r"""
364
Gives the C type for a pointer to this type (as a reference to
365
either a single value or an array) (as a string).
366
367
EXAMPLES:
368
sage: from sage.ext.gen_interpreters import *
369
sage: ty_double.c_ptr_type()
370
'double*'
371
sage: ty_python.c_ptr_type()
372
'PyObject**'
373
sage: ty_mpfr.c_ptr_type()
374
'mpfr_t*'
375
"""
376
return self.c_decl_type() + '*'
377
378
def c_local_type(self):
379
r"""
380
Gives the C type used for a value of this type inside an
381
instruction. For assignable/cheap_copy types, this is the
382
same as c_decl_type; for auto-reference types, this is the
383
pointer type.
384
385
EXAMPLES:
386
sage: from sage.ext.gen_interpreters import *
387
sage: ty_double.c_local_type()
388
'double'
389
sage: ty_python.c_local_type()
390
'PyObject*'
391
sage: ty_mpfr.c_local_type()
392
'mpfr_ptr'
393
"""
394
raise NotImplementedError
395
396
def assign_c_from_py(self, c, py):
397
r"""
398
Given a Cython variable/array reference/etc. of this storage type,
399
and a Python expression, generate code to assign to the Cython
400
variable from the Python expression.
401
402
EXAMPLES:
403
sage: from sage.ext.gen_interpreters import *
404
sage: ty_double.assign_c_from_py('foo', 'bar')
405
u'foo = bar'
406
sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')
407
u'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'
408
sage: ty_mpfr.assign_c_from_py('foo', 'bar')
409
u'rn = self.domain(bar)\nmpfr_set(foo, rn.value, GMP_RNDN)'
410
"""
411
return je("{{ c }} = {{ py }}", c=c, py=py)
412
413
def declare_chunk_class_members(self, name):
414
r"""
415
Returns a string giving the declarations of the class members
416
in a wrapper class for a memory chunk with this storage type
417
and the given name.
418
419
EXAMPLES:
420
sage: from sage.ext.gen_interpreters import *
421
sage: ty_mpfr.declare_chunk_class_members('args')
422
u' cdef int _n_args\n cdef mpfr_t* _args\n'
423
"""
424
return je("""
425
{# XXX Variables here (and everywhere, really) should actually be Py_ssize_t #}
426
cdef int _n_{{ name }}
427
cdef {{ myself.cython_array_type() }} _{{ name }}
428
""", myself=self, name=name)
429
430
def alloc_chunk_data(self, name, len):
431
r"""
432
Returns a string allocating the memory for the class members for
433
a memory chunk with this storage type and the given name.
434
435
EXAMPLES:
436
sage: from sage.ext.gen_interpreters import *
437
sage: print ty_mpfr.alloc_chunk_data('args', 'MY_LENGTH')
438
self._n_args = MY_LENGTH
439
self._args = <mpfr_t*>sage_malloc(sizeof(mpfr_t) * MY_LENGTH)
440
if self._args == NULL: raise MemoryError
441
for i in range(MY_LENGTH):
442
mpfr_init2(self._args[i], self.domain.prec())
443
<BLANKLINE>
444
"""
445
return je("""
446
self._n_{{ name }} = {{ len }}
447
self._{{ name }} = <{{ myself.c_ptr_type() }}>sage_malloc(sizeof({{ myself.c_decl_type() }}) * {{ len }})
448
if self._{{ name }} == NULL: raise MemoryError
449
{% if myself.needs_cython_init_clear() %}
450
for i in range({{ len }}):
451
{{ myself.cython_init('self._%s[i]' % name) }}
452
{% endif %}
453
""", myself=self, name=name, len=len)
454
455
def dealloc_chunk_data(self, name):
456
r"""
457
Returns a string to be put in the __dealloc__ method of a
458
wrapper class using a memory chunk with this storage type, to
459
deallocate the corresponding class members.
460
461
EXAMPLES:
462
sage: from sage.ext.gen_interpreters import *
463
sage: print ty_double.dealloc_chunk_data('args')
464
if self._args:
465
sage_free(self._args)
466
<BLANKLINE>
467
sage: print ty_mpfr.dealloc_chunk_data('constants')
468
if self._constants:
469
for i in range(self._n_constants):
470
mpfr_clear(self._constants[i])
471
sage_free(self._constants)
472
<BLANKLINE>
473
"""
474
return je("""
475
if self._{{ name }}:
476
{% if myself.needs_cython_init_clear() %}
477
for i in range(self._n_{{ name }}):
478
{{ myself.cython_clear('self._%s[i]' % name) }}
479
{% endif %}
480
sage_free(self._{{ name }})
481
""", myself=self, name=name)
482
483
class StorageTypeAssignable(StorageType):
484
r"""
485
StorageTypeAssignable is a subtype of StorageType that deals with
486
types with cheap copies, like primitive types and PyObject*.
487
"""
488
489
def __init__(self, ty):
490
r"""
491
Initializes the property type (the C/Cython name for this type),
492
as well as the properties described in the documentation for
493
StorageType.__init__.
494
495
EXAMPLES:
496
sage: from sage.ext.gen_interpreters import *
497
sage: ty_double.class_member_declarations
498
''
499
sage: ty_double.class_member_initializations
500
''
501
sage: ty_double.local_declarations
502
''
503
sage: ty_double.type
504
'double'
505
sage: ty_python.type
506
'PyObject*'
507
"""
508
StorageType.__init__(self)
509
self.type = ty
510
511
def cheap_copies(self):
512
r"""
513
Returns True or False, depending on whether this StorageType
514
supports cheap copies -- whether it is cheap to copy values of
515
this type from one location to another. (See StorageType.cheap_copies
516
for more on this property.)
517
518
Since having cheap copies is essentially the definition of
519
StorageTypeAssignable, this always returns True.
520
521
EXAMPLES:
522
sage: from sage.ext.gen_interpreters import *
523
sage: ty_double.cheap_copies()
524
True
525
sage: ty_python.cheap_copies()
526
True
527
"""
528
return True
529
530
def c_decl_type(self):
531
r"""
532
Gives the C type for a single value of this type (as a string).
533
534
EXAMPLES:
535
sage: from sage.ext.gen_interpreters import *
536
sage: ty_double.c_decl_type()
537
'double'
538
sage: ty_python.c_decl_type()
539
'PyObject*'
540
"""
541
return self.type
542
543
def c_local_type(self):
544
r"""
545
Gives the C type used for a value of this type inside an
546
instruction. For assignable/cheap_copy types, this is the
547
same as c_decl_type; for auto-reference types, this is the
548
pointer type.
549
550
EXAMPLES:
551
sage: from sage.ext.gen_interpreters import *
552
sage: ty_double.c_local_type()
553
'double'
554
sage: ty_python.c_local_type()
555
'PyObject*'
556
"""
557
return self.type
558
559
class StorageTypeSimple(StorageTypeAssignable):
560
r"""
561
StorageTypeSimple is a subtype of StorageTypeAssignable that deals
562
with non-reference-counted types with cheap copies, like primitive
563
types. As of yet, it has no functionality differences from
564
StorageTypeAssignable.
565
"""
566
pass
567
568
ty_int = StorageTypeSimple('int')
569
ty_double = StorageTypeSimple('double')
570
571
class StorageTypeDoubleComplex(StorageTypeSimple):
572
r"""
573
This is specific to the complex double type. It behaves exactly
574
like a StorageTypeSimple in C, but needs a little help to do
575
conversions in Cython.
576
577
This uses functions defined in CDFInterpreter, and is for use in
578
that context.
579
"""
580
def assign_c_from_py(self, c, py):
581
"""
582
sage: from sage.ext.gen_interpreters import ty_double_complex
583
sage: ty_double_complex.assign_c_from_py('z_c', 'z_py')
584
u'z_c = CDE_to_dz(z_py)'
585
"""
586
return je("{{ c }} = CDE_to_dz({{ py }})", c=c, py=py)
587
588
ty_double_complex = StorageTypeDoubleComplex('double_complex')
589
590
class StorageTypePython(StorageTypeAssignable):
591
r"""
592
StorageTypePython is a subtype of StorageTypeAssignable that deals
593
with Python objects.
594
595
Just allocating an array full of PyObject* leads to problems,
596
because the Python garbage collector must be able to get to every
597
Python object, and it wouldn't know how to get to these arrays.
598
So we allocate the array as a Python list, but then we immediately
599
pull the ob_item out of it and deal only with that from then on.
600
601
We often leave these lists with NULL entries. This is safe for
602
the garbage collector and the deallocator, which is all we care
603
about; but it would be unsafe to provide Python-level access to
604
these lists.
605
606
There is one special thing about StorageTypePython: memory that is
607
used by the interpreter as scratch space (for example, the stack)
608
must be cleared after each call (so we don't hold on to
609
potentially-large objects and waste memory). Since we have to do
610
this anyway, the interpreter gains a tiny bit of speed by assuming
611
that the scratch space is cleared on entry; for example, when
612
pushing a value onto the stack, it doesn't bother to XDECREF the
613
previous value because it's always NULL.
614
"""
615
616
def __init__(self):
617
r"""
618
Initializes the properties described in the documentation
619
for StorageTypeAssignable.__init__. The type is always
620
'PyObject*'.
621
622
EXAMPLES:
623
sage: from sage.ext.gen_interpreters import *
624
sage: ty_python.class_member_declarations
625
''
626
sage: ty_python.class_member_initializations
627
''
628
sage: ty_python.local_declarations
629
''
630
sage: ty_python.type
631
'PyObject*'
632
"""
633
StorageTypeAssignable.__init__(self, 'PyObject*')
634
635
def python_refcounted(self):
636
r"""
637
Says whether this storage type is a Python type, so we need to
638
use INCREF/DECREF.
639
640
Returns True.
641
642
EXAMPLES:
643
sage: from sage.ext.gen_interpreters import *
644
sage: ty_python.python_refcounted()
645
True
646
"""
647
return True
648
649
def cython_decl_type(self):
650
r"""
651
Gives the Cython type for a single value of this type (as a string).
652
653
EXAMPLES:
654
sage: from sage.ext.gen_interpreters import *
655
sage: ty_python.cython_decl_type()
656
'object'
657
"""
658
return 'object'
659
660
def declare_chunk_class_members(self, name):
661
r"""
662
Returns a string giving the declarations of the class members
663
in a wrapper class for a memory chunk with this storage type
664
and the given name.
665
666
EXAMPLES:
667
sage: from sage.ext.gen_interpreters import *
668
sage: ty_python.declare_chunk_class_members('args')
669
u' cdef object _list_args\n cdef int _n_args\n cdef PyObject** _args\n'
670
"""
671
return je("""
672
cdef object _list_{{ name }}
673
cdef int _n_{{ name }}
674
cdef {{ myself.cython_array_type() }} _{{ name }}
675
""", myself=self, name=name)
676
677
def alloc_chunk_data(self, name, len):
678
r"""
679
Returns a string allocating the memory for the class members for
680
a memory chunk with this storage type and the given name.
681
682
EXAMPLES:
683
sage: from sage.ext.gen_interpreters import *
684
sage: print ty_python.alloc_chunk_data('args', 'MY_LENGTH')
685
self._n_args = MY_LENGTH
686
self._list_args = PyList_New(self._n_args)
687
self._args = (<PyListObject *>self._list_args).ob_item
688
<BLANKLINE>
689
"""
690
return je("""
691
self._n_{{ name }} = {{ len }}
692
self._list_{{ name }} = PyList_New(self._n_{{ name }})
693
self._{{ name }} = (<PyListObject *>self._list_{{ name }}).ob_item
694
""", myself=self, name=name, len=len)
695
696
def dealloc_chunk_data(self, name):
697
r"""
698
Returns a string to be put in the __dealloc__ method of a
699
wrapper class using a memory chunk with this storage type, to
700
deallocate the corresponding class members.
701
702
Our array was allocated as a Python list; this means we actually
703
don't need to do anything to deallocate it.
704
705
EXAMPLES:
706
sage: from sage.ext.gen_interpreters import *
707
sage: ty_python.dealloc_chunk_data('args')
708
''
709
"""
710
return ''
711
712
def needs_cython_init_clear(self):
713
r"""
714
Says whether values/arrays of this type need to be initialized
715
before use and cleared before the underlying memory is freed.
716
717
Returns True.
718
719
EXAMPLES:
720
sage: from sage.ext.gen_interpreters import *
721
sage: ty_python.needs_cython_init_clear()
722
True
723
"""
724
return True
725
726
def assign_c_from_py(self, c, py):
727
r"""
728
Given a Cython variable/array reference/etc. of this storage type,
729
and a Python expression, generate code to assign to the Cython
730
variable from the Python expression.
731
732
EXAMPLES:
733
sage: from sage.ext.gen_interpreters import *
734
sage: ty_python.assign_c_from_py('foo[i]', 'bar[j]')
735
u'foo[i] = <PyObject *>bar[j]; Py_INCREF(foo[i])'
736
"""
737
return je("""{{ c }} = <PyObject *>{{ py }}; Py_INCREF({{ c }})""",
738
c=c, py=py)
739
740
def cython_init(self, loc):
741
r"""
742
Generates code to initialize a variable (or array reference)
743
holding a PyObject*. Sets it to NULL.
744
745
EXAMPLES:
746
sage: from sage.ext.gen_interpreters import *
747
sage: ty_python.cython_init('foo[i]')
748
u'foo[i] = NULL'
749
"""
750
return je("{{ loc }} = NULL", loc=loc)
751
752
def cython_clear(self, loc):
753
r"""
754
Generates code to clear a variable (or array reference) holding
755
a PyObject*.
756
757
EXAMPLES:
758
sage: from sage.ext.gen_interpreters import *
759
sage: ty_python.cython_clear('foo[i]')
760
u'Py_CLEAR(foo[i])'
761
"""
762
return je("Py_CLEAR({{ loc }})", loc=loc)
763
764
ty_python = StorageTypePython()
765
766
class StorageTypeAutoReference(StorageType):
767
r"""
768
StorageTypeAutoReference is a subtype of StorageType that deals with
769
types in the style of GMP/MPIR/MPFR/MPFI/FLINT, where copies are
770
not cheap, functions expect arguments to be passed by reference,
771
and the API takes advantage of the C quirk where arrays are
772
automatically converted to pointers to automatically pass
773
arguments by reference.
774
"""
775
776
def __init__(self, decl_ty, ref_ty):
777
r"""
778
Initializes the properties decl_type and ref_type (the C type
779
names used when declaring variables and function parameters,
780
respectively), as well as the properties described in
781
the documentation for StorageType.__init__.
782
783
EXAMPLES:
784
sage: from sage.ext.gen_interpreters import *
785
sage: ty_mpfr.class_member_declarations
786
'cdef RealField_class domain\n'
787
sage: ty_mpfr.class_member_initializations
788
"self.domain = args['domain']\n"
789
sage: ty_mpfr.local_declarations
790
'cdef RealNumber rn\n'
791
sage: ty_mpfr.decl_type
792
'mpfr_t'
793
sage: ty_mpfr.ref_type
794
'mpfr_ptr'
795
"""
796
StorageType.__init__(self)
797
self.decl_type = decl_ty
798
self.ref_type = ref_ty
799
800
def c_decl_type(self):
801
r"""
802
Gives the C type for a single value of this type (as a string).
803
804
EXAMPLES:
805
sage: from sage.ext.gen_interpreters import *
806
sage: ty_mpfr.c_decl_type()
807
'mpfr_t'
808
"""
809
return self.decl_type
810
811
def c_local_type(self):
812
r"""
813
Gives the C type used for a value of this type inside an
814
instruction. For assignable/cheap_copy types, this is the
815
same as c_decl_type; for auto-reference types, this is the
816
pointer type.
817
818
EXAMPLES:
819
sage: from sage.ext.gen_interpreters import *
820
sage: ty_mpfr.c_local_type()
821
'mpfr_ptr'
822
"""
823
return self.ref_type
824
825
def needs_cython_init_clear(self):
826
r"""
827
Says whether values/arrays of this type need to be initialized
828
before use and cleared before the underlying memory is freed.
829
830
All known examples of auto-reference types do need a special
831
initialization call, so this always returns True.
832
833
EXAMPLES:
834
sage: from sage.ext.gen_interpreters import *
835
sage: ty_mpfr.needs_cython_init_clear()
836
True
837
"""
838
return True
839
840
class StorageTypeMPFR(StorageTypeAutoReference):
841
r"""
842
StorageTypeMPFR is a subtype of StorageTypeAutoReference that deals
843
the MPFR's mpfr_t type.
844
845
For any given program that we're interpreting, ty_mpfr can only
846
refer to a single precision. An interpreter that needs to use
847
two precisions of mpfr_t in the same program should instantiate two
848
separate instances of StorageTypeMPFR. (Interpreters that need
849
to handle arbitrarily many precisions in the same program are not
850
handled at all.)
851
"""
852
853
def __init__(self, id=''):
854
r"""
855
Initializes the id property, as well as the properties described
856
in the documentation for StorageTypeAutoReference.__init__.
857
858
The id property is used if you want to have an interpreter
859
that handles two instances of StorageTypeMPFR (that is,
860
handles mpfr_t variables at two different precisions
861
simultaneously). It's a string that's used to generate
862
variable names that don't conflict. (The id system has
863
never actually been used, so bugs probably remain.)
864
865
EXAMPLES:
866
sage: from sage.ext.gen_interpreters import *
867
sage: ty_mpfr.class_member_declarations
868
'cdef RealField_class domain\n'
869
sage: ty_mpfr.class_member_initializations
870
"self.domain = args['domain']\n"
871
sage: ty_mpfr.local_declarations
872
'cdef RealNumber rn\n'
873
sage: ty_mpfr.decl_type
874
'mpfr_t'
875
sage: ty_mpfr.ref_type
876
'mpfr_ptr'
877
878
TESTS:
879
sage: ty_mpfr2 = StorageTypeMPFR(id='_the_second')
880
sage: ty_mpfr2.class_member_declarations
881
'cdef RealField_class domain_the_second\n'
882
sage: ty_mpfr2.class_member_initializations
883
"self.domain_the_second = args['domain_the_second']\n"
884
sage: ty_mpfr2.local_declarations
885
'cdef RealNumber rn_the_second\n'
886
"""
887
StorageTypeAutoReference.__init__(self, 'mpfr_t', 'mpfr_ptr')
888
self.id = id
889
self.class_member_declarations = "cdef RealField_class domain%s\n" % self.id
890
self.class_member_initializations = \
891
"self.domain%s = args['domain%s']\n" % (self.id, self.id)
892
self.local_declarations = "cdef RealNumber rn%s\n" % self.id
893
894
def cython_init(self, loc):
895
r"""
896
Generates code to initialize an mpfr_t reference (a variable, an
897
array reference, etc.)
898
899
EXAMPLES:
900
sage: from sage.ext.gen_interpreters import *
901
sage: ty_mpfr.cython_init('foo[i]')
902
u'mpfr_init2(foo[i], self.domain.prec())'
903
"""
904
return je("mpfr_init2({{ loc }}, self.domain{{ myself.id }}.prec())",
905
myself=self, loc=loc)
906
907
def cython_clear(self, loc):
908
r"""
909
Generates code to clear an mpfr_t reference (a variable, an
910
array reference, etc.)
911
912
EXAMPLES:
913
sage: from sage.ext.gen_interpreters import *
914
sage: ty_mpfr.cython_clear('foo[i]')
915
'mpfr_clear(foo[i])'
916
"""
917
return 'mpfr_clear(%s)' % loc
918
919
def assign_c_from_py(self, c, py):
920
r"""
921
Given a Cython variable/array reference/etc. of this storage type,
922
and a Python expression, generate code to assign to the Cython
923
variable from the Python expression.
924
925
EXAMPLES:
926
sage: from sage.ext.gen_interpreters import *
927
sage: ty_mpfr.assign_c_from_py('foo[i]', 'bar[j]')
928
u'rn = self.domain(bar[j])\nmpfr_set(foo[i], rn.value, GMP_RNDN)'
929
"""
930
return je("""
931
rn{{ myself.id }} = self.domain({{ py }})
932
mpfr_set({{ c }}, rn.value, GMP_RNDN)""", myself=self, c=c, py=py)
933
934
ty_mpfr = StorageTypeMPFR()
935
936
class MemoryChunk(object):
937
r"""
938
Memory chunks control allocation, deallocation, initialization,
939
etc. of the vectors and objects in the interpreter. Basically,
940
there is one memory chunk per argument to the C interpreter.
941
942
There are three "generic" varieties of memory chunk: "constants",
943
"arguments", and "scratch". These are named after their most
944
common use, but they could be used for other things in some
945
interpreters.
946
947
All three kinds of chunks are allocated in the wrapper class.
948
Constants are initialized when the wrapper is constructed;
949
arguments are initialized in the __call__ method, from the
950
caller's arguments. "scratch" chunks are not initialized at all;
951
they are used for scratch storage (often, but not necessarily, for
952
a stack) in the interpreter.
953
954
Interpreters which need memory chunks that don't fit into these
955
categories can create new subclasses of MemoryChunk.
956
"""
957
958
def __init__(self, name, storage_type):
959
r"""
960
Initialize an instance of MemoryChunk.
961
962
This sets the properties "name" (the name of this memory chunk;
963
used in generated variable names, etc.) and "storage_type",
964
which is a StorageType object.
965
966
EXAMPLES:
967
sage: from sage.ext.gen_interpreters import *
968
sage: mc = MemoryChunkArguments('args', ty_mpfr)
969
sage: mc.name
970
'args'
971
sage: mc.storage_type is ty_mpfr
972
True
973
"""
974
self.name = name
975
self.storage_type = storage_type
976
977
def __repr__(self):
978
r"""
979
Give a string representation of this memory chunk.
980
981
EXAMPLES:
982
sage: from sage.ext.gen_interpreters import *
983
sage: mc = MemoryChunkArguments('args', ty_mpfr)
984
sage: mc
985
{MC:args}
986
sage: mc.__repr__()
987
'{MC:args}'
988
"""
989
return '{MC:%s}' % self.name
990
991
def declare_class_members(self):
992
r"""
993
Returns a string giving the declarations of the class members
994
in a wrapper class for this memory chunk.
995
996
EXAMPLES:
997
sage: from sage.ext.gen_interpreters import *
998
sage: mc = MemoryChunkArguments('args', ty_mpfr)
999
sage: mc.declare_class_members()
1000
u' cdef int _n_args\n cdef mpfr_t* _args\n'
1001
"""
1002
return self.storage_type.declare_chunk_class_members(self.name)
1003
1004
def init_class_members(self):
1005
r"""
1006
Returns a string to be put in the __init__ method of a wrapper
1007
class using this memory chunk, to initialize the corresponding
1008
class members.
1009
1010
EXAMPLES:
1011
sage: from sage.ext.gen_interpreters import *
1012
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1013
sage: print mc.init_class_members()
1014
count = args['args']
1015
self._n_args = count
1016
self._args = <mpfr_t*>sage_malloc(sizeof(mpfr_t) * count)
1017
if self._args == NULL: raise MemoryError
1018
for i in range(count):
1019
mpfr_init2(self._args[i], self.domain.prec())
1020
<BLANKLINE>
1021
"""
1022
return ""
1023
1024
def dealloc_class_members(self):
1025
r"""
1026
Returns a string to be put in the __dealloc__ method of a wrapper
1027
class using this memory chunk, to deallocate the corresponding
1028
class members.
1029
1030
EXAMPLES:
1031
sage: from sage.ext.gen_interpreters import *
1032
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1033
sage: print mc.dealloc_class_members()
1034
if self._args:
1035
for i in range(self._n_args):
1036
mpfr_clear(self._args[i])
1037
sage_free(self._args)
1038
<BLANKLINE>
1039
"""
1040
return ""
1041
1042
def declare_parameter(self):
1043
r"""
1044
Returns the string to use to declare the interpreter parameter
1045
corresponding to this memory chunk.
1046
1047
EXAMPLES:
1048
sage: from sage.ext.gen_interpreters import *
1049
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1050
sage: mc.declare_parameter()
1051
'mpfr_t* args'
1052
"""
1053
return '%s %s' % (self.storage_type.c_ptr_type(), self.name)
1054
1055
def declare_call_locals(self):
1056
r"""
1057
Returns a string to put in the __call__ method of a wrapper
1058
class using this memory chunk, to allocate local variables.
1059
1060
EXAMPLES:
1061
sage: from sage.ext.gen_interpreters import *
1062
sage: mc = MemoryChunkRRRetval('retval', ty_mpfr)
1063
sage: mc.declare_call_locals()
1064
u' cdef RealNumber retval = (self.domain)()\n'
1065
"""
1066
return ""
1067
1068
def pass_argument(self):
1069
r"""
1070
Returns the string to pass the argument corresponding to this
1071
memory chunk to the interpreter.
1072
1073
EXAMPLES:
1074
sage: from sage.ext.gen_interpreters import *
1075
sage: mc = MemoryChunkConstants('constants', ty_mpfr)
1076
sage: mc.pass_argument()
1077
'self._constants'
1078
"""
1079
raise NotImplementedError
1080
1081
def pass_call_c_argument(self):
1082
r"""
1083
Returns the string to pass the argument corresponding to this
1084
memory chunk to the interpreter, for use in the call_c method.
1085
Almost always the same as pass_argument.
1086
1087
EXAMPLES:
1088
sage: from sage.ext.gen_interpreters import *
1089
sage: mc = MemoryChunkConstants('constants', ty_mpfr)
1090
sage: mc.pass_call_c_argument()
1091
'self._constants'
1092
"""
1093
return self.pass_argument()
1094
1095
def needs_cleanup_on_error(self):
1096
r"""
1097
In an interpreter that can terminate prematurely (due to an
1098
exception from calling Python code, or divide by zero, or
1099
whatever) it will just return at the end of the current instruction,
1100
skipping the rest of the program. Thus, it may still have
1101
values pushed on the stack, etc.
1102
1103
This method returns True if this memory chunk is modified by the
1104
interpreter and needs some sort of cleanup when an error happens.
1105
1106
EXAMPLES:
1107
sage: from sage.ext.gen_interpreters import *
1108
sage: mc = MemoryChunkConstants('constants', ty_mpfr)
1109
sage: mc.needs_cleanup_on_error()
1110
False
1111
"""
1112
return False
1113
1114
def is_stack(self):
1115
r"""
1116
Says whether this memory chunk is a stack. This affects code
1117
generation for instructions using this memory chunk.
1118
1119
It would be nicer to make this object-oriented somehow, so
1120
that the code generator called MemoryChunk methods instead of
1121
using
1122
if ch.is_stack():
1123
... hardcoded stack code
1124
else:
1125
... hardcoded non-stack code
1126
but that hasn't been done yet.
1127
1128
EXAMPLES:
1129
sage: from sage.ext.gen_interpreters import *
1130
sage: mc = MemoryChunkScratch('scratch', ty_mpfr)
1131
sage: mc.is_stack()
1132
False
1133
sage: mc = MemoryChunkScratch('stack', ty_mpfr, is_stack=True)
1134
sage: mc.is_stack()
1135
True
1136
"""
1137
return False
1138
1139
def is_python_refcounted_stack(self):
1140
r"""
1141
Says whether this memory chunk refers to a stack where the entries
1142
need to be INCREF/DECREF'ed.
1143
1144
It would be nice to make this object-oriented, so that the
1145
code generator called MemoryChunk methods to do the potential
1146
INCREF/DECREF and didn't have to explicitly test
1147
is_python_refcounted_stack.
1148
1149
EXAMPLES:
1150
sage: from sage.ext.gen_interpreters import *
1151
sage: mc = MemoryChunkScratch('args', ty_python)
1152
sage: mc.is_python_refcounted_stack()
1153
False
1154
sage: mc = MemoryChunkScratch('args', ty_python, is_stack=True)
1155
sage: mc.is_python_refcounted_stack()
1156
True
1157
sage: mc = MemoryChunkScratch('args', ty_mpfr, is_stack=True)
1158
sage: mc.is_python_refcounted_stack()
1159
False
1160
"""
1161
return self.is_stack() and self.storage_type.python_refcounted()
1162
1163
class MemoryChunkLonglivedArray(MemoryChunk):
1164
r"""
1165
MemoryChunkLonglivedArray is a subtype of MemoryChunk that deals
1166
with memory chunks that are both 1) allocated as class members (rather
1167
than being allocated in __call__) and 2) are arrays.
1168
"""
1169
1170
def init_class_members(self):
1171
r"""
1172
Returns a string to be put in the __init__ method of a wrapper
1173
class using this memory chunk, to initialize the corresponding
1174
class members.
1175
1176
EXAMPLES:
1177
sage: from sage.ext.gen_interpreters import *
1178
sage: mc = MemoryChunkArguments('args', ty_double)
1179
sage: print mc.init_class_members()
1180
count = args['args']
1181
self._n_args = count
1182
self._args = <double*>sage_malloc(sizeof(double) * count)
1183
if self._args == NULL: raise MemoryError
1184
<BLANKLINE>
1185
"""
1186
return je("""
1187
count = args['{{ myself.name }}']
1188
{% print myself.storage_type.alloc_chunk_data(myself.name, 'count') %}
1189
""", myself=self)
1190
1191
def dealloc_class_members(self):
1192
r"""
1193
Returns a string to be put in the __dealloc__ method of a wrapper
1194
class using this memory chunk, to deallocate the corresponding
1195
class members.
1196
1197
EXAMPLES:
1198
sage: from sage.ext.gen_interpreters import *
1199
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1200
sage: print mc.dealloc_class_members()
1201
if self._args:
1202
for i in range(self._n_args):
1203
mpfr_clear(self._args[i])
1204
sage_free(self._args)
1205
<BLANKLINE>
1206
"""
1207
return self.storage_type.dealloc_chunk_data(self.name)
1208
1209
def pass_argument(self):
1210
r"""
1211
Returns the string to pass the argument corresponding to this
1212
memory chunk to the interpreter.
1213
1214
EXAMPLES:
1215
sage: from sage.ext.gen_interpreters import *
1216
sage: mc = MemoryChunkConstants('constants', ty_mpfr)
1217
sage: mc.pass_argument()
1218
'self._constants'
1219
"""
1220
return 'self._%s' % self.name
1221
1222
class MemoryChunkConstants(MemoryChunkLonglivedArray):
1223
r"""
1224
MemoryChunkConstants is a subtype of MemoryChunkLonglivedArray.
1225
1226
MemoryChunkConstants chunks have their contents set in the
1227
wrapper's __init__ method (and not changed afterward).
1228
"""
1229
1230
def init_class_members(self):
1231
r"""
1232
Returns a string to be put in the __init__ method of a wrapper
1233
class using this memory chunk, to initialize the corresponding
1234
class members.
1235
1236
EXAMPLES:
1237
sage: from sage.ext.gen_interpreters import *
1238
sage: mc = MemoryChunkConstants('constants', ty_mpfr)
1239
sage: print mc.init_class_members()
1240
val = args['constants']
1241
self._n_constants = len(val)
1242
self._constants = <mpfr_t*>sage_malloc(sizeof(mpfr_t) * len(val))
1243
if self._constants == NULL: raise MemoryError
1244
for i in range(len(val)):
1245
mpfr_init2(self._constants[i], self.domain.prec())
1246
for i in range(len(val)):
1247
rn = self.domain(val[i])
1248
mpfr_set(self._constants[i], rn.value, GMP_RNDN)
1249
<BLANKLINE>
1250
"""
1251
return je("""
1252
val = args['{{ myself.name }}']
1253
{% print myself.storage_type.alloc_chunk_data(myself.name, 'len(val)') %}
1254
for i in range(len(val)):
1255
{{ myself.storage_type.assign_c_from_py('self._%s[i]' % myself.name, 'val[i]') | i(12) }}
1256
""", myself=self)
1257
1258
class MemoryChunkArguments(MemoryChunkLonglivedArray):
1259
r"""
1260
MemoryChunkArguments is a subtype of MemoryChunkLonglivedArray,
1261
for dealing with arguments to the wrapper's __call__ method.
1262
1263
Currently the __call__ method is declared to take a varargs
1264
*args argument tuple. We assume that the MemoryChunk named 'args'
1265
will deal with that tuple.
1266
"""
1267
1268
def setup_args(self):
1269
r"""
1270
Handle the arguments of __call__ -- copy them into a pre-allocated
1271
array, ready to pass to the interpreter.
1272
1273
EXAMPLES:
1274
sage: from sage.ext.gen_interpreters import *
1275
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1276
sage: print mc.setup_args()
1277
cdef mpfr_t* c_args = self._args
1278
cdef int i
1279
for i from 0 <= i < len(args):
1280
rn = self.domain(args[i])
1281
mpfr_set(self._args[i], rn.value, GMP_RNDN)
1282
<BLANKLINE>
1283
"""
1284
return je("""
1285
cdef {{ myself.storage_type.c_ptr_type() }} c_args = self._args
1286
cdef int i
1287
for i from 0 <= i < len(args):
1288
{{ myself.storage_type.assign_c_from_py('self._args[i]', 'args[i]') | i(4) }}
1289
""", myself=self)
1290
1291
def pass_argument(self):
1292
r"""
1293
Returns the string to pass the argument corresponding to this
1294
memory chunk to the interpreter.
1295
1296
EXAMPLES:
1297
sage: from sage.ext.gen_interpreters import *
1298
sage: mc = MemoryChunkArguments('args', ty_mpfr)
1299
sage: mc.pass_argument()
1300
'c_args'
1301
"""
1302
return 'c_args'
1303
1304
class MemoryChunkScratch(MemoryChunkLonglivedArray):
1305
r"""
1306
MemoryChunkScratch is a subtype of MemoryChunkLonglivedArray
1307
for dealing with memory chunks that are allocated in the wrapper,
1308
but only used in the interpreter -- stacks, scratch registers, etc.
1309
1310
(Currently these are only used as stacks.)
1311
"""
1312
1313
def __init__(self, name, storage_type, is_stack=False):
1314
r"""
1315
Initialize an instance of MemoryChunkScratch.
1316
1317
Initializes the _is_stack property, as well as
1318
the properties described in the documentation for
1319
MemoryChunk.__init__.
1320
1321
EXAMPLES:
1322
sage: from sage.ext.gen_interpreters import *
1323
sage: mc = MemoryChunkScratch('stack', ty_double, is_stack=True)
1324
sage: mc.name
1325
'stack'
1326
sage: mc.storage_type is ty_double
1327
True
1328
sage: mc._is_stack
1329
True
1330
"""
1331
MemoryChunkLonglivedArray.__init__(self, name, storage_type)
1332
self._is_stack = is_stack
1333
1334
def is_stack(self):
1335
r"""
1336
Says whether this memory chunk is a stack. This affects code
1337
generation for instructions using this memory chunk.
1338
1339
EXAMPLES:
1340
sage: from sage.ext.gen_interpreters import *
1341
sage: mc = MemoryChunkScratch('stack', ty_mpfr, is_stack=True)
1342
sage: mc.is_stack()
1343
True
1344
"""
1345
return self._is_stack
1346
1347
def needs_cleanup_on_error(self):
1348
r"""
1349
In an interpreter that can terminate prematurely (due to an
1350
exception from calling Python code, or divide by zero, or
1351
whatever) it will just return at the end of the current instruction,
1352
skipping the rest of the program. Thus, it may still have
1353
values pushed on the stack, etc.
1354
1355
This method returns True if this memory chunk is modified by the
1356
interpreter and needs some sort of cleanup when an error happens.
1357
1358
EXAMPLES:
1359
sage: from sage.ext.gen_interpreters import *
1360
sage: mc = MemoryChunkScratch('registers', ty_python)
1361
sage: mc.needs_cleanup_on_error()
1362
True
1363
"""
1364
return self.storage_type.python_refcounted()
1365
1366
def handle_cleanup(self):
1367
r"""
1368
Handle the cleanup if the interpreter exits with an error.
1369
1370
For scratch/stack chunks that hold Python-refcounted values,
1371
we assume that they are filled with NULL on every entry to the
1372
interpreter. If the interpreter exited with an error, it may
1373
have left values in the chunk, so we need to go through
1374
the chunk and Py_CLEAR it.
1375
1376
EXAMPLES:
1377
sage: from sage.ext.gen_interpreters import *
1378
sage: mc = MemoryChunkScratch('registers', ty_python)
1379
sage: print mc.handle_cleanup()
1380
for i in range(self._n_registers):
1381
Py_CLEAR(self._registers[i])
1382
<BLANKLINE>
1383
"""
1384
# XXX This is a lot slower than it needs to be, because
1385
# we don't have a "cdef int i" in scope here.
1386
return je("""
1387
for i in range(self._n_{{ myself.name }}):
1388
Py_CLEAR(self._{{ myself.name }}[i])
1389
""", myself=self)
1390
1391
class MemoryChunkRRRetval(MemoryChunk):
1392
r"""
1393
A special-purpose memory chunk, for dealing with the return value
1394
of the RR-based interpreter.
1395
"""
1396
1397
def declare_class_members(self):
1398
r"""
1399
Returns a string giving the declarations of the class members
1400
in a wrapper class for this memory chunk.
1401
1402
EXAMPLES:
1403
sage: from sage.ext.gen_interpreters import *
1404
sage: mc = MemoryChunkRRRetval('retval', ty_mpfr)
1405
sage: mc.declare_class_members()
1406
''
1407
"""
1408
return ""
1409
1410
def declare_call_locals(self):
1411
r"""
1412
Returns a string to put in the __call__ method of a wrapper
1413
class using this memory chunk, to allocate local variables.
1414
1415
EXAMPLES:
1416
sage: from sage.ext.gen_interpreters import *
1417
sage: mc = MemoryChunkRRRetval('retval', ty_mpfr)
1418
sage: mc.declare_call_locals()
1419
u' cdef RealNumber retval = (self.domain)()\n'
1420
"""
1421
return je("""
1422
cdef RealNumber {{ myself.name }} = (self.domain)()
1423
""", myself=self)
1424
1425
def pass_argument(self):
1426
r"""
1427
Returns the string to pass the argument corresponding to this
1428
memory chunk to the interpreter.
1429
1430
EXAMPLES:
1431
sage: from sage.ext.gen_interpreters import *
1432
sage: mc = MemoryChunkRRRetval('retval', ty_mpfr)
1433
sage: mc.pass_argument()
1434
u'&retval.value'
1435
"""
1436
return je("""&{{ myself.name }}.value""", myself=self)
1437
1438
def pass_call_c_argument(self):
1439
r"""
1440
Returns the string to pass the argument corresponding to this
1441
memory chunk to the interpreter, for use in the call_c method.
1442
1443
EXAMPLES:
1444
sage: from sage.ext.gen_interpreters import *
1445
sage: mc = MemoryChunkRRRetval('retval', ty_mpfr)
1446
sage: mc.pass_call_c_argument()
1447
'result'
1448
"""
1449
return "result"
1450
1451
class MemoryChunkPythonArguments(MemoryChunk):
1452
r"""
1453
A special-purpose memory chunk, for the generic Python-object based
1454
interpreter. Rather than copy the arguments into an array allocated
1455
in the wrapper, we use the PyTupleObject internals and pass the array
1456
that's inside the argument tuple.
1457
"""
1458
1459
def declare_class_members(self):
1460
r"""
1461
Returns a string giving the declarations of the class members
1462
in a wrapper class for this memory chunk.
1463
1464
EXAMPLES:
1465
sage: from sage.ext.gen_interpreters import *
1466
sage: mc = MemoryChunkPythonArguments('args', ty_python)
1467
"""
1468
return " cdef int _n_%s\n" % self.name
1469
1470
def init_class_members(self):
1471
r"""
1472
Returns a string to be put in the __init__ method of a wrapper
1473
class using this memory chunk, to initialize the corresponding
1474
class members.
1475
1476
EXAMPLES:
1477
sage: from sage.ext.gen_interpreters import *
1478
sage: mc = MemoryChunkPythonArguments('args', ty_python)
1479
sage: mc.init_class_members()
1480
u" count = args['args']\n self._n_args = count\n"
1481
"""
1482
return je("""
1483
count = args['{{ myself.name }}']
1484
self._n_args = count
1485
""", myself=self)
1486
1487
def setup_args(self):
1488
r"""
1489
Handle the arguments of __call__. Nothing to do.
1490
1491
EXAMPLES:
1492
sage: from sage.ext.gen_interpreters import *
1493
sage: mc = MemoryChunkPythonArguments('args', ty_python)
1494
sage: mc.setup_args()
1495
''
1496
"""
1497
return ''
1498
1499
def pass_argument(self):
1500
r"""
1501
Pass the innards of the argument tuple to the interpreter.
1502
1503
EXAMPLES:
1504
sage: from sage.ext.gen_interpreters import *
1505
sage: mc = MemoryChunkPythonArguments('args', ty_python)
1506
sage: mc.pass_argument()
1507
'(<PyTupleObject*>args).ob_item'
1508
"""
1509
return "(<PyTupleObject*>args).ob_item"
1510
1511
class MemoryChunkElementArguments(MemoryChunkPythonArguments):
1512
r"""
1513
A special-purpose memory chunk, for the Python-object based
1514
interpreters that want to process (and perhaps modify) the data.
1515
1516
We allocate a new list (via the map function) on every call to
1517
hold the modified arguments. That's not strictly necessary --
1518
we could pre-allocate a list and map into it -- but this lets us
1519
use simpler code for a very-likely-negligible efficiency cost.
1520
(The Element interpreter is going to allocate lots of objects
1521
as it runs, anyway.)
1522
"""
1523
1524
def setup_args(self):
1525
r"""
1526
Handle the arguments of __call__. Note: This hardcodes
1527
"self._domain".
1528
1529
EXAMPLES:
1530
sage: from sage.ext.gen_interpreters import *
1531
sage: mc = MemoryChunkElementArguments('args', ty_python)
1532
sage: mc.setup_args()
1533
'mapped_args = map(self._domain, args)\n'
1534
"""
1535
return "mapped_args = map(self._domain, args)\n"
1536
1537
def pass_argument(self):
1538
r"""
1539
Pass the innards of the argument tuple to the interpreter.
1540
1541
EXAMPLES:
1542
sage: from sage.ext.gen_interpreters import *
1543
sage: mc = MemoryChunkElementArguments('args', ty_python)
1544
sage: mc.pass_argument()
1545
'(<PyListObject*>mapped_args).ob_item'
1546
"""
1547
return "(<PyListObject*>mapped_args).ob_item"
1548
1549
class MemoryChunkPyConstant(MemoryChunk):
1550
r"""
1551
A special-purpose memory chunk, for holding a single Python constant
1552
and passing it to the interpreter as a PyObject*.
1553
"""
1554
1555
def __init__(self, name):
1556
r"""
1557
Initialize an instance of MemoryChunkPyConstant.
1558
1559
Always uses the type ty_python.
1560
1561
EXAMPLES:
1562
sage: from sage.ext.gen_interpreters import *
1563
sage: mc = MemoryChunkPyConstant('domain')
1564
sage: mc.name
1565
'domain'
1566
sage: mc.storage_type is ty_python
1567
True
1568
"""
1569
MemoryChunk.__init__(self, name, ty_python)
1570
1571
def declare_class_members(self):
1572
r"""
1573
Returns a string giving the declarations of the class members
1574
in a wrapper class for this memory chunk.
1575
1576
EXAMPLES:
1577
sage: from sage.ext.gen_interpreters import *
1578
sage: mc = MemoryChunkPyConstant('domain')
1579
sage: mc.declare_class_members()
1580
u' cdef object _domain\n'
1581
"""
1582
return je("""
1583
cdef object _{{ myself.name }}
1584
""", myself=self)
1585
1586
def init_class_members(self):
1587
r"""
1588
Returns a string to be put in the __init__ method of a wrapper
1589
class using this memory chunk, to initialize the corresponding
1590
class members.
1591
1592
EXAMPLES:
1593
sage: from sage.ext.gen_interpreters import *
1594
sage: mc = MemoryChunkPyConstant('domain')
1595
sage: mc.init_class_members()
1596
u" self._domain = args['domain']\n"
1597
"""
1598
return je("""
1599
self._{{ myself.name }} = args['{{ myself.name }}']
1600
""", myself=self)
1601
1602
def declare_parameter(self):
1603
r"""
1604
Returns the string to use to declare the interpreter parameter
1605
corresponding to this memory chunk.
1606
1607
EXAMPLES:
1608
sage: from sage.ext.gen_interpreters import *
1609
sage: mc = MemoryChunkPyConstant('domain')
1610
sage: mc.declare_parameter()
1611
'PyObject* domain'
1612
"""
1613
return 'PyObject* %s' % self.name
1614
1615
def pass_argument(self):
1616
r"""
1617
Returns the string to pass the argument corresponding to this
1618
memory chunk to the interpreter.
1619
1620
EXAMPLES:
1621
sage: from sage.ext.gen_interpreters import *
1622
sage: mc = MemoryChunkPyConstant('domain')
1623
sage: mc.pass_argument()
1624
'<PyObject*>self._domain'
1625
"""
1626
return '<PyObject*>self._%s' % self.name
1627
1628
def params_gen(**chunks):
1629
r"""
1630
Instructions have a parameter specification that says where they get
1631
their inputs and where their outputs go. Each parameter has
1632
the same form: it is a triple (chunk, addr, len). The chunk says
1633
where the parameter is read from/written to. The addr says which
1634
value in the chunk is used. If the chunk is a stack chunk, then
1635
addr must be null; the value will be read from/written to the top
1636
of the stack. Otherwise, addr must be an integer, or another chunk;
1637
if addr is another chunk, then the next value is read from that chunk
1638
to be the address.
1639
1640
The len says how many values to read/write. It can be either None
1641
(meaning to read/write only a single value), an integer, or
1642
another chunk; if it is a chunk, then the next value is read from that
1643
chunk to be the len. Note that specifying len changes the types
1644
given to the instruction, so len==None is different than len==1 even
1645
though both mean to use a single value.
1646
1647
These parameter specifications are cumbersome to write by hand, so
1648
there's also a simple string format for them. This (curried)
1649
function parses the simple string format and produces parameter
1650
specifications. The params_gen function takes keyword arguments
1651
mapping single-character names to memory chunks. The string format
1652
uses these names. The params_gen function returns another function,
1653
that takes two strings and returns a pair of lists of parameter
1654
specifications.
1655
1656
Each string is the concatenation of arbitrarily many specifications.
1657
Each specification consists of an address and a length. The
1658
address is either a single character naming a stack chunk,
1659
or a string of the form 'A[B]' where A names a non-stack chunk
1660
and B names the code chunk. The length is either empty, or '@n'
1661
for a number n (meaning to use that many arguments), or '@C', where
1662
C is the code chunk.
1663
1664
EXAMPLES:
1665
sage: from sage.ext.gen_interpreters import *
1666
sage: mc_stack = MemoryChunkScratch('stack', ty_double, is_stack=True)
1667
sage: mc_args = MemoryChunkArguments('args', ty_double)
1668
sage: mc_code = MemoryChunkConstants('code', ty_int)
1669
1670
sage: pg = params_gen(D=mc_code, A=mc_args, S=mc_stack)
1671
sage: pg('S', '')
1672
([({MC:stack}, None, None)], [])
1673
sage: pg('A[D]', '')
1674
([({MC:args}, {MC:code}, None)], [])
1675
sage: pg('S@5', '')
1676
([({MC:stack}, None, 5)], [])
1677
sage: pg('S@D', '')
1678
([({MC:stack}, None, {MC:code})], [])
1679
sage: pg('A[D]@D', '')
1680
([({MC:args}, {MC:code}, {MC:code})], [])
1681
sage: pg('SSS@D', 'A[D]S@D')
1682
([({MC:stack}, None, None), ({MC:stack}, None, None), ({MC:stack}, None, {MC:code})], [({MC:args}, {MC:code}, None), ({MC:stack}, None, {MC:code})])
1683
"""
1684
1685
def make_params(s):
1686
p = []
1687
s = s.strip()
1688
while s:
1689
chunk_code = s[0]
1690
s = s[1:]
1691
chunk = chunks[chunk_code]
1692
addr = None
1693
ch_len = None
1694
# shouldn't hardcode 'code' here
1695
if chunk.is_stack() or chunk.name == 'code':
1696
pass
1697
else:
1698
m = re.match(r'\[(?:([0-9]+)|([a-zA-Z]))\]', s)
1699
if m.group(1):
1700
addr = int(m.group(1))
1701
else:
1702
ch = chunks[m.group(2)]
1703
assert ch.storage_type is ty_int
1704
addr = ch
1705
s = s[m.end():].strip()
1706
if len(s) and s[0] == '@':
1707
m = re.match(r'@(?:([0-9]+)|([a-zA-Z]))', s)
1708
if m.group(1):
1709
ch_len = int(m.group(1))
1710
else:
1711
ch = chunks[m.group(2)]
1712
assert ch.storage_type is ty_int
1713
ch_len = ch
1714
s = s[m.end():].strip()
1715
p.append((chunk, addr, ch_len))
1716
return p
1717
1718
def params(s_ins, s_outs):
1719
ins = make_params(s_ins)
1720
outs = make_params(s_outs)
1721
return (ins, outs)
1722
1723
return params
1724
1725
def string_of_addr(a):
1726
r"""
1727
An address or a length from a parameter specification may be
1728
either None, an integer, or a MemoryChunk. If the address or
1729
length is an integer or a MemoryChunk, this function will convert
1730
it to a string giving an expression that will evaluate to the correct
1731
address or length. (See the docstring for params_gen for more
1732
information on parameter specifications.)
1733
1734
EXAMPLES:
1735
sage: from sage.ext.gen_interpreters import *
1736
sage: mc_code = MemoryChunkConstants('code', ty_int)
1737
sage: string_of_addr(mc_code)
1738
'*code++'
1739
sage: string_of_addr(42r)
1740
'42'
1741
"""
1742
if isinstance(a, (int, long)):
1743
return str(a)
1744
assert(isinstance(a, MemoryChunk))
1745
return '*%s++' % a.name
1746
1747
class InstrSpec(object):
1748
r"""
1749
Each instruction in an interpreter is represented as an InstrSpec.
1750
This contains all the information that we need to generate code
1751
to interpret the instruction; it also is used to build the tables
1752
that fast_callable uses, so this is the nexus point between
1753
users of the interpreter (possibly pure Python) and the
1754
generated C interpreter.
1755
1756
The underlying instructions are matched to the caller by name.
1757
For instance, fast_callable assumes that if the interpreter has an
1758
instruction named 'cos', then it will take a single argument,
1759
return a single result, and implement the cos() function.
1760
1761
The print representation of an instruction (which will probably
1762
only be used when doctesting this file) consists of the name,
1763
a simplified stack effect, and the code (truncated if it's long).
1764
The stack effect has two parts, the input and the output, separated
1765
by '->'; the input shows what will be popped from the stack,
1766
the output what will be placed on the stack. Each consists of
1767
a sequence of 'S' and '*' characters, where 'S' refers to a single
1768
argument and '*' refers to a variable number of arguments.
1769
1770
The code for an instruction is a small snippet of C code. It has
1771
available variables 'i0', 'i1', ..., 'o0', 'o1', ...; one variable
1772
for each input and output; its job is to assign values to the output
1773
variables, based on the values of the input variables.
1774
1775
Normally, in an interpreter that uses doubles, each of the input
1776
and output variables will be a double. If i0 actually represents
1777
a variable number of arguments, then it will be a pointer to
1778
double instead, and there will be another variable n_i0 giving
1779
the actual number of arguments.
1780
1781
When instructions refer to auto-reference types, they actually
1782
get a pointer to the data in its original location; it is
1783
not copied into a local variable. Mostly, this makes no difference,
1784
but there is one potential problem to be aware of. It is possible
1785
for an output variable to point to the same object as an input
1786
variable; in fact, this usually will happen when you're working
1787
with the stack. If the instruction maps to a single function call,
1788
then this is fine; the standard auto-reference implementations
1789
(GMP, MPFR, etc.) are careful to allow having the input and output
1790
be the same. But if the instruction maps to multiple function
1791
calls, you may need to use a temporary variable.
1792
1793
Here's an example of this issue. Suppose you want to make an
1794
instruction that does ``out = a+b*c``. You write code like this:
1795
out = b*c
1796
out = a+out
1797
But out will actually share the same storage as a; so the first line
1798
modifies a, and you actually end up computing 2*(b+c). The fix
1799
is to only write to the output once, at the very end of your
1800
instruction.
1801
1802
Instructions are also allowed to access memory chunks (other than
1803
the stack and code) directly. They are available as C variables
1804
with the same name as the chunk. This is useful if some type of
1805
memory chunk doesn't fit well with the params_gen interface.
1806
1807
There are additional reference-counting rules that must be
1808
followed if your interpreter operates on Python objects; these
1809
rules are described in the docstring of the PythonInterpreter
1810
class.
1811
1812
EXAMPLES:
1813
sage: from sage.ext.gen_interpreters import *
1814
sage: pg = RDFInterpreter().pg
1815
sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;')
1816
add: SS->S = 'o0 = i0+i1;'
1817
"""
1818
1819
def __init__(self, name, io, code=None, uses_error_handler=False, handles_own_decref=False):
1820
r"""
1821
Initialize an InstrSpec.
1822
1823
INPUTS:
1824
name -- the name of the instruction
1825
io -- a pair of lists of parameter specifications for I/O of the
1826
instruction
1827
code -- a string containing a snippet of C code to read
1828
from the input variables and write to the output variables
1829
uses_error_handler -- True if the instruction calls Python
1830
and jumps to error: on a Python error
1831
handles_own_decref -- True if the instruction handles Python
1832
objects and includes its own
1833
reference-counting
1834
1835
EXAMPLES:
1836
sage: from sage.ext.gen_interpreters import *
1837
1838
sage: pg = RDFInterpreter().pg
1839
sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;')
1840
add: SS->S = 'o0 = i0+i1;'
1841
sage: instr = InstrSpec('py_call', pg('P[D]S@D', 'S'), code=('This is very complicated. ' + 'blah ' * 30)); instr
1842
py_call: *->S = 'This is very compli... blah blah blah '
1843
sage: instr.name
1844
'py_call'
1845
sage: instr.inputs
1846
[({MC:py_constants}, {MC:code}, None), ({MC:stack}, None, {MC:code})]
1847
sage: instr.outputs
1848
[({MC:stack}, None, None)]
1849
sage: instr.code
1850
'This is very complicated. blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah '
1851
sage: instr.parameters
1852
['py_constants', 'n_inputs']
1853
sage: instr.n_inputs
1854
0
1855
sage: instr.n_outputs
1856
1
1857
"""
1858
self.name = name
1859
self.inputs = io[0]
1860
self.outputs = io[1]
1861
self.uses_error_handler = uses_error_handler
1862
self.handles_own_decref = handles_own_decref
1863
if code is not None:
1864
self.code = code
1865
# XXX We assume that there is only one stack
1866
n_inputs = 0
1867
n_outputs = 0
1868
in_effect = ''
1869
out_effect = ''
1870
p = []
1871
for (ch, addr, len) in self.inputs:
1872
if ch.is_stack():
1873
if len is None:
1874
n_inputs += 1
1875
in_effect += 'S'
1876
elif isinstance(len, (int, long)):
1877
n_inputs += len
1878
in_effect += 'S%d' % len
1879
else:
1880
p.append('n_inputs')
1881
in_effect += '*'
1882
else:
1883
p.append(ch.name)
1884
for (ch, addr, len) in self.outputs:
1885
if ch.is_stack():
1886
if len is None:
1887
n_outputs += 1
1888
out_effect += 'S'
1889
elif isinstance(len, (int, long)):
1890
n_outputs += len
1891
out_effect += 'S%d' % len
1892
else:
1893
p.append('n_outputs')
1894
out_effect += '*'
1895
else:
1896
p.append(ch.name)
1897
self.parameters = p
1898
self.n_inputs = n_inputs
1899
self.n_outputs = n_outputs
1900
self.in_effect = in_effect
1901
self.out_effect = out_effect
1902
1903
def __repr__(self):
1904
r"""
1905
Produce a string representing a given instruction, consisting
1906
of its name, a brief stack specification, and its code
1907
(possibly abbreviated).
1908
1909
EXAMPLES:
1910
sage: from sage.ext.gen_interpreters import *
1911
sage: pg = RDFInterpreter().pg
1912
sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;')
1913
add: SS->S = 'o0 = i0+i1;'
1914
"""
1915
rcode = repr(self.code)
1916
if len(rcode) > 40:
1917
rcode = rcode[:20] + '...' + rcode[-17:]
1918
return '%s: %s->%s = %s' % \
1919
(self.name, self.in_effect, self.out_effect, rcode)
1920
1921
# Now we have a series of helper functions that make it slightly easier
1922
# to create instructions.
1923
1924
def instr_infix(name, io, op):
1925
r"""
1926
A helper function for creating instructions implemented by
1927
a single infix binary operator.
1928
1929
EXAMPLES:
1930
sage: from sage.ext.gen_interpreters import *
1931
sage: pg = RDFInterpreter().pg
1932
sage: instr_infix('mul', pg('SS', 'S'), '*')
1933
mul: SS->S = 'o0 = i0 * i1;'
1934
"""
1935
return InstrSpec(name, io, code='o0 = i0 %s i1;' % op)
1936
1937
def instr_funcall_2args(name, io, op):
1938
r"""
1939
A helper function for creating instructions implemented by
1940
a two-argument function call.
1941
1942
EXAMPLES:
1943
sage: from sage.ext.gen_interpreters import *
1944
sage: pg = RDFInterpreter().pg
1945
sage: instr_funcall_2args('atan2', pg('SS', 'S'), 'atan2')
1946
atan2: SS->S = 'o0 = atan2(i0, i1);'
1947
"""
1948
return InstrSpec(name, io, code='o0 = %s(i0, i1);' % op)
1949
1950
def instr_unary(name, io, op):
1951
r"""
1952
A helper function for creating instructions with one input
1953
and one output.
1954
1955
EXAMPLES:
1956
sage: from sage.ext.gen_interpreters import *
1957
sage: pg = RDFInterpreter().pg
1958
sage: instr_unary('sin', pg('S','S'), 'sin(i0)')
1959
sin: S->S = 'o0 = sin(i0);'
1960
sage: instr_unary('neg', pg('S','S'), '-i0')
1961
neg: S->S = 'o0 = -i0;'
1962
"""
1963
return InstrSpec(name, io, code='o0 = ' + op + ';')
1964
1965
def instr_funcall_2args_mpfr(name, io, op):
1966
r"""
1967
A helper function for creating MPFR instructions with two inputs
1968
and one output.
1969
1970
EXAMPLES:
1971
sage: from sage.ext.gen_interpreters import *
1972
sage: pg = RRInterpreter().pg
1973
sage: instr_funcall_2args_mpfr('add', pg('SS','S'), 'mpfr_add')
1974
add: SS->S = 'mpfr_add(o0, i0, i1, GMP_RNDN);'
1975
"""
1976
return InstrSpec(name, io, code='%s(o0, i0, i1, GMP_RNDN);' % op)
1977
1978
def instr_funcall_1arg_mpfr(name, io, op):
1979
r"""
1980
A helper function for creating MPFR instructions with one input
1981
and one output.
1982
1983
EXAMPLES:
1984
sage: from sage.ext.gen_interpreters import *
1985
sage: pg = RRInterpreter().pg
1986
sage: instr_funcall_1arg_mpfr('exp', pg('S','S'), 'mpfr_exp')
1987
exp: S->S = 'mpfr_exp(o0, i0, GMP_RNDN);'
1988
"""
1989
return InstrSpec(name, io, code='%s(o0, i0, GMP_RNDN);' % op)
1990
1991
class InterpreterSpec(object):
1992
r"""
1993
Each interpreter to be generated by this module is represented
1994
by an InterpreterSpec.
1995
"""
1996
1997
def __init__(self):
1998
r"""
1999
Initialize an InterpreterSpec.
2000
2001
Initializes the following fields:
2002
2003
header -- a code snippet to go at the top of the C interpreter
2004
source file
2005
pxd_header -- a code snippet to go at the top of the wrapper
2006
class .pxd file
2007
pyx_header -- a code snippet to go at the top of the wrapper
2008
class source file
2009
err_return -- a string indicating the value to be returned
2010
in case of a Python exception
2011
mc_code -- a memory chunk to use for the interpreted code
2012
extra_class_members -- Class members for the wrapper that
2013
don't correspond to memory chunks
2014
extra_members_initialize -- Code to initialize extra_class_members
2015
2016
EXAMPLES:
2017
sage: from sage.ext.gen_interpreters import *
2018
sage: interp = RDFInterpreter()
2019
sage: interp.header
2020
'\n#include <gsl/gsl_math.h>\n'
2021
sage: interp.pxd_header
2022
''
2023
sage: interp.pyx_header
2024
''
2025
sage: interp.err_return
2026
'-1094648009105371'
2027
sage: interp.mc_code
2028
{MC:code}
2029
sage: interp = RRInterpreter()
2030
sage: interp.extra_class_members
2031
''
2032
sage: interp.extra_members_initialize
2033
''
2034
"""
2035
self.header = ''
2036
self.pxd_header = ''
2037
self.pyx_header = ''
2038
self.err_return = 'NULL'
2039
self.mc_code = MemoryChunkConstants('code', ty_int)
2040
self.extra_class_members = ''
2041
self.extra_members_initialize = ''
2042
2043
def _set_opcodes(self):
2044
r"""
2045
Assign opcodes to the instructions in this interpreter.
2046
2047
Must be called at the end of __init__ by any subclass of
2048
InterpreterSpec.
2049
2050
EXAMPLES:
2051
sage: from sage.ext.gen_interpreters import *
2052
sage: interp = RDFInterpreter()
2053
sage: interp.instr_descs[5].opcode
2054
5
2055
"""
2056
for i in range(len(self.instr_descs)):
2057
self.instr_descs[i].opcode = i
2058
2059
2060
class StackInterpreter(InterpreterSpec):
2061
r"""
2062
A subclass of InterpreterSpec, specialized for stack-based
2063
interpreters. (Currently all interpreters are stack-based.)
2064
"""
2065
2066
def __init__(self, type, mc_retval=None):
2067
r"""
2068
Initialize a StackInterpreter.
2069
2070
INPUTS:
2071
type -- A StorageType; the basic type that this interpreter
2072
operates on
2073
mc_retval -- default None; if not None, a special-purpose
2074
MemoryChunk to use as a return value
2075
2076
Initializes the fields described in the documentation for
2077
InterpreterSpec.__init__, as well as the following:
2078
2079
mc_args, mc_constants, mc_stack -- MemoryChunk values
2080
return_type -- the type returned by the C interpreter (None for int,
2081
where 1 means success and 0 means error)
2082
mc_retval -- None, or the MemoryChunk to use as a return value
2083
ipow_range -- the range of exponents supported by the ipow
2084
instruction (default is False, meaning never use ipow)
2085
adjust_retval -- None, or a string naming a function to call
2086
in the wrapper's __call__ to modify the return
2087
value of the interpreter
2088
implement_call_c -- True if the wrapper should have a fast cdef call_c
2089
method (that bypasses the Python call overhead)
2090
(default True)
2091
2092
EXAMPLES:
2093
sage: from sage.ext.gen_interpreters import *
2094
sage: rdf = RDFInterpreter()
2095
sage: rr = RRInterpreter()
2096
sage: el = ElementInterpreter()
2097
sage: rdf.mc_args
2098
{MC:args}
2099
sage: rdf.mc_constants
2100
{MC:constants}
2101
sage: rdf.mc_stack
2102
{MC:stack}
2103
sage: rr.mc_retval
2104
{MC:retval}
2105
sage: rr.return_type is None
2106
True
2107
sage: rdf.return_type.type
2108
'double'
2109
sage: rdf.implement_call_c
2110
True
2111
sage: el.implement_call_c
2112
False
2113
"""
2114
InterpreterSpec.__init__(self)
2115
self.mc_args = MemoryChunkArguments('args', type)
2116
self.mc_constants = MemoryChunkConstants('constants', type)
2117
self.mc_stack = MemoryChunkScratch('stack', type, is_stack=True)
2118
if isinstance(type, StorageTypeAssignable):
2119
self.return_type = type
2120
else:
2121
self.return_type = None
2122
self.mc_retval = mc_retval
2123
self.ipow_range = False
2124
self.adjust_retval = None
2125
self.implement_call_c = True
2126
2127
class RDFInterpreter(StackInterpreter):
2128
r"""
2129
A subclass of StackInterpreter, specifying an interpreter over
2130
machine-floating-point values (C doubles). This is used for
2131
both domain=RDF and domain=float; currently the only difference
2132
between the two is the type of the value returned from the
2133
wrapper (they use the same wrapper and interpreter).
2134
"""
2135
2136
def __init__(self):
2137
r"""
2138
Initialize an RDFInterpreter.
2139
2140
EXAMPLES:
2141
sage: from sage.ext.gen_interpreters import *
2142
sage: interp = RDFInterpreter()
2143
sage: interp.name
2144
'rdf'
2145
sage: interp.extra_class_members
2146
'cdef object _domain\n'
2147
sage: interp.extra_members_initialize
2148
"self._domain = args['domain']\n"
2149
sage: interp.adjust_retval
2150
'self._domain'
2151
sage: interp.mc_py_constants
2152
{MC:py_constants}
2153
sage: interp.chunks
2154
[{MC:args}, {MC:constants}, {MC:py_constants}, {MC:stack}, {MC:code}]
2155
sage: interp.pg('A[D]', 'S')
2156
([({MC:args}, {MC:code}, None)], [({MC:stack}, None, None)])
2157
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2158
sage: instrs['add']
2159
add: SS->S = 'o0 = i0 + i1;'
2160
sage: instrs['py_call']
2161
py_call: *->S = ' \nPyObject *py_arg...goto error;\n}\n'
2162
2163
Make sure that pow behaves reasonably::
2164
2165
sage: var('x,y')
2166
(x, y)
2167
sage: ff = fast_callable(x^y, vars=[x,y], domain=RDF)
2168
sage: ff(1.5, 3)
2169
3.375
2170
sage: ff(-2, 3)
2171
-8.0
2172
sage: ff(-2, 1/3)
2173
Traceback (most recent call last):
2174
...
2175
ValueError: negative number to a fractional power not real
2176
"""
2177
2178
StackInterpreter.__init__(self, ty_double)
2179
self.name = 'rdf'
2180
self.mc_py_constants = MemoryChunkConstants('py_constants', ty_python)
2181
# This is a randomly chosen number. Whenever this number is
2182
# returned, the wrapper has to check whether an exception actually
2183
# happened, so if an expression evaluates to this number execution
2184
# is slightly slower. Hopefully that won't happen too often :)
2185
self.err_return = '-1094648009105371'
2186
self.chunks = [self.mc_args, self.mc_constants, self.mc_py_constants,
2187
self.mc_stack,
2188
self.mc_code]
2189
pg = params_gen(A=self.mc_args, C=self.mc_constants, D=self.mc_code,
2190
S=self.mc_stack, P=self.mc_py_constants)
2191
self.pg = pg
2192
self.header = """
2193
#include <gsl/gsl_math.h>
2194
"""
2195
instrs = [
2196
InstrSpec('load_arg', pg('A[D]', 'S'),
2197
code='o0 = i0;'),
2198
InstrSpec('load_const', pg('C[D]', 'S'),
2199
code='o0 = i0;'),
2200
InstrSpec('return', pg('S', ''),
2201
code='return i0;'),
2202
InstrSpec('py_call', pg('P[D]S@D', 'S'),
2203
uses_error_handler=True,
2204
code="""
2205
PyObject *py_args = PyTuple_New(n_i1);
2206
if (py_args == NULL) goto error;
2207
int i;
2208
for (i = 0; i < n_i1; i++) {
2209
PyObject *arg = PyFloat_FromDouble(i1[i]);
2210
if (arg == NULL) {
2211
Py_DECREF(py_args);
2212
goto error;
2213
}
2214
PyTuple_SET_ITEM(py_args, i, arg);
2215
}
2216
PyObject *result = PyObject_CallObject(i0, py_args);
2217
Py_DECREF(py_args);
2218
if (result == NULL) goto error;
2219
/* If result is not a float, then this will turn it into a float first. */
2220
o0 = PyFloat_AsDouble(result);
2221
Py_DECREF(result);
2222
if (o0 == -1 && PyErr_Occurred()) {
2223
goto error;
2224
}
2225
"""),
2226
InstrSpec('pow', pg('SS', 'S'),
2227
uses_error_handler=True,
2228
code="""
2229
/* See python's pow in floatobject.c */
2230
if (i0 == 0) o0 = 1.0;
2231
else {
2232
if (i0 < 0 && i1 != floor(i1)) {
2233
PyErr_SetString(PyExc_ValueError, "negative number to a fractional power not real");
2234
goto error;
2235
}
2236
o0 = pow(i0, i1);
2237
}
2238
""")
2239
]
2240
for (name, op) in [('add', '+'), ('sub', '-'),
2241
('mul', '*'), ('div', '/')]:
2242
instrs.append(instr_infix(name, pg('SS', 'S'), op))
2243
instrs.append(instr_funcall_2args('ipow', pg('SD', 'S'), 'gsl_pow_int'))
2244
for (name, op) in [('neg', '-i0'), ('invert', '1/i0'),
2245
('abs', 'fabs(i0)')]:
2246
instrs.append(instr_unary(name, pg('S', 'S'), op))
2247
for name in ['sqrt', 'ceil', 'floor', 'sin', 'cos', 'tan',
2248
'asin', 'acos', 'atan', 'sinh', 'cosh', 'tanh',
2249
'asinh', 'acosh', 'atanh', 'exp', 'log']:
2250
instrs.append(instr_unary(name, pg('S', 'S'), "%s(i0)" % name))
2251
self.instr_descs = instrs
2252
self._set_opcodes()
2253
# supported for exponents that fit in an int
2254
self.ipow_range = (int(-2**31), int(2**31-1))
2255
self.extra_class_members = "cdef object _domain\n"
2256
self.extra_members_initialize = "self._domain = args['domain']\n"
2257
self.adjust_retval = 'self._domain'
2258
2259
2260
class CDFInterpreter(StackInterpreter):
2261
r"""
2262
A subclass of StackInterpreter, specifying an interpreter over
2263
complex machine-floating-point values (C doubles).
2264
"""
2265
2266
def __init__(self):
2267
r"""
2268
Initialize a CDFInterpreter.
2269
2270
EXAMPLES:
2271
sage: from sage.ext.gen_interpreters import *
2272
sage: interp = CDFInterpreter()
2273
sage: interp.name
2274
'cdf'
2275
sage: interp.mc_py_constants
2276
{MC:py_constants}
2277
sage: interp.chunks
2278
[{MC:args}, {MC:constants}, {MC:py_constants}, {MC:stack}, {MC:code}]
2279
sage: interp.pg('A[D]', 'S')
2280
([({MC:args}, {MC:code}, None)], [({MC:stack}, None, None)])
2281
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2282
sage: instrs['add']
2283
add: SS->S = 'o0 = i0 + i1;'
2284
sage: instrs['sin']
2285
sin: S->S = 'o0 = csin(i0);'
2286
sage: instrs['py_call']
2287
py_call: *->S = '\nif (!cdf_py_call_...goto error;\n}\n'
2288
"""
2289
2290
StackInterpreter.__init__(self, ty_double_complex)
2291
self.name = 'cdf'
2292
self.mc_py_constants = MemoryChunkConstants('py_constants', ty_python)
2293
# See comment for RDFInterpreter
2294
self.err_return = '-1094648119105371'
2295
self.adjust_retval = "dz_to_CDE"
2296
self.chunks = [self.mc_args, self.mc_constants, self.mc_py_constants,
2297
self.mc_stack,
2298
self.mc_code]
2299
pg = params_gen(A=self.mc_args, C=self.mc_constants, D=self.mc_code,
2300
S=self.mc_stack, P=self.mc_py_constants)
2301
self.pg = pg
2302
self.header = """
2303
#include <stdlib.h>
2304
#include <complex.h>
2305
2306
typedef double complex double_complex;
2307
2308
extern int cdf_py_call_helper(PyObject*, int, double complex*, double complex*);
2309
2310
"""
2311
self.pxd_header = """
2312
# This is to work around a header ordering bug in Cython < 0.11
2313
# (Pari is included from sage.rings.complex_double.)
2314
cdef extern from "pari/paricfg.h":
2315
pass
2316
cdef extern from "pari/pari.h":
2317
pass
2318
cdef extern from "pari/paripriv.h":
2319
pass
2320
2321
# Cython does not (yet) support complex numbers natively, so this is a bit hackish.
2322
cdef extern from "complex.h":
2323
ctypedef double double_complex "double complex"
2324
"""
2325
self.pyx_header = """
2326
from sage.rings.complex_double cimport ComplexDoubleElement
2327
import sage.rings.complex_double
2328
cdef object CDF = sage.rings.complex_double.CDF
2329
2330
cdef extern from "solaris_fixes.h": pass
2331
2332
# Cython does not (yet) support complex numbers natively, so this is a bit hackish.
2333
cdef extern from "complex.h":
2334
ctypedef double double_complex "double complex"
2335
cdef double creal(double_complex)
2336
cdef double cimag(double_complex)
2337
cdef double_complex _Complex_I
2338
2339
cdef inline double_complex CDE_to_dz(zz):
2340
cdef ComplexDoubleElement z = <ComplexDoubleElement>(zz if isinstance(zz, ComplexDoubleElement) else CDF(zz))
2341
return z._complex.dat[0] + _Complex_I * z._complex.dat[1]
2342
2343
cdef inline ComplexDoubleElement dz_to_CDE(double_complex dz):
2344
cdef ComplexDoubleElement z = <ComplexDoubleElement>PY_NEW(ComplexDoubleElement)
2345
z._complex.dat[0] = creal(dz)
2346
z._complex.dat[1] = cimag(dz)
2347
return z
2348
2349
cdef public bint cdf_py_call_helper(object fn,
2350
int n_args,
2351
double_complex* args, double_complex* retval) except 0:
2352
py_args = []
2353
cdef int i
2354
for i from 0 <= i < n_args:
2355
py_args.append(dz_to_CDE(args[i]))
2356
py_result = fn(*py_args)
2357
cdef ComplexDoubleElement result
2358
if isinstance(py_result, ComplexDoubleElement):
2359
result = <ComplexDoubleElement>py_result
2360
else:
2361
result = CDF(py_result)
2362
retval[0] = CDE_to_dz(result)
2363
return 1
2364
2365
"""[1:]
2366
2367
instrs = [
2368
InstrSpec('load_arg', pg('A[D]', 'S'),
2369
code='o0 = i0;'),
2370
InstrSpec('load_const', pg('C[D]', 'S'),
2371
code='o0 = i0;'),
2372
InstrSpec('return', pg('S', ''),
2373
code='return i0;'),
2374
InstrSpec('py_call', pg('P[D]S@D', 'S'),
2375
uses_error_handler=True,
2376
code="""
2377
if (!cdf_py_call_helper(i0, n_i1, i1, &o0)) {
2378
goto error;
2379
}
2380
""")
2381
]
2382
for (name, op) in [('add', '+'), ('sub', '-'),
2383
('mul', '*'), ('div', '/')]:
2384
instrs.append(instr_infix(name, pg('SS', 'S'), op))
2385
instrs.append(instr_funcall_2args('pow', pg('SS', 'S'), 'cpow'))
2386
for (name, op) in [('neg', '-i0'), ('invert', '1/i0'),
2387
('abs', 'cabs(i0)')]:
2388
instrs.append(instr_unary(name, pg('S', 'S'), op))
2389
for name in ['sqrt', 'sin', 'cos', 'tan',
2390
'asin', 'acos', 'atan', 'sinh', 'cosh', 'tanh',
2391
'asinh', 'acosh', 'atanh', 'exp', 'log']:
2392
instrs.append(instr_unary(name, pg('S', 'S'), "c%s(i0)" % name))
2393
self.instr_descs = instrs
2394
self._set_opcodes()
2395
2396
2397
class RRInterpreter(StackInterpreter):
2398
r"""
2399
A subclass of StackInterpreter, specifying an interpreter over
2400
MPFR arbitrary-precision floating-point numbers.
2401
"""
2402
2403
def __init__(self):
2404
r"""
2405
Initialize an RDFInterpreter.
2406
2407
EXAMPLES:
2408
sage: from sage.ext.gen_interpreters import *
2409
sage: interp = RRInterpreter()
2410
sage: interp.name
2411
'rr'
2412
sage: interp.mc_py_constants
2413
{MC:py_constants}
2414
sage: interp.chunks
2415
[{MC:args}, {MC:retval}, {MC:constants}, {MC:py_constants}, {MC:stack}, {MC:code}, {MC:domain}]
2416
sage: interp.pg('A[D]', 'S')
2417
([({MC:args}, {MC:code}, None)], [({MC:stack}, None, None)])
2418
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2419
sage: instrs['add']
2420
add: SS->S = 'mpfr_add(o0, i0, i1, GMP_RNDN);'
2421
sage: instrs['py_call']
2422
py_call: *->S = '\nif (!rr_py_call_h...goto error;\n}\n'
2423
2424
That py_call instruction is particularly interesting, and
2425
demonstrates a useful technique to let you use Cython code
2426
in an interpreter. Let's look more closely:
2427
2428
sage: print instrs['py_call'].code
2429
if (!rr_py_call_helper(domain, i0, n_i1, i1, o0)) {
2430
goto error;
2431
}
2432
2433
This instruction makes use of the function rr_py_call_helper,
2434
which is declared...
2435
2436
sage: print interp.header
2437
#include <mpfr.h>
2438
extern int rr_py_call_helper(PyObject*, PyObject*, int, mpfr_t*, mpfr_t*);
2439
2440
In particular, rr_py_call_helper comes from:
2441
2442
sage: print interp.pyx_header
2443
cdef public bint rr_py_call_helper(object domain, object fn,
2444
int n_args,
2445
mpfr_t* args, mpfr_t* retval) except 0:
2446
py_args = []
2447
cdef int i
2448
cdef RealNumber rn
2449
for i from 0 <= i < n_args:
2450
rn = domain()
2451
mpfr_set(rn.value, args[i], GMP_RNDN)
2452
py_args.append(rn)
2453
cdef RealNumber result = domain(fn(*py_args))
2454
mpfr_set(retval[0], result.value, GMP_RNDN)
2455
return 1
2456
2457
2458
So instructions where you need to interact with Python can
2459
call back into Cython code fairly easily.
2460
"""
2461
2462
StackInterpreter.__init__(self, ty_mpfr, mc_retval= MemoryChunkRRRetval('retval', ty_mpfr))
2463
self.name = 'rr'
2464
self.err_return = '0'
2465
self.mc_py_constants = MemoryChunkConstants('py_constants', ty_python)
2466
self.mc_domain = MemoryChunkPyConstant('domain')
2467
self.chunks = [self.mc_args, self.mc_retval, self.mc_constants,
2468
self.mc_py_constants,
2469
self.mc_stack, self.mc_code, self.mc_domain]
2470
pg = params_gen(A=self.mc_args, C=self.mc_constants, D=self.mc_code,
2471
S=self.mc_stack,
2472
P=self.mc_py_constants)
2473
self.pg = pg
2474
self.header = """
2475
#include <mpfr.h>
2476
extern int rr_py_call_helper(PyObject*, PyObject*, int, mpfr_t*, mpfr_t*);
2477
""".strip()
2478
2479
self.pxd_header = """
2480
from sage.rings.real_mpfr cimport RealField_class, RealNumber
2481
from sage.libs.mpfr cimport *
2482
"""
2483
self.pyx_header = """
2484
cdef public bint rr_py_call_helper(object domain, object fn,
2485
int n_args,
2486
mpfr_t* args, mpfr_t* retval) except 0:
2487
py_args = []
2488
cdef int i
2489
cdef RealNumber rn
2490
for i from 0 <= i < n_args:
2491
rn = domain()
2492
mpfr_set(rn.value, args[i], GMP_RNDN)
2493
py_args.append(rn)
2494
cdef RealNumber result = domain(fn(*py_args))
2495
mpfr_set(retval[0], result.value, GMP_RNDN)
2496
return 1
2497
2498
"""[1:]
2499
instrs = [
2500
InstrSpec('load_arg', pg('A[D]', 'S'),
2501
code='mpfr_set(o0, i0, GMP_RNDN);'),
2502
InstrSpec('load_const', pg('C[D]', 'S'),
2503
code='mpfr_set(o0, i0, GMP_RNDN);'),
2504
InstrSpec('return', pg('S', ''),
2505
code='mpfr_set(retval[0], i0, GMP_RNDN);\nreturn 1;\n'),
2506
InstrSpec('py_call', pg('P[D]S@D', 'S'),
2507
uses_error_handler=True,
2508
code="""
2509
if (!rr_py_call_helper(domain, i0, n_i1, i1, o0)) {
2510
goto error;
2511
}
2512
""")
2513
]
2514
for (name, op) in [('add', 'mpfr_add'), ('sub', 'mpfr_sub'),
2515
('mul', 'mpfr_mul'), ('div', 'mpfr_div'),
2516
('pow', 'mpfr_pow')]:
2517
instrs.append(instr_funcall_2args_mpfr(name, pg('SS', 'S'), op))
2518
instrs.append(instr_funcall_2args_mpfr('ipow', pg('SD', 'S'), 'mpfr_pow_si'))
2519
for name in ['neg', 'abs',
2520
'log', 'log2', 'log10',
2521
'exp', 'exp2', 'exp10',
2522
'cos', 'sin', 'tan',
2523
'sec', 'csc', 'cot',
2524
'acos', 'asin', 'atan',
2525
'cosh', 'sinh', 'tanh',
2526
'sech', 'csch', 'coth',
2527
'acosh', 'asinh', 'atanh',
2528
'log1p', 'expm1', 'eint',
2529
'gamma', 'lngamma',
2530
'zeta', 'erf', 'erfc',
2531
'j0', 'j1', 'y0', 'y1']:
2532
instrs.append(instr_funcall_1arg_mpfr(name, pg('S', 'S'), 'mpfr_' + name))
2533
# mpfr_ui_div constructs a temporary mpfr_t and then calls mpfr_div;
2534
# it would probably be (slightly) faster to use a permanent copy
2535
# of "one" (on the other hand, the constructed temporary copy is
2536
# on the stack, so it's very likely to be in the cache).
2537
instrs.append(InstrSpec('invert', pg('S', 'S'),
2538
code='mpfr_ui_div(o0, 1, i0, GMP_RNDN);'))
2539
self.instr_descs = instrs
2540
self._set_opcodes()
2541
# Supported for exponents that fit in a long, so we could use
2542
# a much wider range on a 64-bit machine. On the other hand,
2543
# it's easier to write the code this way, and constant integer
2544
# exponents outside this range probably aren't very common anyway.
2545
self.ipow_range = (int(-2**31), int(2**31-1))
2546
2547
class PythonInterpreter(StackInterpreter):
2548
r"""
2549
A subclass of StackInterpreter, specifying an interpreter over
2550
Python objects.
2551
2552
Let's discuss how the reference-counting works in Python-object
2553
based interpreters.
2554
2555
There is a simple rule to remember: when executing the code
2556
snippets, the input variables contain borrowed references;
2557
you must fill in the output variables with references you own.
2558
2559
As an optimization, an instruction may set .handles_own_decref; in
2560
that case, it must decref any input variables that came from the
2561
stack. (Input variables that came from arguments/constants chunks
2562
must NOT be decref'ed!) In addition, with .handles_own_decref, if
2563
any of your input variables are arbitrary-count, then you must
2564
NULL out these variables as you decref them. (Use Py_CLEAR to do
2565
this, unless you understand the documentation of Py_CLEAR and why
2566
it's different than Py_XDECREF followed by assigning NULL.)
2567
2568
Note that as a tiny optimization, the interpreter always assumes
2569
(and ensures) that empty parts of the stack contain NULL, so
2570
it doesn't bother to Py_XDECREF before it pushes onto the stack.
2571
"""
2572
2573
def __init__(self):
2574
r"""
2575
Initialize a PythonInterpreter.
2576
2577
EXAMPLES:
2578
sage: from sage.ext.gen_interpreters import *
2579
sage: interp = PythonInterpreter()
2580
sage: interp.name
2581
'py'
2582
sage: interp.mc_args
2583
{MC:args}
2584
sage: interp.chunks
2585
[{MC:args}, {MC:constants}, {MC:stack}, {MC:code}]
2586
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2587
sage: instrs['add']
2588
add: SS->S = 'o0 = PyNumber_Add(i0, i1);'
2589
sage: instrs['py_call']
2590
py_call: *->S = '\nPyObject *py_args...CREF(py_args);\n'
2591
"""
2592
2593
StackInterpreter.__init__(self, ty_python)
2594
self.name = 'py'
2595
# StackInterpreter.__init__ gave us a MemoryChunkArguments.
2596
# Override with MemoryChunkPythonArguments.
2597
self.mc_args = MemoryChunkPythonArguments('args', ty_python)
2598
self.chunks = [self.mc_args, self.mc_constants, self.mc_stack,
2599
self.mc_code]
2600
pg = params_gen(A=self.mc_args, C=self.mc_constants, D=self.mc_code,
2601
S=self.mc_stack)
2602
self.pg = pg
2603
self.header = """
2604
#include <Python.h>
2605
#define CHECK(x) (x != NULL)
2606
"""
2607
instrs = [
2608
InstrSpec('load_arg', pg('A[D]', 'S'),
2609
code='o0 = i0; Py_INCREF(o0);'),
2610
InstrSpec('load_const', pg('C[D]', 'S'),
2611
code='o0 = i0; Py_INCREF(o0);'),
2612
InstrSpec('return', pg('S', ''),
2613
code='return i0;',
2614
handles_own_decref=True),
2615
InstrSpec('py_call', pg('C[D]S@D', 'S'),
2616
handles_own_decref=True,
2617
code="""
2618
PyObject *py_args = PyTuple_New(n_i1);
2619
if (py_args == NULL) goto error;
2620
int i;
2621
for (i = 0; i < n_i1; i++) {
2622
PyObject *arg = i1[i];
2623
PyTuple_SET_ITEM(py_args, i, arg);
2624
i1[i] = NULL;
2625
}
2626
o0 = PyObject_CallObject(i0, py_args);
2627
Py_DECREF(py_args);
2628
""")
2629
]
2630
for (name, op) in [('add', 'PyNumber_Add'),
2631
('sub', 'PyNumber_Subtract'),
2632
('mul', 'PyNumber_Multiply'),
2633
('div', 'PyNumber_Divide')]:
2634
instrs.append(instr_funcall_2args(name, pg('SS', 'S'), op))
2635
instrs.append(InstrSpec('pow', pg('SS', 'S'),
2636
code='o0 = PyNumber_Power(i0, i1, Py_None);'))
2637
instrs.append(InstrSpec('ipow', pg('SC[D]', 'S'),
2638
code='o0 = PyNumber_Power(i0, i1, Py_None);'))
2639
for (name, op) in [('neg', 'PyNumber_Negative'),
2640
('invert', 'PyNumber_Invert'),
2641
('abs', 'PyNumber_Absolute')]:
2642
instrs.append(instr_unary(name, pg('S', 'S'), '%s(i0)'%op))
2643
self.instr_descs = instrs
2644
self._set_opcodes()
2645
# Always use ipow
2646
self.ipow_range = True
2647
# We don't yet support call_c for Python-object interpreters
2648
# (the default implementation doesn't work, because of
2649
# object vs. PyObject* confusion)
2650
self.implement_call_c = False
2651
2652
class ElementInterpreter(PythonInterpreter):
2653
r"""
2654
A subclass of PythonInterpreter, specifying an interpreter over
2655
Sage elements with a particular parent.
2656
2657
This is very similar to the PythonInterpreter, but after every
2658
instruction, the result is checked to make sure it actually an
2659
element with the correct parent; if not, we attempt to convert it.
2660
2661
Uses the same instructions (with the same implementation) as
2662
PythonInterpreter.
2663
"""
2664
2665
def __init__(self):
2666
r"""
2667
Initialize an ElementInterpreter.
2668
2669
EXAMPLES:
2670
sage: from sage.ext.gen_interpreters import *
2671
sage: interp = ElementInterpreter()
2672
sage: interp.name
2673
'el'
2674
sage: interp.mc_args
2675
{MC:args}
2676
sage: interp.chunks
2677
[{MC:args}, {MC:constants}, {MC:stack}, {MC:domain}, {MC:code}]
2678
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2679
sage: instrs['add']
2680
add: SS->S = 'o0 = PyNumber_Add(i0, i1);'
2681
sage: instrs['py_call']
2682
py_call: *->S = '\nPyObject *py_args...CREF(py_args);\n'
2683
"""
2684
2685
PythonInterpreter.__init__(self)
2686
self.name = 'el'
2687
# PythonInterpreter.__init__ gave us a MemoryChunkPythonArguments.
2688
# Override with MemoryChunkElementArguments.
2689
self.mc_args = MemoryChunkElementArguments('args', ty_python)
2690
self.mc_domain_info = MemoryChunkPyConstant('domain')
2691
self.chunks = [self.mc_args, self.mc_constants, self.mc_stack,
2692
self.mc_domain_info, self.mc_code]
2693
self.header = """
2694
#include <Python.h>
2695
2696
extern PyObject* el_check_element(PyObject*, PyObject*);
2697
2698
#define CHECK(x) do_check(&(x), domain)
2699
2700
static inline int do_check(PyObject **x, PyObject *domain) {
2701
if (*x == NULL) return 0;
2702
PyObject *new_x = el_check_element(*x, domain);
2703
Py_DECREF(*x);
2704
*x = new_x;
2705
if (*x == NULL) return 0;
2706
return 1;
2707
}
2708
"""
2709
self.pyx_header = """
2710
from sage.structure.element cimport Element
2711
2712
cdef public object el_check_element(object v, parent):
2713
cdef Element v_el
2714
2715
if PY_TYPE_CHECK(v, Element):
2716
v_el = <Element>v
2717
if v_el._parent is parent:
2718
return v_el
2719
2720
return parent(v)
2721
2722
"""[1:]
2723
2724
class InterpreterGenerator(object):
2725
r"""
2726
This class takes an InterpreterSpec and generates the corresponding
2727
C interpreter and Cython wrapper.
2728
2729
See the documentation for methods get_wrapper and get_interpreter
2730
for more information.
2731
"""
2732
2733
def __init__(self, spec):
2734
r"""
2735
Initialize an InterpreterGenerator.
2736
2737
INPUTS:
2738
spec -- an InterpreterSpec
2739
2740
EXAMPLES:
2741
sage: from sage.ext.gen_interpreters import *
2742
sage: interp = RDFInterpreter()
2743
sage: gen = InterpreterGenerator(interp)
2744
sage: gen._spec is interp
2745
True
2746
sage: gen.uses_error_handler
2747
False
2748
"""
2749
2750
self._spec = spec
2751
self.uses_error_handler = False
2752
2753
def gen_code(self, instr_desc, write):
2754
r"""
2755
Generates code for a single instruction.
2756
2757
INPUTS:
2758
instr_desc -- an InstrSpec
2759
write -- a Python callable
2760
2761
This function calls its write parameter successively with
2762
strings; when these strings are concatenated, the result is
2763
the code for the given instruction.
2764
2765
See the documentation for the get_interpreter method for more
2766
information.
2767
2768
EXAMPLES:
2769
sage: from sage.ext.gen_interpreters import *
2770
sage: interp = RDFInterpreter()
2771
sage: gen = InterpreterGenerator(interp)
2772
sage: import cStringIO
2773
sage: buff = cStringIO.StringIO()
2774
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
2775
sage: gen.gen_code(instrs['div'], buff.write)
2776
sage: print buff.getvalue()
2777
case 8: /* div */
2778
{
2779
double i1 = *--stack;
2780
double i0 = *--stack;
2781
double o0;
2782
o0 = i0 / i1;
2783
*stack++ = o0;
2784
}
2785
break;
2786
<BLANKLINE>
2787
"""
2788
2789
d = instr_desc
2790
w = write
2791
s = self._spec
2792
2793
if d.uses_error_handler:
2794
self.uses_error_handler = True
2795
2796
w(je("""
2797
case {{ d.opcode }}: /* {{ d.name }} */
2798
{
2799
""", d=d))
2800
2801
# If the inputs to an instruction come from the stack,
2802
# then we want to generate code for the inputs in reverse order:
2803
# for instance, the divide instruction, which takes inputs A and B
2804
# and generates A/B, needs to pop B off the stack first.
2805
# On the other hand, if the inputs come from the constant pool,
2806
# then we want to generate code for the inputs in normal order,
2807
# because the addresses in the code stream will be in that order.
2808
# We handle this by running through the inputs in two passes:
2809
# first a forward pass, where we handle non-stack inputs
2810
# (and lengths for stack inputs), and then a reverse pass,
2811
# where we handle stack inputs.
2812
for i in range(len(d.inputs)):
2813
(ch, addr, input_len) = d.inputs[i]
2814
chst = ch.storage_type
2815
if addr is not None:
2816
w(" int ai%d = %s;\n" % (i, string_of_addr(addr)))
2817
if input_len is not None:
2818
w(" int n_i%d = %s;\n" % (i, string_of_addr(input_len)))
2819
if not ch.is_stack():
2820
# Shouldn't hardcode 'code' here
2821
if ch.name == 'code':
2822
w(" %s i%d = %s;\n" % (chst.c_local_type(), i, string_of_addr(ch)))
2823
elif input_len is not None:
2824
w(" %s i%d = %s + ai%d;\n" %
2825
(chst.c_ptr_type(), i, ch.name, i))
2826
else:
2827
w(" %s i%d = %s[ai%d];\n" %
2828
(chst.c_local_type(), i, ch.name, i))
2829
2830
for i in reversed(range(len(d.inputs))):
2831
(ch, addr, input_len) = d.inputs[i]
2832
chst = ch.storage_type
2833
if ch.is_stack():
2834
if input_len is not None:
2835
w(" %s -= n_i%d;\n" % (ch.name, i))
2836
w(" %s i%d = %s;\n" % (chst.c_ptr_type(), i, ch.name))
2837
else:
2838
w(" %s i%d = *--%s;\n" % (chst.c_local_type(), i, ch.name))
2839
if ch.is_python_refcounted_stack():
2840
w(" *%s = NULL;\n" % ch.name)
2841
2842
for i in range(len(d.outputs)):
2843
(ch, addr, output_len) = d.outputs[i]
2844
chst = ch.storage_type
2845
if addr is not None:
2846
w(" int ao%d = %s;\n" % (i, string_of_addr(addr)))
2847
if output_len is not None:
2848
w(" int n_o%d = %s;\n" % (i, string_of_addr(output_len)))
2849
if ch.is_stack():
2850
w(" %s o%d = %s;\n" %
2851
(chst.c_ptr_type(), i, ch.name))
2852
w(" %s += n_o%d;\n" % (ch.name, i))
2853
else:
2854
w(" %s o%d = %s + ao%d;\n" %
2855
(chst.c_ptr_type(), i, ch.name, i))
2856
2857
else:
2858
if not chst.cheap_copies():
2859
if ch.is_stack():
2860
w(" %s o%d = *%s++;\n" %
2861
(chst.c_local_type(), i, ch.name))
2862
else:
2863
w(" %s o%d = %s[ao%d];\n" %
2864
(chst.c_local_type(), i, ch.name, i))
2865
else:
2866
w(" %s o%d;\n" % (chst.c_local_type(), i))
2867
2868
w(indent_lines(8, d.code.rstrip('\n') + '\n'))
2869
2870
stack_offsets = defaultdict(int)
2871
for i in range(len(d.inputs)):
2872
(ch, addr, input_len) = d.inputs[i]
2873
chst = ch.storage_type
2874
if ch.is_python_refcounted_stack() and not d.handles_own_decref:
2875
if input_len is None:
2876
w(" Py_DECREF(i%d);\n" % i)
2877
stack_offsets[ch] += 1
2878
else:
2879
w(je("""
2880
int {{ iter }};
2881
for ({{ iter }} = 0; {{ iter }} < n_i{{ i }}; {{ iter }}++) {
2882
Py_CLEAR(i{{ i }}[{{ iter }}]);
2883
}
2884
""", iter='_interp_iter_%d' % i, i=i))
2885
2886
for i in range(len(d.outputs)):
2887
ch = d.outputs[i][0]
2888
chst = ch.storage_type
2889
if chst.python_refcounted():
2890
# We don't yet support code chunks
2891
# that produce multiple Python values, because of
2892
# the way it complicates error handling.
2893
assert i == 0
2894
w(" if (!CHECK(o%d)) {\n" % i)
2895
w(" Py_XDECREF(o%d);\n" % i)
2896
w(" goto error;\n")
2897
w(" }\n")
2898
self.uses_error_handler = True
2899
if chst.cheap_copies():
2900
if ch.is_stack():
2901
w(" *%s++ = o%d;\n" % (ch.name, i))
2902
else:
2903
w(" %s[ao%d] = o%d;\n" % (ch.name, i, i))
2904
2905
w(je("""
2906
}
2907
break;
2908
"""))
2909
2910
def func_header(self, cython=False):
2911
r"""
2912
Generates the function header for the declaration (in the Cython
2913
wrapper) or the definition (in the C interpreter) of the interpreter
2914
function.
2915
2916
EXAMPLES:
2917
sage: from sage.ext.gen_interpreters import *
2918
sage: interp = ElementInterpreter()
2919
sage: gen = InterpreterGenerator(interp)
2920
sage: print gen.func_header()
2921
PyObject* interp_el(PyObject** args,
2922
PyObject** constants,
2923
PyObject** stack,
2924
PyObject* domain,
2925
int* code)
2926
sage: print gen.func_header(cython=True)
2927
object interp_el(PyObject** args,
2928
PyObject** constants,
2929
PyObject** stack,
2930
PyObject* domain,
2931
int* code)
2932
"""
2933
s = self._spec
2934
ret_ty = 'bint' if cython else 'int'
2935
if s.return_type:
2936
ret_ty = s.return_type.c_decl_type()
2937
if cython:
2938
ret_ty = s.return_type.cython_decl_type()
2939
return je("""{{ ret_ty }} interp_{{ s.name }}(
2940
{%- for ch in s.chunks %}
2941
{% if not loop.first %},
2942
{% endif %}{{ ch.declare_parameter() }}
2943
{%- endfor %})""", ret_ty=ret_ty, s=s)
2944
2945
def write_interpreter(self, write):
2946
r"""
2947
Generate the code for the C interpreter.
2948
2949
This function calls its write parameter successively with
2950
strings; when these strings are concatenated, the result is
2951
the code for the interpreter.
2952
2953
See the documentation for the get_interpreter method for more
2954
information.
2955
2956
EXAMPLES:
2957
sage: from sage.ext.gen_interpreters import *
2958
sage: interp = RDFInterpreter()
2959
sage: gen = InterpreterGenerator(interp)
2960
sage: import cStringIO
2961
sage: buff = cStringIO.StringIO()
2962
sage: gen.write_interpreter(buff.write)
2963
sage: print buff.getvalue()
2964
/* Automatically generated by ext/gen_interpreters.py. Do not edit! */ ...
2965
"""
2966
s = self._spec
2967
w = write
2968
w(je("""
2969
/* Automatically generated by ext/gen_interpreters.py. Do not edit! */
2970
#include <Python.h>
2971
{% print s.header %}
2972
{{ myself.func_header() }} {
2973
while (1) {
2974
switch (*code++) {
2975
""", s=s, myself=self, i=indent_lines))
2976
for instr_desc in s.instr_descs:
2977
self.gen_code(instr_desc, w)
2978
w(je("""
2979
}
2980
}
2981
{% if myself.uses_error_handler %}
2982
error:
2983
return {{ s.err_return }};
2984
{% endif %}
2985
}
2986
2987
""", s=s, i=indent_lines, myself=self))
2988
2989
def write_wrapper(self, write):
2990
r"""
2991
Generate the code for the Cython wrapper.
2992
This function calls its write parameter successively with
2993
strings; when these strings are concatenated, the result is
2994
the code for the wrapper.
2995
2996
See the documentation for the get_wrapper method for more
2997
information.
2998
2999
EXAMPLES:
3000
sage: from sage.ext.gen_interpreters import *
3001
sage: interp = RDFInterpreter()
3002
sage: gen = InterpreterGenerator(interp)
3003
sage: import cStringIO
3004
sage: buff = cStringIO.StringIO()
3005
sage: gen.write_wrapper(buff.write)
3006
sage: print buff.getvalue()
3007
# Automatically generated by ext/gen_interpreters.py. Do not edit! ...
3008
"""
3009
s = self._spec
3010
w = write
3011
types = set()
3012
do_cleanup = False
3013
for ch in s.chunks:
3014
if ch.storage_type is not None:
3015
types.add(ch.storage_type)
3016
do_cleanup = do_cleanup or ch.needs_cleanup_on_error()
3017
for ch in s.chunks:
3018
if ch.name == 'args':
3019
arg_ch = ch
3020
3021
the_call = je("""
3022
{% if s.return_type %}return {% endif -%}
3023
{% if s.adjust_retval %}{{ s.adjust_retval }}({% endif %}
3024
interp_{{ s.name }}({{ arg_ch.pass_argument() }}
3025
{% for ch in s.chunks[1:] %}
3026
, {{ ch.pass_argument() }}
3027
{% endfor %}
3028
){% if s.adjust_retval %}){% endif %}
3029
3030
""", s=s, arg_ch=arg_ch)
3031
3032
the_call_c = je("""
3033
{% if s.return_type %}result[0] = {% endif %}
3034
interp_{{ s.name }}(args
3035
{% for ch in s.chunks[1:] %}
3036
, {{ ch.pass_call_c_argument() }}
3037
{% endfor %}
3038
)
3039
3040
""", s=s, arg_ch=arg_ch)
3041
3042
w(je("""
3043
# Automatically generated by ext/gen_interpreters.py. Do not edit!
3044
3045
include "../stdsage.pxi"
3046
from python_object cimport PyObject
3047
cdef extern from "Python.h":
3048
void Py_DECREF(PyObject *o)
3049
void Py_INCREF(PyObject *o)
3050
void Py_CLEAR(PyObject *o)
3051
3052
cdef extern from "listobject.h":
3053
object PyList_New(Py_ssize_t len)
3054
ctypedef struct PyListObject:
3055
PyObject **ob_item
3056
3057
cdef extern from "tupleobject.h":
3058
ctypedef struct PyTupleObject:
3059
PyObject **ob_item
3060
3061
from sage.ext.fast_callable cimport Wrapper
3062
{% print s.pyx_header %}
3063
3064
cdef extern {{ myself.func_header(cython=true) -}}
3065
{% if s.err_return != 'NULL' %}
3066
except? {{ s.err_return -}}
3067
{% endif %}
3068
3069
cdef class Wrapper_{{ s.name }}(Wrapper):
3070
# attributes are declared in corresponding .pxd file
3071
3072
def __init__(self, args):
3073
Wrapper.__init__(self, args, metadata)
3074
cdef int i
3075
cdef int count
3076
{% for ty in types %}
3077
{% print indent_lines(8, ty.local_declarations) %}
3078
{% print indent_lines(8, ty.class_member_initializations) %}
3079
{% endfor %}
3080
{% for ch in s.chunks %}
3081
{% print ch.init_class_members() %}
3082
{% endfor %}
3083
{% print indent_lines(8, s.extra_members_initialize) %}
3084
3085
def __dealloc__(self):
3086
cdef int i
3087
{% for ch in s.chunks %}
3088
{% print ch.dealloc_class_members() %}
3089
{% endfor %}
3090
3091
def __call__(self, *args):
3092
if self._n_args != len(args): raise ValueError
3093
{% for ty in types %}
3094
{% print indent_lines(8, ty.local_declarations) %}
3095
{% endfor %}
3096
{% print indent_lines(8, arg_ch.setup_args()) %}
3097
{% for ch in s.chunks %}
3098
{% print ch.declare_call_locals() %}
3099
{% endfor %}
3100
{% if do_cleanup %}
3101
try:
3102
{% print indent_lines(4, the_call) %}
3103
except:
3104
{% for ch in s.chunks %}
3105
{% if ch.needs_cleanup_on_error() %}
3106
{% print indent_lines(12, ch.handle_cleanup()) %}
3107
{% endif %}
3108
{% endfor %}
3109
raise
3110
{% else %}
3111
{% print the_call %}
3112
{% endif %}
3113
{% if not s.return_type %}
3114
return retval
3115
{% endif %}
3116
3117
{% if s.implement_call_c %}
3118
cdef bint call_c(self,
3119
{{ arg_ch.storage_type.c_ptr_type() }} args,
3120
{{ arg_ch.storage_type.c_ptr_type() }} result) except 0:
3121
{% if do_cleanup %}
3122
try:
3123
{% print indent_lines(4, the_call_c) %}
3124
except:
3125
{% for ch in s.chunks %}
3126
{% if ch.needs_cleanup_on_error() %}
3127
{% print indent_lines(12, ch.handle_cleanup()) %}
3128
{% endif %}
3129
{% endfor %}
3130
raise
3131
{% else %}
3132
{% print the_call_c %}
3133
{% endif %}
3134
return 1
3135
{% endif %}
3136
3137
from sage.ext.fast_callable import CompilerInstrSpec, InterpreterMetadata
3138
metadata = InterpreterMetadata(by_opname={
3139
{% for instr in s.instr_descs %}
3140
'{{ instr.name }}':
3141
(CompilerInstrSpec({{ instr.n_inputs }}, {{ instr.n_outputs }}, {{ instr.parameters }}), {{ instr.opcode }}),
3142
{% endfor %}
3143
},
3144
by_opcode=[
3145
{% for instr in s.instr_descs %}
3146
('{{ instr.name }}',
3147
CompilerInstrSpec({{ instr.n_inputs }}, {{ instr.n_outputs }}, {{ instr.parameters }})),
3148
{% endfor %}
3149
],
3150
ipow_range={{ s.ipow_range }})
3151
""", s=s, myself=self, types=types, arg_ch=arg_ch, indent_lines=indent_lines, the_call=the_call, the_call_c=the_call_c, do_cleanup=do_cleanup))
3152
3153
def write_pxd(self, write):
3154
r"""
3155
Generate the pxd file for the Cython wrapper.
3156
This function calls its write parameter successively with
3157
strings; when these strings are concatenated, the result is
3158
the code for the pxd file.
3159
3160
See the documentation for the get_pxd method for more
3161
information.
3162
3163
EXAMPLES:
3164
sage: from sage.ext.gen_interpreters import *
3165
sage: interp = RDFInterpreter()
3166
sage: gen = InterpreterGenerator(interp)
3167
sage: import cStringIO
3168
sage: buff = cStringIO.StringIO()
3169
sage: gen.write_pxd(buff.write)
3170
sage: print buff.getvalue()
3171
# Automatically generated by ext/gen_interpreters.py. Do not edit! ...
3172
"""
3173
s = self._spec
3174
w = write
3175
types = set()
3176
for ch in s.chunks:
3177
if ch.storage_type is not None:
3178
types.add(ch.storage_type)
3179
for ch in s.chunks:
3180
if ch.name == 'args':
3181
arg_ch = ch
3182
3183
w(je("""
3184
# Automatically generated by ext/gen_interpreters.py. Do not edit!
3185
3186
from python_object cimport PyObject
3187
3188
from sage.ext.fast_callable cimport Wrapper
3189
{% print s.pxd_header %}
3190
3191
cdef class Wrapper_{{ s.name }}(Wrapper):
3192
{% for ty in types %}
3193
{% print indent_lines(4, ty.class_member_declarations) %}
3194
{% endfor %}
3195
{% for ch in s.chunks %}
3196
{% print ch.declare_class_members() %}
3197
{% endfor %}
3198
{% print indent_lines(4, s.extra_class_members) %}
3199
{% if s.implement_call_c %}
3200
cdef bint call_c(self,
3201
{{ arg_ch.storage_type.c_ptr_type() }} args,
3202
{{ arg_ch.storage_type.c_ptr_type() }} result) except 0
3203
{% endif %}
3204
""", s=s, myself=self, types=types, indent_lines=indent_lines, arg_ch=arg_ch))
3205
3206
def get_interpreter(self):
3207
r"""
3208
Returns the code for the C interpreter.
3209
3210
EXAMPLES:
3211
3212
First we get the InterpreterSpec for several interpreters:
3213
sage: from sage.ext.gen_interpreters import *
3214
sage: rdf_spec = RDFInterpreter()
3215
sage: rr_spec = RRInterpreter()
3216
sage: el_spec = ElementInterpreter()
3217
3218
Then we get the actual interpreter code:
3219
sage: rdf_interp = InterpreterGenerator(rdf_spec).get_interpreter()
3220
sage: rr_interp = InterpreterGenerator(rr_spec).get_interpreter()
3221
sage: el_interp = InterpreterGenerator(el_spec).get_interpreter()
3222
3223
Now we can look through these interpreters.
3224
3225
Each interpreter starts with a file header; this can be
3226
customized on a per-interpreter basis:
3227
sage: print rr_interp
3228
/* Automatically generated by ext/gen_interpreters.py. Do not edit! */
3229
#include <Python.h>
3230
#include <mpfr.h>
3231
...
3232
3233
Next is the function header, with one argument per memory chunk
3234
in the interpreter spec.
3235
sage: print el_interp
3236
/* ... */ ...
3237
PyObject* interp_el(PyObject** args,
3238
PyObject** constants,
3239
PyObject** stack,
3240
PyObject* domain,
3241
int* code) {
3242
...
3243
3244
Currently, the interpreters have a very simple structure; just
3245
grab the next instruction and execute it, in a switch
3246
statement.
3247
sage: print rdf_interp
3248
/* ... */ ...
3249
while (1) {
3250
switch (*code++) {
3251
...
3252
3253
Then comes the code for each instruction. Here is one of the
3254
simplest instructions:
3255
sage: print rdf_interp
3256
/* ... */ ...
3257
case 10: /* neg */
3258
{
3259
double i0 = *--stack;
3260
double o0;
3261
o0 = -i0;
3262
*stack++ = o0;
3263
}
3264
break;
3265
...
3266
3267
We simply pull the top of the stack into a variable, negate it,
3268
and write the result back onto the stack.
3269
3270
Let's look at the MPFR-based version of this instruction.
3271
This is an example of an interpreter with an auto-reference
3272
type.
3273
sage: print rr_interp
3274
/* ... */ ...
3275
case 10: /* neg */
3276
{
3277
mpfr_ptr i0 = *--stack;
3278
mpfr_ptr o0 = *stack++;
3279
mpfr_neg(o0, i0, GMP_RNDN);
3280
}
3281
break;
3282
...
3283
3284
Here we see that the input and output variables are actually
3285
just pointers into the stack. But due to the auto-reference
3286
trick, the actual code snippet, ``mpfr_net(o0, i0, GMP_RNDN);``,
3287
is exactly the same as if i0 and o0 were declared as local
3288
mpfr_t variables.
3289
3290
For completeness, let's look at this instruction in the
3291
Python-object element interpreter.
3292
sage: print el_interp
3293
/* ... */ ...
3294
case 10: /* neg */
3295
{
3296
PyObject* i0 = *--stack;
3297
*stack = NULL;
3298
PyObject* o0;
3299
o0 = PyNumber_Negative(i0);
3300
Py_DECREF(i0);
3301
if (!CHECK(o0)) {
3302
Py_XDECREF(o0);
3303
goto error;
3304
}
3305
*stack++ = o0;
3306
}
3307
break;
3308
...
3309
3310
The original code snippet was only ``o0 = PyNumber_Negative(i0);``;
3311
all the rest is automatically generated. For ElementInterpreter,
3312
the CHECK macro actually checks for an exception (makes sure that
3313
o0 is not NULL), tests if the o0 is an element with the correct
3314
parent, and if not converts it into the correct parent. (That is,
3315
it can potentially modify the variable o0.)
3316
"""
3317
import cStringIO
3318
buff = cStringIO.StringIO()
3319
self.write_interpreter(buff.write)
3320
return buff.getvalue()
3321
3322
def get_wrapper(self):
3323
r"""
3324
Returns the code for the Cython wrapper.
3325
3326
EXAMPLES:
3327
3328
First we get the InterpreterSpec for several interpreters:
3329
sage: from sage.ext.gen_interpreters import *
3330
sage: rdf_spec = RDFInterpreter()
3331
sage: rr_spec = RRInterpreter()
3332
sage: el_spec = ElementInterpreter()
3333
3334
Then we get the actual wrapper code:
3335
sage: rdf_wrapper = InterpreterGenerator(rdf_spec).get_wrapper()
3336
sage: rr_wrapper = InterpreterGenerator(rr_spec).get_wrapper()
3337
sage: el_wrapper = InterpreterGenerator(el_spec).get_wrapper()
3338
3339
Now we can look through these wrappers.
3340
3341
Each wrapper starts with a file header; this can be
3342
customized on a per-interpreter basis (some blank lines have been
3343
elided below):
3344
sage: print rdf_wrapper
3345
# Automatically generated by ext/gen_interpreters.py. Do not edit!
3346
include "../stdsage.pxi"
3347
from python_object cimport PyObject
3348
cdef extern from "Python.h":
3349
void Py_DECREF(PyObject *o)
3350
void Py_INCREF(PyObject *o)
3351
void Py_CLEAR(PyObject *o)
3352
cdef extern from "listobject.h":
3353
object PyList_New(Py_ssize_t len)
3354
ctypedef struct PyListObject:
3355
PyObject **ob_item
3356
cdef extern from "tupleobject.h":
3357
ctypedef struct PyTupleObject:
3358
PyObject **ob_item
3359
from sage.ext.fast_callable cimport Wrapper
3360
...
3361
3362
Next is the declaration of the C interpreter function.
3363
sage: print rdf_wrapper
3364
# ...
3365
cdef extern double interp_rdf(double* args,
3366
double* constants,
3367
PyObject** py_constants,
3368
double* stack,
3369
int* code) except? -1094648009105371
3370
...
3371
3372
We need a way to propagate exceptions back to the wrapper,
3373
even though we only return a double from interp_rdf. The
3374
``except? -1094648009105371`` (that's a randomly chosen
3375
number) means that we will return that number if there's an
3376
exception, but the wrapper still has to check whether that's a
3377
legitimate return or an exception. (Cython does this
3378
automatically.)
3379
3380
Next comes the actual wrapper class. The member declarations
3381
are in the corresponding pxd file; see the documentation for
3382
get_pxd to see them.
3383
sage: print rdf_wrapper
3384
# ...
3385
cdef class Wrapper_rdf(Wrapper):
3386
# attributes are declared in corresponding .pxd file
3387
...
3388
3389
Next is the __init__ method, which starts like this:
3390
sage: print rdf_wrapper
3391
# ...
3392
def __init__(self, args):
3393
Wrapper.__init__(self, args, metadata)
3394
cdef int i
3395
cdef int count
3396
...
3397
3398
To make it possible to generate code for all expression
3399
interpreters with a single code generator, all wrappers
3400
have the same API. The __init__ method takes a single
3401
argument (here called *args*), which is a dictionary holding
3402
all the information needed to initialize this wrapper.
3403
3404
We call Wrapper.__init__, which saves a copy of this arguments
3405
object and of the interpreter metadata in the wrapper. (This is
3406
only used for debugging.)
3407
3408
Now we allocate memory for each memory chunk. (We allocate
3409
the memory here, and reuse it on each call of the
3410
wrapper/interpreter. This is for speed reasons; in a fast
3411
interpreter like RDFInterpreter, there are no memory allocations
3412
involved in a call of the wrapper, except for the ones that
3413
are required by the Python calling convention. Eventually
3414
we will support alternate Cython-only entry points that do
3415
absolutely no memory allocation.)
3416
3417
Basically the same code is repeated, with minor variations, for
3418
each memory chunk; for brevity, we'll only show the code
3419
for 'constants'.
3420
3421
sage: print rdf_wrapper
3422
# ...
3423
val = args['constants']
3424
self._n_constants = len(val)
3425
self._constants = <double*>sage_malloc(sizeof(double) * len(val))
3426
if self._constants == NULL: raise MemoryError
3427
for i in range(len(val)):
3428
self._constants[i] = val[i]
3429
...
3430
3431
Recall that _n_constants is an int, and _constants is a
3432
double*.
3433
3434
The RRInterpreter version is more complicated, because it has to
3435
call mpfr_init.
3436
sage: print rr_wrapper
3437
# ...
3438
cdef RealNumber rn
3439
...
3440
val = args['constants']
3441
self._n_constants = len(val)
3442
self._constants = <mpfr_t*>sage_malloc(sizeof(mpfr_t) * len(val))
3443
if self._constants == NULL: raise MemoryError
3444
for i in range(len(val)):
3445
mpfr_init2(self._constants[i], self.domain.prec())
3446
for i in range(len(val)):
3447
rn = self.domain(val[i])
3448
mpfr_set(self._constants[i], rn.value, GMP_RNDN)
3449
...
3450
3451
And as described in the documentation for get_pxd, in
3452
Python-object based interpreters we actually allocate the
3453
memory as a Python list.
3454
sage: print el_wrapper
3455
# ...
3456
val = args['constants']
3457
self._n_constants = len(val)
3458
self._list_constants = PyList_New(self._n_constants)
3459
self._constants = (<PyListObject *>self._list_constants).ob_item
3460
for i in range(len(val)):
3461
self._constants[i] = <PyObject *>val[i]; Py_INCREF(self._constants[i])
3462
...
3463
3464
Of course, once we've allocated the memory, we eventually have
3465
to free it. (Again, we'll only look at 'constants'.)
3466
sage: print rdf_wrapper
3467
# ...
3468
def __dealloc__(self):
3469
...
3470
if self._constants:
3471
sage_free(self._constants)
3472
...
3473
3474
The RRInterpreter code is more complicated again because it has
3475
to call mpfr_clear.
3476
sage: print rr_wrapper
3477
# ...
3478
def __dealloc__(self):
3479
cdef int i
3480
...
3481
if self._constants:
3482
for i in range(self._n_constants):
3483
mpfr_clear(self._constants[i])
3484
sage_free(self._constants)
3485
...
3486
3487
But the ElementInterpreter code is extremely simple --
3488
it doesn't have to do anything to deallocate constants!
3489
(Since the memory for constants is actually allocated as a
3490
Python list, and Cython knows how to deallocate Python lists.)
3491
3492
Finally we get to the __call__ method. We grab the arguments
3493
passed by the caller, stuff them in our pre-allocated
3494
argument array, and then call the C interpreter.
3495
3496
We optionally adjust the return value of the interpreter
3497
(currently only the RDF/float interpreter performs this step;
3498
this is the only place where domain=RDF differs than
3499
domain=float):
3500
3501
sage: print rdf_wrapper
3502
# ...
3503
def __call__(self, *args):
3504
if self._n_args != len(args): raise ValueError
3505
cdef double* c_args = self._args
3506
cdef int i
3507
for i from 0 <= i < len(args):
3508
self._args[i] = args[i]
3509
return self._domain(interp_rdf(c_args
3510
, self._constants
3511
, self._py_constants
3512
, self._stack
3513
, self._code
3514
))
3515
...
3516
3517
In Python-object based interpreters, the call to the C
3518
interpreter has to be a little more complicated. We don't
3519
want to hold on to Python objects from an old computation by
3520
leaving them referenced from the stack. In normal operation,
3521
the C interpreter clears out the stack as it runs, leaving the
3522
stack totally clear when the interpreter finishes. However,
3523
this doesn't happen if the C interpreter raises an exception.
3524
In that case, we have to clear out any remnants from the stack
3525
in the wrapper.
3526
sage: print el_wrapper
3527
# ...
3528
try:
3529
return interp_el((<PyListObject*>mapped_args).ob_item
3530
, self._constants
3531
, self._stack
3532
, <PyObject*>self._domain
3533
, self._code
3534
)
3535
except:
3536
for i in range(self._n_stack):
3537
Py_CLEAR(self._stack[i])
3538
raise
3539
...
3540
3541
Finally, we define a cdef call_c method, for quickly calling
3542
this object from Cython. (The method is omitted from
3543
Python-object based interpreters.)
3544
sage: print rdf_wrapper
3545
# ...
3546
cdef bint call_c(self,
3547
double* args,
3548
double* result) except 0:
3549
result[0] = interp_rdf(args
3550
, self._constants
3551
, self._py_constants
3552
, self._stack
3553
, self._code
3554
)
3555
return 1
3556
...
3557
3558
The method for the RR interpreter is slightly different, because
3559
the interpreter takes a pointer to a result location instead of
3560
returning the value.
3561
sage: print rr_wrapper
3562
# ...
3563
cdef bint call_c(self,
3564
mpfr_t* args,
3565
mpfr_t* result) except 0:
3566
interp_rr(args
3567
, result
3568
, self._constants
3569
, self._py_constants
3570
, self._stack
3571
, self._code
3572
, <PyObject*>self._domain
3573
)
3574
return 1
3575
...
3576
3577
That's it for the wrapper class. The only thing remaining is
3578
the interpreter metadata. This is the information necessary
3579
for the code generator to map instruction names to opcodes; it
3580
also gives information about stack usage, etc. This is fully
3581
documented at InterpreterMetadata; for now, we'll just show
3582
what it looks like.
3583
3584
Currently, there are three parts to the metadata; the first maps
3585
instruction names to instruction descriptions. The second one
3586
maps opcodes to instruction descriptions. Note that we don't
3587
use InstrSpec objects here; instead, we use CompilerInstrSpec
3588
objects, which are much simpler and contain only the information
3589
we'll need at runtime. The third part says what range the
3590
ipow instruction is defined over.
3591
3592
First the part that maps instruction names to
3593
(CompilerInstrSpec, opcode) pairs.
3594
3595
sage: print rdf_wrapper
3596
# ...
3597
from sage.ext.fast_callable import CompilerInstrSpec, InterpreterMetadata
3598
metadata = InterpreterMetadata(by_opname={
3599
...
3600
'return':
3601
(CompilerInstrSpec(1, 0, []), 2),
3602
'py_call':
3603
(CompilerInstrSpec(0, 1, ['py_constants', 'n_inputs']), 3),
3604
'pow':
3605
(CompilerInstrSpec(2, 1, []), 4),
3606
'add':
3607
(CompilerInstrSpec(2, 1, []), 5),
3608
...
3609
}, ...)
3610
3611
There's also a table that maps opcodes to (instruction name,
3612
CompilerInstrSpec) pairs:
3613
sage: print rdf_wrapper
3614
# ...
3615
metadata = InterpreterMetadata(..., by_opcode=[
3616
...
3617
('return',
3618
CompilerInstrSpec(1, 0, [])),
3619
('py_call',
3620
CompilerInstrSpec(0, 1, ['py_constants', 'n_inputs'])),
3621
('pow',
3622
CompilerInstrSpec(2, 1, [])),
3623
('add',
3624
CompilerInstrSpec(2, 1, [])),
3625
...
3626
], ...)
3627
3628
And then the ipow range:
3629
sage: print rdf_wrapper
3630
# ...
3631
metadata = InterpreterMetadata(...,
3632
ipow_range=(-2147483648, 2147483647))
3633
3634
3635
And that's it for the wrapper.
3636
"""
3637
import cStringIO
3638
buff = cStringIO.StringIO()
3639
self.write_wrapper(buff.write)
3640
return buff.getvalue()
3641
3642
def get_pxd(self):
3643
r"""
3644
Returns the code for the Cython .pxd file.
3645
3646
EXAMPLES:
3647
3648
First we get the InterpreterSpec for several interpreters:
3649
sage: from sage.ext.gen_interpreters import *
3650
sage: rdf_spec = RDFInterpreter()
3651
sage: rr_spec = RRInterpreter()
3652
sage: el_spec = ElementInterpreter()
3653
3654
Then we get the corresponding .pxd:
3655
sage: rdf_pxd = InterpreterGenerator(rdf_spec).get_pxd()
3656
sage: rr_pxd = InterpreterGenerator(rr_spec).get_pxd()
3657
sage: el_pxd = InterpreterGenerator(el_spec).get_pxd()
3658
3659
Now we can look through these pxd files.
3660
3661
Each .pxd starts with a file header; this can be
3662
customized on a per-interpreter basis (some blank lines have been
3663
elided below):
3664
sage: print rdf_pxd
3665
# Automatically generated by ext/gen_interpreters.py. Do not edit!
3666
from python_object cimport PyObject
3667
from sage.ext.fast_callable cimport Wrapper
3668
...
3669
sage: print rr_pxd
3670
# ...
3671
from sage.rings.real_mpfr cimport RealField_class, RealNumber
3672
from sage.libs.mpfr cimport *
3673
...
3674
3675
Next and last is the declaration of the wrapper class, which
3676
starts off with a list of member declarations.
3677
sage: print rdf_pxd
3678
# ...
3679
cdef class Wrapper_rdf(Wrapper):
3680
cdef int _n_args
3681
cdef double* _args
3682
cdef int _n_constants
3683
cdef double* _constants
3684
cdef object _list_py_constants
3685
cdef int _n_py_constants
3686
cdef PyObject** _py_constants
3687
cdef int _n_stack
3688
cdef double* _stack
3689
cdef int _n_code
3690
cdef int* _code
3691
...
3692
3693
Contrast the declaration of ``_stack`` here with the
3694
ElementInterpreter version. To simplify our handling of
3695
reference counting and garbage collection, in a Python-object
3696
based interpreter, we allocate arrays as Python lists,
3697
and then pull the array out of the innards of the list.
3698
sage: print el_pxd
3699
# ...
3700
cdef object _list_stack
3701
cdef int _n_stack
3702
cdef PyObject** _stack
3703
...
3704
3705
Then, at the end of the wrapper class, we declare a cdef method
3706
for quickly calling the wrapper object from Cython. (This method
3707
is omitted from Python-object based interpreters.)
3708
sage: print rdf_pxd
3709
# ...
3710
cdef bint call_c(self,
3711
double* args,
3712
double* result) except 0
3713
sage: print rr_pxd
3714
# ...
3715
cdef bint call_c(self,
3716
mpfr_t* args,
3717
mpfr_t* result) except 0
3718
3719
"""
3720
import cStringIO
3721
buff = cStringIO.StringIO()
3722
self.write_pxd(buff.write)
3723
return buff.getvalue()
3724
3725
def write_if_changed(fn, value):
3726
r"""
3727
Writes value to the file named fn, if value is different than
3728
the current contents.
3729
3730
EXAMPLES:
3731
sage: from sage.ext.gen_interpreters import *
3732
sage: def last_modification(fn): return os.stat(fn).st_mtime
3733
sage: fn = tmp_filename('gen_interp')
3734
sage: write_if_changed(fn, 'Hello, world')
3735
sage: t1 = last_modification(fn)
3736
sage: open(fn).read()
3737
'Hello, world'
3738
sage: sleep(2) # long time
3739
sage: write_if_changed(fn, 'Goodbye, world')
3740
sage: t2 = last_modification(fn)
3741
sage: open(fn).read()
3742
'Goodbye, world'
3743
sage: sleep(2) # long time
3744
sage: write_if_changed(fn, 'Goodbye, world')
3745
sage: t3 = last_modification(fn)
3746
sage: open(fn).read()
3747
'Goodbye, world'
3748
sage: t1 == t2 # long time
3749
False
3750
sage: t2 == t3
3751
True
3752
"""
3753
old_value = None
3754
try:
3755
with open(fn) as file:
3756
old_value = file.read()
3757
except IOError:
3758
pass
3759
3760
if value != old_value:
3761
# We try to remove the file, in case it exists. This is to
3762
# automatically break hardlinks... see #5350 for motivation.
3763
try:
3764
os.remove(fn)
3765
except OSError:
3766
pass
3767
3768
with open(fn, 'w') as file:
3769
file.write(value)
3770
3771
def build_interp(interp_spec, dir):
3772
r"""
3773
Given an InterpreterSpec, writes the C interpreter and the Cython
3774
wrapper (generates a pyx and a pxd file).
3775
3776
EXAMPLES:
3777
sage: from sage.ext.gen_interpreters import *
3778
sage: testdir = tmp_filename()
3779
sage: os.mkdir(testdir)
3780
sage: rdf_interp = RDFInterpreter()
3781
sage: build_interp(rdf_interp, testdir)
3782
sage: open(testdir + '/interp_rdf.c').readline()
3783
'/* Automatically generated by ext/gen_interpreters.py. Do not edit! */\n'
3784
"""
3785
ig = InterpreterGenerator(interp_spec)
3786
interp_fn = '%s/interp_%s.c' % (dir, interp_spec.name)
3787
wrapper_fn = '%s/wrapper_%s.pyx' % (dir, interp_spec.name)
3788
pxd_fn = '%s/wrapper_%s.pxd' % (dir, interp_spec.name)
3789
interp = ig.get_interpreter()
3790
wrapper = ig.get_wrapper()
3791
pxd = ig.get_pxd()
3792
write_if_changed(interp_fn, interp)
3793
write_if_changed(wrapper_fn, wrapper)
3794
write_if_changed(pxd_fn, pxd)
3795
3796
def rebuild(dir):
3797
r"""
3798
Check whether the interpreter and wrapper sources have been written
3799
since the last time this module was changed. If not, write them.
3800
3801
EXAMPLES:
3802
sage: from sage.ext.gen_interpreters import *
3803
sage: testdir = tmp_filename()
3804
sage: os.mkdir(testdir)
3805
sage: rebuild(testdir)
3806
Building interpreters for fast_callable
3807
sage: rebuild(testdir)
3808
sage: open(testdir + '/wrapper_el.pyx').readline()
3809
'# Automatically generated by ext/gen_interpreters.py. Do not edit!\n'
3810
"""
3811
module_mtime = os.stat(__file__).st_mtime
3812
try:
3813
if os.stat(dir + '/timestamp').st_mtime > module_mtime:
3814
# No need to rebuild.
3815
return
3816
except OSError:
3817
pass
3818
3819
# This line will show up in "sage -b" (once per upgrade, not every time
3820
# you run it).
3821
print "Building interpreters for fast_callable"
3822
3823
interp = RDFInterpreter()
3824
build_interp(interp, dir)
3825
3826
interp = CDFInterpreter()
3827
build_interp(interp, dir)
3828
3829
interp = RRInterpreter()
3830
build_interp(interp, dir)
3831
3832
interp = PythonInterpreter()
3833
build_interp(interp, dir)
3834
3835
interp = ElementInterpreter()
3836
build_interp(interp, dir)
3837
3838
# Do this last, so we don't do it if there's an error above.
3839
with open(dir + '/timestamp', 'w'):
3840
pass
3841
3842
# This list of modules gets added to the list in module_list.py.
3843
# For now, that's not important -- we could have just put this
3844
# list in module_list.py directly. But eventually, we'll have
3845
# interpreters that are conditionally built (for example,
3846
# interpreters that rely on SSE so they only work on x86), so
3847
# it makes sense to keep the decisions about which interpreters
3848
# to write and which interpreters to build in the same place.
3849
modules = [
3850
Extension('sage.ext.interpreters.wrapper_rdf',
3851
sources = ['sage/ext/interpreters/wrapper_rdf.pyx',
3852
'sage/ext/interpreters/interp_rdf.c'],
3853
libraries = ['gsl']),
3854
3855
Extension('sage.ext.interpreters.wrapper_cdf',
3856
sources = ['sage/ext/interpreters/wrapper_cdf.pyx',
3857
'sage/ext/interpreters/interp_cdf.c'],
3858
libraries = (['mc', 'md'] if 'CYGWIN' in os.uname()[0] else []),
3859
),
3860
3861
Extension('sage.ext.interpreters.wrapper_rr',
3862
sources = ['sage/ext/interpreters/wrapper_rr.pyx',
3863
'sage/ext/interpreters/interp_rr.c'],
3864
libraries=['mpfr']),
3865
3866
Extension('sage.ext.interpreters.wrapper_py',
3867
sources = ['sage/ext/interpreters/wrapper_py.pyx',
3868
'sage/ext/interpreters/interp_py.c']),
3869
3870
Extension('sage.ext.interpreters.wrapper_el',
3871
sources = ['sage/ext/interpreters/wrapper_el.pyx',
3872
'sage/ext/interpreters/interp_el.c']),
3873
3874
]
3875
3876