MNghia commited on
Commit
3a81eb2
·
verified ·
1 Parent(s): 029af54

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.10/site-packages/sympy/categories/__pycache__/baseclasses.cpython-310.pyc +0 -0
  2. lib/python3.10/site-packages/sympy/categories/__pycache__/diagram_drawing.cpython-310.pyc +0 -0
  3. lib/python3.10/site-packages/sympy/categories/tests/__init__.py +0 -0
  4. lib/python3.10/site-packages/sympy/categories/tests/test_baseclasses.py +209 -0
  5. lib/python3.10/site-packages/sympy/categories/tests/test_drawing.py +919 -0
  6. lib/python3.10/site-packages/sympy/codegen/__pycache__/__init__.cpython-310.pyc +0 -0
  7. lib/python3.10/site-packages/sympy/codegen/__pycache__/abstract_nodes.cpython-310.pyc +0 -0
  8. lib/python3.10/site-packages/sympy/codegen/__pycache__/algorithms.cpython-310.pyc +0 -0
  9. lib/python3.10/site-packages/sympy/codegen/__pycache__/approximations.cpython-310.pyc +0 -0
  10. lib/python3.10/site-packages/sympy/codegen/__pycache__/ast.cpython-310.pyc +0 -0
  11. lib/python3.10/site-packages/sympy/codegen/__pycache__/cfunctions.cpython-310.pyc +0 -0
  12. lib/python3.10/site-packages/sympy/codegen/__pycache__/cnodes.cpython-310.pyc +0 -0
  13. lib/python3.10/site-packages/sympy/codegen/__pycache__/cutils.cpython-310.pyc +0 -0
  14. lib/python3.10/site-packages/sympy/codegen/__pycache__/cxxnodes.cpython-310.pyc +0 -0
  15. lib/python3.10/site-packages/sympy/codegen/__pycache__/fnodes.cpython-310.pyc +0 -0
  16. lib/python3.10/site-packages/sympy/codegen/__pycache__/futils.cpython-310.pyc +0 -0
  17. lib/python3.10/site-packages/sympy/codegen/__pycache__/matrix_nodes.cpython-310.pyc +0 -0
  18. lib/python3.10/site-packages/sympy/codegen/__pycache__/numpy_nodes.cpython-310.pyc +0 -0
  19. lib/python3.10/site-packages/sympy/codegen/__pycache__/pynodes.cpython-310.pyc +0 -0
  20. lib/python3.10/site-packages/sympy/codegen/__pycache__/pyutils.cpython-310.pyc +0 -0
  21. lib/python3.10/site-packages/sympy/codegen/__pycache__/rewriting.cpython-310.pyc +0 -0
  22. lib/python3.10/site-packages/sympy/codegen/__pycache__/scipy_nodes.cpython-310.pyc +0 -0
  23. lib/python3.10/site-packages/sympy/codegen/tests/__init__.py +0 -0
  24. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/__init__.cpython-310.pyc +0 -0
  25. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_abstract_nodes.cpython-310.pyc +0 -0
  26. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_algorithms.cpython-310.pyc +0 -0
  27. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_applications.cpython-310.pyc +0 -0
  28. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_approximations.cpython-310.pyc +0 -0
  29. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_ast.cpython-310.pyc +0 -0
  30. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cfunctions.cpython-310.pyc +0 -0
  31. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cnodes.cpython-310.pyc +0 -0
  32. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cxxnodes.cpython-310.pyc +0 -0
  33. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_fnodes.cpython-310.pyc +0 -0
  34. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_matrix_nodes.cpython-310.pyc +0 -0
  35. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_numpy_nodes.cpython-310.pyc +0 -0
  36. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_pynodes.cpython-310.pyc +0 -0
  37. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_pyutils.cpython-310.pyc +0 -0
  38. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_rewriting.cpython-310.pyc +0 -0
  39. lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_scipy_nodes.cpython-310.pyc +0 -0
  40. lib/python3.10/site-packages/sympy/codegen/tests/test_abstract_nodes.py +14 -0
  41. lib/python3.10/site-packages/sympy/codegen/tests/test_algorithms.py +179 -0
  42. lib/python3.10/site-packages/sympy/codegen/tests/test_applications.py +57 -0
  43. lib/python3.10/site-packages/sympy/codegen/tests/test_approximations.py +53 -0
  44. lib/python3.10/site-packages/sympy/codegen/tests/test_ast.py +661 -0
  45. lib/python3.10/site-packages/sympy/codegen/tests/test_cfunctions.py +165 -0
  46. lib/python3.10/site-packages/sympy/codegen/tests/test_cnodes.py +112 -0
  47. lib/python3.10/site-packages/sympy/codegen/tests/test_cxxnodes.py +14 -0
  48. lib/python3.10/site-packages/sympy/codegen/tests/test_fnodes.py +213 -0
  49. lib/python3.10/site-packages/sympy/codegen/tests/test_matrix_nodes.py +50 -0
  50. lib/python3.10/site-packages/sympy/codegen/tests/test_numpy_nodes.py +50 -0
lib/python3.10/site-packages/sympy/categories/__pycache__/baseclasses.cpython-310.pyc ADDED
Binary file (28.3 kB). View file
 
lib/python3.10/site-packages/sympy/categories/__pycache__/diagram_drawing.cpython-310.pyc ADDED
Binary file (65.5 kB). View file
 
