ChangeLog: add some numbered bugs I fixed
[maxima.git] / share / pytranslate / pytranslate.py
blobbad1dd5fba4c968d71676e15e3db79b0dcf3832b
1 import math
2 import numpy as np
3 import matplotlib.pyplot as plt
4 from collections.abc import MutableMapping
5 from fractions import Fraction
6 from mpmath import quad
7 from mpl_toolkits.mplot3d import axes3d, Axes3D
8 from matplotlib import cm
10 class Stack(MutableMapping):
11 '''
12 Implements a stack holding variable bindings for execution of translated Maxima code.
13 Provides access via Python dictionary like bindings.
14 '''
15 def __init__(self, data={}, sub={}):
16 '''
17 data parameter is a dictionary holding values for the current stack frame.
18 sub is either an instance of Stack or dictionary, holding values at stack frames below the current one.
19 '''
20 self.mapping = data
21 self.sub = sub
23 def __getitem__(self, key):
24 if key in self.mapping:
25 return self.mapping[key]
26 else:
27 return self.sub[key]
29 def __delitem__(self, key):
30 if key in self.mapping:
31 del self.mapping[key]
32 else:
33 del self.sub[key]
35 def __setitem__(self, key, value):
36 if key in self.mapping:
37 self.mapping[key] = value
38 else:
39 self.sub[key] = value
40 return(value)
42 def __iter__(self):
43 return iter({**self.sub, **self.mapping})
45 def __len__(self):
46 return len(self.mapping) + len(self.sub)
48 def __repr__(self):
49 return f"{self.mapping}, sub:{self.sub}"
51 def ins(self, data):
52 self.mapping={**self.mapping, **data}
54 # v contains the standard variable mapping from Maxima and is the base for all Stack instances for translated code
55 v = {
56 'fpprec': 16,
57 'pi': math.pi,
58 'e': math.e,
59 'ratepsilon': 2.0E-15
62 def plot2d(mapping, *constraints, v = v):
63 '''
64 provides functionality for plotting functions in 2D plane.
65 mapping is either:
66 1) A single function/lambda taking one input in the domain defined by constraints.
67 2) List of functions/lambda as defined in 1 above.
69 Example:
70 plot2d(lambda x: x**2, ['x', 0, 1])
71 where 0 and 1 are the lower and upper bounds respectively.
72 '''
73 plt.ion()
74 if type(mapping) != list:
75 mapping = [mapping]
76 for expr in mapping:
77 if len(constraints) == 1:
78 X = np.arange(constraints[0][1],
79 constraints[0][2],
80 0.0001,
81 dtype = 'float')
82 Y = np.array([expr(xi) for xi in X])
83 plt.plot(X, Y)
84 plt.draw()
86 def plot3d(mapping, *constraints, v = v):
87 '''
88 provides functionality for plotting functions in 3D plane.
89 mapping is either:
90 1) A single function/lambda taking two inputs in the domain defined by constraints.
91 2) List of functions/lambda as defined in 1 above.
93 Example:
94 plot2d(lambda x, y: x**2 + y**2, ['x', 0, 1], ['y', 0, 2])
95 where 0 and 1 are the lower and upper bounds respectively for first input and
96 0 and 2 are the lower and upper bounds respectively for the second input.
97 '''
98 fig = plt.figure()
99 ax = Axes3D(fig)
100 plt.ion()
101 if type(mapping) != list:
102 mapping = [mapping]
103 for expr in mapping:
104 vexpr = np.vectorize(expr)
105 if len(constraints) == 2:
106 X = np.arange(constraints[0][1],
107 constraints[0][2],
108 0.01,
109 dtype = 'float')
110 Y = np.arange(constraints[1][1],
111 constraints[1][2],
112 0.01,
113 dtype = 'float')
114 X, Y = np.meshgrid(X, Y)
115 Z = vexpr(X, Y)
116 surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False)
117 plt.show()
119 # f contains the function mapping used by translated functions from Maxima
120 f = {
121 'sin': math.sin,
122 'pow': math.pow,
123 'factorial': math.factorial,
124 'floor': math.floor,
125 'sqrt': math.sqrt,
126 'num':lambda x:x,
127 'denom': lambda x:1,
128 'print': print,
129 'listp': lambda x: type(x) == list,
130 'numberp': lambda x: (type(x) == int or
131 type(x) == float or
132 type(x) == Fraction or
133 type(x) == np.float64 or
134 type(x) == np.float128 or
135 type(x) == np.float32 or
136 type(x) == np.float16 or
137 type(x) == np.float),
138 'length': len,
139 # As defined in "Concrete Mathematics", Section 3.4
140 'mod': lambda x,y: (x if y == 0 else x - y * math.floor(x / y)),
141 'emptyp': lambda x: (True if len(x) == 0 else False),
142 'first': lambda x: x[0],
143 'integerp': lambda x: type(x) == int,
144 'append': lambda *x: [i for l in x for i in l],
145 'plot2d': plot2d,
146 'plot3d': plot3d,
147 'map': lambda f, i: list(map(f, i)),
148 'abs': abs,
149 'every': lambda func, l: all(map(func, l)),
150 'quad_qagi': quad,
151 'cos': math.cos,
152 'float': float,
153 'signum': lambda x: 0 if x==0 else x/abs(x)
156 def assign(lhs, rhs, v = v):
157 v[lhs] = rhs
158 return rhs