lib/python3.10/site-packages/sympy/categories/tests/__init__.py ADDED
File without changes
lib/python3.10/site-packages/sympy/categories/tests/test_baseclasses.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.categories import (Object, Morphism, IdentityMorphism,
2
+ NamedMorphism, CompositeMorphism,
3
+ Diagram, Category)
4
+ from sympy.categories.baseclasses import Class
5
+ from sympy.testing.pytest import raises
6
+ from sympy.core.containers import (Dict, Tuple)
7
+ from sympy.sets import EmptySet
8
+ from sympy.sets.sets import FiniteSet
9
+
10
+
11
+ def test_morphisms():
12
+ A = Object("A")
13
+ B = Object("B")
14
+ C = Object("C")
15
+ D = Object("D")
16
+
17
+ # Test the base morphism.
18
+ f = NamedMorphism(A, B, "f")
19
+ assert f.domain == A
20
+ assert f.codomain == B
21
+ assert f == NamedMorphism(A, B, "f")
22
+
23
+ # Test identities.
24
+ id_A = IdentityMorphism(A)
25
+ id_B = IdentityMorphism(B)
26
+ assert id_A.domain == A
27
+ assert id_A.codomain == A
28
+ assert id_A == IdentityMorphism(A)
29
+ assert id_A != id_B
30
+
31
+ # Test named morphisms.
32
+ g = NamedMorphism(B, C, "g")
33
+ assert g.name == "g"
34
+ assert g != f
35
+ assert g == NamedMorphism(B, C, "g")
36
+ assert g != NamedMorphism(B, C, "f")
37
+
38
+ # Test composite morphisms.
39
+ assert f == CompositeMorphism(f)
40
+
41
+ k = g.compose(f)
42
+ assert k.domain == A
43
+ assert k.codomain == C
44
+ assert k.components == Tuple(f, g)
45
+ assert g * f == k
46
+ assert CompositeMorphism(f, g) == k
47
+
48
+ assert CompositeMorphism(g * f) == g * f
49
+
50
+ # Test the associativity of composition.
51
+ h = NamedMorphism(C, D, "h")
52
+
53
+ p = h * g
54
+ u = h * g * f
55
+
56
+ assert h * k == u
57
+ assert p * f == u
58
+ assert CompositeMorphism(f, g, h) == u
59
+
60
+ # Test flattening.
61
+ u2 = u.flatten("u")
62
+ assert isinstance(u2, NamedMorphism)
63
+ assert u2.name == "u"
64
+ assert u2.domain == A
65
+ assert u2.codomain == D
66
+
67
+ # Test identities.
68
+ assert f * id_A == f
69
+ assert id_B * f == f
70
+ assert id_A * id_A == id_A
71
+ assert CompositeMorphism(id_A) == id_A
72
+
73
+ # Test bad compositions.
74
+ raises(ValueError, lambda: f * g)
75
+
76
+ raises(TypeError, lambda: f.compose(None))
77
+ raises(TypeError, lambda: id_A.compose(None))
78
+ raises(TypeError, lambda: f * None)
79
+ raises(TypeError, lambda: id_A * None)
80
+
81
+ raises(TypeError, lambda: CompositeMorphism(f, None, 1))
82
+
83
+ raises(ValueError, lambda: NamedMorphism(A, B, ""))
84
+ raises(NotImplementedError, lambda: Morphism(A, B))
85
+
86
+
87
+ def test_diagram():
88
+ A = Object("A")
89
+ B = Object("B")
90
+ C = Object("C")
91
+
92
+ f = NamedMorphism(A, B, "f")
93
+ g = NamedMorphism(B, C, "g")
94
+ id_A = IdentityMorphism(A)
95
+ id_B = IdentityMorphism(B)
96
+
97
+ empty = EmptySet
98
+
99
+ # Test the addition of identities.
100
+ d1 = Diagram([f])
101
+
102
+ assert d1.objects == FiniteSet(A, B)
103
+ assert d1.hom(A, B) == (FiniteSet(f), empty)
104
+ assert d1.hom(A, A) == (FiniteSet(id_A), empty)
105
+ assert d1.hom(B, B) == (FiniteSet(id_B), empty)
106
+
107
+ assert d1 == Diagram([id_A, f])
108
+ assert d1 == Diagram([f, f])
109
+
110
+ # Test the addition of composites.
111
+ d2 = Diagram([f, g])
112
+ homAC = d2.hom(A, C)[0]
113
+
114
+ assert d2.objects == FiniteSet(A, B, C)
115
+ assert g * f in d2.premises.keys()
116
+ assert homAC == FiniteSet(g * f)
117
+
118
+ # Test equality, inequality and hash.
119
+ d11 = Diagram([f])
120
+
121
+ assert d1 == d11
122
+ assert d1 != d2
123
+ assert hash(d1) == hash(d11)
124
+
125
+ d11 = Diagram({f: "unique"})
126
+ assert d1 != d11
127
+
128
+ # Make sure that (re-)adding composites (with new properties)
129
+ # works as expected.
130
+ d = Diagram([f, g], {g * f: "unique"})
131
+ assert d.conclusions == Dict({g * f: FiniteSet("unique")})
132
+
133
+ # Check the hom-sets when there are premises and conclusions.
134
+ assert d.hom(A, C) == (FiniteSet(g * f), FiniteSet(g * f))
135
+ d = Diagram([f, g], [g * f])
136
+ assert d.hom(A, C) == (FiniteSet(g * f), FiniteSet(g * f))
137
+
138
+ # Check how the properties of composite morphisms are computed.
139
+ d = Diagram({f: ["unique", "isomorphism"], g: "unique"})
140
+ assert d.premises[g * f] == FiniteSet("unique")
141
+
142
+ # Check that conclusion morphisms with new objects are not allowed.
143
+ d = Diagram([f], [g])
144
+ assert d.conclusions == Dict({})
145
+
146
+ # Test an empty diagram.
147
+ d = Diagram()
148
+ assert d.premises == Dict({})
149
+ assert d.conclusions == Dict({})
150
+ assert d.objects == empty
151
+
152
+ # Check a SymPy Dict object.
153
+ d = Diagram(Dict({f: FiniteSet("unique", "isomorphism"), g: "unique"}))
154
+ assert d.premises[g * f] == FiniteSet("unique")
155
+
156
+ # Check the addition of components of composite morphisms.
157
+ d = Diagram([g * f])
158
+ assert f in d.premises
159
+ assert g in d.premises
160
+
161
+ # Check subdiagrams.
162
+ d = Diagram([f, g], {g * f: "unique"})
163
+
164
+ d1 = Diagram([f])
165
+ assert d.is_subdiagram(d1)
166
+ assert not d1.is_subdiagram(d)
167
+
168
+ d = Diagram([NamedMorphism(B, A, "f'")])
169
+ assert not d.is_subdiagram(d1)
170
+ assert not d1.is_subdiagram(d)
171
+
172
+ d1 = Diagram([f, g], {g * f: ["unique", "something"]})
173
+ assert not d.is_subdiagram(d1)
174
+ assert not d1.is_subdiagram(d)
175
+
176
+ d = Diagram({f: "blooh"})
177
+ d1 = Diagram({f: "bleeh"})
178
+ assert not d.is_subdiagram(d1)
179
+ assert not d1.is_subdiagram(d)
180
+
181
+ d = Diagram([f, g], {f: "unique", g * f: "veryunique"})
182
+ d1 = d.subdiagram_from_objects(FiniteSet(A, B))
183
+ assert d1 == Diagram([f], {f: "unique"})
184
+ raises(ValueError, lambda: d.subdiagram_from_objects(FiniteSet(A,
185
+ Object("D"))))
186
+
187
+ raises(ValueError, lambda: Diagram({IdentityMorphism(A): "unique"}))
188
+
189
+
190
+ def test_category():
191
+ A = Object("A")
192
+ B = Object("B")
193
+ C = Object("C")
194
+
195
+ f = NamedMorphism(A, B, "f")
196
+ g = NamedMorphism(B, C, "g")
197
+
198
+ d1 = Diagram([f, g])
199
+ d2 = Diagram([f])
200
+
201
+ objects = d1.objects | d2.objects
202
+
203
+ K = Category("K", objects, commutative_diagrams=[d1, d2])
204
+
205
+ assert K.name == "K"
206
+ assert K.objects == Class(objects)
207
+ assert K.commutative_diagrams == FiniteSet(d1, d2)
208
+
209
+ raises(ValueError, lambda: Category(""))
lib/python3.10/site-packages/sympy/categories/tests/test_drawing.py ADDED
@@ -0,0 +1,919 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.categories.diagram_drawing import _GrowableGrid, ArrowStringDescription
2
+ from sympy.categories import (DiagramGrid, Object, NamedMorphism,
3
+ Diagram, XypicDiagramDrawer, xypic_draw_diagram)
4
+ from sympy.sets.sets import FiniteSet
5
+
6
+
7
+ def test_GrowableGrid():
8
+ grid = _GrowableGrid(1, 2)
9
+
10
+ # Check dimensions.
11
+ assert grid.width == 1
12
+ assert grid.height == 2
13
+
14
+ # Check initialization of elements.
15
+ assert grid[0, 0] is None
16
+ assert grid[1, 0] is None
17
+
18
+ # Check assignment to elements.
19
+ grid[0, 0] = 1
20
+ grid[1, 0] = "two"
21
+
22
+ assert grid[0, 0] == 1
23
+ assert grid[1, 0] == "two"
24
+
25
+ # Check appending a row.
26
+ grid.append_row()
27
+
28
+ assert grid.width == 1
29
+ assert grid.height == 3
30
+
31
+ assert grid[0, 0] == 1
32
+ assert grid[1, 0] == "two"
33
+ assert grid[2, 0] is None
34
+
35
+ # Check appending a column.
36
+ grid.append_column()
37
+ assert grid.width == 2
38
+ assert grid.height == 3
39
+
40
+ assert grid[0, 0] == 1
41
+ assert grid[1, 0] == "two"
42
+ assert grid[2, 0] is None
43
+
44
+ assert grid[0, 1] is None
45
+ assert grid[1, 1] is None
46
+ assert grid[2, 1] is None
47
+
48
+ grid = _GrowableGrid(1, 2)
49
+ grid[0, 0] = 1
50
+ grid[1, 0] = "two"
51
+
52
+ # Check prepending a row.
53
+ grid.prepend_row()
54
+ assert grid.width == 1
55
+ assert grid.height == 3
56
+
57
+ assert grid[0, 0] is None
58
+ assert grid[1, 0] == 1
59
+ assert grid[2, 0] == "two"
60
+
61
+ # Check prepending a column.
62
+ grid.prepend_column()
63
+ assert grid.width == 2
64
+ assert grid.height == 3
65
+
66
+ assert grid[0, 0] is None
67
+ assert grid[1, 0] is None
68
+ assert grid[2, 0] is None
69
+
70
+ assert grid[0, 1] is None
71
+ assert grid[1, 1] == 1
72
+ assert grid[2, 1] == "two"
73
+
74
+
75
+ def test_DiagramGrid():
76
+ # Set up some objects and morphisms.
77
+ A = Object("A")
78
+ B = Object("B")
79
+ C = Object("C")
80
+ D = Object("D")
81
+ E = Object("E")
82
+
83
+ f = NamedMorphism(A, B, "f")
84
+ g = NamedMorphism(B, C, "g")
85
+ h = NamedMorphism(D, A, "h")
86
+ k = NamedMorphism(D, B, "k")
87
+
88
+ # A one-morphism diagram.
89
+ d = Diagram([f])
90
+ grid = DiagramGrid(d)
91
+
92
+ assert grid.width == 2
93
+ assert grid.height == 1
94
+ assert grid[0, 0] == A
95
+ assert grid[0, 1] == B
96
+ assert grid.morphisms == {f: FiniteSet()}
97
+
98
+ # A triangle.
99
+ d = Diagram([f, g], {g * f: "unique"})
100
+ grid = DiagramGrid(d)
101
+
102
+ assert grid.width == 2
103
+ assert grid.height == 2
104
+ assert grid[0, 0] == A
105
+ assert grid[0, 1] == B
106
+ assert grid[1, 0] == C
107
+ assert grid[1, 1] is None
108
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(),
109
+ g * f: FiniteSet("unique")}
110
+
111
+ # A triangle with a "loop" morphism.
112
+ l_A = NamedMorphism(A, A, "l_A")
113
+ d = Diagram([f, g, l_A])
114
+ grid = DiagramGrid(d)
115
+
116
+ assert grid.width == 2
117
+ assert grid.height == 2
118
+ assert grid[0, 0] == A
119
+ assert grid[0, 1] == B
120
+ assert grid[1, 0] is None
121
+ assert grid[1, 1] == C
122
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), l_A: FiniteSet()}
123
+
124
+ # A simple diagram.
125
+ d = Diagram([f, g, h, k])
126
+ grid = DiagramGrid(d)
127
+
128
+ assert grid.width == 3
129
+ assert grid.height == 2
130
+ assert grid[0, 0] == A
131
+ assert grid[0, 1] == B
132
+ assert grid[0, 2] == D
133
+ assert grid[1, 0] is None
134
+ assert grid[1, 1] == C
135
+ assert grid[1, 2] is None
136
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(),
137
+ k: FiniteSet()}
138
+
139
+ assert str(grid) == '[[Object("A"), Object("B"), Object("D")], ' \
140
+ '[None, Object("C"), None]]'
141
+
142
+ # A chain of morphisms.
143
+ f = NamedMorphism(A, B, "f")
144
+ g = NamedMorphism(B, C, "g")
145
+ h = NamedMorphism(C, D, "h")
146
+ k = NamedMorphism(D, E, "k")
147
+ d = Diagram([f, g, h, k])
148
+ grid = DiagramGrid(d)
149
+
150
+ assert grid.width == 3
151
+ assert grid.height == 3
152
+ assert grid[0, 0] == A
153
+ assert grid[0, 1] == B
154
+ assert grid[0, 2] is None
155
+ assert grid[1, 0] is None
156
+ assert grid[1, 1] == C
157
+ assert grid[1, 2] == D
158
+ assert grid[2, 0] is None
159
+ assert grid[2, 1] is None
160
+ assert grid[2, 2] == E
161
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(),
162
+ k: FiniteSet()}
163
+
164
+ # A square.
165
+ f = NamedMorphism(A, B, "f")
166
+ g = NamedMorphism(B, D, "g")
167
+ h = NamedMorphism(A, C, "h")
168
+ k = NamedMorphism(C, D, "k")
169
+ d = Diagram([f, g, h, k])
170
+ grid = DiagramGrid(d)
171
+
172
+ assert grid.width == 2
173
+ assert grid.height == 2
174
+ assert grid[0, 0] == A
175
+ assert grid[0, 1] == B
176
+ assert grid[1, 0] == C
177
+ assert grid[1, 1] == D
178
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(),
179
+ k: FiniteSet()}
180
+
181
+ # A strange diagram which resulted from a typo when creating a
182
+ # test for five lemma, but which allowed to stop one extra problem
183
+ # in the algorithm.
184
+ A = Object("A")
185
+ B = Object("B")
186
+ C = Object("C")
187
+ D = Object("D")
188
+ E = Object("E")
189
+ A_ = Object("A'")
190
+ B_ = Object("B'")
191
+ C_ = Object("C'")
192
+ D_ = Object("D'")
193
+ E_ = Object("E'")
194
+
195
+ f = NamedMorphism(A, B, "f")
196
+ g = NamedMorphism(B, C, "g")
197
+ h = NamedMorphism(C, D, "h")
198
+ i = NamedMorphism(D, E, "i")
199
+
200
+ # These 4 morphisms should be between primed objects.
201
+ j = NamedMorphism(A, B, "j")
202
+ k = NamedMorphism(B, C, "k")
203
+ l = NamedMorphism(C, D, "l")
204
+ m = NamedMorphism(D, E, "m")
205
+
206
+ o = NamedMorphism(A, A_, "o")
207
+ p = NamedMorphism(B, B_, "p")
208
+ q = NamedMorphism(C, C_, "q")
209
+ r = NamedMorphism(D, D_, "r")
210
+ s = NamedMorphism(E, E_, "s")
211
+
212
+ d = Diagram([f, g, h, i, j, k, l, m, o, p, q, r, s])
213
+ grid = DiagramGrid(d)
214
+
215
+ assert grid.width == 3
216
+ assert grid.height == 4
217
+ assert grid[0, 0] is None
218
+ assert grid[0, 1] == A
219
+ assert grid[0, 2] == A_
220
+ assert grid[1, 0] == C
221
+ assert grid[1, 1] == B
222
+ assert grid[1, 2] == B_
223
+ assert grid[2, 0] == C_
224
+ assert grid[2, 1] == D
225
+ assert grid[2, 2] == D_
226
+ assert grid[3, 0] is None
227
+ assert grid[3, 1] == E
228
+ assert grid[3, 2] == E_
229
+
230
+ morphisms = {}
231
+ for m in [f, g, h, i, j, k, l, m, o, p, q, r, s]:
232
+ morphisms[m] = FiniteSet()
233
+ assert grid.morphisms == morphisms
234
+
235
+ # A cube.
236
+ A1 = Object("A1")
237
+ A2 = Object("A2")
238
+ A3 = Object("A3")
239
+ A4 = Object("A4")
240
+ A5 = Object("A5")
241
+ A6 = Object("A6")
242
+ A7 = Object("A7")
243
+ A8 = Object("A8")
244
+
245
+ # The top face of the cube.
246
+ f1 = NamedMorphism(A1, A2, "f1")
247
+ f2 = NamedMorphism(A1, A3, "f2")
248
+ f3 = NamedMorphism(A2, A4, "f3")
249
+ f4 = NamedMorphism(A3, A4, "f3")
250
+
251
+ # The bottom face of the cube.
252
+ f5 = NamedMorphism(A5, A6, "f5")
253
+ f6 = NamedMorphism(A5, A7, "f6")
254
+ f7 = NamedMorphism(A6, A8, "f7")
255
+ f8 = NamedMorphism(A7, A8, "f8")
256
+
257
+ # The remaining morphisms.
258
+ f9 = NamedMorphism(A1, A5, "f9")
259
+ f10 = NamedMorphism(A2, A6, "f10")
260
+ f11 = NamedMorphism(A3, A7, "f11")
261
+ f12 = NamedMorphism(A4, A8, "f11")
262
+
263
+ d = Diagram([f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12])
264
+ grid = DiagramGrid(d)
265
+
266
+ assert grid.width == 4
267
+ assert grid.height == 3
268
+ assert grid[0, 0] is None
269
+ assert grid[0, 1] == A5
270
+ assert grid[0, 2] == A6
271
+ assert grid[0, 3] is None
272
+ assert grid[1, 0] is None
273
+ assert grid[1, 1] == A1
274
+ assert grid[1, 2] == A2
275
+ assert grid[1, 3] is None
276
+ assert grid[2, 0] == A7
277
+ assert grid[2, 1] == A3
278
+ assert grid[2, 2] == A4
279
+ assert grid[2, 3] == A8
280
+
281
+ morphisms = {}
282
+ for m in [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12]:
283
+ morphisms[m] = FiniteSet()
284
+ assert grid.morphisms == morphisms
285
+
286
+ # A line diagram.
287
+ A = Object("A")
288
+ B = Object("B")
289
+ C = Object("C")
290
+ D = Object("D")
291
+ E = Object("E")
292
+
293
+ f = NamedMorphism(A, B, "f")
294
+ g = NamedMorphism(B, C, "g")
295
+ h = NamedMorphism(C, D, "h")
296
+ i = NamedMorphism(D, E, "i")
297
+ d = Diagram([f, g, h, i])
298
+ grid = DiagramGrid(d, layout="sequential")
299
+
300
+ assert grid.width == 5
301
+ assert grid.height == 1
302
+ assert grid[0, 0] == A
303
+ assert grid[0, 1] == B
304
+ assert grid[0, 2] == C
305
+ assert grid[0, 3] == D
306
+ assert grid[0, 4] == E
307
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(),
308
+ i: FiniteSet()}
309
+
310
+ # Test the transposed version.
311
+ grid = DiagramGrid(d, layout="sequential", transpose=True)
312
+
313
+ assert grid.width == 1
314
+ assert grid.height == 5
315
+ assert grid[0, 0] == A
316
+ assert grid[1, 0] == B
317
+ assert grid[2, 0] == C
318
+ assert grid[3, 0] == D
319
+ assert grid[4, 0] == E
320
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(),
321
+ i: FiniteSet()}
322
+
323
+ # A pullback.
324
+ m1 = NamedMorphism(A, B, "m1")
325
+ m2 = NamedMorphism(A, C, "m2")
326
+ s1 = NamedMorphism(B, D, "s1")
327
+ s2 = NamedMorphism(C, D, "s2")
328
+ f1 = NamedMorphism(E, B, "f1")
329
+ f2 = NamedMorphism(E, C, "f2")
330
+ g = NamedMorphism(E, A, "g")
331
+
332
+ d = Diagram([m1, m2, s1, s2, f1, f2], {g: "unique"})
333
+ grid = DiagramGrid(d)
334
+
335
+ assert grid.width == 3
336
+ assert grid.height == 2
337
+ assert grid[0, 0] == A
338
+ assert grid[0, 1] == B
339
+ assert grid[0, 2] == E
340
+ assert grid[1, 0] == C
341
+ assert grid[1, 1] == D
342
+ assert grid[1, 2] is None
343
+
344
+ morphisms = {g: FiniteSet("unique")}
345
+ for m in [m1, m2, s1, s2, f1, f2]:
346
+ morphisms[m] = FiniteSet()
347
+ assert grid.morphisms == morphisms
348
+
349
+ # Test the pullback with sequential layout, just for stress
350
+ # testing.
351
+ grid = DiagramGrid(d, layout="sequential")
352
+
353
+ assert grid.width == 5
354
+ assert grid.height == 1
355
+ assert grid[0, 0] == D
356
+ assert grid[0, 1] == B
357
+ assert grid[0, 2] == A
358
+ assert grid[0, 3] == C
359
+ assert grid[0, 4] == E
360
+ assert grid.morphisms == morphisms
361
+
362
+ # Test a pullback with object grouping.
363
+ grid = DiagramGrid(d, groups=FiniteSet(E, FiniteSet(A, B, C, D)))
364
+
365
+ assert grid.width == 3
366
+ assert grid.height == 2
367
+ assert grid[0, 0] == E
368
+ assert grid[0, 1] == A
369
+ assert grid[0, 2] == B
370
+ assert grid[1, 0] is None
371
+ assert grid[1, 1] == C
372
+ assert grid[1, 2] == D
373
+ assert grid.morphisms == morphisms
374
+
375
+ # Five lemma, actually.
376
+ A = Object("A")
377
+ B = Object("B")
378
+ C = Object("C")
379
+ D = Object("D")
380
+ E = Object("E")
381
+ A_ = Object("A'")
382
+ B_ = Object("B'")
383
+ C_ = Object("C'")
384
+ D_ = Object("D'")
385
+ E_ = Object("E'")
386
+
387
+ f = NamedMorphism(A, B, "f")
388
+ g = NamedMorphism(B, C, "g")
389
+ h = NamedMorphism(C, D, "h")
390
+ i = NamedMorphism(D, E, "i")
391
+
392
+ j = NamedMorphism(A_, B_, "j")
393
+ k = NamedMorphism(B_, C_, "k")
394
+ l = NamedMorphism(C_, D_, "l")
395
+ m = NamedMorphism(D_, E_, "m")
396
+
397
+ o = NamedMorphism(A, A_, "o")
398
+ p = NamedMorphism(B, B_, "p")
399
+ q = NamedMorphism(C, C_, "q")
400
+ r = NamedMorphism(D, D_, "r")
401
+ s = NamedMorphism(E, E_, "s")
402
+
403
+ d = Diagram([f, g, h, i, j, k, l, m, o, p, q, r, s])
404
+ grid = DiagramGrid(d)
405
+
406
+ assert grid.width == 5
407
+ assert grid.height == 3
408
+ assert grid[0, 0] is None
409
+ assert grid[0, 1] == A
410
+ assert grid[0, 2] == A_
411
+ assert grid[0, 3] is None
412
+ assert grid[0, 4] is None
413
+ assert grid[1, 0] == C
414
+ assert grid[1, 1] == B
415
+ assert grid[1, 2] == B_
416
+ assert grid[1, 3] == C_
417
+ assert grid[1, 4] is None
418
+ assert grid[2, 0] == D
419
+ assert grid[2, 1] == E
420
+ assert grid[2, 2] is None
421
+ assert grid[2, 3] == D_
422
+ assert grid[2, 4] == E_
423
+
424
+ morphisms = {}
425
+ for m in [f, g, h, i, j, k, l, m, o, p, q, r, s]:
426
+ morphisms[m] = FiniteSet()
427
+ assert grid.morphisms == morphisms
428
+
429
+ # Test the five lemma with object grouping.
430
+ grid = DiagramGrid(d, FiniteSet(
431
+ FiniteSet(A, B, C, D, E), FiniteSet(A_, B_, C_, D_, E_)))
432
+
433
+ assert grid.width == 6
434
+ assert grid.height == 3
435
+ assert grid[0, 0] == A
436
+ assert grid[0, 1] == B
437
+ assert grid[0, 2] is None
438
+ assert grid[0, 3] == A_
439
+ assert grid[0, 4] == B_
440
+ assert grid[0, 5] is None
441
+ assert grid[1, 0] is None
442
+ assert grid[1, 1] == C
443
+ assert grid[1, 2] == D
444
+ assert grid[1, 3] is None
445
+ assert grid[1, 4] == C_
446
+ assert grid[1, 5] == D_
447
+ assert grid[2, 0] is None
448
+ assert grid[2, 1] is None
449
+ assert grid[2, 2] == E
450
+ assert grid[2, 3] is None
451
+ assert grid[2, 4] is None
452
+ assert grid[2, 5] == E_
453
+ assert grid.morphisms == morphisms
454
+
455
+ # Test the five lemma with object grouping, but mixing containers
456
+ # to represent groups.
457
+ grid = DiagramGrid(d, [(A, B, C, D, E), {A_, B_, C_, D_, E_}])
458
+
459
+ assert grid.width == 6
460
+ assert grid.height == 3
461
+ assert grid[0, 0] == A
462
+ assert grid[0, 1] == B
463
+ assert grid[0, 2] is None
464
+ assert grid[0, 3] == A_
465
+ assert grid[0, 4] == B_
466
+ assert grid[0, 5] is None
467
+ assert grid[1, 0] is None
468
+ assert grid[1, 1] == C
469
+ assert grid[1, 2] == D
470
+ assert grid[1, 3] is None
471
+ assert grid[1, 4] == C_
472
+ assert grid[1, 5] == D_
473
+ assert grid[2, 0] is None
474
+ assert grid[2, 1] is None
475
+ assert grid[2, 2] == E
476
+ assert grid[2, 3] is None
477
+ assert grid[2, 4] is None
478
+ assert grid[2, 5] == E_
479
+ assert grid.morphisms == morphisms
480
+
481
+ # Test the five lemma with object grouping and hints.
482
+ grid = DiagramGrid(d, {
483
+ FiniteSet(A, B, C, D, E): {"layout": "sequential",
484
+ "transpose": True},
485
+ FiniteSet(A_, B_, C_, D_, E_): {"layout": "sequential",
486
+ "transpose": True}},
487
+ transpose=True)
488
+
489
+ assert grid.width == 5
490
+ assert grid.height == 2
491
+ assert grid[0, 0] == A
492
+ assert grid[0, 1] == B
493
+ assert grid[0, 2] == C
494
+ assert grid[0, 3] == D
495
+ assert grid[0, 4] == E
496
+ assert grid[1, 0] == A_
497
+ assert grid[1, 1] == B_
498
+ assert grid[1, 2] == C_
499
+ assert grid[1, 3] == D_
500
+ assert grid[1, 4] == E_
501
+ assert grid.morphisms == morphisms
502
+
503
+ # A two-triangle disconnected diagram.
504
+ f = NamedMorphism(A, B, "f")
505
+ g = NamedMorphism(B, C, "g")
506
+ f_ = NamedMorphism(A_, B_, "f")
507
+ g_ = NamedMorphism(B_, C_, "g")
508
+ d = Diagram([f, g, f_, g_], {g * f: "unique", g_ * f_: "unique"})
509
+ grid = DiagramGrid(d)
510
+
511
+ assert grid.width == 4
512
+ assert grid.height == 2
513
+ assert grid[0, 0] == A
514
+ assert grid[0, 1] == B
515
+ assert grid[0, 2] == A_
516
+ assert grid[0, 3] == B_
517
+ assert grid[1, 0] == C
518
+ assert grid[1, 1] is None
519
+ assert grid[1, 2] == C_
520
+ assert grid[1, 3] is None
521
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), f_: FiniteSet(),
522
+ g_: FiniteSet(), g * f: FiniteSet("unique"),
523
+ g_ * f_: FiniteSet("unique")}
524
+
525
+ # A two-morphism disconnected diagram.
526
+ f = NamedMorphism(A, B, "f")
527
+ g = NamedMorphism(C, D, "g")
528
+ d = Diagram([f, g])
529
+ grid = DiagramGrid(d)
530
+
531
+ assert grid.width == 4
532
+ assert grid.height == 1
533
+ assert grid[0, 0] == A
534
+ assert grid[0, 1] == B
535
+ assert grid[0, 2] == C
536
+ assert grid[0, 3] == D
537
+ assert grid.morphisms == {f: FiniteSet(), g: FiniteSet()}
538
+
539
+ # Test a one-object diagram.
540
+ f = NamedMorphism(A, A, "f")
541
+ d = Diagram([f])
542
+ grid = DiagramGrid(d)
543
+
544
+ assert grid.width == 1
545
+ assert grid.height == 1
546
+ assert grid[0, 0] == A
547
+
548
+ # Test a two-object disconnected diagram.
549
+ g = NamedMorphism(B, B, "g")
550
+ d = Diagram([f, g])
551
+ grid = DiagramGrid(d)
552
+
553
+ assert grid.width == 2
554
+ assert grid.height == 1
555
+ assert grid[0, 0] == A
556
+ assert grid[0, 1] == B
557
+
558
+
559
+ def test_DiagramGrid_pseudopod():
560
+ # Test a diagram in which even growing a pseudopod does not
561
+ # eventually help.
562
+ A = Object("A")
563
+ B = Object("B")
564
+ C = Object("C")
565
+ D = Object("D")
566
+ E = Object("E")
567
+ F = Object("F")
568
+ A_ = Object("A'")
569
+ B_ = Object("B'")
570
+ C_ = Object("C'")
571
+ D_ = Object("D'")
572
+ E_ = Object("E'")
573
+
574
+ f1 = NamedMorphism(A, B, "f1")
575
+ f2 = NamedMorphism(A, C, "f2")
576
+ f3 = NamedMorphism(A, D, "f3")
577
+ f4 = NamedMorphism(A, E, "f4")
578
+ f5 = NamedMorphism(A, A_, "f5")
579
+ f6 = NamedMorphism(A, B_, "f6")
580
+ f7 = NamedMorphism(A, C_, "f7")
581
+ f8 = NamedMorphism(A, D_, "f8")
582
+ f9 = NamedMorphism(A, E_, "f9")
583
+ f10 = NamedMorphism(A, F, "f10")
584
+ d = Diagram([f1, f2, f3, f4, f5, f6, f7, f8, f9, f10])
585
+ grid = DiagramGrid(d)
586
+
587
+ assert grid.width == 5
588
+ assert grid.height == 3
589
+ assert grid[0, 0] == E
590
+ assert grid[0, 1] == C
591
+ assert grid[0, 2] == C_
592
+ assert grid[0, 3] == E_
593
+ assert grid[0, 4] == F
594
+ assert grid[1, 0] == D
595
+ assert grid[1, 1] == A
596
+ assert grid[1, 2] == A_
597
+ assert grid[1, 3] is None
598
+ assert grid[1, 4] is None
599
+ assert grid[2, 0] == D_
600
+ assert grid[2, 1] == B
601
+ assert grid[2, 2] == B_
602
+ assert grid[2, 3] is None
603
+ assert grid[2, 4] is None
604
+
605
+ morphisms = {}
606
+ for f in [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10]:
607
+ morphisms[f] = FiniteSet()
608
+ assert grid.morphisms == morphisms
609
+
610
+
611
+ def test_ArrowStringDescription():
612
+ astr = ArrowStringDescription("cm", "", None, "", "", "d", "r", "_", "f")
613
+ assert str(astr) == "\\ar[dr]_{f}"
614
+
615
+ astr = ArrowStringDescription("cm", "", 12, "", "", "d", "r", "_", "f")
616
+ assert str(astr) == "\\ar[dr]_{f}"
617
+
618
+ astr = ArrowStringDescription("cm", "^", 12, "", "", "d", "r", "_", "f")
619
+ assert str(astr) == "\\ar@/^12cm/[dr]_{f}"
620
+
621
+ astr = ArrowStringDescription("cm", "", 12, "r", "", "d", "r", "_", "f")
622
+ assert str(astr) == "\\ar[dr]_{f}"
623
+
624
+ astr = ArrowStringDescription("cm", "", 12, "r", "u", "d", "r", "_", "f")
625
+ assert str(astr) == "\\ar@(r,u)[dr]_{f}"
626
+
627
+ astr = ArrowStringDescription("cm", "", 12, "r", "u", "d", "r", "_", "f")
628
+ assert str(astr) == "\\ar@(r,u)[dr]_{f}"
629
+
630
+ astr = ArrowStringDescription("cm", "", 12, "r", "u", "d", "r", "_", "f")
631
+ astr.arrow_style = "{-->}"
632
+ assert str(astr) == "\\ar@(r,u)@{-->}[dr]_{f}"
633
+
634
+ astr = ArrowStringDescription("cm", "_", 12, "", "", "d", "r", "_", "f")
635
+ astr.arrow_style = "{-->}"
636
+ assert str(astr) == "\\ar@/_12cm/@{-->}[dr]_{f}"
637
+
638
+
639
+ def test_XypicDiagramDrawer_line():
640
+ # A linear diagram.
641
+ A = Object("A")
642
+ B = Object("B")
643
+ C = Object("C")
644
+ D = Object("D")
645
+ E = Object("E")
646
+
647
+ f = NamedMorphism(A, B, "f")
648
+ g = NamedMorphism(B, C, "g")
649
+ h = NamedMorphism(C, D, "h")
650
+ i = NamedMorphism(D, E, "i")
651
+ d = Diagram([f, g, h, i])
652
+ grid = DiagramGrid(d, layout="sequential")
653
+ drawer = XypicDiagramDrawer()
654
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
655
+ "A \\ar[r]^{f} & B \\ar[r]^{g} & C \\ar[r]^{h} & D \\ar[r]^{i} & E \n" \
656
+ "}\n"
657
+
658
+ # The same diagram, transposed.
659
+ grid = DiagramGrid(d, layout="sequential", transpose=True)
660
+ drawer = XypicDiagramDrawer()
661
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
662
+ "A \\ar[d]^{f} \\\\\n" \
663
+ "B \\ar[d]^{g} \\\\\n" \
664
+ "C \\ar[d]^{h} \\\\\n" \
665
+ "D \\ar[d]^{i} \\\\\n" \
666
+ "E \n" \
667
+ "}\n"
668
+
669
+
670
+ def test_XypicDiagramDrawer_triangle():
671
+ # A triangle diagram.
672
+ A = Object("A")
673
+ B = Object("B")
674
+ C = Object("C")
675
+ f = NamedMorphism(A, B, "f")
676
+ g = NamedMorphism(B, C, "g")
677
+
678
+ d = Diagram([f, g], {g * f: "unique"})
679
+ grid = DiagramGrid(d)
680
+ drawer = XypicDiagramDrawer()
681
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
682
+ "A \\ar[d]_{g\\circ f} \\ar[r]^{f} & B \\ar[ld]^{g} \\\\\n" \
683
+ "C & \n" \
684
+ "}\n"
685
+
686
+ # The same diagram, transposed.
687
+ grid = DiagramGrid(d, transpose=True)
688
+ drawer = XypicDiagramDrawer()
689
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
690
+ "A \\ar[r]^{g\\circ f} \\ar[d]_{f} & C \\\\\n" \
691
+ "B \\ar[ru]_{g} & \n" \
692
+ "}\n"
693
+
694
+ # The same diagram, with a masked morphism.
695
+ assert drawer.draw(d, grid, masked=[g]) == "\\xymatrix{\n" \
696
+ "A \\ar[r]^{g\\circ f} \\ar[d]_{f} & C \\\\\n" \
697
+ "B & \n" \
698
+ "}\n"
699
+
700
+ # The same diagram with a formatter for "unique".
701
+ def formatter(astr):
702
+ astr.label = "\\exists !" + astr.label
703
+ astr.arrow_style = "{-->}"
704
+
705
+ drawer.arrow_formatters["unique"] = formatter
706
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
707
+ "A \\ar@{-->}[r]^{\\exists !g\\circ f} \\ar[d]_{f} & C \\\\\n" \
708
+ "B \\ar[ru]_{g} & \n" \
709
+ "}\n"
710
+
711
+ # The same diagram with a default formatter.
712
+ def default_formatter(astr):
713
+ astr.label_displacement = "(0.45)"
714
+
715
+ drawer.default_arrow_formatter = default_formatter
716
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
717
+ "A \\ar@{-->}[r]^(0.45){\\exists !g\\circ f} \\ar[d]_(0.45){f} & C \\\\\n" \
718
+ "B \\ar[ru]_(0.45){g} & \n" \
719
+ "}\n"
720
+
721
+ # A triangle diagram with a lot of morphisms between the same
722
+ # objects.
723
+ f1 = NamedMorphism(B, A, "f1")
724
+ f2 = NamedMorphism(A, B, "f2")
725
+ g1 = NamedMorphism(C, B, "g1")
726
+ g2 = NamedMorphism(B, C, "g2")
727
+ d = Diagram([f, f1, f2, g, g1, g2], {f1 * g1: "unique", g2 * f2: "unique"})
728
+
729
+ grid = DiagramGrid(d, transpose=True)
730
+ drawer = XypicDiagramDrawer()
731
+ assert drawer.draw(d, grid, masked=[f1*g1*g2*f2, g2*f2*f1*g1]) == \
732
+ "\\xymatrix{\n" \
733
+ "A \\ar[r]^{g_{2}\\circ f_{2}} \\ar[d]_{f} \\ar@/^3mm/[d]^{f_{2}} " \
734
+ "& C \\ar@/^3mm/[l]^{f_{1}\\circ g_{1}} \\ar@/^3mm/[ld]^{g_{1}} \\\\\n" \
735
+ "B \\ar@/^3mm/[u]^{f_{1}} \\ar[ru]_{g} \\ar@/^3mm/[ru]^{g_{2}} & \n" \
736
+ "}\n"
737
+
738
+
739
+ def test_XypicDiagramDrawer_cube():
740
+ # A cube diagram.
741
+ A1 = Object("A1")
742
+ A2 = Object("A2")
743
+ A3 = Object("A3")
744
+ A4 = Object("A4")
745
+ A5 = Object("A5")
746
+ A6 = Object("A6")
747
+ A7 = Object("A7")
748
+ A8 = Object("A8")
749
+
750
+ # The top face of the cube.
751
+ f1 = NamedMorphism(A1, A2, "f1")
752
+ f2 = NamedMorphism(A1, A3, "f2")
753
+ f3 = NamedMorphism(A2, A4, "f3")
754
+ f4 = NamedMorphism(A3, A4, "f3")
755
+
756
+ # The bottom face of the cube.
757
+ f5 = NamedMorphism(A5, A6, "f5")
758
+ f6 = NamedMorphism(A5, A7, "f6")
759
+ f7 = NamedMorphism(A6, A8, "f7")
760
+ f8 = NamedMorphism(A7, A8, "f8")
761
+
762
+ # The remaining morphisms.
763
+ f9 = NamedMorphism(A1, A5, "f9")
764
+ f10 = NamedMorphism(A2, A6, "f10")
765
+ f11 = NamedMorphism(A3, A7, "f11")
766
+ f12 = NamedMorphism(A4, A8, "f11")
767
+
768
+ d = Diagram([f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12])
769
+ grid = DiagramGrid(d)
770
+ drawer = XypicDiagramDrawer()
771
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
772
+ "& A_{5} \\ar[r]^{f_{5}} \\ar[ldd]_{f_{6}} & A_{6} \\ar[rdd]^{f_{7}} " \
773
+ "& \\\\\n" \
774
+ "& A_{1} \\ar[r]^{f_{1}} \\ar[d]^{f_{2}} \\ar[u]^{f_{9}} & A_{2} " \
775
+ "\\ar[d]^{f_{3}} \\ar[u]_{f_{10}} & \\\\\n" \
776
+ "A_{7} \\ar@/_3mm/[rrr]_{f_{8}} & A_{3} \\ar[r]^{f_{3}} \\ar[l]_{f_{11}} " \
777
+ "& A_{4} \\ar[r]^{f_{11}} & A_{8} \n" \
778
+ "}\n"
779
+
780
+ # The same diagram, transposed.
781
+ grid = DiagramGrid(d, transpose=True)
782
+ drawer = XypicDiagramDrawer()
783
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
784
+ "& & A_{7} \\ar@/^3mm/[ddd]^{f_{8}} \\\\\n" \
785
+ "A_{5} \\ar[d]_{f_{5}} \\ar[rru]^{f_{6}} & A_{1} \\ar[d]^{f_{1}} " \
786
+ "\\ar[r]^{f_{2}} \\ar[l]^{f_{9}} & A_{3} \\ar[d]_{f_{3}} " \
787
+ "\\ar[u]^{f_{11}} \\\\\n" \
788
+ "A_{6} \\ar[rrd]_{f_{7}} & A_{2} \\ar[r]^{f_{3}} \\ar[l]^{f_{10}} " \
789
+ "& A_{4} \\ar[d]_{f_{11}} \\\\\n" \
790
+ "& & A_{8} \n" \
791
+ "}\n"
792
+
793
+
794
+ def test_XypicDiagramDrawer_curved_and_loops():
795
+ # A simple diagram, with a curved arrow.
796
+ A = Object("A")
797
+ B = Object("B")
798
+ C = Object("C")
799
+ D = Object("D")
800
+
801
+ f = NamedMorphism(A, B, "f")
802
+ g = NamedMorphism(B, C, "g")
803
+ h = NamedMorphism(D, A, "h")
804
+ k = NamedMorphism(D, B, "k")
805
+ d = Diagram([f, g, h, k])
806
+ grid = DiagramGrid(d)
807
+ drawer = XypicDiagramDrawer()
808
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
809
+ "A \\ar[r]_{f} & B \\ar[d]^{g} & D \\ar[l]^{k} \\ar@/_3mm/[ll]_{h} \\\\\n" \
810
+ "& C & \n" \
811
+ "}\n"
812
+
813
+ # The same diagram, transposed.
814
+ grid = DiagramGrid(d, transpose=True)
815
+ drawer = XypicDiagramDrawer()
816
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
817
+ "A \\ar[d]^{f} & \\\\\n" \
818
+ "B \\ar[r]^{g} & C \\\\\n" \
819
+ "D \\ar[u]_{k} \\ar@/^3mm/[uu]^{h} & \n" \
820
+ "}\n"
821
+
822
+ # The same diagram, larger and rotated.
823
+ assert drawer.draw(d, grid, diagram_format="@+1cm@dr") == \
824
+ "\\xymatrix@+1cm@dr{\n" \
825
+ "A \\ar[d]^{f} & \\\\\n" \
826
+ "B \\ar[r]^{g} & C \\\\\n" \
827
+ "D \\ar[u]_{k} \\ar@/^3mm/[uu]^{h} & \n" \
828
+ "}\n"
829
+
830
+ # A simple diagram with three curved arrows.
831
+ h1 = NamedMorphism(D, A, "h1")
832
+ h2 = NamedMorphism(A, D, "h2")
833
+ k = NamedMorphism(D, B, "k")
834
+ d = Diagram([f, g, h, k, h1, h2])
835
+ grid = DiagramGrid(d)
836
+ drawer = XypicDiagramDrawer()
837
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
838
+ "A \\ar[r]_{f} \\ar@/^3mm/[rr]^{h_{2}} & B \\ar[d]^{g} & D \\ar[l]^{k} " \
839
+ "\\ar@/_7mm/[ll]_{h} \\ar@/_11mm/[ll]_{h_{1}} \\\\\n" \
840
+ "& C & \n" \
841
+ "}\n"
842
+
843
+ # The same diagram, transposed.
844
+ grid = DiagramGrid(d, transpose=True)
845
+ drawer = XypicDiagramDrawer()
846
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
847
+ "A \\ar[d]^{f} \\ar@/_3mm/[dd]_{h_{2}} & \\\\\n" \
848
+ "B \\ar[r]^{g} & C \\\\\n" \
849
+ "D \\ar[u]_{k} \\ar@/^7mm/[uu]^{h} \\ar@/^11mm/[uu]^{h_{1}} & \n" \
850
+ "}\n"
851
+
852
+ # The same diagram, with "loop" morphisms.
853
+ l_A = NamedMorphism(A, A, "l_A")
854
+ l_D = NamedMorphism(D, D, "l_D")
855
+ l_C = NamedMorphism(C, C, "l_C")
856
+ d = Diagram([f, g, h, k, h1, h2, l_A, l_D, l_C])
857
+ grid = DiagramGrid(d)
858
+ drawer = XypicDiagramDrawer()
859
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
860
+ "A \\ar[r]_{f} \\ar@/^3mm/[rr]^{h_{2}} \\ar@(u,l)[]^{l_{A}} " \
861
+ "& B \\ar[d]^{g} & D \\ar[l]^{k} \\ar@/_7mm/[ll]_{h} " \
862
+ "\\ar@/_11mm/[ll]_{h_{1}} \\ar@(r,u)[]^{l_{D}} \\\\\n" \
863
+ "& C \\ar@(l,d)[]^{l_{C}} & \n" \
864
+ "}\n"
865
+
866
+ # The same diagram with "loop" morphisms, transposed.
867
+ grid = DiagramGrid(d, transpose=True)
868
+ drawer = XypicDiagramDrawer()
869
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
870
+ "A \\ar[d]^{f} \\ar@/_3mm/[dd]_{h_{2}} \\ar@(r,u)[]^{l_{A}} & \\\\\n" \
871
+ "B \\ar[r]^{g} & C \\ar@(r,u)[]^{l_{C}} \\\\\n" \
872
+ "D \\ar[u]_{k} \\ar@/^7mm/[uu]^{h} \\ar@/^11mm/[uu]^{h_{1}} " \
873
+ "\\ar@(l,d)[]^{l_{D}} & \n" \
874
+ "}\n"
875
+
876
+ # The same diagram with two "loop" morphisms per object.
877
+ l_A_ = NamedMorphism(A, A, "n_A")
878
+ l_D_ = NamedMorphism(D, D, "n_D")
879
+ l_C_ = NamedMorphism(C, C, "n_C")
880
+ d = Diagram([f, g, h, k, h1, h2, l_A, l_D, l_C, l_A_, l_D_, l_C_])
881
+ grid = DiagramGrid(d)
882
+ drawer = XypicDiagramDrawer()
883
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
884
+ "A \\ar[r]_{f} \\ar@/^3mm/[rr]^{h_{2}} \\ar@(u,l)[]^{l_{A}} " \
885
+ "\\ar@/^3mm/@(l,d)[]^{n_{A}} & B \\ar[d]^{g} & D \\ar[l]^{k} " \
886
+ "\\ar@/_7mm/[ll]_{h} \\ar@/_11mm/[ll]_{h_{1}} \\ar@(r,u)[]^{l_{D}} " \
887
+ "\\ar@/^3mm/@(d,r)[]^{n_{D}} \\\\\n" \
888
+ "& C \\ar@(l,d)[]^{l_{C}} \\ar@/^3mm/@(d,r)[]^{n_{C}} & \n" \
889
+ "}\n"
890
+
891
+ # The same diagram with two "loop" morphisms per object, transposed.
892
+ grid = DiagramGrid(d, transpose=True)
893
+ drawer = XypicDiagramDrawer()
894
+ assert drawer.draw(d, grid) == "\\xymatrix{\n" \
895
+ "A \\ar[d]^{f} \\ar@/_3mm/[dd]_{h_{2}} \\ar@(r,u)[]^{l_{A}} " \
896
+ "\\ar@/^3mm/@(u,l)[]^{n_{A}} & \\\\\n" \
897
+ "B \\ar[r]^{g} & C \\ar@(r,u)[]^{l_{C}} \\ar@/^3mm/@(d,r)[]^{n_{C}} \\\\\n" \
898
+ "D \\ar[u]_{k} \\ar@/^7mm/[uu]^{h} \\ar@/^11mm/[uu]^{h_{1}} " \
899
+ "\\ar@(l,d)[]^{l_{D}} \\ar@/^3mm/@(d,r)[]^{n_{D}} & \n" \
900
+ "}\n"
901
+
902
+
903
+ def test_xypic_draw_diagram():
904
+ # A linear diagram.
905
+ A = Object("A")
906
+ B = Object("B")
907
+ C = Object("C")
908
+ D = Object("D")
909
+ E = Object("E")
910
+
911
+ f = NamedMorphism(A, B, "f")
912
+ g = NamedMorphism(B, C, "g")
913
+ h = NamedMorphism(C, D, "h")
914
+ i = NamedMorphism(D, E, "i")
915
+ d = Diagram([f, g, h, i])
916
+
917
+ grid = DiagramGrid(d, layout="sequential")
918
+ drawer = XypicDiagramDrawer()
919
+ assert drawer.draw(d, grid) == xypic_draw_diagram(d, layout="sequential")
lib/python3.10/site-packages/sympy/codegen/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (1.12 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/abstract_nodes.cpython-310.pyc ADDED
Binary file (976 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/algorithms.cpython-310.pyc ADDED
Binary file (6.81 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/approximations.cpython-310.pyc ADDED
Binary file (6.36 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/ast.cpython-310.pyc ADDED
Binary file (60.5 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/cfunctions.cpython-310.pyc ADDED
Binary file (14.1 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/cnodes.cpython-310.pyc ADDED
Binary file (4.92 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/cutils.cpython-310.pyc ADDED
Binary file (744 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/cxxnodes.cpython-310.pyc ADDED
Binary file (727 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/fnodes.cpython-310.pyc ADDED
Binary file (21.3 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/futils.cpython-310.pyc ADDED
Binary file (2.04 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/matrix_nodes.cpython-310.pyc ADDED
Binary file (2.79 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/numpy_nodes.cpython-310.pyc ADDED
Binary file (3.87 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/pynodes.cpython-310.pyc ADDED
Binary file (695 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/pyutils.cpython-310.pyc ADDED
Binary file (1.19 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/rewriting.cpython-310.pyc ADDED
Binary file (13.5 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/__pycache__/scipy_nodes.cpython-310.pyc ADDED
Binary file (3.29 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__init__.py ADDED
File without changes
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (210 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_abstract_nodes.cpython-310.pyc ADDED
Binary file (896 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_algorithms.cpython-310.pyc ADDED
Binary file (7.12 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_applications.cpython-310.pyc ADDED
Binary file (2.37 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_approximations.cpython-310.pyc ADDED
Binary file (2.13 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_ast.cpython-310.pyc ADDED
Binary file (22.6 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cfunctions.cpython-310.pyc ADDED
Binary file (4.9 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cnodes.cpython-310.pyc ADDED
Binary file (3.79 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_cxxnodes.cpython-310.pyc ADDED
Binary file (690 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_fnodes.cpython-310.pyc ADDED
Binary file (7.05 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_matrix_nodes.cpython-310.pyc ADDED
Binary file (2.51 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_numpy_nodes.cpython-310.pyc ADDED
Binary file (1.85 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_pynodes.cpython-310.pyc ADDED
Binary file (866 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_pyutils.cpython-310.pyc ADDED
Binary file (599 Bytes). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_rewriting.cpython-310.pyc ADDED
Binary file (14.8 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/__pycache__/test_scipy_nodes.cpython-310.pyc ADDED
Binary file (1.71 kB). View file
 
lib/python3.10/site-packages/sympy/codegen/tests/test_abstract_nodes.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.symbol import symbols
2
+ from sympy.codegen.abstract_nodes import List
3
+
4
+
5
+ def test_List():
6
+ l = List(2, 3, 4)
7
+ assert l == List(2, 3, 4)
8
+ assert str(l) == "[2, 3, 4]"
9
+ x, y, z = symbols('x y z')
10
+ l = List(x**2,y**3,z**4)
11
+ # contrary to python's built-in list, we can call e.g. "replace" on List.
12
+ m = l.replace(lambda arg: arg.is_Pow and arg.exp>2, lambda p: p.base-p.exp)
13
+ assert m == [x**2, y-3, z-4]
14
+ hash(m)
lib/python3.10/site-packages/sympy/codegen/tests/test_algorithms.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ from sympy import log, Min, Max, sqrt
3
+ from sympy.core.numbers import Float
4
+ from sympy.core.symbol import Symbol, symbols
5
+ from sympy.functions.elementary.trigonometric import cos
6
+ from sympy.codegen.ast import Assignment, Raise, RuntimeError_, QuotedString
7
+ from sympy.codegen.algorithms import newtons_method, newtons_method_function
8
+ from sympy.codegen.cfunctions import expm1
9
+ from sympy.codegen.fnodes import bind_C
10
+ from sympy.codegen.futils import render_as_module as f_module
11
+ from sympy.codegen.pyutils import render_as_module as py_module
12
+ from sympy.external import import_module
13
+ from sympy.printing.codeprinter import ccode
14
+ from sympy.utilities._compilation import compile_link_import_strings, has_c, has_fortran
15
+ from sympy.utilities._compilation.util import may_xfail
16
+ from sympy.testing.pytest import skip, raises
17
+
18
+ cython = import_module('cython')
19
+ wurlitzer = import_module('wurlitzer')
20
+
21
+ def test_newtons_method():
22
+ x, dx, atol = symbols('x dx atol')
23
+ expr = cos(x) - x**3
24
+ algo = newtons_method(expr, x, atol, dx)
25
+ assert algo.has(Assignment(dx, -expr/expr.diff(x)))
26
+
27
+
28
+ @may_xfail
29
+ def test_newtons_method_function__ccode():
30
+ x = Symbol('x', real=True)
31
+ expr = cos(x) - x**3
32
+ func = newtons_method_function(expr, x)
33
+
34
+ if not cython:
35
+ skip("cython not installed.")
36
+ if not has_c():
37
+ skip("No C compiler found.")
38
+
39
+ compile_kw = {"std": 'c99'}
40
+ with tempfile.TemporaryDirectory() as folder:
41
+ mod, info = compile_link_import_strings([
42
+ ('newton.c', ('#include <math.h>\n'
43
+ '#include <stdio.h>\n') + ccode(func)),
44
+ ('_newton.pyx', ("#cython: language_level={}\n".format("3") +
45
+ "cdef extern double newton(double)\n"
46
+ "def py_newton(x):\n"
47
+ " return newton(x)\n"))
48
+ ], build_dir=folder, compile_kwargs=compile_kw)
49
+ assert abs(mod.py_newton(0.5) - 0.865474033102) < 1e-12
50
+
51
+
52
+ @may_xfail
53
+ def test_newtons_method_function__fcode():
54
+ x = Symbol('x', real=True)
55
+ expr = cos(x) - x**3
56
+ func = newtons_method_function(expr, x, attrs=[bind_C(name='newton')])
57
+
58
+ if not cython:
59
+ skip("cython not installed.")
60
+ if not has_fortran():
61
+ skip("No Fortran compiler found.")
62
+
63
+ f_mod = f_module([func], 'mod_newton')
64
+ with tempfile.TemporaryDirectory() as folder:
65
+ mod, info = compile_link_import_strings([
66
+ ('newton.f90', f_mod),
67
+ ('_newton.pyx', ("#cython: language_level={}\n".format("3") +
68
+ "cdef extern double newton(double*)\n"
69
+ "def py_newton(double x):\n"
70
+ " return newton(&x)\n"))
71
+ ], build_dir=folder)
72
+ assert abs(mod.py_newton(0.5) - 0.865474033102) < 1e-12
73
+
74
+
75
+ def test_newtons_method_function__pycode():
76
+ x = Symbol('x', real=True)
77
+ expr = cos(x) - x**3
78
+ func = newtons_method_function(expr, x)
79
+ py_mod = py_module(func)
80
+ namespace = {}
81
+ exec(py_mod, namespace, namespace)
82
+ res = eval('newton(0.5)', namespace)
83
+ assert abs(res - 0.865474033102) < 1e-12
84
+
85
+
86
+ @may_xfail
87
+ def test_newtons_method_function__ccode_parameters():
88
+ args = x, A, k, p = symbols('x A k p')
89
+ expr = A*cos(k*x) - p*x**3
90
+ raises(ValueError, lambda: newtons_method_function(expr, x))
91
+ use_wurlitzer = wurlitzer
92
+
93
+ func = newtons_method_function(expr, x, args, debug=use_wurlitzer)
94
+
95
+ if not has_c():
96
+ skip("No C compiler found.")
97
+ if not cython:
98
+ skip("cython not installed.")
99
+
100
+ compile_kw = {"std": 'c99'}
101
+ with tempfile.TemporaryDirectory() as folder:
102
+ mod, info = compile_link_import_strings([
103
+ ('newton_par.c', ('#include <math.h>\n'
104
+ '#include <stdio.h>\n') + ccode(func)),
105
+ ('_newton_par.pyx', ("#cython: language_level={}\n".format("3") +
106
+ "cdef extern double newton(double, double, double, double)\n"
107
+ "def py_newton(x, A=1, k=1, p=1):\n"
108
+ " return newton(x, A, k, p)\n"))
109
+ ], compile_kwargs=compile_kw, build_dir=folder)
110
+
111
+ if use_wurlitzer:
112
+ with wurlitzer.pipes() as (out, err):
113
+ result = mod.py_newton(0.5)
114
+ else:
115
+ result = mod.py_newton(0.5)
116
+
117
+ assert abs(result - 0.865474033102) < 1e-12
118
+
119
+ if not use_wurlitzer:
120
+ skip("C-level output only tested when package 'wurlitzer' is available.")
121
+
122
+ out, err = out.read(), err.read()
123
+ assert err == ''
124
+ assert out == """\
125
+ x= 0.5
126
+ x= 1.1121 d_x= 0.61214
127
+ x= 0.90967 d_x= -0.20247
128
+ x= 0.86726 d_x= -0.042409
129
+ x= 0.86548 d_x= -0.0017867
130
+ x= 0.86547 d_x= -3.1022e-06
131
+ x= 0.86547 d_x= -9.3421e-12
132
+ x= 0.86547 d_x= 3.6902e-17
133
+ """ # try to run tests with LC_ALL=C if this assertion fails
134
+
135
+
136
+ def test_newtons_method_function__rtol_cse_nan():
137
+ a, b, c, N_geo, N_tot = symbols('a b c N_geo N_tot', real=True, nonnegative=True)
138
+ i = Symbol('i', integer=True, nonnegative=True)
139
+ N_ari = N_tot - N_geo - 1
140
+ delta_ari = (c-b)/N_ari
141
+ ln_delta_geo = log(b) + log(-expm1((log(a)-log(b))/N_geo))
142
+ eqb_log = ln_delta_geo - log(delta_ari)
143
+
144
+ def _clamp(low, expr, high):
145
+ return Min(Max(low, expr), high)
146
+
147
+ meth_kw = {
148
+ 'clamped_newton': {'delta_fn': lambda e, x: _clamp(
149
+ (sqrt(a*x)-x)*0.99,
150
+ -e/e.diff(x),
151
+ (sqrt(c*x)-x)*0.99
152
+ )},
153
+ 'halley': {'delta_fn': lambda e, x: (-2*(e*e.diff(x))/(2*e.diff(x)**2 - e*e.diff(x, 2)))},
154
+ 'halley_alt': {'delta_fn': lambda e, x: (-e/e.diff(x)/(1-e/e.diff(x)*e.diff(x,2)/2/e.diff(x)))},
155
+ }
156
+ args = eqb_log, b
157
+ for use_cse in [False, True]:
158
+ kwargs = {
159
+ 'params': (b, a, c, N_geo, N_tot), 'itermax': 60, 'debug': True, 'cse': use_cse,
160
+ 'counter': i, 'atol': 1e-100, 'rtol': 2e-16, 'bounds': (a,c),
161
+ 'handle_nan': Raise(RuntimeError_(QuotedString("encountered NaN.")))
162
+ }
163
+ func = {k: newtons_method_function(*args, func_name=f"{k}_b", **dict(kwargs, **kw)) for k, kw in meth_kw.items()}
164
+ py_mod = {k: py_module(v) for k, v in func.items()}
165
+ namespace = {}
166
+ root_find_b = {}
167
+ for k, v in py_mod.items():
168
+ ns = namespace[k] = {}
169
+ exec(v, ns, ns)
170
+ root_find_b[k] = ns[f'{k}_b']
171
+ ref = Float('13.2261515064168768938151923226496')
172
+ reftol = {'clamped_newton': 2e-16, 'halley': 2e-16, 'halley_alt': 3e-16}
173
+ guess = 4.0
174
+ for meth, func in root_find_b.items():
175
+ result = func(guess, 1e-2, 1e2, 50, 100)
176
+ req = ref*reftol[meth]
177
+ if use_cse:
178
+ req *= 2
179
+ assert abs(result - ref) < req
lib/python3.10/site-packages/sympy/codegen/tests/test_applications.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file contains tests that exercise multiple AST nodes
2
+
3
+ import tempfile
4
+
5
+ from sympy.external import import_module
6
+ from sympy.printing.codeprinter import ccode
7
+ from sympy.utilities._compilation import compile_link_import_strings, has_c
8
+ from sympy.utilities._compilation.util import may_xfail
9
+ from sympy.testing.pytest import skip
10
+ from sympy.codegen.ast import (
11
+ FunctionDefinition, FunctionPrototype, Variable, Pointer, real, Assignment,
12
+ integer, CodeBlock, While
13
+ )
14
+ from sympy.codegen.cnodes import void, PreIncrement
15
+ from sympy.codegen.cutils import render_as_source_file
16
+
17
+ cython = import_module('cython')
18
+ np = import_module('numpy')
19
+
20
+ def _mk_func1():
21
+ declars = n, inp, out = Variable('n', integer), Pointer('inp', real), Pointer('out', real)
22
+ i = Variable('i', integer)
23
+ whl = While(i<n, [Assignment(out[i], inp[i]), PreIncrement(i)])
24
+ body = CodeBlock(i.as_Declaration(value=0), whl)
25
+ return FunctionDefinition(void, 'our_test_function', declars, body)
26
+
27
+
28
+ def _render_compile_import(funcdef, build_dir):
29
+ code_str = render_as_source_file(funcdef, settings={"contract": False})
30
+ declar = ccode(FunctionPrototype.from_FunctionDefinition(funcdef))
31
+ return compile_link_import_strings([
32
+ ('our_test_func.c', code_str),
33
+ ('_our_test_func.pyx', ("#cython: language_level={}\n".format("3") +
34
+ "cdef extern {declar}\n"
35
+ "def _{fname}({typ}[:] inp, {typ}[:] out):\n"
36
+ " {fname}(inp.size, &inp[0], &out[0])").format(
37
+ declar=declar, fname=funcdef.name, typ='double'
38
+ ))
39
+ ], build_dir=build_dir)
40
+
41
+
42
+ @may_xfail
43
+ def test_copying_function():
44
+ if not np:
45
+ skip("numpy not installed.")
46
+ if not has_c():
47
+ skip("No C compiler found.")
48
+ if not cython:
49
+ skip("Cython not found.")
50
+
51
+ info = None
52
+ with tempfile.TemporaryDirectory() as folder:
53
+ mod, info = _render_compile_import(_mk_func1(), build_dir=folder)
54
+ inp = np.arange(10.0)
55
+ out = np.empty_like(inp)
56
+ mod._our_test_function(inp, out)
57
+ assert np.allclose(inp, out)
lib/python3.10/site-packages/sympy/codegen/tests/test_approximations.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from sympy.core.symbol import symbols
3
+ from sympy.functions.elementary.exponential import exp
4
+ from sympy.codegen.rewriting import optimize
5
+ from sympy.codegen.approximations import SumApprox, SeriesApprox
6
+
7
+
8
+ def test_SumApprox_trivial():
9
+ x = symbols('x')
10
+ expr1 = 1 + x
11
+ sum_approx = SumApprox(bounds={x: (-1e-20, 1e-20)}, reltol=1e-16)
12
+ apx1 = optimize(expr1, [sum_approx])
13
+ assert apx1 - 1 == 0
14
+
15
+
16
+ def test_SumApprox_monotone_terms():
17
+ x, y, z = symbols('x y z')
18
+ expr1 = exp(z)*(x**2 + y**2 + 1)
19
+ bnds1 = {x: (0, 1e-3), y: (100, 1000)}
20
+ sum_approx_m2 = SumApprox(bounds=bnds1, reltol=1e-2)
21
+ sum_approx_m5 = SumApprox(bounds=bnds1, reltol=1e-5)
22
+ sum_approx_m11 = SumApprox(bounds=bnds1, reltol=1e-11)
23
+ assert (optimize(expr1, [sum_approx_m2])/exp(z) - (y**2)).simplify() == 0
24
+ assert (optimize(expr1, [sum_approx_m5])/exp(z) - (y**2 + 1)).simplify() == 0
25
+ assert (optimize(expr1, [sum_approx_m11])/exp(z) - (y**2 + 1 + x**2)).simplify() == 0
26
+
27
+
28
+ def test_SeriesApprox_trivial():
29
+ x, z = symbols('x z')
30
+ for factor in [1, exp(z)]:
31
+ x = symbols('x')
32
+ expr1 = exp(x)*factor
33
+ bnds1 = {x: (-1, 1)}
34
+ series_approx_50 = SeriesApprox(bounds=bnds1, reltol=0.50)
35
+ series_approx_10 = SeriesApprox(bounds=bnds1, reltol=0.10)
36
+ series_approx_05 = SeriesApprox(bounds=bnds1, reltol=0.05)
37
+ c = (bnds1[x][1] + bnds1[x][0])/2 # 0.0
38
+ f0 = math.exp(c) # 1.0
39
+
40
+ ref_50 = f0 + x + x**2/2
41
+ ref_10 = f0 + x + x**2/2 + x**3/6
42
+ ref_05 = f0 + x + x**2/2 + x**3/6 + x**4/24
43
+
44
+ res_50 = optimize(expr1, [series_approx_50])
45
+ res_10 = optimize(expr1, [series_approx_10])
46
+ res_05 = optimize(expr1, [series_approx_05])
47
+
48
+ assert (res_50/factor - ref_50).simplify() == 0
49
+ assert (res_10/factor - ref_10).simplify() == 0
50
+ assert (res_05/factor - ref_05).simplify() == 0
51
+
52
+ max_ord3 = SeriesApprox(bounds=bnds1, reltol=0.05, max_order=3)
53
+ assert optimize(expr1, [max_ord3]) == expr1
lib/python3.10/site-packages/sympy/codegen/tests/test_ast.py ADDED
@@ -0,0 +1,661 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from sympy.core.containers import Tuple
3
+ from sympy.core.numbers import nan, oo, Float, Integer
4
+ from sympy.core.relational import Lt
5
+ from sympy.core.symbol import symbols, Symbol
6
+ from sympy.functions.elementary.trigonometric import sin
7
+ from sympy.matrices.dense import Matrix
8
+ from sympy.matrices.expressions.matexpr import MatrixSymbol
9
+ from sympy.sets.fancysets import Range
10
+ from sympy.tensor.indexed import Idx, IndexedBase
11
+ from sympy.testing.pytest import raises
12
+
13
+
14
+ from sympy.codegen.ast import (
15
+ Assignment, Attribute, aug_assign, CodeBlock, For, Type, Variable, Pointer, Declaration,
16
+ AddAugmentedAssignment, SubAugmentedAssignment, MulAugmentedAssignment,
17
+ DivAugmentedAssignment, ModAugmentedAssignment, value_const, pointer_const,
18
+ integer, real, complex_, int8, uint8, float16 as f16, float32 as f32,
19
+ float64 as f64, float80 as f80, float128 as f128, complex64 as c64, complex128 as c128,
20
+ While, Scope, String, Print, QuotedString, FunctionPrototype, FunctionDefinition, Return,
21
+ FunctionCall, untyped, IntBaseType, intc, Node, none, NoneToken, Token, Comment
22
+ )
23
+
24
+ x, y, z, t, x0, x1, x2, a, b = symbols("x, y, z, t, x0, x1, x2, a, b")
25
+ n = symbols("n", integer=True)
26
+ A = MatrixSymbol('A', 3, 1)
27
+ mat = Matrix([1, 2, 3])
28
+ B = IndexedBase('B')
29
+ i = Idx("i", n)
30
+ A22 = MatrixSymbol('A22',2,2)
31
+ B22 = MatrixSymbol('B22',2,2)
32
+
33
+
34
+ def test_Assignment():
35
+ # Here we just do things to show they don't error
36
+ Assignment(x, y)
37
+ Assignment(x, 0)
38
+ Assignment(A, mat)
39
+ Assignment(A[1,0], 0)
40
+ Assignment(A[1,0], x)
41
+ Assignment(B[i], x)
42
+ Assignment(B[i], 0)
43
+ a = Assignment(x, y)
44
+ assert a.func(*a.args) == a
45
+ assert a.op == ':='
46
+ # Here we test things to show that they error
47
+ # Matrix to scalar
48
+ raises(ValueError, lambda: Assignment(B[i], A))
49
+ raises(ValueError, lambda: Assignment(B[i], mat))
50
+ raises(ValueError, lambda: Assignment(x, mat))
51
+ raises(ValueError, lambda: Assignment(x, A))
52
+ raises(ValueError, lambda: Assignment(A[1,0], mat))
53
+ # Scalar to matrix
54
+ raises(ValueError, lambda: Assignment(A, x))
55
+ raises(ValueError, lambda: Assignment(A, 0))
56
+ # Non-atomic lhs
57
+ raises(TypeError, lambda: Assignment(mat, A))
58
+ raises(TypeError, lambda: Assignment(0, x))
59
+ raises(TypeError, lambda: Assignment(x*x, 1))
60
+ raises(TypeError, lambda: Assignment(A + A, mat))
61
+ raises(TypeError, lambda: Assignment(B, 0))
62
+
63
+
64
+ def test_AugAssign():
65
+ # Here we just do things to show they don't error
66
+ aug_assign(x, '+', y)
67
+ aug_assign(x, '+', 0)
68
+ aug_assign(A, '+', mat)
69
+ aug_assign(A[1, 0], '+', 0)
70
+ aug_assign(A[1, 0], '+', x)
71
+ aug_assign(B[i], '+', x)
72
+ aug_assign(B[i], '+', 0)
73
+
74
+ # Check creation via aug_assign vs constructor
75
+ for binop, cls in [
76
+ ('+', AddAugmentedAssignment),
77
+ ('-', SubAugmentedAssignment),
78
+ ('*', MulAugmentedAssignment),
79
+ ('/', DivAugmentedAssignment),
80
+ ('%', ModAugmentedAssignment),
81
+ ]:
82
+ a = aug_assign(x, binop, y)
83
+ b = cls(x, y)
84
+ assert a.func(*a.args) == a == b
85
+ assert a.binop == binop
86
+ assert a.op == binop + '='
87
+
88
+ # Here we test things to show that they error
89
+ # Matrix to scalar
90
+ raises(ValueError, lambda: aug_assign(B[i], '+', A))
91
+ raises(ValueError, lambda: aug_assign(B[i], '+', mat))
92
+ raises(ValueError, lambda: aug_assign(x, '+', mat))
93
+ raises(ValueError, lambda: aug_assign(x, '+', A))
94
+ raises(ValueError, lambda: aug_assign(A[1, 0], '+', mat))
95
+ # Scalar to matrix
96
+ raises(ValueError, lambda: aug_assign(A, '+', x))
97
+ raises(ValueError, lambda: aug_assign(A, '+', 0))
98
+ # Non-atomic lhs
99
+ raises(TypeError, lambda: aug_assign(mat, '+', A))
100
+ raises(TypeError, lambda: aug_assign(0, '+', x))
101
+ raises(TypeError, lambda: aug_assign(x * x, '+', 1))
102
+ raises(TypeError, lambda: aug_assign(A + A, '+', mat))
103
+ raises(TypeError, lambda: aug_assign(B, '+', 0))
104
+
105
+
106
+ def test_Assignment_printing():
107
+ assignment_classes = [
108
+ Assignment,
109
+ AddAugmentedAssignment,
110
+ SubAugmentedAssignment,
111
+ MulAugmentedAssignment,
112
+ DivAugmentedAssignment,
113
+ ModAugmentedAssignment,
114
+ ]
115
+ pairs = [
116
+ (x, 2 * y + 2),
117
+ (B[i], x),
118
+ (A22, B22),
119
+ (A[0, 0], x),
120
+ ]
121
+
122
+ for cls in assignment_classes:
123
+ for lhs, rhs in pairs:
124
+ a = cls(lhs, rhs)
125
+ assert repr(a) == '%s(%s, %s)' % (cls.__name__, repr(lhs), repr(rhs))
126
+
127
+
128
+ def test_CodeBlock():
129
+ c = CodeBlock(Assignment(x, 1), Assignment(y, x + 1))
130
+ assert c.func(*c.args) == c
131
+
132
+ assert c.left_hand_sides == Tuple(x, y)
133
+ assert c.right_hand_sides == Tuple(1, x + 1)
134
+
135
+ def test_CodeBlock_topological_sort():
136
+ assignments = [
137
+ Assignment(x, y + z),
138
+ Assignment(z, 1),
139
+ Assignment(t, x),
140
+ Assignment(y, 2),
141
+ ]
142
+
143
+ ordered_assignments = [
144
+ # Note that the unrelated z=1 and y=2 are kept in that order
145
+ Assignment(z, 1),
146
+ Assignment(y, 2),
147
+ Assignment(x, y + z),
148
+ Assignment(t, x),
149
+ ]
150
+ c1 = CodeBlock.topological_sort(assignments)
151
+ assert c1 == CodeBlock(*ordered_assignments)
152
+
153
+ # Cycle
154
+ invalid_assignments = [
155
+ Assignment(x, y + z),
156
+ Assignment(z, 1),
157
+ Assignment(y, x),
158
+ Assignment(y, 2),
159
+ ]
160
+
161
+ raises(ValueError, lambda: CodeBlock.topological_sort(invalid_assignments))
162
+
163
+ # Free symbols
164
+ free_assignments = [
165
+ Assignment(x, y + z),
166
+ Assignment(z, a * b),
167
+ Assignment(t, x),
168
+ Assignment(y, b + 3),
169
+ ]
170
+
171
+ free_assignments_ordered = [
172
+ Assignment(z, a * b),
173
+ Assignment(y, b + 3),
174
+ Assignment(x, y + z),
175
+ Assignment(t, x),
176
+ ]
177
+
178
+ c2 = CodeBlock.topological_sort(free_assignments)
179
+ assert c2 == CodeBlock(*free_assignments_ordered)
180
+
181
+ def test_CodeBlock_free_symbols():
182
+ c1 = CodeBlock(
183
+ Assignment(x, y + z),
184
+ Assignment(z, 1),
185
+ Assignment(t, x),
186
+ Assignment(y, 2),
187
+ )
188
+ assert c1.free_symbols == set()
189
+
190
+ c2 = CodeBlock(
191
+ Assignment(x, y + z),
192
+ Assignment(z, a * b),
193
+ Assignment(t, x),
194
+ Assignment(y, b + 3),
195
+ )
196
+ assert c2.free_symbols == {a, b}
197
+
198
+ def test_CodeBlock_cse():
199
+ c1 = CodeBlock(
200
+ Assignment(y, 1),
201
+ Assignment(x, sin(y)),
202
+ Assignment(z, sin(y)),
203
+ Assignment(t, x*z),
204
+ )
205
+ assert c1.cse() == CodeBlock(
206
+ Assignment(y, 1),
207
+ Assignment(x0, sin(y)),
208
+ Assignment(x, x0),
209
+ Assignment(z, x0),
210
+ Assignment(t, x*z),
211
+ )
212
+
213
+ # Multiple assignments to same symbol not supported
214
+ raises(NotImplementedError, lambda: CodeBlock(
215
+ Assignment(x, 1),
216
+ Assignment(y, 1), Assignment(y, 2)
217
+ ).cse())
218
+
219
+ # Check auto-generated symbols do not collide with existing ones
220
+ c2 = CodeBlock(
221
+ Assignment(x0, sin(y) + 1),
222
+ Assignment(x1, 2 * sin(y)),
223
+ Assignment(z, x * y),
224
+ )
225
+ assert c2.cse() == CodeBlock(
226
+ Assignment(x2, sin(y)),
227
+ Assignment(x0, x2 + 1),
228
+ Assignment(x1, 2 * x2),
229
+ Assignment(z, x * y),
230
+ )
231
+
232
+
233
+ def test_CodeBlock_cse__issue_14118():
234
+ # see https://github.com/sympy/sympy/issues/14118
235
+ c = CodeBlock(
236
+ Assignment(A22, Matrix([[x, sin(y)],[3, 4]])),
237
+ Assignment(B22, Matrix([[sin(y), 2*sin(y)], [sin(y)**2, 7]]))
238
+ )
239
+ assert c.cse() == CodeBlock(
240
+ Assignment(x0, sin(y)),
241
+ Assignment(A22, Matrix([[x, x0],[3, 4]])),
242
+ Assignment(B22, Matrix([[x0, 2*x0], [x0**2, 7]]))
243
+ )
244
+
245
+ def test_For():
246
+ f = For(n, Range(0, 3), (Assignment(A[n, 0], x + n), aug_assign(x, '+', y)))
247
+ f = For(n, (1, 2, 3, 4, 5), (Assignment(A[n, 0], x + n),))
248
+ assert f.func(*f.args) == f
249
+ raises(TypeError, lambda: For(n, x, (x + y,)))
250
+
251
+
252
+ def test_none():
253
+ assert none.is_Atom
254
+ assert none == none
255
+ class Foo(Token):
256
+ pass
257
+ foo = Foo()
258
+ assert foo != none
259
+ assert none == None
260
+ assert none == NoneToken()
261
+ assert none.func(*none.args) == none
262
+
263
+
264
+ def test_String():
265
+ st = String('foobar')
266
+ assert st.is_Atom
267
+ assert st == String('foobar')
268
+ assert st.text == 'foobar'
269
+ assert st.func(**st.kwargs()) == st
270
+ assert st.func(*st.args) == st
271
+
272
+
273
+ class Signifier(String):
274
+ pass
275
+
276
+ si = Signifier('foobar')
277
+ assert si != st
278
+ assert si.text == st.text
279
+ s = String('foo')
280
+ assert str(s) == 'foo'
281
+ assert repr(s) == "String('foo')"
282
+
283
+ def test_Comment():
284
+ c = Comment('foobar')
285
+ assert c.text == 'foobar'
286
+ assert str(c) == 'foobar'
287
+
288
+ def test_Node():
289
+ n = Node()
290
+ assert n == Node()
291
+ assert n.func(*n.args) == n
292
+
293
+
294
+ def test_Type():
295
+ t = Type('MyType')
296
+ assert len(t.args) == 1
297
+ assert t.name == String('MyType')
298
+ assert str(t) == 'MyType'
299
+ assert repr(t) == "Type(String('MyType'))"
300
+ assert Type(t) == t
301
+ assert t.func(*t.args) == t
302
+ t1 = Type('t1')
303
+ t2 = Type('t2')
304
+ assert t1 != t2
305
+ assert t1 == t1 and t2 == t2
306
+ t1b = Type('t1')
307
+ assert t1 == t1b
308
+ assert t2 != t1b
309
+
310
+
311
+ def test_Type__from_expr():
312
+ assert Type.from_expr(i) == integer
313
+ u = symbols('u', real=True)
314
+ assert Type.from_expr(u) == real
315
+ assert Type.from_expr(n) == integer
316
+ assert Type.from_expr(3) == integer
317
+ assert Type.from_expr(3.0) == real
318
+ assert Type.from_expr(3+1j) == complex_
319
+ raises(ValueError, lambda: Type.from_expr(sum))
320
+
321
+
322
+ def test_Type__cast_check__integers():
323
+ # Rounding
324
+ raises(ValueError, lambda: integer.cast_check(3.5))
325
+ assert integer.cast_check('3') == 3
326
+ assert integer.cast_check(Float('3.0000000000000000000')) == 3
327
+ assert integer.cast_check(Float('3.0000000000000000001')) == 3 # unintuitive maybe?
328
+
329
+ # Range
330
+ assert int8.cast_check(127.0) == 127
331
+ raises(ValueError, lambda: int8.cast_check(128))
332
+ assert int8.cast_check(-128) == -128
333
+ raises(ValueError, lambda: int8.cast_check(-129))
334
+
335
+ assert uint8.cast_check(0) == 0
336
+ assert uint8.cast_check(128) == 128
337
+ raises(ValueError, lambda: uint8.cast_check(256.0))
338
+ raises(ValueError, lambda: uint8.cast_check(-1))
339
+
340
+ def test_Attribute():
341
+ noexcept = Attribute('noexcept')
342
+ assert noexcept == Attribute('noexcept')
343
+ alignas16 = Attribute('alignas', [16])
344
+ alignas32 = Attribute('alignas', [32])
345
+ assert alignas16 != alignas32
346
+ assert alignas16.func(*alignas16.args) == alignas16
347
+
348
+
349
+ def test_Variable():
350
+ v = Variable(x, type=real)
351
+ assert v == Variable(v)
352
+ assert v == Variable('x', type=real)
353
+ assert v.symbol == x
354
+ assert v.type == real
355
+ assert value_const not in v.attrs
356
+ assert v.func(*v.args) == v
357
+ assert str(v) == 'Variable(x, type=real)'
358
+
359
+ w = Variable(y, f32, attrs={value_const})
360
+ assert w.symbol == y
361
+ assert w.type == f32
362
+ assert value_const in w.attrs
363
+ assert w.func(*w.args) == w
364
+
365
+ v_n = Variable(n, type=Type.from_expr(n))
366
+ assert v_n.type == integer
367
+ assert v_n.func(*v_n.args) == v_n
368
+ v_i = Variable(i, type=Type.from_expr(n))
369
+ assert v_i.type == integer
370
+ assert v_i != v_n
371
+
372
+ a_i = Variable.deduced(i)
373
+ assert a_i.type == integer
374
+ assert Variable.deduced(Symbol('x', real=True)).type == real
375
+ assert a_i.func(*a_i.args) == a_i
376
+
377
+ v_n2 = Variable.deduced(n, value=3.5, cast_check=False)
378
+ assert v_n2.func(*v_n2.args) == v_n2
379
+ assert abs(v_n2.value - 3.5) < 1e-15
380
+ raises(ValueError, lambda: Variable.deduced(n, value=3.5, cast_check=True))
381
+
382
+ v_n3 = Variable.deduced(n)
383
+ assert v_n3.type == integer
384
+ assert str(v_n3) == 'Variable(n, type=integer)'
385
+ assert Variable.deduced(z, value=3).type == integer
386
+ assert Variable.deduced(z, value=3.0).type == real
387
+ assert Variable.deduced(z, value=3.0+1j).type == complex_
388
+
389
+
390
+ def test_Pointer():
391
+ p = Pointer(x)
392
+ assert p.symbol == x
393
+ assert p.type == untyped
394
+ assert value_const not in p.attrs
395
+ assert pointer_const not in p.attrs
396
+ assert p.func(*p.args) == p
397
+
398
+ u = symbols('u', real=True)
399
+ pu = Pointer(u, type=Type.from_expr(u), attrs={value_const, pointer_const})
400
+ assert pu.symbol is u
401
+ assert pu.type == real
402
+ assert value_const in pu.attrs
403
+ assert pointer_const in pu.attrs
404
+ assert pu.func(*pu.args) == pu
405
+
406
+ i = symbols('i', integer=True)
407
+ deref = pu[i]
408
+ assert deref.indices == (i,)
409
+
410
+
411
+ def test_Declaration():
412
+ u = symbols('u', real=True)
413
+ vu = Variable(u, type=Type.from_expr(u))
414
+ assert Declaration(vu).variable.type == real
415
+ vn = Variable(n, type=Type.from_expr(n))
416
+ assert Declaration(vn).variable.type == integer
417
+
418
+ # PR 19107, does not allow comparison between expressions and Basic
419
+ # lt = StrictLessThan(vu, vn)
420
+ # assert isinstance(lt, StrictLessThan)
421
+
422
+ vuc = Variable(u, Type.from_expr(u), value=3.0, attrs={value_const})
423
+ assert value_const in vuc.attrs
424
+ assert pointer_const not in vuc.attrs
425
+ decl = Declaration(vuc)
426
+ assert decl.variable == vuc
427
+ assert isinstance(decl.variable.value, Float)
428
+ assert decl.variable.value == 3.0
429
+ assert decl.func(*decl.args) == decl
430
+ assert vuc.as_Declaration() == decl
431
+ assert vuc.as_Declaration(value=None, attrs=None) == Declaration(vu)
432
+
433
+ vy = Variable(y, type=integer, value=3)
434
+ decl2 = Declaration(vy)
435
+ assert decl2.variable == vy
436
+ assert decl2.variable.value == Integer(3)
437
+
438
+ vi = Variable(i, type=Type.from_expr(i), value=3.0)
439
+ decl3 = Declaration(vi)
440
+ assert decl3.variable.type == integer
441
+ assert decl3.variable.value == 3.0
442
+
443
+ raises(ValueError, lambda: Declaration(vi, 42))
444
+
445
+
446
+ def test_IntBaseType():
447
+ assert intc.name == String('intc')
448
+ assert intc.args == (intc.name,)
449
+ assert str(IntBaseType('a').name) == 'a'
450
+
451
+
452
+ def test_FloatType():
453
+ assert f16.dig == 3
454
+ assert f32.dig == 6
455
+ assert f64.dig == 15
456
+ assert f80.dig == 18
457
+ assert f128.dig == 33
458
+
459
+ assert f16.decimal_dig == 5
460
+ assert f32.decimal_dig == 9
461
+ assert f64.decimal_dig == 17
462
+ assert f80.decimal_dig == 21
463
+ assert f128.decimal_dig == 36
464
+
465
+ assert f16.max_exponent == 16
466
+ assert f32.max_exponent == 128
467
+ assert f64.max_exponent == 1024
468
+ assert f80.max_exponent == 16384
469
+ assert f128.max_exponent == 16384
470
+
471
+ assert f16.min_exponent == -13
472
+ assert f32.min_exponent == -125
473
+ assert f64.min_exponent == -1021
474
+ assert f80.min_exponent == -16381
475
+ assert f128.min_exponent == -16381
476
+
477
+ assert abs(f16.eps / Float('0.00097656', precision=16) - 1) < 0.1*10**-f16.dig
478
+ assert abs(f32.eps / Float('1.1920929e-07', precision=32) - 1) < 0.1*10**-f32.dig
479
+ assert abs(f64.eps / Float('2.2204460492503131e-16', precision=64) - 1) < 0.1*10**-f64.dig
480
+ assert abs(f80.eps / Float('1.08420217248550443401e-19', precision=80) - 1) < 0.1*10**-f80.dig
481
+ assert abs(f128.eps / Float(' 1.92592994438723585305597794258492732e-34', precision=128) - 1) < 0.1*10**-f128.dig
482
+
483
+ assert abs(f16.max / Float('65504', precision=16) - 1) < .1*10**-f16.dig
484
+ assert abs(f32.max / Float('3.40282347e+38', precision=32) - 1) < 0.1*10**-f32.dig
485
+ assert abs(f64.max / Float('1.79769313486231571e+308', precision=64) - 1) < 0.1*10**-f64.dig # cf. np.finfo(np.float64).max
486
+ assert abs(f80.max / Float('1.18973149535723176502e+4932', precision=80) - 1) < 0.1*10**-f80.dig
487
+ assert abs(f128.max / Float('1.18973149535723176508575932662800702e+4932', precision=128) - 1) < 0.1*10**-f128.dig
488
+
489
+ # cf. np.finfo(np.float32).tiny
490
+ assert abs(f16.tiny / Float('6.1035e-05', precision=16) - 1) < 0.1*10**-f16.dig
491
+ assert abs(f32.tiny / Float('1.17549435e-38', precision=32) - 1) < 0.1*10**-f32.dig
492
+ assert abs(f64.tiny / Float('2.22507385850720138e-308', precision=64) - 1) < 0.1*10**-f64.dig
493
+ assert abs(f80.tiny / Float('3.36210314311209350626e-4932', precision=80) - 1) < 0.1*10**-f80.dig
494
+ assert abs(f128.tiny / Float('3.3621031431120935062626778173217526e-4932', precision=128) - 1) < 0.1*10**-f128.dig
495
+
496
+ assert f64.cast_check(0.5) == Float(0.5, 17)
497
+ assert abs(f64.cast_check(3.7) - 3.7) < 3e-17
498
+ assert isinstance(f64.cast_check(3), (Float, float))
499
+
500
+ assert f64.cast_nocheck(oo) == float('inf')
501
+ assert f64.cast_nocheck(-oo) == float('-inf')
502
+ assert f64.cast_nocheck(float(oo)) == float('inf')
503
+ assert f64.cast_nocheck(float(-oo)) == float('-inf')
504
+ assert math.isnan(f64.cast_nocheck(nan))
505
+
506
+ assert f32 != f64
507
+ assert f64 == f64.func(*f64.args)
508
+
509
+
510
+ def test_Type__cast_check__floating_point():
511
+ raises(ValueError, lambda: f32.cast_check(123.45678949))
512
+ raises(ValueError, lambda: f32.cast_check(12.345678949))
513
+ raises(ValueError, lambda: f32.cast_check(1.2345678949))
514
+ raises(ValueError, lambda: f32.cast_check(.12345678949))
515
+ assert abs(123.456789049 - f32.cast_check(123.456789049) - 4.9e-8) < 1e-8
516
+ assert abs(0.12345678904 - f32.cast_check(0.12345678904) - 4e-11) < 1e-11
517
+
518
+ dcm21 = Float('0.123456789012345670499') # 21 decimals
519
+ assert abs(dcm21 - f64.cast_check(dcm21) - 4.99e-19) < 1e-19
520
+
521
+ f80.cast_check(Float('0.12345678901234567890103', precision=88))
522
+ raises(ValueError, lambda: f80.cast_check(Float('0.12345678901234567890149', precision=88)))
523
+
524
+ v10 = 12345.67894
525
+ raises(ValueError, lambda: f32.cast_check(v10))
526
+ assert abs(Float(str(v10), precision=64+8) - f64.cast_check(v10)) < v10*1e-16
527
+
528
+ assert abs(f32.cast_check(2147483647) - 2147483650) < 1
529
+
530
+
531
+ def test_Type__cast_check__complex_floating_point():
532
+ val9_11 = 123.456789049 + 0.123456789049j
533
+ raises(ValueError, lambda: c64.cast_check(.12345678949 + .12345678949j))
534
+ assert abs(val9_11 - c64.cast_check(val9_11) - 4.9e-8) < 1e-8
535
+
536
+ dcm21 = Float('0.123456789012345670499') + 1e-20j # 21 decimals
537
+ assert abs(dcm21 - c128.cast_check(dcm21) - 4.99e-19) < 1e-19
538
+ v19 = Float('0.1234567890123456749') + 1j*Float('0.1234567890123456749')
539
+ raises(ValueError, lambda: c128.cast_check(v19))
540
+
541
+
542
+ def test_While():
543
+ xpp = AddAugmentedAssignment(x, 1)
544
+ whl1 = While(x < 2, [xpp])
545
+ assert whl1.condition.args[0] == x
546
+ assert whl1.condition.args[1] == 2
547
+ assert whl1.condition == Lt(x, 2, evaluate=False)
548
+ assert whl1.body.args == (xpp,)
549
+ assert whl1.func(*whl1.args) == whl1
550
+
551
+ cblk = CodeBlock(AddAugmentedAssignment(x, 1))
552
+ whl2 = While(x < 2, cblk)
553
+ assert whl1 == whl2
554
+ assert whl1 != While(x < 3, [xpp])
555
+
556
+
557
+ def test_Scope():
558
+ assign = Assignment(x, y)
559
+ incr = AddAugmentedAssignment(x, 1)
560
+ scp = Scope([assign, incr])
561
+ cblk = CodeBlock(assign, incr)
562
+ assert scp.body == cblk
563
+ assert scp == Scope(cblk)
564
+ assert scp != Scope([incr, assign])
565
+ assert scp.func(*scp.args) == scp
566
+
567
+
568
+ def test_Print():
569
+ fmt = "%d %.3f"
570
+ ps = Print([n, x], fmt)
571
+ assert str(ps.format_string) == fmt
572
+ assert ps.print_args == Tuple(n, x)
573
+ assert ps.args == (Tuple(n, x), QuotedString(fmt), none)
574
+ assert ps == Print((n, x), fmt)
575
+ assert ps != Print([x, n], fmt)
576
+ assert ps.func(*ps.args) == ps
577
+
578
+ ps2 = Print([n, x])
579
+ assert ps2 == Print([n, x])
580
+ assert ps2 != ps
581
+ assert ps2.format_string == None
582
+
583
+
584
+ def test_FunctionPrototype_and_FunctionDefinition():
585
+ vx = Variable(x, type=real)
586
+ vn = Variable(n, type=integer)
587
+ fp1 = FunctionPrototype(real, 'power', [vx, vn])
588
+ assert fp1.return_type == real
589
+ assert fp1.name == String('power')
590
+ assert fp1.parameters == Tuple(vx, vn)
591
+ assert fp1 == FunctionPrototype(real, 'power', [vx, vn])
592
+ assert fp1 != FunctionPrototype(real, 'power', [vn, vx])
593
+ assert fp1.func(*fp1.args) == fp1
594
+
595
+
596
+ body = [Assignment(x, x**n), Return(x)]
597
+ fd1 = FunctionDefinition(real, 'power', [vx, vn], body)
598
+ assert fd1.return_type == real
599
+ assert str(fd1.name) == 'power'
600
+ assert fd1.parameters == Tuple(vx, vn)
601
+ assert fd1.body == CodeBlock(*body)
602
+ assert fd1 == FunctionDefinition(real, 'power', [vx, vn], body)
603
+ assert fd1 != FunctionDefinition(real, 'power', [vx, vn], body[::-1])
604
+ assert fd1.func(*fd1.args) == fd1
605
+
606
+ fp2 = FunctionPrototype.from_FunctionDefinition(fd1)
607
+ assert fp2 == fp1
608
+
609
+ fd2 = FunctionDefinition.from_FunctionPrototype(fp1, body)
610
+ assert fd2 == fd1
611
+
612
+
613
+ def test_Return():
614
+ rs = Return(x)
615
+ assert rs.args == (x,)
616
+ assert rs == Return(x)
617
+ assert rs != Return(y)
618
+ assert rs.func(*rs.args) == rs
619
+
620
+
621
+ def test_FunctionCall():
622
+ fc = FunctionCall('power', (x, 3))
623
+ assert fc.function_args[0] == x
624
+ assert fc.function_args[1] == 3
625
+ assert len(fc.function_args) == 2
626
+ assert isinstance(fc.function_args[1], Integer)
627
+ assert fc == FunctionCall('power', (x, 3))
628
+ assert fc != FunctionCall('power', (3, x))
629
+ assert fc != FunctionCall('Power', (x, 3))
630
+ assert fc.func(*fc.args) == fc
631
+
632
+ fc2 = FunctionCall('fma', [2, 3, 4])
633
+ assert len(fc2.function_args) == 3
634
+ assert fc2.function_args[0] == 2
635
+ assert fc2.function_args[1] == 3
636
+ assert fc2.function_args[2] == 4
637
+ assert str(fc2) in ( # not sure if QuotedString is a better default...
638
+ 'FunctionCall(fma, function_args=(2, 3, 4))',
639
+ 'FunctionCall("fma", function_args=(2, 3, 4))',
640
+ )
641
+
642
+ def test_ast_replace():
643
+ x = Variable('x', real)
644
+ y = Variable('y', real)
645
+ n = Variable('n', integer)
646
+
647
+ pwer = FunctionDefinition(real, 'pwer', [x, n], [pow(x.symbol, n.symbol)])
648
+ pname = pwer.name
649
+ pcall = FunctionCall('pwer', [y, 3])
650
+
651
+ tree1 = CodeBlock(pwer, pcall)
652
+ assert str(tree1.args[0].name) == 'pwer'
653
+ assert str(tree1.args[1].name) == 'pwer'
654
+ for a, b in zip(tree1, [pwer, pcall]):
655
+ assert a == b
656
+
657
+ tree2 = tree1.replace(pname, String('power'))
658
+ assert str(tree1.args[0].name) == 'pwer'
659
+ assert str(tree1.args[1].name) == 'pwer'
660
+ assert str(tree2.args[0].name) == 'power'
661
+ assert str(tree2.args[1].name) == 'power'
lib/python3.10/site-packages/sympy/codegen/tests/test_cfunctions.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.numbers import (Rational, pi)
2
+ from sympy.core.singleton import S
3
+ from sympy.core.symbol import (Symbol, symbols)
4
+ from sympy.functions.elementary.exponential import (exp, log)
5
+ from sympy.codegen.cfunctions import (
6
+ expm1, log1p, exp2, log2, fma, log10, Sqrt, Cbrt, hypot
7
+ )
8
+ from sympy.core.function import expand_log
9
+
10
+
11
+ def test_expm1():
12
+ # Eval
13
+ assert expm1(0) == 0
14
+
15
+ x = Symbol('x', real=True)
16
+
17
+ # Expand and rewrite
18
+ assert expm1(x).expand(func=True) - exp(x) == -1
19
+ assert expm1(x).rewrite('tractable') - exp(x) == -1
20
+ assert expm1(x).rewrite('exp') - exp(x) == -1
21
+
22
+ # Precision
23
+ assert not ((exp(1e-10).evalf() - 1) - 1e-10 - 5e-21) < 1e-22 # for comparison
24
+ assert abs(expm1(1e-10).evalf() - 1e-10 - 5e-21) < 1e-22
25
+
26
+ # Properties
27
+ assert expm1(x).is_real
28
+ assert expm1(x).is_finite
29
+
30
+ # Diff
31
+ assert expm1(42*x).diff(x) - 42*exp(42*x) == 0
32
+ assert expm1(42*x).diff(x) - expm1(42*x).expand(func=True).diff(x) == 0
33
+
34
+
35
+ def test_log1p():
36
+ # Eval
37
+ assert log1p(0) == 0
38
+ d = S(10)
39
+ assert expand_log(log1p(d**-1000) - log(d**1000 + 1) + log(d**1000)) == 0
40
+
41
+ x = Symbol('x', real=True)
42
+
43
+ # Expand and rewrite
44
+ assert log1p(x).expand(func=True) - log(x + 1) == 0
45
+ assert log1p(x).rewrite('tractable') - log(x + 1) == 0
46
+ assert log1p(x).rewrite('log') - log(x + 1) == 0
47
+
48
+ # Precision
49
+ assert not abs(log(1e-99 + 1).evalf() - 1e-99) < 1e-100 # for comparison
50
+ assert abs(expand_log(log1p(1e-99)).evalf() - 1e-99) < 1e-100
51
+
52
+ # Properties
53
+ assert log1p(-2**Rational(-1, 2)).is_real
54
+
55
+ assert not log1p(-1).is_finite
56
+ assert log1p(pi).is_finite
57
+
58
+ assert not log1p(x).is_positive
59
+ assert log1p(Symbol('y', positive=True)).is_positive
60
+
61
+ assert not log1p(x).is_zero
62
+ assert log1p(Symbol('z', zero=True)).is_zero
63
+
64
+ assert not log1p(x).is_nonnegative
65
+ assert log1p(Symbol('o', nonnegative=True)).is_nonnegative
66
+
67
+ # Diff
68
+ assert log1p(42*x).diff(x) - 42/(42*x + 1) == 0
69
+ assert log1p(42*x).diff(x) - log1p(42*x).expand(func=True).diff(x) == 0
70
+
71
+
72
+ def test_exp2():
73
+ # Eval
74
+ assert exp2(2) == 4
75
+
76
+ x = Symbol('x', real=True)
77
+
78
+ # Expand
79
+ assert exp2(x).expand(func=True) - 2**x == 0
80
+
81
+ # Diff
82
+ assert exp2(42*x).diff(x) - 42*exp2(42*x)*log(2) == 0
83
+ assert exp2(42*x).diff(x) - exp2(42*x).diff(x) == 0
84
+
85
+
86
+ def test_log2():
87
+ # Eval
88
+ assert log2(8) == 3
89
+ assert log2(pi) != log(pi)/log(2) # log2 should *save* (CPU) instructions
90
+
91
+ x = Symbol('x', real=True)
92
+ assert log2(x) != log(x)/log(2)
93
+ assert log2(2**x) == x
94
+
95
+ # Expand
96
+ assert log2(x).expand(func=True) - log(x)/log(2) == 0
97
+
98
+ # Diff
99
+ assert log2(42*x).diff() - 1/(log(2)*x) == 0
100
+ assert log2(42*x).diff() - log2(42*x).expand(func=True).diff(x) == 0
101
+
102
+
103
+ def test_fma():
104
+ x, y, z = symbols('x y z')
105
+
106
+ # Expand
107
+ assert fma(x, y, z).expand(func=True) - x*y - z == 0
108
+
109
+ expr = fma(17*x, 42*y, 101*z)
110
+
111
+ # Diff
112
+ assert expr.diff(x) - expr.expand(func=True).diff(x) == 0
113
+ assert expr.diff(y) - expr.expand(func=True).diff(y) == 0
114
+ assert expr.diff(z) - expr.expand(func=True).diff(z) == 0
115
+
116
+ assert expr.diff(x) - 17*42*y == 0
117
+ assert expr.diff(y) - 17*42*x == 0
118
+ assert expr.diff(z) - 101 == 0
119
+
120
+
121
+ def test_log10():
122
+ x = Symbol('x')
123
+
124
+ # Expand
125
+ assert log10(x).expand(func=True) - log(x)/log(10) == 0
126
+
127
+ # Diff
128
+ assert log10(42*x).diff(x) - 1/(log(10)*x) == 0
129
+ assert log10(42*x).diff(x) - log10(42*x).expand(func=True).diff(x) == 0
130
+
131
+
132
+ def test_Cbrt():
133
+ x = Symbol('x')
134
+
135
+ # Expand
136
+ assert Cbrt(x).expand(func=True) - x**Rational(1, 3) == 0
137
+
138
+ # Diff
139
+ assert Cbrt(42*x).diff(x) - 42*(42*x)**(Rational(1, 3) - 1)/3 == 0
140
+ assert Cbrt(42*x).diff(x) - Cbrt(42*x).expand(func=True).diff(x) == 0
141
+
142
+
143
+ def test_Sqrt():
144
+ x = Symbol('x')
145
+
146
+ # Expand
147
+ assert Sqrt(x).expand(func=True) - x**S.Half == 0
148
+
149
+ # Diff
150
+ assert Sqrt(42*x).diff(x) - 42*(42*x)**(S.Half - 1)/2 == 0
151
+ assert Sqrt(42*x).diff(x) - Sqrt(42*x).expand(func=True).diff(x) == 0
152
+
153
+
154
+ def test_hypot():
155
+ x, y = symbols('x y')
156
+
157
+ # Expand
158
+ assert hypot(x, y).expand(func=True) - (x**2 + y**2)**S.Half == 0
159
+
160
+ # Diff
161
+ assert hypot(17*x, 42*y).diff(x).expand(func=True) - hypot(17*x, 42*y).expand(func=True).diff(x) == 0
162
+ assert hypot(17*x, 42*y).diff(y).expand(func=True) - hypot(17*x, 42*y).expand(func=True).diff(y) == 0
163
+
164
+ assert hypot(17*x, 42*y).diff(x).expand(func=True) - 2*17*17*x*((17*x)**2 + (42*y)**2)**Rational(-1, 2)/2 == 0
165
+ assert hypot(17*x, 42*y).diff(y).expand(func=True) - 2*42*42*y*((17*x)**2 + (42*y)**2)**Rational(-1, 2)/2 == 0
lib/python3.10/site-packages/sympy/codegen/tests/test_cnodes.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.symbol import symbols
2
+ from sympy.printing.codeprinter import ccode
3
+ from sympy.codegen.ast import Declaration, Variable, float64, int64, String, CodeBlock
4
+ from sympy.codegen.cnodes import (
5
+ alignof, CommaOperator, goto, Label, PreDecrement, PostDecrement, PreIncrement, PostIncrement,
6
+ sizeof, union, struct
7
+ )
8
+
9
+ x, y = symbols('x y')
10
+
11
+
12
+ def test_alignof():
13
+ ax = alignof(x)
14
+ assert ccode(ax) == 'alignof(x)'
15
+ assert ax.func(*ax.args) == ax
16
+
17
+
18
+ def test_CommaOperator():
19
+ expr = CommaOperator(PreIncrement(x), 2*x)
20
+ assert ccode(expr) == '(++(x), 2*x)'
21
+ assert expr.func(*expr.args) == expr
22
+
23
+
24
+ def test_goto_Label():
25
+ s = 'early_exit'
26
+ g = goto(s)
27
+ assert g.func(*g.args) == g
28
+ assert g != goto('foobar')
29
+ assert ccode(g) == 'goto early_exit'
30
+
31
+ l1 = Label(s)
32
+ assert ccode(l1) == 'early_exit:'
33
+ assert l1 == Label('early_exit')
34
+ assert l1 != Label('foobar')
35
+
36
+ body = [PreIncrement(x)]
37
+ l2 = Label(s, body)
38
+ assert l2.name == String("early_exit")
39
+ assert l2.body == CodeBlock(PreIncrement(x))
40
+ assert ccode(l2) == ("early_exit:\n"
41
+ "++(x);")
42
+
43
+ body = [PreIncrement(x), PreDecrement(y)]
44
+ l2 = Label(s, body)
45
+ assert l2.name == String("early_exit")
46
+ assert l2.body == CodeBlock(PreIncrement(x), PreDecrement(y))
47
+ assert ccode(l2) == ("early_exit:\n"
48
+ "{\n ++(x);\n --(y);\n}")
49
+
50
+
51
+ def test_PreDecrement():
52
+ p = PreDecrement(x)
53
+ assert p.func(*p.args) == p
54
+ assert ccode(p) == '--(x)'
55
+
56
+
57
+ def test_PostDecrement():
58
+ p = PostDecrement(x)
59
+ assert p.func(*p.args) == p
60
+ assert ccode(p) == '(x)--'
61
+
62
+
63
+ def test_PreIncrement():
64
+ p = PreIncrement(x)
65
+ assert p.func(*p.args) == p
66
+ assert ccode(p) == '++(x)'
67
+
68
+
69
+ def test_PostIncrement():
70
+ p = PostIncrement(x)
71
+ assert p.func(*p.args) == p
72
+ assert ccode(p) == '(x)++'
73
+
74
+
75
+ def test_sizeof():
76
+ typename = 'unsigned int'
77
+ sz = sizeof(typename)
78
+ assert ccode(sz) == 'sizeof(%s)' % typename
79
+ assert sz.func(*sz.args) == sz
80
+ assert not sz.is_Atom
81
+ assert sz.atoms() == {String('unsigned int'), String('sizeof')}
82
+
83
+
84
+ def test_struct():
85
+ vx, vy = Variable(x, type=float64), Variable(y, type=float64)
86
+ s = struct('vec2', [vx, vy])
87
+ assert s.func(*s.args) == s
88
+ assert s == struct('vec2', (vx, vy))
89
+ assert s != struct('vec2', (vy, vx))
90
+ assert str(s.name) == 'vec2'
91
+ assert len(s.declarations) == 2
92
+ assert all(isinstance(arg, Declaration) for arg in s.declarations)
93
+ assert ccode(s) == (
94
+ "struct vec2 {\n"
95
+ " double x;\n"
96
+ " double y;\n"
97
+ "}")
98
+
99
+
100
+ def test_union():
101
+ vx, vy = Variable(x, type=float64), Variable(y, type=int64)
102
+ u = union('dualuse', [vx, vy])
103
+ assert u.func(*u.args) == u
104
+ assert u == union('dualuse', (vx, vy))
105
+ assert str(u.name) == 'dualuse'
106
+ assert len(u.declarations) == 2
107
+ assert all(isinstance(arg, Declaration) for arg in u.declarations)
108
+ assert ccode(u) == (
109
+ "union dualuse {\n"
110
+ " double x;\n"
111
+ " int64_t y;\n"
112
+ "}")
lib/python3.10/site-packages/sympy/codegen/tests/test_cxxnodes.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.symbol import Symbol
2
+ from sympy.codegen.ast import Type
3
+ from sympy.codegen.cxxnodes import using
4
+ from sympy.printing.codeprinter import cxxcode
5
+
6
+ x = Symbol('x')
7
+
8
+ def test_using():
9
+ v = Type('std::vector')
10
+ u1 = using(v)
11
+ assert cxxcode(u1) == 'using std::vector'
12
+
13
+ u2 = using(v, 'vec')
14
+ assert cxxcode(u2) == 'using vec = std::vector'
lib/python3.10/site-packages/sympy/codegen/tests/test_fnodes.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ from sympy.core.symbol import (Symbol, symbols)
4
+ from sympy.codegen.ast import (
5
+ Assignment, Print, Declaration, FunctionDefinition, Return, real,
6
+ FunctionCall, Variable, Element, integer
7
+ )
8
+ from sympy.codegen.fnodes import (
9
+ allocatable, ArrayConstructor, isign, dsign, cmplx, kind, literal_dp,
10
+ Program, Module, use, Subroutine, dimension, assumed_extent, ImpliedDoLoop,
11
+ intent_out, size, Do, SubroutineCall, sum_, array, bind_C
12
+ )
13
+ from sympy.codegen.futils import render_as_module
14
+ from sympy.core.expr import unchanged
15
+ from sympy.external import import_module
16
+ from sympy.printing.codeprinter import fcode
17
+ from sympy.utilities._compilation import has_fortran, compile_run_strings, compile_link_import_strings
18
+ from sympy.utilities._compilation.util import may_xfail
19
+ from sympy.testing.pytest import skip, XFAIL
20
+
21
+ cython = import_module('cython')
22
+ np = import_module('numpy')
23
+
24
+
25
+ def test_size():
26
+ x = Symbol('x', real=True)
27
+ sx = size(x)
28
+ assert fcode(sx, source_format='free') == 'size(x)'
29
+
30
+
31
+ @may_xfail
32
+ def test_size_assumed_shape():
33
+ if not has_fortran():
34
+ skip("No fortran compiler found.")
35
+ a = Symbol('a', real=True)
36
+ body = [Return((sum_(a**2)/size(a))**.5)]
37
+ arr = array(a, dim=[':'], intent='in')
38
+ fd = FunctionDefinition(real, 'rms', [arr], body)
39
+ render_as_module([fd], 'mod_rms')
40
+
41
+ (stdout, stderr), info = compile_run_strings([
42
+ ('rms.f90', render_as_module([fd], 'mod_rms')),
43
+ ('main.f90', (
44
+ 'program myprog\n'
45
+ 'use mod_rms, only: rms\n'
46
+ 'real*8, dimension(4), parameter :: x = [4, 2, 2, 2]\n'
47
+ 'print *, dsqrt(7d0) - rms(x)\n'
48
+ 'end program\n'
49
+ ))
50
+ ], clean=True)
51
+ assert '0.00000' in stdout
52
+ assert stderr == ''
53
+ assert info['exit_status'] == os.EX_OK
54
+
55
+
56
+ @XFAIL # https://github.com/sympy/sympy/issues/20265
57
+ @may_xfail
58
+ def test_ImpliedDoLoop():
59
+ if not has_fortran():
60
+ skip("No fortran compiler found.")
61
+
62
+ a, i = symbols('a i', integer=True)
63
+ idl = ImpliedDoLoop(i**3, i, -3, 3, 2)
64
+ ac = ArrayConstructor([-28, idl, 28])
65
+ a = array(a, dim=[':'], attrs=[allocatable])
66
+ prog = Program('idlprog', [
67
+ a.as_Declaration(),
68
+ Assignment(a, ac),
69
+ Print([a])
70
+ ])
71
+ fsrc = fcode(prog, standard=2003, source_format='free')
72
+ (stdout, stderr), info = compile_run_strings([('main.f90', fsrc)], clean=True)
73
+ for numstr in '-28 -27 -1 1 27 28'.split():
74
+ assert numstr in stdout
75
+ assert stderr == ''
76
+ assert info['exit_status'] == os.EX_OK
77
+
78
+
79
+ @may_xfail
80
+ def test_Program():
81
+ x = Symbol('x', real=True)
82
+ vx = Variable.deduced(x, 42)
83
+ decl = Declaration(vx)
84
+ prnt = Print([x, x+1])
85
+ prog = Program('foo', [decl, prnt])
86
+ if not has_fortran():
87
+ skip("No fortran compiler found.")
88
+
89
+ (stdout, stderr), info = compile_run_strings([('main.f90', fcode(prog, standard=90))], clean=True)
90
+ assert '42' in stdout
91
+ assert '43' in stdout
92
+ assert stderr == ''
93
+ assert info['exit_status'] == os.EX_OK
94
+
95
+
96
+ @may_xfail
97
+ def test_Module():
98
+ x = Symbol('x', real=True)
99
+ v_x = Variable.deduced(x)
100
+ sq = FunctionDefinition(real, 'sqr', [v_x], [Return(x**2)])
101
+ mod_sq = Module('mod_sq', [], [sq])
102
+ sq_call = FunctionCall('sqr', [42.])
103
+ prg_sq = Program('foobar', [
104
+ use('mod_sq', only=['sqr']),
105
+ Print(['"Square of 42 = "', sq_call])
106
+ ])
107
+ if not has_fortran():
108
+ skip("No fortran compiler found.")
109
+ (stdout, stderr), info = compile_run_strings([
110
+ ('mod_sq.f90', fcode(mod_sq, standard=90)),
111
+ ('main.f90', fcode(prg_sq, standard=90))
112
+ ], clean=True)
113
+ assert '42' in stdout
114
+ assert str(42**2) in stdout
115
+ assert stderr == ''
116
+
117
+
118
+ @XFAIL # https://github.com/sympy/sympy/issues/20265
119
+ @may_xfail
120
+ def test_Subroutine():
121
+ # Code to generate the subroutine in the example from
122
+ # http://www.fortran90.org/src/best-practices.html#arrays
123
+ r = Symbol('r', real=True)
124
+ i = Symbol('i', integer=True)
125
+ v_r = Variable.deduced(r, attrs=(dimension(assumed_extent), intent_out))
126
+ v_i = Variable.deduced(i)
127
+ v_n = Variable('n', integer)
128
+ do_loop = Do([
129
+ Assignment(Element(r, [i]), literal_dp(1)/i**2)
130
+ ], i, 1, v_n)
131
+ sub = Subroutine("f", [v_r], [
132
+ Declaration(v_n),
133
+ Declaration(v_i),
134
+ Assignment(v_n, size(r)),
135
+ do_loop
136
+ ])
137
+ x = Symbol('x', real=True)
138
+ v_x3 = Variable.deduced(x, attrs=[dimension(3)])
139
+ mod = Module('mymod', definitions=[sub])
140
+ prog = Program('foo', [
141
+ use(mod, only=[sub]),
142
+ Declaration(v_x3),
143
+ SubroutineCall(sub, [v_x3]),
144
+ Print([sum_(v_x3), v_x3])
145
+ ])
146
+
147
+ if not has_fortran():
148
+ skip("No fortran compiler found.")
149
+
150
+ (stdout, stderr), info = compile_run_strings([
151
+ ('a.f90', fcode(mod, standard=90)),
152
+ ('b.f90', fcode(prog, standard=90))
153
+ ], clean=True)
154
+ ref = [1.0/i**2 for i in range(1, 4)]
155
+ assert str(sum(ref))[:-3] in stdout
156
+ for _ in ref:
157
+ assert str(_)[:-3] in stdout
158
+ assert stderr == ''
159
+
160
+
161
+ def test_isign():
162
+ x = Symbol('x', integer=True)
163
+ assert unchanged(isign, 1, x)
164
+ assert fcode(isign(1, x), standard=95, source_format='free') == 'isign(1, x)'
165
+
166
+
167
+ def test_dsign():
168
+ x = Symbol('x')
169
+ assert unchanged(dsign, 1, x)
170
+ assert fcode(dsign(literal_dp(1), x), standard=95, source_format='free') == 'dsign(1d0, x)'
171
+
172
+
173
+ def test_cmplx():
174
+ x = Symbol('x')
175
+ assert unchanged(cmplx, 1, x)
176
+
177
+
178
+ def test_kind():
179
+ x = Symbol('x')
180
+ assert unchanged(kind, x)
181
+
182
+
183
+ def test_literal_dp():
184
+ assert fcode(literal_dp(0), source_format='free') == '0d0'
185
+
186
+
187
+ @may_xfail
188
+ def test_bind_C():
189
+ if not has_fortran():
190
+ skip("No fortran compiler found.")
191
+ if not cython:
192
+ skip("Cython not found.")
193
+ if not np:
194
+ skip("NumPy not found.")
195
+
196
+ a = Symbol('a', real=True)
197
+ s = Symbol('s', integer=True)
198
+ body = [Return((sum_(a**2)/s)**.5)]
199
+ arr = array(a, dim=[s], intent='in')
200
+ fd = FunctionDefinition(real, 'rms', [arr, s], body, attrs=[bind_C('rms')])
201
+ f_mod = render_as_module([fd], 'mod_rms')
202
+
203
+ with tempfile.TemporaryDirectory() as folder:
204
+ mod, info = compile_link_import_strings([
205
+ ('rms.f90', f_mod),
206
+ ('_rms.pyx', (
207
+ "#cython: language_level={}\n".format("3") +
208
+ "cdef extern double rms(double*, int*)\n"
209
+ "def py_rms(double[::1] x):\n"
210
+ " cdef int s = x.size\n"
211
+ " return rms(&x[0], &s)\n"))
212
+ ], build_dir=folder)
213
+ assert abs(mod.py_rms(np.array([2., 4., 2., 2.])) - 7**0.5) < 1e-14
lib/python3.10/site-packages/sympy/codegen/tests/test_matrix_nodes.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.symbol import symbols
2
+ from sympy.core.function import Function
3
+ from sympy.matrices.dense import Matrix
4
+ from sympy.matrices.dense import zeros
5
+ from sympy.simplify.simplify import simplify
6
+ from sympy.codegen.matrix_nodes import MatrixSolve
7
+ from sympy.utilities.lambdify import lambdify
8
+ from sympy.printing.numpy import NumPyPrinter
9
+ from sympy.testing.pytest import skip
10
+ from sympy.external import import_module
11
+
12
+
13
+ def test_matrix_solve_issue_24862():
14
+ A = Matrix(3, 3, symbols('a:9'))
15
+ b = Matrix(3, 1, symbols('b:3'))
16
+ hash(MatrixSolve(A, b))
17
+
18
+
19
+ def test_matrix_solve_derivative_exact():
20
+ q = symbols('q')
21
+ a11, a12, a21, a22, b1, b2 = (
22
+ f(q) for f in symbols('a11 a12 a21 a22 b1 b2', cls=Function))
23
+ A = Matrix([[a11, a12], [a21, a22]])
24
+ b = Matrix([b1, b2])
25
+ x_lu = A.LUsolve(b)
26
+ dxdq_lu = A.LUsolve(b.diff(q) - A.diff(q) * A.LUsolve(b))
27
+ assert simplify(x_lu.diff(q) - dxdq_lu) == zeros(2, 1)
28
+ # dxdq_ms is the MatrixSolve equivalent of dxdq_lu
29
+ dxdq_ms = MatrixSolve(A, b.diff(q) - A.diff(q) * MatrixSolve(A, b))
30
+ assert MatrixSolve(A, b).diff(q) == dxdq_ms
31
+
32
+
33
+ def test_matrix_solve_derivative_numpy():
34
+ np = import_module('numpy')
35
+ if not np:
36
+ skip("numpy not installed.")
37
+ q = symbols('q')
38
+ a11, a12, a21, a22, b1, b2 = (
39
+ f(q) for f in symbols('a11 a12 a21 a22 b1 b2', cls=Function))
40
+ A = Matrix([[a11, a12], [a21, a22]])
41
+ b = Matrix([b1, b2])
42
+ dx_lu = A.LUsolve(b).diff(q)
43
+ subs = {a11.diff(q): 0.2, a12.diff(q): 0.3, a21.diff(q): 0.1,
44
+ a22.diff(q): 0.5, b1.diff(q): 0.4, b2.diff(q): 0.9,
45
+ a11: 1.3, a12: 0.5, a21: 1.2, a22: 4, b1: 6.2, b2: 3.5}
46
+ p, p_vals = zip(*subs.items())
47
+ dx_sm = MatrixSolve(A, b).diff(q)
48
+ np.testing.assert_allclose(
49
+ lambdify(p, dx_sm, printer=NumPyPrinter)(*p_vals),
50
+ lambdify(p, dx_lu, printer=NumPyPrinter)(*p_vals))
lib/python3.10/site-packages/sympy/codegen/tests/test_numpy_nodes.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from itertools import product
2
+ from sympy.core.singleton import S
3
+ from sympy.core.symbol import symbols
4
+ from sympy.functions.elementary.exponential import (exp, log)
5
+ from sympy.printing.repr import srepr
6
+ from sympy.codegen.numpy_nodes import logaddexp, logaddexp2
7
+
8
+ x, y, z = symbols('x y z')
9
+
10
+ def test_logaddexp():
11
+ lae_xy = logaddexp(x, y)
12
+ ref_xy = log(exp(x) + exp(y))
13
+ for wrt, deriv_order in product([x, y, z], range(3)):
14
+ assert (
15
+ lae_xy.diff(wrt, deriv_order) -
16
+ ref_xy.diff(wrt, deriv_order)
17
+ ).rewrite(log).simplify() == 0
18
+
19
+ one_third_e = 1*exp(1)/3
20
+ two_thirds_e = 2*exp(1)/3
21
+ logThirdE = log(one_third_e)
22
+ logTwoThirdsE = log(two_thirds_e)
23
+ lae_sum_to_e = logaddexp(logThirdE, logTwoThirdsE)
24
+ assert lae_sum_to_e.rewrite(log) == 1
25
+ assert lae_sum_to_e.simplify() == 1
26
+ was = logaddexp(2, 3)
27
+ assert srepr(was) == srepr(was.simplify()) # cannot simplify with 2, 3
28
+
29
+
30
+ def test_logaddexp2():
31
+ lae2_xy = logaddexp2(x, y)
32
+ ref2_xy = log(2**x + 2**y)/log(2)
33
+ for wrt, deriv_order in product([x, y, z], range(3)):
34
+ assert (
35
+ lae2_xy.diff(wrt, deriv_order) -
36
+ ref2_xy.diff(wrt, deriv_order)
37
+ ).rewrite(log).cancel() == 0
38
+
39
+ def lb(x):
40
+ return log(x)/log(2)
41
+
42
+ two_thirds = S.One*2/3
43
+ four_thirds = 2*two_thirds
44
+ lbTwoThirds = lb(two_thirds)
45
+ lbFourThirds = lb(four_thirds)
46
+ lae2_sum_to_2 = logaddexp2(lbTwoThirds, lbFourThirds)
47
+ assert lae2_sum_to_2.rewrite(log) == 1
48
+ assert lae2_sum_to_2.simplify() == 1
49
+ was = logaddexp2(x, y)
50
+ assert srepr(was) == srepr(was.simplify()) # cannot simplify with x, y