passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
sage/misc/latex.py ADDED
@@ -0,0 +1,2673 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ """
3
+ LaTeX printing support
4
+
5
+ In order to support latex formatting, an object should define a
6
+ special method ``_latex_(self)`` that returns a string, which will be typeset
7
+ in a mathematical mode (the exact mode depends on circumstances).
8
+
9
+ This module focuses on using LaTeX for printing. For the use of LaTeX for
10
+ rendering math in HTML by MathJax, see :class:`~sage.misc.html.MathJax` defined in
11
+ :mod:`sage.misc.html`.
12
+
13
+ AUTHORS:
14
+
15
+ - William Stein: original implementation
16
+
17
+ - Joel B. Mohler: latex_variable_name() drastic rewrite and many doc-tests
18
+ """
19
+ # ****************************************************************************
20
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
21
+ #
22
+ # Distributed under the terms of the GNU General Public License (GPL)
23
+ # as published by the Free Software Foundation; either version 2 of
24
+ # the License, or (at your option) any later version.
25
+ # https://www.gnu.org/licenses/
26
+ # ****************************************************************************
27
+
28
+ import os
29
+ import random
30
+ import re
31
+ import shutil
32
+ from subprocess import call, run, PIPE
33
+ from tempfile import TemporaryDirectory
34
+
35
+ from sage.misc.cachefunc import cached_function, cached_method
36
+ from sage.misc.lazy_attribute import lazy_attribute
37
+ from sage.structure.sage_object import SageObject
38
+
39
+
40
+ COMMON_HEADER = r'''\usepackage{amsmath}
41
+ \usepackage{amssymb}
42
+ \usepackage{amsfonts}
43
+ \usepackage{graphicx}
44
+ \usepackage{mathrsfs}
45
+ \pagestyle{empty}
46
+ \usepackage[utf8]{inputenc}
47
+ \usepackage[T1]{fontenc}
48
+ '''
49
+
50
+ LATEX_HEADER = (r'''\documentclass{article}
51
+ ''' + COMMON_HEADER +
52
+ r'''\oddsidemargin 0.0in
53
+ \evensidemargin 0.0in
54
+ \textwidth 6.45in
55
+ \topmargin 0.0in
56
+ \headheight 0.0in
57
+ \headsep 0.0in
58
+ \textheight 9.0in
59
+ ''')
60
+
61
+ SLIDE_HEADER = (r'''\documentclass[a0,8pt]{beamer}
62
+ ''' + COMMON_HEADER +
63
+ r'''\textwidth=1.1\textwidth
64
+ \textheight=2\textheight
65
+ ''')
66
+
67
+
68
+ def list_function(x):
69
+ r"""
70
+ Return the LaTeX code for a list ``x``.
71
+
72
+ INPUT:
73
+
74
+ - ``x`` -- list
75
+
76
+ EXAMPLES::
77
+
78
+ sage: from sage.misc.latex import list_function
79
+ sage: list_function([1,2,3])
80
+ '\\left[1, 2, 3\\right]'
81
+ sage: latex([1,2,3]) # indirect doctest
82
+ \left[1, 2, 3\right]
83
+ sage: latex([Matrix(ZZ, 3, range(9)), # indirect doctest # needs sage.modules
84
+ ....: Matrix(ZZ, 3, range(9))])
85
+ \left[\left(\begin{array}{rrr}
86
+ 0 & 1 & 2 \\
87
+ 3 & 4 & 5 \\
88
+ 6 & 7 & 8
89
+ \end{array}\right), \left(\begin{array}{rrr}
90
+ 0 & 1 & 2 \\
91
+ 3 & 4 & 5 \\
92
+ 6 & 7 & 8
93
+ \end{array}\right)\right]
94
+ """
95
+ return "\\left[" + ", ".join(latex(v) for v in x) + "\\right]"
96
+
97
+
98
+ def tuple_function(x, combine_all=False):
99
+ r"""
100
+ Return the LaTeX code for a tuple ``x``.
101
+
102
+ INPUT:
103
+
104
+ - ``x`` -- tuple
105
+
106
+ - ``combine_all`` -- boolean (default: ``False``); if ``combine_all`` is
107
+ ``True``, then it does not return a tuple and instead returns a string
108
+ with all the elements separated by a single space. It does not collapse
109
+ tuples which are inside tuples.
110
+
111
+ EXAMPLES::
112
+
113
+ sage: from sage.misc.latex import tuple_function
114
+ sage: tuple_function((1,2,3))
115
+ '\\left(1, 2, 3\\right)'
116
+
117
+ Check that :issue:`11775` is fixed::
118
+
119
+ sage: tuple_function((1,2,3), combine_all=True)
120
+ '1 2 3'
121
+ sage: tuple_function(((1,2),3), combine_all=True)
122
+ '\\left(1, 2\\right) 3'
123
+ """
124
+ if combine_all:
125
+ return " ".join(latex(v) for v in x)
126
+ return "\\left(" + ", ".join(latex(v) for v in x) + "\\right)"
127
+
128
+
129
+ def bool_function(x):
130
+ r"""
131
+ Return the LaTeX code for a boolean ``x``.
132
+
133
+ INPUT:
134
+
135
+ - ``x`` -- boolean
136
+
137
+ EXAMPLES::
138
+
139
+ sage: from sage.misc.latex import bool_function
140
+ sage: print(bool_function(2==3))
141
+ \mathrm{False}
142
+ sage: print(bool_function(3==(2+1)))
143
+ \mathrm{True}
144
+ """
145
+ return r"\mathrm{%s}" % bool(x)
146
+
147
+
148
+ def builtin_constant_function(x):
149
+ r"""
150
+ Return the LaTeX code for a builtin constant ``x``.
151
+
152
+ INPUT:
153
+
154
+ - ``x`` -- builtin constant
155
+
156
+ .. SEEALSO:: Python built-in Constants http://docs.python.org/library/constants.html
157
+
158
+ EXAMPLES::
159
+
160
+ sage: from sage.misc.latex import builtin_constant_function
161
+ sage: builtin_constant_function(True)
162
+ '\\mbox{\\rm True}'
163
+ sage: builtin_constant_function(None)
164
+ '\\mbox{\\rm None}'
165
+ sage: builtin_constant_function(NotImplemented)
166
+ '\\mbox{\\rm NotImplemented}'
167
+ sage: builtin_constant_function(Ellipsis)
168
+ '\\mbox{\\rm Ellipsis}'
169
+ """
170
+ return "\\mbox{\\rm %s}" % x
171
+
172
+
173
+ def None_function(x):
174
+ r"""
175
+ Return the LaTeX code for ``None``.
176
+
177
+ INPUT:
178
+
179
+ - ``x`` -- ``None``
180
+
181
+ EXAMPLES::
182
+
183
+ sage: from sage.misc.latex import None_function
184
+ sage: print(None_function(None))
185
+ \mathrm{None}
186
+ """
187
+ assert x is None
188
+ return r"\mathrm{None}"
189
+
190
+
191
+ def str_function(x):
192
+ r"""
193
+ Return a LaTeX representation of the string ``x``.
194
+
195
+ The main purpose of this function is to generate LaTeX representation for
196
+ classes that do not provide a customized method.
197
+
198
+ If ``x`` contains only digits with, possibly, a single decimal point and/or
199
+ a sign in front, it is considered to be its own representation. Otherwise
200
+ each line of ``x`` is wrapped in a ``\texttt`` command and these lines are
201
+ assembled in a left-justified array. This gives to complicated strings the
202
+ closest look to their "terminal representation".
203
+
204
+ .. WARNING::
205
+
206
+ Such wrappers **cannot** be used as arguments of LaTeX
207
+ commands or in command definitions. If this causes you any problems,
208
+ they probably can be solved by implementing a suitable ``_latex_``
209
+ method for an appropriate class.
210
+
211
+ INPUT:
212
+
213
+ - ``x`` -- string
214
+
215
+ OUTPUT: string
216
+
217
+ EXAMPLES::
218
+
219
+ sage: from sage.misc.latex import str_function
220
+ sage: str_function('34')
221
+ '34'
222
+ sage: str_function('34.5')
223
+ '34.5'
224
+ sage: str_function('-34.5')
225
+ '-34.5'
226
+ sage: str_function('+34.5')
227
+ '+34.5'
228
+ sage: str_function('hello_world')
229
+ '\\text{\\texttt{hello{\\char`\\_}world}}'
230
+ sage: str_function('-1.00000?') # trac 12178
231
+ '-1.00000?'
232
+ """
233
+ # Check if x is just a number with a possible sign, and/or decimal
234
+ # point, and/or ends with "?"
235
+ if re.match(r'(\+|-)?[0-9]*\.?[0-9]*\??$', x):
236
+ return x
237
+ # Deal with special characters
238
+ char_wrapper = r"{\char`\%s}"
239
+ x = "".join(char_wrapper % c if c in r"#$%&\^_{}~" else c for c in x)
240
+ # Avoid grouping spaces into one
241
+ x = x.replace(" ", "{ }")
242
+ # And dashes too, since it causes issues for the command line...
243
+ x = x.replace("-", "{-}")
244
+ # Make it work in math mode, but look like typewriter
245
+ line_wrapper = r"\text{\texttt{%s}}"
246
+ x = "\\\\\n".join(line_wrapper % line for line in x.split("\n"))
247
+ # Preserve line breaks
248
+ if "\n" in x:
249
+ x = "\\begin{array}{l}\n%s\n\\end{array}" % x
250
+ return x
251
+
252
+
253
+ def dict_function(x):
254
+ r"""
255
+ Return the LaTeX code for a dictionary ``x``.
256
+
257
+ INPUT:
258
+
259
+ - ``x`` -- dictionary
260
+
261
+ EXAMPLES::
262
+
263
+ sage: # needs sage.symbolic
264
+ sage: from sage.misc.latex import dict_function
265
+ sage: x,y,z = var('x,y,z')
266
+ sage: print(dict_function({x/2: y^2}))
267
+ \left\{\frac{1}{2} \, x : y^{2}\right\}
268
+ sage: d = {(1,2,x^2): [sin(z^2), y/2]}
269
+ sage: latex(d)
270
+ \left\{\left(1, 2, x^{2}\right) :
271
+ \left[\sin\left(z^{2}\right), \frac{1}{2} \, y\right]\right\}
272
+ """
273
+ return "".join([r"\left\{",
274
+ ", ".join(r"%s : %s" % (latex(key), latex(value))
275
+ for key, value in x.items()),
276
+ r"\right\}"])
277
+
278
+ # One can add to the latex_table in order to install latexing
279
+ # functionality for other types. (Suggested by Robert Kerns of Enthought.)
280
+
281
+
282
+ def float_function(x):
283
+ r"""
284
+ Return the LaTeX code for a python float ``x``.
285
+
286
+ INPUT:
287
+
288
+ - ``x`` -- a python float
289
+
290
+ EXAMPLES::
291
+
292
+ sage: from sage.misc.latex import float_function
293
+ sage: float_function(float(3.14))
294
+ 3.14
295
+ sage: float_function(float(1e-10))
296
+ 1 \times 10^{-10}
297
+ sage: float_function(float(2e10))
298
+ 20000000000.0
299
+
300
+ TESTS:
301
+
302
+ Check that :issue:`7356` is fixed::
303
+
304
+ sage: latex(float(2e-13))
305
+ 2 \times 10^{-13}
306
+ """
307
+ from sage.rings.real_double import RDF
308
+ return latex(RDF(x))
309
+
310
+
311
+ latex_table = {
312
+ type(None): None_function,
313
+ bool: bool_function,
314
+ dict: dict_function,
315
+ float: float_function,
316
+ int: str,
317
+ list: list_function,
318
+ str: str_function,
319
+ tuple: tuple_function,
320
+ type(NotImplemented): builtin_constant_function,
321
+ type(Ellipsis): builtin_constant_function
322
+ }
323
+
324
+
325
+ class LatexExpr(str):
326
+ r"""
327
+ A class for LaTeX expressions.
328
+
329
+ Normally, objects of this class are created by a :func:`latex` call. It is
330
+ also possible to generate :class:`LatexExpr` directly from a string, which
331
+ must contain valid LaTeX code for typesetting in math mode (without dollar
332
+ signs). In the Jupyter notebook, use
333
+ :func:`~sage.repl.rich_output.pretty_print.pretty_print` to actually see
334
+ the typeset LaTeX code; alternatively, from either the command-line or the
335
+ notebook, use the :func:`view` function.
336
+
337
+ INPUT:
338
+
339
+ - ``str`` -- string with valid math mode LaTeX code (or something
340
+ which can be converted to such a string)
341
+
342
+ OUTPUT: :class:`LatexExpr` wrapping the string representation of the input
343
+
344
+ EXAMPLES::
345
+
346
+ sage: latex(x^20 + 1) # needs sage.symbolic
347
+ x^{20} + 1
348
+ sage: LatexExpr(r"\frac{x^2 + 1}{x - 2}") # needs sage.symbolic
349
+ \frac{x^2 + 1}{x - 2}
350
+
351
+ ``LatexExpr`` simply converts to string without doing anything
352
+ extra, it does *not* call :func:`latex`::
353
+
354
+ sage: latex(ZZ)
355
+ \Bold{Z}
356
+ sage: LatexExpr(ZZ)
357
+ Integer Ring
358
+
359
+ The result of :func:`latex` is of type ``LatexExpr``::
360
+
361
+ sage: L = latex(x^20 + 1) # needs sage.symbolic
362
+ sage: L # needs sage.symbolic
363
+ x^{20} + 1
364
+ sage: type(L) # needs sage.symbolic
365
+ <class 'sage.misc.latex.LatexExpr'>
366
+
367
+ A ``LatexExpr`` can be converted to a plain string::
368
+
369
+ sage: str(latex(x^20 + 1)) # needs sage.symbolic
370
+ 'x^{20} + 1'
371
+ """
372
+ def __add__(self, other):
373
+ r"""
374
+ Add a LatexExpr and another LatexExpr (or a string).
375
+
376
+ EXAMPLES::
377
+
378
+ sage: o = LatexExpr(r"\Delta\neq") + LatexExpr(r"\frac{x}{2}"); o
379
+ \Delta\neq \frac{x}{2}
380
+ sage: type(o)
381
+ <class 'sage.misc.latex.LatexExpr'>
382
+ sage: o = LatexExpr(r"\Delta\neq") + r"\frac{x}{2}"; o
383
+ \Delta\neq \frac{x}{2}
384
+ sage: type(o)
385
+ <class 'sage.misc.latex.LatexExpr'>
386
+
387
+ We add extra space only if it was not there yet::
388
+
389
+ sage: LatexExpr("foo ") + LatexExpr("bar")
390
+ foo bar
391
+ sage: LatexExpr("foo") + LatexExpr(" bar")
392
+ foo bar
393
+ sage: str(LatexExpr("") + LatexExpr("bar"))
394
+ 'bar'
395
+ sage: str(LatexExpr("foo") + LatexExpr(""))
396
+ 'foo'
397
+ """
398
+ left = str(self)
399
+ right = str(other)
400
+ # Add a space if self ends with a non-space and other starts
401
+ # with a non-space
402
+ try:
403
+ if left[-1] != ' ' and right[0] != ' ':
404
+ left += ' '
405
+ except IndexError:
406
+ pass
407
+ return LatexExpr(left + right)
408
+
409
+ def __radd__(self, other):
410
+ r"""
411
+ Add a string and a LatexExpr.
412
+
413
+ EXAMPLES::
414
+
415
+ sage: o = "a =" + LatexExpr("b")
416
+ sage: o
417
+ a = b
418
+ sage: type(o)
419
+ <class 'sage.misc.latex.LatexExpr'>
420
+ """
421
+ return LatexExpr(other) + self
422
+
423
+ def __repr__(self):
424
+ """
425
+ Return a string representation of ``self``.
426
+
427
+ EXAMPLES::
428
+
429
+ sage: LatexExpr("abc").__repr__()
430
+ 'abc'
431
+ """
432
+ return str(self)
433
+
434
+ def _latex_(self):
435
+ """
436
+ Return a LaTeX representation of ``self``.
437
+
438
+ EXAMPLES::
439
+
440
+ sage: latex(LatexExpr("abc")) # indirect doctest
441
+ abc
442
+ """
443
+ return str(self)
444
+
445
+
446
+ def has_latex_attr(x) -> bool:
447
+ """
448
+ Return ``True`` if ``x`` has a ``_latex_`` attribute, except if ``x``
449
+ is a ``type``, in which case return ``False``.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.misc.latex import has_latex_attr
454
+ sage: has_latex_attr(identity_matrix(3)) # needs sage.modules
455
+ True
456
+ sage: has_latex_attr("abc") # strings have no _latex_ method
457
+ False
458
+
459
+ Types inherit the ``_latex_`` method of the class to which they refer,
460
+ but calling it is broken::
461
+
462
+ sage: # needs sage.libs.flint sage.modules
463
+ sage: T = type(identity_matrix(3)); T
464
+ <class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>
465
+ sage: hasattr(T, '_latex_')
466
+ True
467
+ sage: T._latex_()
468
+ Traceback (most recent call last):
469
+ ...
470
+ TypeError: ..._latex_... needs an argument
471
+ sage: has_latex_attr(T)
472
+ False
473
+ """
474
+ return hasattr(x, '_latex_') and not isinstance(x, type)
475
+
476
+
477
+ @cached_function
478
+ def default_engine():
479
+ """
480
+ Return the default latex engine and the official name of the engine.
481
+ This is determined by availability of the popular engines on the user's
482
+ system. It is assumed that at least latex is available.
483
+
484
+ This function is deprecated as part of the public API. There is
485
+ instead an internal counterpart :func:`_default_engine`, but no
486
+ stability promises are made with regards to its interface.
487
+
488
+ EXAMPLES::
489
+
490
+ sage: from sage.misc.latex import default_engine
491
+ sage: default_engine() # random
492
+ ('lualatex', 'LuaLaTeX')
493
+ """
494
+ from sage.misc.superseded import deprecation
495
+ deprecation(39351, "default_engine is being removed from the public API and replaced with the internal function _default_engine")
496
+
497
+ from sage.features.latex import pdflatex, xelatex, lualatex
498
+ if lualatex().is_present():
499
+ return 'lualatex', 'LuaLaTeX'
500
+ if xelatex().is_present():
501
+ return 'xelatex', 'XeLaTeX'
502
+ if pdflatex().is_present():
503
+ return 'pdflatex', 'pdfLaTeX'
504
+ return 'latex', 'LaTeX'
505
+
506
+
507
+ @cached_function
508
+ def _default_engine():
509
+ r"""
510
+ Return the name of the default latex engine.
511
+
512
+ This is determined by availability of the popular engines on the
513
+ user's system. It is assumed that at least "latex" is available.
514
+
515
+ EXAMPLES::
516
+
517
+ sage: from sage.misc.latex import _default_engine
518
+ sage: _default_engine() # random
519
+ 'lualatex'
520
+
521
+ TESTS:
522
+
523
+ Ensure that this (expensive) function is not necessary to obtain
524
+ the latex representation of a matrix (doing so probes the latex
525
+ options dict for the delimiters)::
526
+
527
+ sage: import sage.misc.latex
528
+ sage: real_de = sage.misc.latex._default_engine
529
+ sage: def crash():
530
+ ....: raise ValueError
531
+ sage: sage.misc.latex._default_engine = crash
532
+ sage: latex(matrix.identity(QQ, 2)) # needs sage.modules
533
+ \left(\begin{array}{rr}
534
+ 1 & 0 \\
535
+ 0 & 1
536
+ \end{array}\right)
537
+ sage: sage.misc.latex._default_engine = real_de
538
+ """
539
+ from sage.features.latex import pdflatex, xelatex, lualatex
540
+ if lualatex().is_present():
541
+ return 'lualatex'
542
+ if xelatex().is_present():
543
+ return 'xelatex'
544
+ if pdflatex().is_present():
545
+ return 'pdflatex'
546
+ return 'latex'
547
+
548
+
549
+ class _Latex_prefs_object(SageObject):
550
+ """
551
+ An object that holds LaTeX global preferences.
552
+ """
553
+ def __init__(self, bb=False, delimiters=["(", ")"],
554
+ matrix_column_alignment='r'):
555
+ """
556
+ Define an object that holds LaTeX global preferences.
557
+
558
+ EXAMPLES::
559
+
560
+ sage: from sage.misc.latex import _Latex_prefs_object
561
+ sage: latex_prefs = _Latex_prefs_object()
562
+ sage: TestSuite(latex_prefs).run(skip ='_test_pickling')
563
+ """
564
+ self.__option = {}
565
+ self.__option["blackboard_bold"] = bb
566
+ self.__option["matrix_delimiters"] = list(delimiters)
567
+ self.__option["vector_delimiters"] = list(delimiters)
568
+ self.__option["matrix_column_alignment"] = matrix_column_alignment
569
+ self.__option["macros"] = ""
570
+ self.__option["preamble"] = ""
571
+
572
+ # If None, the _default_engine() will be used.
573
+ self.__option["engine"] = None
574
+
575
+ @lazy_attribute
576
+ def _option(self):
577
+ """
578
+ This attribute contains the preferences list.
579
+
580
+ EXAMPLES::
581
+
582
+ sage: from sage.misc.latex import _Latex_prefs_object
583
+ sage: sorted(_Latex_prefs_object()._option.items())
584
+ [('blackboard_bold', False),
585
+ ('engine', None),
586
+ ('macros', ''),
587
+ ('matrix_column_alignment', 'r'),
588
+ ('matrix_delimiters', ['(', ')']),
589
+ ('preamble', ''),
590
+ ('vector_delimiters', ['(', ')'])]
591
+
592
+ """
593
+ return self.__option
594
+
595
+
596
+ _Latex_prefs = _Latex_prefs_object()
597
+
598
+
599
+ def latex_extra_preamble():
600
+ r"""
601
+ Return the string containing the user-configured preamble,
602
+ ``sage_latex_macros``, and any user-configured macros. This is
603
+ used in the :meth:`~Latex.eval` method for the :class:`Latex`
604
+ class, and in :func:`_latex_file_`; it follows either
605
+ ``LATEX_HEADER`` or ``SLIDE_HEADER`` (defined at the top of this
606
+ file) which is a string containing the documentclass and standard
607
+ usepackage commands.
608
+
609
+ EXAMPLES::
610
+
611
+ sage: from sage.misc.latex import latex_extra_preamble
612
+ sage: print(latex_extra_preamble())
613
+ <BLANKLINE>
614
+ \newcommand{\ZZ}{\Bold{Z}}
615
+ \newcommand{\NN}{\Bold{N}}
616
+ ...
617
+ sage: print(latex_extra_preamble()) # needs sage.all
618
+ <BLANKLINE>
619
+ \newcommand{\ZZ}{\Bold{Z}}
620
+ \newcommand{\NN}{\Bold{N}}
621
+ \newcommand{\RR}{\Bold{R}}
622
+ \newcommand{\CC}{\Bold{C}}
623
+ \newcommand{\QQ}{\Bold{Q}}
624
+ \newcommand{\QQbar}{\overline{\QQ}}
625
+ \newcommand{\GF}[1]{\Bold{F}_{#1}}
626
+ \newcommand{\Zp}[1]{\Bold{Z}_{#1}}
627
+ \newcommand{\Qp}[1]{\Bold{Q}_{#1}}
628
+ \newcommand{\Zmod}[1]{\ZZ/#1\ZZ}
629
+ \newcommand{\CDF}{\Bold{C}}
630
+ \newcommand{\CIF}{\Bold{C}}
631
+ \newcommand{\CLF}{\Bold{C}}
632
+ \newcommand{\RDF}{\Bold{R}}
633
+ \newcommand{\RIF}{\Bold{I} \Bold{R}}
634
+ \newcommand{\RLF}{\Bold{R}}
635
+ \newcommand{\SL}{\mathrm{SL}}
636
+ \newcommand{\PSL}{\mathrm{PSL}}
637
+ \newcommand{\lcm}{\mathop{\operatorname{lcm}}}
638
+ \newcommand{\dist}{\mathrm{dist}}
639
+ \newcommand{\im}{\mathop{\operatorname{im}}}
640
+ \newcommand{\rank}{\mathop{\operatorname{rank}}}
641
+ \newcommand{\PP}{\Bold{P}}
642
+ \newcommand{\OO}{\mathcal{O}}
643
+ \newcommand{\Bold}[1]{\mathbf{#1}}
644
+ <BLANKLINE>
645
+ """
646
+ from sage.misc.latex_macros import sage_latex_macros
647
+ return "\n".join([_Latex_prefs._option['preamble'],
648
+ "\n".join(sage_latex_macros()),
649
+ _Latex_prefs._option['macros']])
650
+
651
+
652
+ def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_in_background=False):
653
+ """
654
+ This runs LaTeX on the TeX file "filename.tex". It produces files
655
+ ``filename.dvi`` (or ``filename.pdf`` if ``engine`` is either ``'pdflatex'``,
656
+ ``'xelatex'``, or ``'lualatex'``) and if ``png`` is ``True``, ``filename.png``.
657
+ If ``png`` is ``True`` and ``dvipng`` cannot convert the dvi file to png
658
+ (because of postscript specials or other issues), then ``dvips`` is called, and
659
+ the PS file is converted to a png file.
660
+
661
+ INPUT:
662
+
663
+ - ``filename`` -- string; file to process, including full path
664
+
665
+ - ``debug`` -- boolean (default: ``False``); whether to print
666
+ verbose debugging output
667
+
668
+ - ``density`` -- integer (default: 150); how big output
669
+ image is
670
+
671
+ - ``engine`` -- string; latex engine to use
672
+
673
+ - ``png`` -- boolean (default: ``False``); whether to produce a
674
+ png file
675
+
676
+ - ``do_in_background`` -- boolean (default: ``False``); unused,
677
+ kept for backwards compatibility
678
+
679
+ OUTPUT:
680
+
681
+ A string which could be a string starting with ``'Error'`` (if there was a
682
+ problem), or it could be ``'pdf'`` or ``'dvi'``. If ``engine`` is
683
+ ``'latex'`` or ``None``, then a dvi file is created, but if there appear to
684
+ be problems with it (because of PS special commands, for example), then a
685
+ pdf file is created instead. The function returns ``'dvi'`` or ``'pdf'``
686
+ to indicate which type of file is created. (Detecting problems requires
687
+ that ``dvipng`` be installed; if it is not, then the dvi file is not checked
688
+ for problems and ``'dvi'`` is returned.) If ``engine`` is ``'pdflatex'``,
689
+ ``'xelatex'`` or ``'lualatex'`` and there are no errors, then ``'pdf'`` is
690
+ returned.
691
+
692
+ .. WARNING::
693
+
694
+ If ``png`` is ``True``, then when using latex (the default), you
695
+ must have ``dvipng`` (or ``dvips`` and ``convert``) installed on your
696
+ operating system, or this command will not work. When using
697
+ ``pdflatex``, ``xelatex`` or ``lualatex``, you must have ``convert`` installed.
698
+
699
+ EXAMPLES::
700
+
701
+ sage: from sage.misc.latex import _run_latex_, _latex_file_
702
+ sage: from tempfile import NamedTemporaryFile
703
+ sage: with NamedTemporaryFile(mode='w+t', suffix='.tex') as f: # random, optional - latex
704
+ ....: _ = f.write(_latex_file_([ZZ['x'], RR]))
705
+ ....: f.flush()
706
+ ....: _run_latex_(f.name)
707
+ 'dvi'
708
+ """
709
+ if engine is None:
710
+ engine = _Latex_prefs._option["engine"]
711
+ if engine is None:
712
+ engine = _default_engine()
713
+
714
+ if not engine or engine == "latex":
715
+ from sage.features.latex import latex
716
+ latex().require()
717
+ command = "latex"
718
+ # 'suffix' is used in the 'convert' command list
719
+ suffix = "ps"
720
+ return_suffix = "dvi"
721
+ elif engine == "pdflatex":
722
+ from sage.features.latex import pdflatex
723
+ pdflatex().require()
724
+ command = "pdflatex"
725
+ suffix = "pdf"
726
+ return_suffix = "pdf"
727
+ elif engine == "xelatex":
728
+ from sage.features.latex import xelatex
729
+ xelatex().require()
730
+ command = "xelatex"
731
+ suffix = "pdf"
732
+ return_suffix = "pdf"
733
+ elif engine == "lualatex":
734
+ from sage.features.latex import lualatex
735
+ lualatex().require()
736
+ command = "lualatex"
737
+ suffix = "pdf"
738
+ return_suffix = "pdf"
739
+ else:
740
+ raise ValueError("Unsupported LaTeX engine.")
741
+
742
+ # if png output + latex, check to see if dvipng or magick/convert is installed.
743
+ from sage.features.imagemagick import ImageMagick
744
+ from sage.features.dvipng import dvipng
745
+ if png:
746
+ if ((not engine or engine == "latex")
747
+ and not (dvipng().is_present() or ImageMagick().is_present())):
748
+ print()
749
+ print("Error: neither dvipng nor magick/convert (from the ImageMagick suite)")
750
+ print("appear to be installed. Displaying LaTeX, PDFLaTeX output")
751
+ print("requires at least one of these programs, so please install")
752
+ print("and try again.")
753
+ print()
754
+ print("Go to http://sourceforge.net/projects/dvipng/ and")
755
+ print("http://www.imagemagick.org to download these programs.")
756
+ return "Error"
757
+ # if png output + [pdf|xe|lua]latex, check to see if magick/convert is installed.
758
+ elif engine in ["pdflatex", "xelatex", "lualatex"]:
759
+ ImageMagick().require()
760
+ # check_validity: check to see if the dvi file is okay by trying
761
+ # to convert to a png file. if this fails, return_suffix will be
762
+ # set to "pdf". return_suffix is the return value for this
763
+ # function.
764
+ #
765
+ # thus if not png output, check validity of dvi output if dvipng
766
+ # or magick/convert is installed.
767
+ else:
768
+ check_validity = dvipng().is_present()
769
+ # set up filenames, other strings:
770
+ base, filename = os.path.split(filename)
771
+ filename = os.path.splitext(filename)[0] # get rid of extension
772
+ if len(filename.split()) > 1:
773
+ raise ValueError("filename must contain no spaces")
774
+ if not debug:
775
+ redirect = PIPE
776
+ else:
777
+ redirect = None
778
+ # if do_in_background:
779
+ # background = ' &'
780
+ # else:
781
+ # background = ''
782
+
783
+ # Define the commands to be used:
784
+ lt = [command, r'\nonstopmode', r'\input{' + filename + '.tex}']
785
+ # dvipng is run with the 'picky' option: this means that if
786
+ # there are warnings, no png file is created.
787
+ dvipng = ['dvipng', '--picky', '-q', '-T', 'tight',
788
+ '-D', str(density), filename + '.dvi', '-o', filename + '.png']
789
+
790
+ dvips = ['dvips', filename + '.dvi']
791
+
792
+ ps2pdf = ['ps2pdf', filename + '.ps']
793
+
794
+ # We seem to need a larger size when using magick/convert compared to
795
+ # when using dvipng:
796
+ density = int(1.4 * density / 1.3)
797
+ from sage.features.imagemagick import Magick
798
+ magick = [Magick().executable, '-density',
799
+ '{0}x{0}'.format(density), '-trim', filename + '.' + suffix,
800
+ filename + '.png']
801
+
802
+ # it is possible to get through the following commands
803
+ # without running a program, so in that case we force error
804
+ e = False
805
+
806
+ # our standard way of calling programs here; change this if we want
807
+ # finer-grained analysis of the return code. Think of the output as
808
+ # a boolean: "the command exited normally"
809
+ def subpcall(x):
810
+ return not call(x, stdout=redirect,
811
+ stderr=redirect, cwd=base)
812
+ if engine in ['pdflatex', 'xelatex', 'lualatex']:
813
+ if debug:
814
+ print(lt)
815
+ if png:
816
+ print(magick)
817
+ e = subpcall(lt)
818
+ if png:
819
+ e = e and subpcall(magick)
820
+ else: # latex
821
+ if (png or check_validity):
822
+ if dvipng().is_present():
823
+ if debug:
824
+ print(lt)
825
+ print(dvipng)
826
+ e = subpcall(lt) and subpcall(dvipng)
827
+ dvipng_error = not os.path.exists(os.path.join(base, filename + '.png'))
828
+ # If there is no png file, then either the latex
829
+ # process failed or dvipng failed. Assume that dvipng
830
+ # failed, and try running dvips and magick/convert. (If the
831
+ # latex process failed, then dvips and magick/convert will
832
+ # fail also, so we'll still catch the error.)
833
+ if dvipng_error:
834
+ if png:
835
+ if ImageMagick().is_present():
836
+ if debug:
837
+ print("'dvipng' failed; trying 'magick/convert' instead...")
838
+ print(dvips)
839
+ print(magick)
840
+ e = subpcall(dvips) and subpcall(magick)
841
+ else:
842
+ print("Error: 'dvipng' failed and 'magick/convert' is not installed.")
843
+ return "Error: dvipng failed."
844
+ else: # not png, i.e., check_validity
845
+ return_suffix = "pdf"
846
+ if debug:
847
+ print("bad dvi file; running dvips and ps2pdf instead...")
848
+ print(dvips)
849
+ print(ps2pdf)
850
+ e = subpcall(dvips) and subpcall(ps2pdf)
851
+ if not e: # error running dvips and/or ps2pdf
852
+ pdflt = lt[:]
853
+ pdflt[1] = 'pdflatex'
854
+ if debug:
855
+ print("error running dvips and ps2pdf; trying pdflatex instead...")
856
+ print(pdflt)
857
+ e = subpcall(pdflt)
858
+ else: # do not have dvipng, so must have magick/convert. run latex, dvips, magick/convert.
859
+ if debug:
860
+ print(lt)
861
+ print(dvips)
862
+ print(magick)
863
+ e = subpcall(lt) and subpcall(dvips) and subpcall(magick)
864
+ if not e:
865
+ print("An error occurred.")
866
+ try:
867
+ with open(base + '/' + filename + '.log') as f:
868
+ print(f.read())
869
+ except OSError:
870
+ pass
871
+ return "Error latexing slide."
872
+ return return_suffix
873
+
874
+
875
+ # -------------------------------------------------------
876
+ # The Latex class is used to make slides and LaTeX output
877
+ # -------------------------------------------------------
878
+
879
+
880
+ class LatexCall:
881
+ r"""
882
+ Typeset Sage objects via a ``__call__`` method to this class,
883
+ typically by calling those objects' ``_latex_`` methods. The
884
+ class :class:`Latex` inherits from this. This class is used in
885
+ :mod:`~sage.misc.latex_macros`, while functions from
886
+ :mod:`~sage.misc.latex_macros` are used in :class:`Latex`, so this
887
+ is here primarily to avoid circular imports.
888
+
889
+ EXAMPLES::
890
+
891
+ sage: from sage.misc.latex import LatexCall
892
+ sage: LatexCall()(ZZ)
893
+ \Bold{Z}
894
+ sage: LatexCall().__call__(ZZ)
895
+ \Bold{Z}
896
+
897
+ This returns an instance of the class :class:`LatexExpr`::
898
+
899
+ sage: type(LatexCall()(ZZ))
900
+ <class 'sage.misc.latex.LatexExpr'>
901
+ """
902
+ def __call__(self, x, combine_all=False):
903
+ r"""
904
+ Return a :class:`LatexExpr` built out of the argument ``x``.
905
+
906
+ INPUT:
907
+
908
+ - ``x`` -- a Sage object
909
+
910
+ - ``combine_all`` -- boolean (default: ``False``); if ``combine_all``
911
+ is ``True`` and the input is a tuple, then it does not return a
912
+ tuple and instead returns a string with all the elements separated by
913
+ a single space
914
+
915
+ OUTPUT: a :class:`LatexExpr` built from ``x``
916
+
917
+ EXAMPLES::
918
+
919
+ sage: latex(Integer(3)) # indirect doctest
920
+ 3
921
+ sage: latex(1==0)
922
+ \mathrm{False}
923
+ sage: print(latex([x, 2])) # needs sage.symbolic
924
+ \left[x, 2\right]
925
+
926
+ Check that :issue:`11775` is fixed::
927
+
928
+ sage: latex((x,2), combine_all=True) # needs sage.symbolic
929
+ x 2
930
+ """
931
+ if has_latex_attr(x):
932
+ return LatexExpr(x._latex_())
933
+ try:
934
+ f = latex_table[type(x)]
935
+ if isinstance(x, tuple):
936
+ return LatexExpr(f(x, combine_all=combine_all))
937
+ return LatexExpr(f(x))
938
+ except KeyError:
939
+ return LatexExpr(str_function(str(x)))
940
+
941
+
942
+ class Latex(LatexCall):
943
+ r"""nodetex
944
+ Enter, e.g.,
945
+
946
+ ::
947
+
948
+ %latex
949
+ The equation $y^2 = x^3 + x$ defines an elliptic curve.
950
+ We have $2006 = \sage{factor(2006)}$.
951
+
952
+ in an input cell in the notebook to get a typeset version. Use
953
+ ``%latex_debug`` to get debugging output.
954
+
955
+ Use ``latex(...)`` to typeset a Sage object. Use :class:`LatexExpr`
956
+ to typeset LaTeX code that you create by hand.
957
+
958
+ Use ``%slide`` instead to typeset slides.
959
+
960
+ .. WARNING::
961
+
962
+ You must have dvipng (or dvips and magick/convert) installed
963
+ on your operating system, or this command will not work.
964
+
965
+ EXAMPLES::
966
+
967
+ sage: latex(x^20 + 1) # needs sage.symbolic
968
+ x^{20} + 1
969
+ sage: latex(FiniteField(25,'a')) # needs sage.rings.finite_rings
970
+ \Bold{F}_{5^{2}}
971
+ sage: latex("hello")
972
+ \text{\texttt{hello}}
973
+ sage: LatexExpr(r"\frac{x^2 - 1}{x + 1} = x - 1")
974
+ \frac{x^2 - 1}{x + 1} = x - 1
975
+
976
+ LaTeX expressions can be added; note that a space is automatically
977
+ inserted::
978
+
979
+ sage: LatexExpr(r"y \neq") + latex(x^20 + 1) # needs sage.symbolic
980
+ y \neq x^{20} + 1
981
+ """
982
+ def __init__(self, debug=False, slide=False, density=150, engine=None):
983
+ """
984
+ Initialize the latex builder.
985
+
986
+ EXAMPLES::
987
+
988
+ sage: from sage.misc.latex import Latex
989
+ sage: l = Latex()
990
+ sage: TestSuite(l).run(skip ='_test_pickling')
991
+ """
992
+ self.__debug = debug
993
+ self.__slide = slide
994
+ self.__engine = engine
995
+ self.__density = density
996
+
997
+ def _relation_symbols(self):
998
+ """
999
+ Return a dictionary whose keys are attributes of the
1000
+ :mod:`operator` module and whose values are the corresponding
1001
+ LaTeX expressions.
1002
+
1003
+ EXAMPLES::
1004
+
1005
+ sage: import operator
1006
+ sage: latex._relation_symbols()[operator.ge]
1007
+ ' \\geq '
1008
+ """
1009
+ import operator
1010
+ return {operator.lt: ' < ', operator.le: ' \\leq ',
1011
+ operator.eq: ' = ', operator.ne: ' \\neq ',
1012
+ operator.ge: ' \\geq ', operator.gt: ' > '}
1013
+
1014
+ def _latex_preparse(self, s, locals):
1015
+ r"""
1016
+ Replace instances of ``'\sage{x}'`` in ``s`` with the LaTeX version of
1017
+ ``x`` in the running session.
1018
+
1019
+ EXAMPLES::
1020
+
1021
+ sage: s = 2
1022
+ sage: sage.misc.latex.Latex()._latex_preparse(r'\sage{s}', locals())
1023
+ '2'
1024
+ """
1025
+ from sage.misc.sage_eval import sage_eval
1026
+ i0 = -1
1027
+ while True:
1028
+ i = s.find('\\sage{')
1029
+ if i == -1 or i == i0:
1030
+ return s
1031
+ i0 = i
1032
+ t = s[i + 6:]
1033
+ j = t.find('}')
1034
+ if j == -1:
1035
+ return s
1036
+
1037
+ var = t[:j]
1038
+ try:
1039
+ k = str(latex(sage_eval(var, locals)))
1040
+ except Exception as msg:
1041
+ print(msg)
1042
+ k = '\\mbox{\\rm [%s undefined]}' % var
1043
+ s = s[:i] + k + t[j + 1:]
1044
+
1045
+ def eval(self, x, globals, strip=False, filename=None, debug=None,
1046
+ density=None, engine=None, locals={}):
1047
+ r"""
1048
+ Compile the formatted tex given by ``x`` as a png and writes the
1049
+ output file to the directory given by ``filename``.
1050
+
1051
+ INPUT:
1052
+
1053
+ - ``globals`` -- a globals dictionary
1054
+
1055
+ - ``x`` -- string to evaluate
1056
+
1057
+ - ``strip`` -- ignored
1058
+
1059
+ - ``filename`` -- output filename
1060
+
1061
+ - ``debug`` -- whether to print verbose debugging output
1062
+
1063
+ - ``density`` -- how big output image is
1064
+
1065
+ - ``engine`` -- latex engine to use. Currently ``'latex'``,
1066
+ ``'pdflatex'``, ``'xelatex'`` and ``'lualatex'`` are supported
1067
+
1068
+ - ``locals`` -- extra local variables used when evaluating Sage code in ``x``
1069
+
1070
+ .. WARNING::
1071
+
1072
+ When using ``'latex'`` (the default), you must have ``dvipng`` (or
1073
+ ``dvips`` and ``magick/convert``) installed on your operating system, or
1074
+ this command will not work. When using ``'pdflatex'``, ``'xelatex'``
1075
+ or ``'lualatex'``, you must have ``magick/convert`` installed.
1076
+
1077
+ OUTPUT:
1078
+
1079
+ If it compiled successfully, this returns an empty string ``''``,
1080
+ otherwise it returns ``None``.
1081
+
1082
+ EXAMPLES::
1083
+
1084
+ sage: fn = tmp_filename()
1085
+ sage: latex.eval("$\\ZZ[x]$", locals(), filename=fn) # not tested
1086
+ ''
1087
+ sage: latex.eval(r"\ThisIsAnInvalidCommand", {}) # optional -- latex ImageMagick
1088
+ An error occurred...
1089
+ """
1090
+ MACROS = latex_extra_preamble()
1091
+
1092
+ if density is None:
1093
+ density = self.__density
1094
+ if filename is None:
1095
+ filename = 'sage%s' % random.randint(1, 100) # to defeat browser caches
1096
+ else:
1097
+ filename = os.path.splitext(filename)[0] # get rid of extension
1098
+
1099
+ result = None
1100
+ with TemporaryDirectory() as base:
1101
+ orig_base, filename = os.path.split(os.path.abspath(filename))
1102
+ if len(filename.split()) > 1:
1103
+ raise ValueError("filename must contain no spaces")
1104
+ if debug is None:
1105
+ debug = self.__debug
1106
+ x = self._latex_preparse(x, locals)
1107
+ O = open(os.path.join(base, filename + ".tex"), 'w')
1108
+ if self.__slide:
1109
+ O.write(SLIDE_HEADER)
1110
+ O.write(MACROS)
1111
+ O.write('\\begin{document}\n\n')
1112
+ else:
1113
+ O.write(LATEX_HEADER)
1114
+ O.write(MACROS)
1115
+ O.write('\\begin{document}\n')
1116
+
1117
+ O.write(x)
1118
+ if self.__slide:
1119
+ O.write('\n\n\\end{document}')
1120
+ else:
1121
+ O.write('\n\n\\end{document}\n')
1122
+
1123
+ O.close()
1124
+ if engine is None:
1125
+ engine = self.__engine
1126
+ if engine is None:
1127
+ engine = _Latex_prefs._option["engine"]
1128
+ if engine is None:
1129
+ engine = _default_engine()
1130
+
1131
+ e = _run_latex_(os.path.join(base, filename + ".tex"),
1132
+ debug=debug,
1133
+ density=density,
1134
+ engine=engine,
1135
+ png=True)
1136
+
1137
+ if e.find("Error") == -1:
1138
+ shutil.copy(os.path.join(base, filename + ".png"),
1139
+ os.path.join(orig_base, filename + ".png"))
1140
+ result = ''
1141
+
1142
+ return result
1143
+
1144
+ def blackboard_bold(self, t=None):
1145
+ r"""nodetex
1146
+ Controls whether Sage uses blackboard bold or ordinary bold
1147
+ face for typesetting ``ZZ``, ``RR``, etc.
1148
+
1149
+ INPUT:
1150
+
1151
+ - ``t`` -- boolean or ``None``
1152
+
1153
+ OUTPUT:
1154
+
1155
+ If ``t`` is ``None``, return the current setting (``True`` or
1156
+ ``False``).
1157
+
1158
+ If ``t`` is ``True``, use blackboard bold (``\mathbb``); otherwise use
1159
+ boldface (``\mathbf``).
1160
+
1161
+ EXAMPLES::
1162
+
1163
+ sage: latex.blackboard_bold()
1164
+ False
1165
+ sage: latex.blackboard_bold(True)
1166
+ sage: latex.blackboard_bold()
1167
+ True
1168
+ sage: latex.blackboard_bold(False)
1169
+ """
1170
+ if t is None:
1171
+ return _Latex_prefs._option["blackboard_bold"]
1172
+ from .latex_macros import sage_configurable_latex_macros
1173
+ old = _Latex_prefs._option["blackboard_bold"]
1174
+ _Latex_prefs._option["blackboard_bold"] = bool(t)
1175
+ if bool(old) != bool(t):
1176
+ if old:
1177
+ old_macro = "\\newcommand{\\Bold}[1]{\\mathbb{#1}}"
1178
+ else:
1179
+ old_macro = "\\newcommand{\\Bold}[1]{\\mathbf{#1}}"
1180
+ if bool(t):
1181
+ macro = "\\newcommand{\\Bold}[1]{\\mathbb{#1}}"
1182
+ else:
1183
+ macro = "\\newcommand{\\Bold}[1]{\\mathbf{#1}}"
1184
+ sage_configurable_latex_macros.remove(old_macro)
1185
+ sage_configurable_latex_macros.append(macro)
1186
+
1187
+ def matrix_delimiters(self, left=None, right=None):
1188
+ r"""nodetex
1189
+ Change the left and right delimiters for the LaTeX representation
1190
+ of matrices
1191
+
1192
+ INPUT:
1193
+
1194
+ - ``left``, ``right`` -- strings or ``None``
1195
+
1196
+ If both ``left`` and ``right`` are ``None``, then return the
1197
+ current delimiters. Otherwise, set the left and/or right
1198
+ delimiters, whichever are specified.
1199
+
1200
+ Good choices for ``left`` and ``right`` are any delimiters which
1201
+ LaTeX understands and knows how to resize; some examples are:
1202
+
1203
+ - parentheses: ``'('``, ``')'``
1204
+ - brackets: ``'['``, ``']'``
1205
+ - braces: ``'\\{'``, ``'\\}'``
1206
+ - vertical lines: ``'|'``
1207
+ - angle brackets: ``'\\langle'``, ``'\\rangle'``
1208
+
1209
+ .. NOTE::
1210
+
1211
+ Putting aside aesthetics, you may combine these in any way
1212
+ imaginable; for example, you could set ``left`` to be a right-hand
1213
+ bracket ``']'`` and ``right`` to be a right-hand brace ``'\\}'``,
1214
+ and it will be typeset correctly.
1215
+
1216
+ EXAMPLES::
1217
+
1218
+ sage: # needs sage.modules
1219
+ sage: a = matrix(1, 1, [17])
1220
+ sage: latex(a)
1221
+ \left(\begin{array}{r}
1222
+ 17
1223
+ \end{array}\right)
1224
+ sage: latex.matrix_delimiters('[', ']')
1225
+ sage: latex(a)
1226
+ \left[\begin{array}{r}
1227
+ 17
1228
+ \end{array}\right]
1229
+ sage: latex.matrix_delimiters(left='\\{')
1230
+ sage: latex(a)
1231
+ \left\{\begin{array}{r}
1232
+ 17
1233
+ \end{array}\right]
1234
+ sage: latex.matrix_delimiters()
1235
+ ['\\{', ']']
1236
+
1237
+ Restore defaults::
1238
+
1239
+ sage: latex.matrix_delimiters('(', ')')
1240
+ """
1241
+ if left is None and right is None:
1242
+ return _Latex_prefs._option['matrix_delimiters']
1243
+ else:
1244
+ if left is not None:
1245
+ _Latex_prefs._option['matrix_delimiters'][0] = left
1246
+ if right is not None:
1247
+ _Latex_prefs._option['matrix_delimiters'][1] = right
1248
+
1249
+ def vector_delimiters(self, left=None, right=None):
1250
+ r"""nodetex
1251
+ Change the left and right delimiters for the LaTeX representation
1252
+ of vectors
1253
+
1254
+ INPUT:
1255
+
1256
+ - ``left``, ``right`` -- strings or ``None``
1257
+
1258
+ If both ``left`` and ``right`` are ``None``, then return the
1259
+ current delimiters. Otherwise, set the left and/or right
1260
+ delimiters, whichever are specified.
1261
+
1262
+ Good choices for ``left`` and ``right`` are any delimiters which
1263
+ LaTeX understands and knows how to resize; some examples are:
1264
+
1265
+ - parentheses: ``'('``, ``')'``
1266
+ - brackets: ``'['``, ``']'``
1267
+ - braces: ``'\\{'``, ``'\\}'``
1268
+ - vertical lines: ``'|'``
1269
+ - angle brackets: ``'\\langle'``, ``'\\rangle'``
1270
+
1271
+ .. NOTE::
1272
+
1273
+ Putting aside aesthetics, you may combine these in any way
1274
+ imaginable; for example, you could set ``left`` to be a right-hand
1275
+ bracket ``']'`` and ``right`` to be a right-hand brace ``'\\}'``, and it
1276
+ will be typeset correctly.
1277
+
1278
+ EXAMPLES::
1279
+
1280
+ sage: # needs sage.modules
1281
+ sage: a = vector(QQ, [1,2,3])
1282
+ sage: latex(a)
1283
+ \left(1,\,2,\,3\right)
1284
+ sage: latex.vector_delimiters('[', ']')
1285
+ sage: latex(a)
1286
+ \left[1,\,2,\,3\right]
1287
+ sage: latex.vector_delimiters(right='\\}')
1288
+ sage: latex(a)
1289
+ \left[1,\,2,\,3\right\}
1290
+ sage: latex.vector_delimiters()
1291
+ ['[', '\\}']
1292
+
1293
+ Restore defaults::
1294
+
1295
+ sage: latex.vector_delimiters('(', ')')
1296
+ """
1297
+ if left is None and right is None:
1298
+ return _Latex_prefs._option['vector_delimiters']
1299
+ else:
1300
+ if left is not None:
1301
+ _Latex_prefs._option['vector_delimiters'][0] = left
1302
+ if right is not None:
1303
+ _Latex_prefs._option['vector_delimiters'][1] = right
1304
+
1305
+ def matrix_column_alignment(self, align=None):
1306
+ r"""nodetex
1307
+ Changes the column-alignment of the LaTeX representation of
1308
+ matrices.
1309
+
1310
+ INPUT:
1311
+
1312
+ - ``align`` -- string (``'r'`` for right, ``'c'`` for center,
1313
+ ``'l'`` for left) or ``None``
1314
+
1315
+ OUTPUT:
1316
+
1317
+ If ``align`` is ``None``, then returns the current
1318
+ alignment-string. Otherwise, set this alignment.
1319
+
1320
+ The input ``align`` can be any string which the LaTeX
1321
+ ``array``-environment understands as a parameter for
1322
+ aligning a column.
1323
+
1324
+ EXAMPLES::
1325
+
1326
+ sage: # needs sage.modules
1327
+ sage: a = matrix(1, 1, [42])
1328
+ sage: latex(a)
1329
+ \left(\begin{array}{r}
1330
+ 42
1331
+ \end{array}\right)
1332
+ sage: latex.matrix_column_alignment('c')
1333
+ sage: latex(a)
1334
+ \left(\begin{array}{c}
1335
+ 42
1336
+ \end{array}\right)
1337
+ sage: latex.matrix_column_alignment('l')
1338
+ sage: latex(a)
1339
+ \left(\begin{array}{l}
1340
+ 42
1341
+ \end{array}\right)
1342
+
1343
+ Restore defaults::
1344
+
1345
+ sage: latex.matrix_column_alignment('r')
1346
+ """
1347
+ if align is None:
1348
+ return _Latex_prefs._option['matrix_column_alignment']
1349
+ else:
1350
+ _Latex_prefs._option['matrix_column_alignment'] = align
1351
+
1352
+ @cached_method
1353
+ def has_file(self, file_name) -> bool:
1354
+ """
1355
+ INPUT:
1356
+
1357
+ - ``file_name`` -- string
1358
+
1359
+ Tests whether the local LaTeX installation includes ``file_name``.
1360
+
1361
+ EXAMPLES::
1362
+
1363
+ sage: latex.has_file("article.cls") # optional - latex
1364
+ True
1365
+ sage: latex.has_file("some_inexistent_file.sty")
1366
+ False
1367
+ """
1368
+ assert isinstance(file_name, str)
1369
+ try:
1370
+ retcode = call("kpsewhich %s" % file_name, shell=True,
1371
+ stdout=PIPE, stderr=PIPE)
1372
+ return (retcode == 0)
1373
+ except OSError:
1374
+ return False
1375
+
1376
+ @cached_method
1377
+ def check_file(self, file_name, more_info=""):
1378
+ """
1379
+ INPUT:
1380
+
1381
+ - ``file_name`` -- string
1382
+
1383
+ - ``more_info`` -- string (default: ``''``)
1384
+
1385
+ Emit a warning if the local LaTeX installation does not
1386
+ include ``file_name``. The string ``more_info`` is appended
1387
+ to the warning message. The warning is only emitted the first
1388
+ time this method is called.
1389
+
1390
+ EXAMPLES::
1391
+
1392
+ sage: latex.check_file("article.cls") # optional - latex
1393
+ sage: latex.check_file("some_inexistent_file.sty")
1394
+ Warning: `some_inexistent_file.sty` is not part of this computer's TeX installation.
1395
+ sage: latex.check_file("some_inexistent_file.sty")
1396
+ sage: latex.check_file("some_inexistent_file.sty", "This file is required for blah. It can be downloaded from: http://blah.org/")
1397
+ Warning: `some_inexistent_file.sty` is not part of this computer's TeX installation.
1398
+ This file is required for blah. It can be downloaded from: http://blah.org/
1399
+
1400
+ This test checks that the bug in :issue:`9091` is fixed::
1401
+
1402
+ sage: latex.check_file("article.cls", "The article class is really critical.") # optional - latex
1403
+ """
1404
+ assert isinstance(file_name, str)
1405
+ if not self.has_file(file_name):
1406
+ print("""
1407
+ Warning: `{}` is not part of this computer's TeX installation.""".format(file_name))
1408
+ if more_info:
1409
+ print(more_info)
1410
+
1411
+ def extra_macros(self, macros=None):
1412
+ r"""nodetex
1413
+ String containing extra LaTeX macros to use with ``%latex`` and ``%html``.
1414
+
1415
+ INPUT:
1416
+
1417
+ - ``macros`` -- string (default: ``None``)
1418
+
1419
+ If ``macros`` is ``None``, return the current string. Otherwise,
1420
+ set it to ``macros``. If you want to *append* to the string
1421
+ of macros instead of replacing it, use
1422
+ :meth:`latex.add_macro <Latex.add_macro>`.
1423
+
1424
+ EXAMPLES::
1425
+
1426
+ sage: latex.extra_macros("\\newcommand{\\foo}{bar}")
1427
+ sage: latex.extra_macros()
1428
+ '\\newcommand{\\foo}{bar}'
1429
+ sage: latex.extra_macros("")
1430
+ sage: latex.extra_macros()
1431
+ ''
1432
+ """
1433
+ if macros is None:
1434
+ return _Latex_prefs._option['macros']
1435
+ else:
1436
+ _Latex_prefs._option['macros'] = macros
1437
+
1438
+ def add_macro(self, macro):
1439
+ r"""nodetex
1440
+ Append to the string of extra LaTeX macros, for use with %latex and %html.
1441
+
1442
+ INPUT:
1443
+
1444
+ - ``macro`` -- string
1445
+
1446
+ EXAMPLES::
1447
+
1448
+ sage: latex.extra_macros()
1449
+ ''
1450
+ sage: latex.add_macro("\\newcommand{\\foo}{bar}")
1451
+ sage: latex.extra_macros()
1452
+ '\\newcommand{\\foo}{bar}'
1453
+ sage: latex.extra_macros("") # restore to default
1454
+ """
1455
+ current = latex.extra_macros()
1456
+ if current.find(macro) == -1:
1457
+ _Latex_prefs._option['macros'] += macro
1458
+
1459
+ def extra_preamble(self, s=None):
1460
+ r"""nodetex
1461
+ String containing extra preamble to be used with %latex.
1462
+
1463
+ INPUT:
1464
+
1465
+ - ``s`` -- string or ``None``
1466
+
1467
+ If ``s`` is ``None``, return the current preamble. Otherwise, set
1468
+ it to ``s``. If you want to *append* to the current extra
1469
+ preamble instead of replacing it, use
1470
+ :meth:`latex.add_to_preamble <Latex.add_to_preamble>`.
1471
+
1472
+ You will almost certainly need to use this when using the
1473
+ XeLaTeX engine; see below or the documentation for
1474
+ :func:`engine` for a suggested preamble.
1475
+
1476
+ EXAMPLES::
1477
+
1478
+ sage: latex.extra_preamble("\\DeclareMathOperator{\\Ext}{Ext}")
1479
+ sage: latex.extra_preamble()
1480
+ '\\DeclareMathOperator{\\Ext}{Ext}'
1481
+ sage: latex.extra_preamble("\\"+r"usepackage{fontspec,xunicode,xltxtra}\setmainfont[Mapping=tex-text]{UnBatang}\setmonofont[Mapping=tex-text]{UnDotum}")
1482
+ sage: latex.extra_preamble()
1483
+ '\\usepackage{fontspec,xunicode,xltxtra}\\setmainfont[Mapping=tex-text]{UnBatang}\\setmonofont[Mapping=tex-text]{UnDotum}'
1484
+ sage: latex.extra_preamble("")
1485
+ sage: latex.extra_preamble()
1486
+ ''
1487
+ """
1488
+ if s is None:
1489
+ return _Latex_prefs._option['preamble']
1490
+ else:
1491
+ _Latex_prefs._option['preamble'] = s
1492
+
1493
+ def add_to_preamble(self, s):
1494
+ r"""nodetex
1495
+ Append to the string ``s`` of extra LaTeX macros, for use with
1496
+ ``%latex``.
1497
+
1498
+ EXAMPLES::
1499
+
1500
+ sage: latex.extra_preamble()
1501
+ ''
1502
+ sage: latex.add_to_preamble("\\DeclareMathOperator{\\Ext}{Ext}")
1503
+
1504
+ At this point, a notebook cell containing
1505
+
1506
+ ::
1507
+
1508
+ %latex
1509
+ $\Ext_A^*(\GF{2}, \GF{2}) \Rightarrow \pi_*^s*(S^0)$
1510
+
1511
+ will be typeset correctly.
1512
+
1513
+ ::
1514
+
1515
+ sage: latex.add_to_preamble("\\usepackage{xypic}")
1516
+ sage: latex.extra_preamble()
1517
+ '\\DeclareMathOperator{\\Ext}{Ext}\\usepackage{xypic}'
1518
+
1519
+ Now one can put various xypic diagrams into a ``%latex`` cell, such as
1520
+
1521
+ ::
1522
+
1523
+ %latex
1524
+ \[ \xymatrix{ \circ \ar `r[d]^{a} `[rr]^{b} `/4pt[rr]^{c} `[rrr]^{d}
1525
+ `_dl[drrr]^{e} [drrr]^{f} & \circ & \circ & \circ \\ \circ & \circ &
1526
+ \circ & \circ } \]
1527
+
1528
+ Reset the preamble to its default, the empty string::
1529
+
1530
+ sage: latex.extra_preamble('')
1531
+ sage: latex.extra_preamble()
1532
+ ''
1533
+ """
1534
+ current = latex.extra_preamble()
1535
+ if current.find(s) == -1:
1536
+ _Latex_prefs._option['preamble'] += s
1537
+
1538
+ def add_package_to_preamble_if_available(self, package_name):
1539
+ r"""
1540
+ Add a ``\usepackage{package_name}`` instruction to the latex
1541
+ preamble if not yet present there, and if ``package_name.sty``
1542
+ is available in the LaTeX installation.
1543
+
1544
+ INPUT:
1545
+
1546
+ - ``package_name`` -- string
1547
+
1548
+ .. SEEALSO::
1549
+
1550
+ - :meth:`add_to_preamble`
1551
+ - :meth:`has_file`.
1552
+
1553
+ TESTS::
1554
+
1555
+ sage: latex.add_package_to_preamble_if_available("tkz-graph")
1556
+ sage: latex.add_package_to_preamble_if_available("nonexistent_package")
1557
+ sage: latex.extra_preamble() # optional - latex latex_package_tkz_graph
1558
+ '\\usepackage{tkz-graph}\n'
1559
+ sage: latex.extra_preamble('')
1560
+ """
1561
+ assert isinstance(package_name, str)
1562
+ if self.has_file(package_name + ".sty"):
1563
+ self.add_to_preamble("\\usepackage{%s}\n" % package_name)
1564
+
1565
+ def engine(self, e=None):
1566
+ r"""
1567
+ Set Sage to use ``e`` as latex engine when typesetting with
1568
+ :func:`view`, in ``%latex`` cells, etc.
1569
+
1570
+ INPUT:
1571
+
1572
+ - ``e`` -- ``'latex'``, ``'pdflatex'``, ``'xelatex'``, ``'lualatex'`` or ``None``
1573
+
1574
+ If ``e`` is ``None``, return the current engine.
1575
+
1576
+ If using the XeLaTeX engine, it will almost always be necessary
1577
+ to set the proper preamble with :func:`extra_preamble` or
1578
+ :func:`add_to_preamble`. For example::
1579
+
1580
+ latex.extra_preamble(r'''\usepackage{fontspec,xunicode,xltxtra}
1581
+ \setmainfont[Mapping=tex-text]{some font here}
1582
+ \setmonofont[Mapping=tex-text]{another font here}''')
1583
+
1584
+ EXAMPLES::
1585
+
1586
+ sage: latex.engine() # random
1587
+ 'lualatex'
1588
+ sage: latex.engine("latex")
1589
+ sage: latex.engine()
1590
+ 'latex'
1591
+ sage: latex.engine("pdflatex")
1592
+ sage: latex.engine()
1593
+ 'pdflatex'
1594
+ """
1595
+ if e is None:
1596
+ e = _Latex_prefs._option["engine"]
1597
+ if e is None:
1598
+ return _default_engine()
1599
+ else:
1600
+ return e
1601
+
1602
+ if e not in ["latex", "pdflatex", "xelatex", "luatex"]:
1603
+ raise ValueError("%s is not a supported LaTeX engine. Use latex, pdflatex, xelatex, or lualatex" % e)
1604
+
1605
+ _Latex_prefs._option["engine"] = e
1606
+
1607
+
1608
+ # Note: latex used to be a separate function, which by default was
1609
+ # only loaded in command-line mode: in the old notebook,
1610
+ # latex was defined by 'latex = Latex(density=130)'.
1611
+ # Meanwhile, the __call__ method for Latex used to call the latex
1612
+ # function. This has been changed around so that the contents of the
1613
+ # old latex function are now in Latex.__call__; thus the following
1614
+ # assignment.
1615
+ latex = Latex()
1616
+ # Ensure that latex appear in the sphinx doc as a function
1617
+ # so that the link :func:`latex` is correctly set up.
1618
+ latex.__doc__ = Latex.__call__.__doc__
1619
+
1620
+
1621
+ def _latex_file_(objects, title='SAGE', debug=False,
1622
+ sep='', tiny=False, math_left='\\[',
1623
+ math_right='\\]',
1624
+ extra_preamble=''):
1625
+ r"""nodetex
1626
+ Produce a string to be used as a LaTeX file, containing a
1627
+ representation of each object in objects.
1628
+
1629
+ INPUT:
1630
+
1631
+ - ``objects`` -- list (or object)
1632
+
1633
+ - ``title`` -- string (default: ``'Sage'``); title for the document
1634
+
1635
+ - ``math_left`` -- string (default: ``'\\['``); left delimiter for math mode
1636
+
1637
+ - ``math_right`` -- string (default: ``'\\]'``); right delimiter for math mode
1638
+
1639
+ - ``debug`` -- boolean (default: ``False``); print verbose output
1640
+
1641
+ - ``sep`` -- string (default: ``''``); separator between math objects
1642
+
1643
+ - ``tiny`` -- boolean (default: ``False``); use 'tiny' font
1644
+
1645
+ - ``extra_preamble`` -- string (default: ``''``); extra LaTeX commands;
1646
+ inserted before ``'\\begin{document}'``
1647
+
1648
+ This creates a string intended to be a LaTeX file containing the
1649
+ LaTeX representations of objects. It contains the following:
1650
+
1651
+ - a header (with documentclass and usepackage commands)
1652
+
1653
+ - ``extra_preamble``
1654
+
1655
+ - the title (centered)
1656
+
1657
+ - a size specification if ``tiny`` is ``True``
1658
+
1659
+ - LaTeX representation of the first element of ``objects``,
1660
+ surrounded by ``math_left`` and ``math_right``
1661
+
1662
+ Then if ``objects`` contains more than one element, for each
1663
+ remaining element:
1664
+
1665
+ - the string ``sep``; you can use this, for example, to add
1666
+ vertical space between objects with ``sep='\\vspace{15mm}'``,
1667
+ or to add a horizontal line between objects with
1668
+ ``sep='\\hrule'``, or to insert a page break between objects
1669
+ with ``sep='\\newpage'``.
1670
+
1671
+ - the LaTeX representation of the element
1672
+
1673
+ The string ends with ``'\\end{document}'``.
1674
+
1675
+ EXAMPLES::
1676
+
1677
+ sage: from sage.misc.latex import _latex_file_
1678
+ sage: _latex_file_(3, title="The number three")
1679
+ '\\documentclass{article}...\\begin{document}\n\\begin{center}{\\Large\\bf The number three}\\end{center}\n\\vspace{40mm}\\[3\\]\n\\end{document}'
1680
+ sage: _latex_file_([7, 8, 9], title="Why was six afraid of seven?", sep='\\vfill\\hrule\\vfill')
1681
+ '\\documentclass{article}...\\begin{document}\n\\begin{center}{\\Large\\bf Why was six afraid of seven?}\\end{center}\n\\vspace{40mm}\\[7\\]\n\n\\vfill\\hrule\\vfill\n\n\\[8\\]\n\n\\vfill\\hrule\\vfill\n\n\\[9\\]\n\\end{document}'
1682
+
1683
+ TESTS:
1684
+
1685
+ This makes sure that latex is called only once on an object::
1686
+
1687
+ sage: class blah():
1688
+ ....: def _latex_(x):
1689
+ ....: print("coucou")
1690
+ ....: return "x"
1691
+ sage: latex(blah())
1692
+ coucou
1693
+ x
1694
+ sage: s = sage.misc.latex._latex_file_(blah())
1695
+ coucou
1696
+ """
1697
+ process = True
1698
+ if has_latex_attr(objects):
1699
+ objects = [objects]
1700
+
1701
+ if not isinstance(objects, list):
1702
+ objects = [objects]
1703
+
1704
+ if tiny:
1705
+ size = '\\tiny\n'
1706
+ else:
1707
+ size = ''
1708
+
1709
+ formatted_title = "\n\\begin{center}{\\Large\\bf %s}\\end{center}\n" % str(title) if title else ""
1710
+ s = '%s\n\\begin{document}%s%s' % (extra_preamble, formatted_title, size)
1711
+
1712
+ if title:
1713
+ s += '\\vspace{40mm}'
1714
+ if process:
1715
+ for i in range(len(objects)):
1716
+ x = objects[i]
1717
+ L = latex(x)
1718
+ if '\\begin{pgfpicture}' in L:
1719
+ # Resize the pgf figure to the text width if larger.
1720
+ s += r'\begingroup\makeatletter\@ifundefined{pgffigure}{\newsavebox{\pgffigure}}{}\makeatother\endgroup'
1721
+ s += r'\begin{lrbox}{\pgffigure}' + '\n'
1722
+ s += '%s' % L
1723
+ s += r'\end{lrbox}'
1724
+ s += r'\resizebox{\ifdim\width>\textwidth\textwidth\else\width\fi}{!}{\usebox{\pgffigure}}' + '\n'
1725
+ elif '\\begin{verbatim}' not in L:
1726
+ s += '%s%s%s' % (math_left, L, math_right)
1727
+ else:
1728
+ s += '%s' % L
1729
+ if i < len(objects) - 1:
1730
+ s += '\n\n%s\n\n' % sep
1731
+ else:
1732
+ s += "\n\n".join(str(x) for x in objects)
1733
+
1734
+ # latex_extra_preamble() is called here and not before because some objects
1735
+ # may require additional packages to be displayed in LaTeX. Hence, the call
1736
+ # to latex(x) in the previous loop may change the result of
1737
+ # latex_extra_preamble()
1738
+ MACROS = latex_extra_preamble()
1739
+ s = LATEX_HEADER + '\n' + MACROS + s + '\n\\end{document}'
1740
+
1741
+ if debug:
1742
+ print('----')
1743
+ print(s)
1744
+ print('----')
1745
+
1746
+ return s
1747
+
1748
+
1749
+ def view(objects, title='Sage', debug=False, sep='', tiny=False,
1750
+ engine=None, viewer=None, tightpage=True, margin=None,
1751
+ mode='inline', combine_all=False, **kwds):
1752
+ r"""nodetex
1753
+ Compute a latex representation of each object in objects, compile,
1754
+ and display typeset. If used from the command line, this requires
1755
+ that latex be installed.
1756
+
1757
+ INPUT:
1758
+
1759
+ - ``objects`` -- list (or object)
1760
+
1761
+ - ``title`` -- string (default: ``'Sage'``); title for the
1762
+ document
1763
+
1764
+ - ``debug`` -- boolean (default: ``False``); print verbose
1765
+ output
1766
+
1767
+ - ``sep`` -- string (default: ``''``); separator between
1768
+ math objects
1769
+
1770
+ - ``tiny`` -- boolean (default: ``False``); use tiny font
1771
+
1772
+ - ``engine`` -- string or ``None`` (default: ``None``); can take the
1773
+ following values:
1774
+
1775
+ - ``None`` -- the value defined in the LaTeX global preferences
1776
+ ``latex.engine()`` is used
1777
+
1778
+ - ``'pdflatex'`` -- compilation does ``tex`` -> ``pdf``
1779
+
1780
+ - ``'xelatex'`` -- compilation does ``tex`` -> ``pdf``
1781
+
1782
+ - ``'lualatex'`` -- compilation does ``tex`` -> ``pdf``
1783
+
1784
+ - ``'latex'`` -- compilation first tries ``tex`` -> ``dvi`` -> ``png`` and if an
1785
+ error occurs then tries ``dvi`` -> ``ps`` -> ``pdf``. This is slower than
1786
+ ``'pdflatex'`` and known to be broken when overfull hboxes are detected.
1787
+
1788
+ - ``viewer`` -- string or ``None`` (default: ``None``); specify a viewer
1789
+ to use; currently the only options are ``None`` and ``'pdf'``
1790
+
1791
+ - ``tightpage`` -- boolean (default: ``True``); use the LaTeX package
1792
+ ``preview`` with the 'tightpage' option
1793
+
1794
+ - ``margin`` -- float or ``None`` (default: ``None``); adds a margin
1795
+ of ``margin`` mm. Has no affect if the option ``tightpage`` is ``False``.
1796
+
1797
+ - ``mode`` -- string (default: ``'inline'``); ``'display'`` for
1798
+ displaymath or ``'inline'`` for inline math
1799
+
1800
+ - ``combine_all`` -- boolean (default: ``False``); if ``combine_all`` is
1801
+ ``True`` and the input is a tuple, then it does not return a tuple and
1802
+ instead returns a string with all the elements separated by a single
1803
+ space
1804
+
1805
+ OUTPUT: display typeset objects
1806
+
1807
+ The output is displayed in a separate viewer displaying a dvi (or pdf)
1808
+ file, with the following: the title string is printed, centered, at the
1809
+ top. Beneath that, each object in ``objects`` is typeset on its own line,
1810
+ with the string ``sep`` inserted between these lines.
1811
+
1812
+ The value of ``sep`` is inserted between each element of the list
1813
+ ``objects``; you can, for example, add vertical space between
1814
+ objects with ``sep='\\vspace{15mm}'``, while ``sep='\\hrule'``
1815
+ adds a horizontal line between objects, and ``sep='\\newpage'``
1816
+ inserts a page break between objects.
1817
+
1818
+ If the ``engine`` is either ``'pdflatex'``, ``'xelatex'``, or ``'lualatex'``,
1819
+ it produces a pdf file. Otherwise, it produces a dvi file, and if the program
1820
+ ``dvipng`` is installed, it checks the dvi file by trying to convert it to a
1821
+ png file. If this conversion fails, the dvi file probably contains some
1822
+ postscript special commands or it has other issues which might make
1823
+ displaying it a problem; in this case, the file is converted to a pdf file,
1824
+ which is then displayed.
1825
+
1826
+ Setting ``viewer`` to ``'pdf'`` forces the use of a separate
1827
+ viewer, even in notebook mode. This also sets the latex engine to be
1828
+ ``pdflatex`` if the current engine is ``latex``.
1829
+
1830
+ Setting the option ``tightpage`` to ``True`` (this is the default setting)
1831
+ tells LaTeX to use the package 'preview' with the 'tightpage' option.
1832
+ Then, each object is typeset in its own page, and that page is cropped to
1833
+ exactly the size of the object. This is typically useful for very
1834
+ large pictures (like graphs) generated with tikz. This only works
1835
+ when using a separate viewer. Note that the object are currently
1836
+ typeset in plain math mode rather than displaymath, because the
1837
+ latter imposes a limit on the width of the picture. Technically,
1838
+ ``tightpage`` adds ::
1839
+
1840
+ \\usepackage[tightpage,active]{preview}
1841
+ \\PreviewEnvironment{page}
1842
+
1843
+ to the LaTeX preamble, and replaces the ``\\[`` and ``\\]`` around
1844
+ each object by ``\\begin{page}$`` and ``$\\end{page}``.
1845
+ Setting ``tightpage`` to ``False`` turns off this behavior and provides
1846
+ the latex output as a full page. If ``tightpage`` is set to ``True``,
1847
+ the ``Title`` is ignored.
1848
+
1849
+ TESTS::
1850
+
1851
+ sage: from sage.misc.latex import _run_latex_, _latex_file_
1852
+ sage: from tempfile import NamedTemporaryFile
1853
+ sage: g = sage.misc.latex.latex_examples.graph()
1854
+ sage: latex.add_to_preamble(r"\usepackage{tkz-graph}") # optional - latex_package_tkz_graph
1855
+ sage: with NamedTemporaryFile(mode='w+t', suffix='.tex') as f: # optional - latex latex_package_tkz_graph
1856
+ ....: _ = f.write(_latex_file_(g))
1857
+ ....: f.flush()
1858
+ ....: _run_latex_(f.name, engine='pdflatex')
1859
+ 'pdf'
1860
+
1861
+ sage: view(4, margin=5, debug=True) # not tested
1862
+ \documentclass{article}
1863
+ ...
1864
+ \usepackage[tightpage,active]{preview}
1865
+ \PreviewEnvironment{page}
1866
+ \setlength\PreviewBorder{5.000000mm}
1867
+ \begin{document}\begin{page}$4$\end{page}
1868
+ \end{document}
1869
+ ...
1870
+
1871
+ sage: view(4, debug=True) # not tested
1872
+ \documentclass{article}
1873
+ ...
1874
+ \usepackage[tightpage,active]{preview}
1875
+ \PreviewEnvironment{page}
1876
+ \begin{document}\begin{page}$4$\end{page}
1877
+ \end{document}
1878
+ ...
1879
+
1880
+
1881
+ sage: latex.extra_preamble('') # reset the preamble
1882
+
1883
+ sage: view(4, engine='garbage')
1884
+ Traceback (most recent call last):
1885
+ ...
1886
+ ValueError: Unsupported LaTeX engine.
1887
+ """
1888
+ if tightpage:
1889
+ if margin is None:
1890
+ margin_str = ""
1891
+ else:
1892
+ margin_str = '\n\\setlength\\PreviewBorder{%fmm}' % margin
1893
+ latex_options = {'extra_preamble':
1894
+ '\\usepackage[tightpage,active]{preview}\n' +
1895
+ '\\PreviewEnvironment{page}%s' % margin_str,
1896
+ 'math_left': '\\begin{page}$',
1897
+ 'math_right': '$\\end{page}'}
1898
+ title = None
1899
+ else:
1900
+ latex_options = {}
1901
+
1902
+ s = _latex_file_(objects, title=title, sep=sep, tiny=tiny, debug=debug, **latex_options)
1903
+ if engine is None:
1904
+ engine = _Latex_prefs._option["engine"]
1905
+ if engine is None:
1906
+ engine = _default_engine()
1907
+
1908
+ if viewer == "pdf" and engine == "latex":
1909
+ engine = "pdflatex"
1910
+ # command line or notebook with viewer
1911
+
1912
+ # We can't automatically delete the temporary file in this case
1913
+ # because we need it to live at least long enough for the viewer
1914
+ # to open it. Since we're launching the viewer asynchronously,
1915
+ # that would be tricky.
1916
+ tmp = TemporaryDirectory()
1917
+
1918
+ tex_file = os.path.join(tmp.name, "sage.tex")
1919
+ with open(tex_file, 'w') as file:
1920
+ file.write(s)
1921
+ suffix = _run_latex_(tex_file, debug=debug, engine=engine, png=False)
1922
+ if suffix == "pdf":
1923
+ from sage.misc.viewer import pdf_viewer
1924
+ viewer = pdf_viewer()
1925
+ elif suffix == "dvi":
1926
+ from sage.misc.viewer import dvi_viewer
1927
+ viewer = dvi_viewer()
1928
+ else:
1929
+ print("Latex error")
1930
+ tmp.cleanup()
1931
+ return
1932
+ output_file = os.path.join(tmp.name, "sage." + suffix)
1933
+
1934
+ if debug:
1935
+ print(f'temporary file: "{output_file}"')
1936
+ print(f'viewer: "{viewer}"')
1937
+
1938
+ # Return immediately but only clean up the temporary file after
1939
+ # the viewer has closed. This function is synchronous and waits
1940
+ # for the process to complete...
1941
+ def run_viewer():
1942
+ run([*viewer.split(), output_file], capture_output=True)
1943
+ tmp.cleanup()
1944
+
1945
+ # ...but we execute it asynchronously so that view() completes
1946
+ # immediately. The "daemon" flag is important because, without it,
1947
+ # sage won't quit until the viewer does.
1948
+ from threading import Thread
1949
+ t = Thread(target=run_viewer)
1950
+ t.daemon = True
1951
+ t.start()
1952
+
1953
+
1954
+ def pdf(x, filename, tiny=False, tightpage=True, margin=None, engine=None, debug=False):
1955
+ """
1956
+ Create an image from the latex representation of ``x`` and save it as a pdf
1957
+ file with the given filename.
1958
+
1959
+ INPUT:
1960
+
1961
+ - ``x`` -- a Sage object
1962
+
1963
+ - ``filename`` -- the filename with which to save the image
1964
+
1965
+ - ``tiny`` -- boolean (default: ``False``); if ``True``, use a tiny font
1966
+
1967
+ - ``tightpage`` -- boolean (default: ``True``); use the LaTeX package
1968
+ ``preview`` with the 'tightpage' option
1969
+
1970
+ - ``margin`` -- float (default: no margin); width of border, only effective
1971
+ with 'tight page'
1972
+
1973
+ - ``engine`` -- (default: ``None``) ``'latex'``, ``'pdflatex'``,
1974
+ ``'xelatex'`` or ``'lualatex'``; if ``None``, the value defined in the
1975
+ LaTeX global preferences ``latex.engine()`` is used
1976
+
1977
+ - ``debug`` -- boolean (default: ``False``); if ``True``, print verbose output
1978
+
1979
+ EXAMPLES::
1980
+
1981
+ sage: # optional - latex
1982
+ sage: from sage.misc.latex import pdf
1983
+ sage: import tempfile
1984
+ sage: with tempfile.NamedTemporaryFile(suffix=".pdf") as f: # random
1985
+ ....: pdf(ZZ[x], f.name)
1986
+ """
1987
+ from sage.plot.graphics import Graphics
1988
+ if isinstance(x, Graphics):
1989
+ x.save(filename)
1990
+ return
1991
+
1992
+ if tightpage:
1993
+ if margin is None:
1994
+ margin_str = ""
1995
+ else:
1996
+ margin_str = '\n\\setlength\\PreviewBorder{%fmm}' % margin
1997
+ latex_options = {'extra_preamble':
1998
+ '\\usepackage[tightpage,active]{preview}\n' +
1999
+ '\\PreviewEnvironment{page}%s' % margin_str,
2000
+ 'math_left': '\\begin{page}$',
2001
+ 'math_right': '$\\end{page}'}
2002
+ else:
2003
+ latex_options = {}
2004
+
2005
+ # create a string of latex code to write in a file
2006
+ s = _latex_file_([x], title='', tiny=tiny, debug=debug, **latex_options)
2007
+ if engine is None:
2008
+ engine = _Latex_prefs._option["engine"]
2009
+ if engine is None:
2010
+ engine = _default_engine()
2011
+
2012
+ # path name for permanent pdf output
2013
+ abs_path_to_pdf = os.path.abspath(filename)
2014
+ # temporary directory to store stuff
2015
+ with TemporaryDirectory() as tmp:
2016
+ tex_file = os.path.join(tmp, "sage.tex")
2017
+ pdf_file = os.path.join(tmp, "sage.pdf")
2018
+ # write latex string to file
2019
+ with open(tex_file, 'w') as file:
2020
+ file.write(s)
2021
+ # run latex on the file
2022
+ e = _run_latex_(tex_file, debug=debug, engine=engine)
2023
+ if e == 'pdf':
2024
+ # if no errors, copy pdf_file to the appropriate place
2025
+ shutil.copy(pdf_file, abs_path_to_pdf)
2026
+ else:
2027
+ print("Latex error or no pdf was generated.")
2028
+
2029
+
2030
+ def png(x, filename, density=150, debug=False,
2031
+ do_in_background=False, tiny=False, engine=None):
2032
+ """
2033
+ Create a png image representation of ``x`` and save to the given
2034
+ filename.
2035
+
2036
+ INPUT:
2037
+
2038
+ - ``x`` -- object to be displayed
2039
+
2040
+ - ``filename`` -- file in which to save the image
2041
+
2042
+ - ``density`` -- integer (default: 150)
2043
+
2044
+ - ``debug`` -- boolean (default: ``False``); print verbose output
2045
+
2046
+ - ``do_in_background`` -- boolean (default: ``False``); unused, kept for
2047
+ backwards compatibility
2048
+
2049
+ - ``tiny`` -- boolean (default: ``False``); use tiny font
2050
+
2051
+ - ``engine`` -- (default: ``None``) ``'latex'``, ``'pdflatex'``,
2052
+ ``'xelatex'`` or ``'lualatex'``
2053
+
2054
+ EXAMPLES::
2055
+
2056
+ sage: # optional - imagemagick latex, needs sage.plot
2057
+ sage: from sage.misc.latex import png
2058
+ sage: import tempfile
2059
+ sage: with tempfile.NamedTemporaryFile(suffix='.png') as f: # random
2060
+ ....: png(ZZ[x], f.name)
2061
+ """
2062
+ import sage.plot.all
2063
+ if isinstance(x, sage.plot.graphics.Graphics):
2064
+ x.save(filename)
2065
+ return
2066
+ # if not graphics: create a string of latex code to write in a file
2067
+ s = _latex_file_([x], math_left='$\\displaystyle', math_right='$', title='',
2068
+ debug=debug, tiny=tiny,
2069
+ extra_preamble='\\textheight=2\\textheight')
2070
+ if engine is None:
2071
+ engine = _Latex_prefs._option["engine"]
2072
+ if engine is None:
2073
+ engine = _default_engine()
2074
+
2075
+ # path name for permanent png output
2076
+ abs_path_to_png = os.path.abspath(filename)
2077
+ # temporary directory to store stuff
2078
+ with TemporaryDirectory() as tmp:
2079
+ tex_file = os.path.join(tmp, "sage.tex")
2080
+ png_file = os.path.join(tmp, "sage.png")
2081
+ # write latex string to file
2082
+ with open(tex_file, 'w') as file:
2083
+ file.write(s)
2084
+ # run latex on the file, producing png output to png_file
2085
+ e = _run_latex_(tex_file, density=density, debug=debug,
2086
+ png=True, engine=engine)
2087
+ if e.find("Error") == -1:
2088
+ # if no errors, copy png_file to the appropriate place
2089
+ shutil.copy(png_file, abs_path_to_png)
2090
+ else:
2091
+ print("Latex error")
2092
+
2093
+ if debug:
2094
+ return s
2095
+ return
2096
+
2097
+
2098
+ def coeff_repr(c):
2099
+ r"""
2100
+ LaTeX string representing coefficients in a linear combination.
2101
+
2102
+ INPUT:
2103
+
2104
+ - ``c`` -- a coefficient (i.e., an element of a ring)
2105
+
2106
+ OUTPUT: string
2107
+
2108
+ EXAMPLES::
2109
+
2110
+ sage: from sage.misc.latex import coeff_repr
2111
+ sage: coeff_repr(QQ(1/2))
2112
+ '\\frac{1}{2}'
2113
+ sage: coeff_repr(-x^2) # needs sage.symbolic
2114
+ '\\left(-x^{2}\\right)'
2115
+ """
2116
+ try:
2117
+ return c._latex_coeff_repr()
2118
+ except AttributeError:
2119
+ pass
2120
+ if isinstance(c, (int, float)):
2121
+ return str(c)
2122
+ s = latex(c)
2123
+ if s.find("+") != -1 or s.find("-") != -1:
2124
+ return "(%s)" % s
2125
+ return s
2126
+
2127
+
2128
+ def repr_lincomb(symbols, coeffs):
2129
+ r"""
2130
+ Compute a latex representation of a linear combination of some
2131
+ formal symbols.
2132
+
2133
+ INPUT:
2134
+
2135
+ - ``symbols`` -- list of symbols
2136
+
2137
+ - ``coeffs`` -- list of coefficients of the symbols
2138
+
2139
+ OUTPUT: string
2140
+
2141
+ EXAMPLES::
2142
+
2143
+ sage: t = PolynomialRing(QQ, 't').0
2144
+ sage: from sage.misc.latex import repr_lincomb
2145
+ sage: repr_lincomb(['a', 's', ''], [-t, t - 2, t^12 + 2])
2146
+ '-t\\text{\\texttt{a}} + \\left(t - 2\\right)\\text{\\texttt{s}} + \\left(t^{12} + 2\\right)'
2147
+ sage: repr_lincomb(['a', 'b'], [1,1])
2148
+ '\\text{\\texttt{a}} + \\text{\\texttt{b}}'
2149
+
2150
+ Verify that a certain corner case works (see :issue:`5707` and
2151
+ :issue:`5766`)::
2152
+
2153
+ sage: repr_lincomb([1,5,-3],[2,8/9,7])
2154
+ '2\\cdot 1 + \\frac{8}{9}\\cdot 5 + 7\\cdot -3'
2155
+
2156
+ Verify that :issue:`17299` (latex representation of modular symbols)
2157
+ is fixed::
2158
+
2159
+ sage: x = EllipticCurve('64a1').modular_symbol_space(sign=1).basis()[0] # needs database_cremona_mini_ellcurve sage.schemes
2160
+ sage: from sage.misc.latex import repr_lincomb
2161
+ sage: latex(x.modular_symbol_rep()) # needs database_cremona_mini_ellcurve sage.schemes
2162
+ \left\{\frac{-3}{11}, \frac{-1}{4}\right\} - \left\{\frac{3}{13}, \frac{1}{4}\right\}
2163
+
2164
+ Verify that it works when the symbols are numbers::
2165
+
2166
+ sage: x = FormalSum([(1,2),(3,4)])
2167
+ sage: latex(x)
2168
+ 2 + 3\cdot 4
2169
+
2170
+ Verify that it works when ``bv in CC`` raises an error::
2171
+
2172
+ sage: x = FormalSum([(1,'x'),(2,'y')])
2173
+ sage: latex(x)
2174
+ \text{\texttt{x}} + 2\text{\texttt{y}}
2175
+ """
2176
+ s = ""
2177
+ first = True
2178
+ i = 0
2179
+
2180
+ from sage.rings.cc import CC
2181
+
2182
+ for c in coeffs:
2183
+ bv = symbols[i]
2184
+ b = latex(bv)
2185
+ if c != 0:
2186
+ if c == 1:
2187
+ if first:
2188
+ s += b
2189
+ else:
2190
+ s += " + %s" % b
2191
+ else:
2192
+ coeff = coeff_repr(c)
2193
+ if coeff == "-1":
2194
+ coeff = "-"
2195
+ if first:
2196
+ coeff = str(coeff)
2197
+ else:
2198
+ coeff = " + %s" % coeff
2199
+ # this is a hack: i want to say that if the symbol
2200
+ # happens to be a number, then we should put a
2201
+ # multiplication sign in
2202
+ try:
2203
+ if bv in CC:
2204
+ s += r"%s\cdot %s" % (coeff, b)
2205
+ else:
2206
+ s += "%s%s" % (coeff, b)
2207
+ except Exception:
2208
+ s += "%s%s" % (coeff, b)
2209
+ first = False
2210
+ i += 1
2211
+ if first:
2212
+ s = "0"
2213
+ s = s.replace("+ -", "- ")
2214
+ return s
2215
+
2216
+
2217
+ common_varnames = ['alpha',
2218
+ 'beta',
2219
+ 'gamma',
2220
+ 'Gamma',
2221
+ 'delta',
2222
+ 'Delta',
2223
+ 'epsilon',
2224
+ 'zeta',
2225
+ 'eta',
2226
+ 'theta',
2227
+ 'Theta',
2228
+ 'iota',
2229
+ 'kappa',
2230
+ 'lambda',
2231
+ 'Lambda',
2232
+ 'mu',
2233
+ 'nu',
2234
+ 'xi',
2235
+ 'Xi',
2236
+ 'pi',
2237
+ 'Pi',
2238
+ 'rho',
2239
+ 'sigma',
2240
+ 'Sigma',
2241
+ 'tau',
2242
+ 'upsilon',
2243
+ 'phi',
2244
+ 'Phi',
2245
+ 'varphi',
2246
+ 'chi',
2247
+ 'psi',
2248
+ 'Psi',
2249
+ 'omega',
2250
+ 'Omega',
2251
+ 'ast',
2252
+ 'bullet',
2253
+ 'circ',
2254
+ 'times',
2255
+ 'star']
2256
+
2257
+
2258
+ def latex_varify(a, is_fname=False):
2259
+ r"""
2260
+ Convert a string ``a`` to a LaTeX string: if it's an element of
2261
+ ``common_varnames``, then prepend a backslash. If ``a`` consists
2262
+ of a single letter, then return it. Otherwise, return
2263
+ either "{\\rm a}" or "\\mbox{a}" if "is_fname" flag is ``True``
2264
+ or ``False``.
2265
+
2266
+ INPUT:
2267
+
2268
+ - ``a`` -- string
2269
+
2270
+ OUTPUT: string
2271
+
2272
+ EXAMPLES::
2273
+
2274
+ sage: from sage.misc.latex import latex_varify
2275
+ sage: latex_varify('w')
2276
+ 'w'
2277
+ sage: latex_varify('aleph')
2278
+ '\\mathit{aleph}'
2279
+ sage: latex_varify('aleph', is_fname=True)
2280
+ '{\\rm aleph}'
2281
+ sage: latex_varify('alpha')
2282
+ '\\alpha'
2283
+ sage: latex_varify('ast')
2284
+ '\\ast'
2285
+
2286
+ TESTS:
2287
+
2288
+ sage: abc = var('abc') # needs sage.symbolic
2289
+ sage: latex((abc/(abc+1)+42)/(abc-1)) # trac #15870 # needs sage.symbolic
2290
+ \frac{\frac{\mathit{abc}}{\mathit{abc} + 1} + 42}{\mathit{abc} - 1}
2291
+ """
2292
+ if a in common_varnames:
2293
+ return "\\" + a
2294
+ elif len(a) == 0:
2295
+ return ''
2296
+ elif len(a) == 1:
2297
+ return a
2298
+ elif is_fname is True:
2299
+ return '{\\rm %s}' % a
2300
+ else:
2301
+ return '\\mathit{%s}' % a
2302
+
2303
+
2304
+ def latex_variable_name(x, is_fname=False):
2305
+ r"""
2306
+ Return latex version of a variable name.
2307
+
2308
+ Here are some guiding principles for usage of this function:
2309
+
2310
+ 1. If the variable is a single letter, that is the latex version.
2311
+
2312
+ 2. If the variable name is suffixed by a number, we put the number
2313
+ in the subscript.
2314
+
2315
+ 3. If the variable name contains an ``'_'`` we start the subscript at
2316
+ the underscore. Note that #3 trumps rule #2.
2317
+
2318
+ 4. If a component of the variable is a Greek letter, escape it
2319
+ properly.
2320
+
2321
+ 5. Recurse nicely with subscripts.
2322
+
2323
+ Refer to the examples section for how these rules might play out in
2324
+ practice.
2325
+
2326
+ EXAMPLES::
2327
+
2328
+ sage: from sage.misc.latex import latex_variable_name
2329
+ sage: latex_variable_name('a')
2330
+ 'a'
2331
+ sage: latex_variable_name('abc')
2332
+ '\\mathit{abc}'
2333
+ sage: latex_variable_name('sigma')
2334
+ '\\sigma'
2335
+ sage: latex_variable_name('sigma_k')
2336
+ '\\sigma_{k}'
2337
+ sage: latex_variable_name('sigma389')
2338
+ '\\sigma_{389}'
2339
+ sage: latex_variable_name('beta_00')
2340
+ '\\beta_{00}'
2341
+ sage: latex_variable_name('Omega84')
2342
+ '\\Omega_{84}'
2343
+ sage: latex_variable_name('sigma_alpha')
2344
+ '\\sigma_{\\alpha}'
2345
+ sage: latex_variable_name('nothing1')
2346
+ '\\mathit{nothing}_{1}'
2347
+ sage: latex_variable_name('nothing1', is_fname=True)
2348
+ '{\\rm nothing}_{1}'
2349
+ sage: latex_variable_name('nothing_abc')
2350
+ '\\mathit{nothing}_{\\mathit{abc}}'
2351
+ sage: latex_variable_name('nothing_abc', is_fname=True)
2352
+ '{\\rm nothing}_{{\\rm abc}}'
2353
+ sage: latex_variable_name('alpha_beta_gamma12')
2354
+ '\\alpha_{\\beta_{\\gamma_{12}}}'
2355
+ sage: latex_variable_name('x_ast')
2356
+ 'x_{\\ast}'
2357
+
2358
+ TESTS::
2359
+
2360
+ sage: latex_variable_name('_C') # trac #16007 # needs sage.symbolic
2361
+ 'C'
2362
+ sage: latex_variable_name('_K1') # needs sage.symbolic
2363
+ 'K_{1}'
2364
+
2365
+ sage: latex_variable_name('5') # needs sage.symbolic
2366
+ '5'
2367
+ """
2368
+ # if x is an integer (it might be the case for padics), we return x
2369
+ if re.match(r'\d+$', x):
2370
+ return x
2371
+ underscore = x.find("_")
2372
+ if underscore == -1:
2373
+ # * The "\d|[.,]" means "decimal digit" or period or comma
2374
+ # * The "+" means "1 or more"
2375
+ # * The "$" means "at the end of the line"
2376
+ m = re.search(r'(\d|[.,])+$', x)
2377
+ if m is None:
2378
+ prefix = x
2379
+ suffix = None
2380
+ else:
2381
+ prefix = x[:m.start()]
2382
+ suffix = x[m.start():]
2383
+ else:
2384
+ prefix = x[:underscore]
2385
+ suffix = x[underscore + 1:]
2386
+ if prefix == '':
2387
+ from sage.calculus.calculus import symtable
2388
+ for sym in symtable.values():
2389
+ if sym[0] == '_' and sym[1:] == suffix:
2390
+ return latex_variable_name(suffix)
2391
+ if suffix and len(suffix):
2392
+ # handle the suffix specially because it very well might be numeric
2393
+ # I use strip to avoid using regex's -- It makes it a bit faster (and the code is more comprehensible to non-regex'ed people)
2394
+ if suffix.strip("1234567890") != "":
2395
+ suffix = latex_variable_name(suffix, is_fname) # recurse to deal with recursive subscripts
2396
+ return '%s_{%s}' % (latex_varify(prefix, is_fname), suffix)
2397
+ else:
2398
+ return latex_varify(prefix, is_fname)
2399
+
2400
+
2401
+ class LatexExamples:
2402
+ r"""
2403
+ A catalogue of Sage objects with complicated ``_latex_`` methods.
2404
+ Use these for testing :func:`latex`, :func:`view`, the Typeset
2405
+ button in the notebook, etc.
2406
+
2407
+ The classes here only have ``__init__``, ``_repr_``, and ``_latex_``
2408
+ methods.
2409
+
2410
+ EXAMPLES::
2411
+
2412
+ sage: from sage.misc.latex import latex_examples
2413
+ sage: K = latex_examples.knot()
2414
+ sage: K
2415
+ LaTeX example for testing display of a knot produced by xypic...
2416
+ sage: latex(K)
2417
+ \vtop{\vbox{\xygraph{!{0;/r1.5pc/:}
2418
+ [u] !{\vloop<(-.005)\khole||\vcrossneg \vunder- }
2419
+ [] !{\ar @{-}@'{p-(1,0)@+}+(-1,1)}
2420
+ [ul] !{\vcap[3]>\khole}
2421
+ [rrr] !{\ar @{-}@'{p-(0,1)@+}-(1,1)}
2422
+ }}}
2423
+ """
2424
+ class graph(SageObject):
2425
+ """
2426
+ LaTeX example for testing display of graphs. See its string
2427
+ representation for details.
2428
+
2429
+ EXAMPLES::
2430
+
2431
+ sage: from sage.misc.latex import latex_examples
2432
+ sage: G = latex_examples.graph()
2433
+ sage: G
2434
+ LaTeX example for testing display of graphs...
2435
+ """
2436
+
2437
+ def _repr_(self):
2438
+ """
2439
+ String representation.
2440
+
2441
+ EXAMPLES::
2442
+
2443
+ sage: from sage.misc.latex import latex_examples
2444
+ sage: G = latex_examples.graph()
2445
+ sage: len(G._repr_()) > 300
2446
+ True
2447
+ """
2448
+ return r"""LaTeX example for testing display of graphs.
2449
+
2450
+ To use, first try calling 'view' on this object -- it will not work.
2451
+ Now, make sure that you have the most recent version of the TeX
2452
+ package pgf installed, along with the LaTeX package tkz-graph. Run
2453
+ 'latex.add_to_preamble("\\usepackage{tkz-graph}")', and try viewing it
2454
+ again. From the command line, this should pop open a nice window with
2455
+ a picture of a graph.
2456
+
2457
+ (LaTeX code taken from the documentation of the LaTeX package tkz-graph
2458
+ https://www.ctan.org/pkg/tkz-graph)
2459
+ """
2460
+
2461
+ def _latex_(self):
2462
+ """
2463
+ LaTeX representation.
2464
+
2465
+ EXAMPLES::
2466
+
2467
+ sage: from sage.misc.latex import latex_examples
2468
+ sage: len(latex_examples.graph()._latex_()) > 500
2469
+ True
2470
+ sage: len(latex_examples.graph()._latex_()) > 600
2471
+ False
2472
+ """
2473
+ return r"""\begin{tikzpicture}[node distance = 4 cm]
2474
+ \GraphInit[vstyle=Shade]
2475
+ \tikzset{LabelStyle/.style = {draw,
2476
+ fill = yellow,
2477
+ text = red}}
2478
+ \Vertex{A}
2479
+ \EA(A){B}
2480
+ \EA(B){C}
2481
+ \tikzset{node distance = 8 cm}
2482
+ \NO(B){D}
2483
+ \Edge[label=1](B)(D)
2484
+ \tikzset{EdgeStyle/.append style = {bend left}}
2485
+ \Edge[label=4](A)(B)
2486
+ \Edge[label=5](B)(A)
2487
+ \Edge[label=6](B)(C)
2488
+ \Edge[label=7](C)(B)
2489
+ \Edge[label=2](A)(D)
2490
+ \Edge[label=3](D)(C)
2491
+ \end{tikzpicture}"""
2492
+
2493
+ class pstricks(SageObject):
2494
+ """
2495
+ LaTeX example for testing display of pstricks output. See its
2496
+ string representation for details.
2497
+
2498
+ EXAMPLES::
2499
+
2500
+ sage: from sage.misc.latex import latex_examples
2501
+ sage: PS = latex_examples.pstricks()
2502
+ sage: PS
2503
+ LaTeX example for testing display of pstricks...
2504
+ """
2505
+
2506
+ def _repr_(self):
2507
+ """
2508
+ String representation.
2509
+
2510
+ EXAMPLES::
2511
+
2512
+ sage: from sage.misc.latex import latex_examples
2513
+ sage: len(latex_examples.pstricks()._repr_()) > 300
2514
+ True
2515
+ """
2516
+ return """LaTeX example for testing display of pstricks output.
2517
+
2518
+ To use, first try calling 'view' on this object -- it will not work. Now,
2519
+ make sure that you have the most recent version of the TeX package
2520
+ pstricks installed. Run 'latex.add_to_preamble("\\usepackage{pstricks}")'
2521
+ and try viewing it again. Call 'view' with the option `engine='latex'`
2522
+ -- the default behavior is to use lualatex, which does not work with
2523
+ pstricks. From the command line, this should pop open a nice window
2524
+ with a picture of forces acting on a mass on a pendulum."""
2525
+
2526
+ def _latex_(self):
2527
+ """
2528
+ LaTeX representation.
2529
+
2530
+ EXAMPLES::
2531
+
2532
+ sage: from sage.misc.latex import latex_examples
2533
+ sage: len(latex_examples.pstricks()._latex_()) > 250
2534
+ True
2535
+ """
2536
+ return r"""\begin{pspicture}(0,-4)(14,0)
2537
+ \psline{-}(0,0)(0,-4)
2538
+ \psline[linewidth=2pt]{-}(0,0)(1,-3)
2539
+ \qdisk(1,-3){3pt}
2540
+ \psarc{-}(0,0){0.6}{270}{292}
2541
+ \psline{->}(1,-3.3)(1,-4)
2542
+ \psline{->}(1.1,-2.7)(0.85,-1.95)
2543
+ \psline{-}(5,0)(5,-4)
2544
+ \psline[linewidth=2pt]{-}(5,0)(6,-3)
2545
+ \qdisk(6,-3){3pt}
2546
+ \psarc{-}(5,0){0.6}{270}{292}
2547
+ \psarc{-}(5,0){3.2}{270}{290}
2548
+ \end{pspicture}"""
2549
+
2550
+ class knot(SageObject):
2551
+ """
2552
+ LaTeX example for testing display of knots. See its string
2553
+ representation for details.
2554
+
2555
+ EXAMPLES::
2556
+
2557
+ sage: from sage.misc.latex import latex_examples
2558
+ sage: K = latex_examples.knot()
2559
+ sage: K
2560
+ LaTeX example for testing display of a knot...
2561
+ """
2562
+
2563
+ def _repr_(self):
2564
+ """
2565
+ String representation.
2566
+
2567
+ EXAMPLES::
2568
+
2569
+ sage: from sage.misc.latex import latex_examples
2570
+ sage: len(latex_examples.knot()._repr_()) > 250
2571
+ True
2572
+ """
2573
+ return r"""LaTeX example for testing display of a knot produced by xypic.
2574
+
2575
+ To use, try to view this object -- it will not work. Now try
2576
+ 'latex.add_to_preamble("\\usepackage[graph,knot,poly,curve]{xypic}")',
2577
+ and try viewing again.
2578
+
2579
+ (LaTeX code taken from the xypic manual)
2580
+ """
2581
+
2582
+ def _latex_(self):
2583
+ """
2584
+ LaTeX representation.
2585
+
2586
+ EXAMPLES::
2587
+
2588
+ sage: from sage.misc.latex import latex_examples
2589
+ sage: len(latex_examples.knot()._latex_()) > 180
2590
+ True
2591
+ """
2592
+ return r"""\vtop{\vbox{\xygraph{!{0;/r1.5pc/:}
2593
+ [u] !{\vloop<(-.005)\khole||\vcrossneg \vunder- }
2594
+ [] !{\ar @{-}@'{p-(1,0)@+}+(-1,1)}
2595
+ [ul] !{\vcap[3]>\khole}
2596
+ [rrr] !{\ar @{-}@'{p-(0,1)@+}-(1,1)}
2597
+ }}}"""
2598
+
2599
+ class diagram(SageObject):
2600
+ """
2601
+ LaTeX example for testing display of commutative diagrams.
2602
+ See its string representation for details.
2603
+
2604
+ EXAMPLES::
2605
+
2606
+ sage: from sage.misc.latex import latex_examples
2607
+ sage: CD = latex_examples.diagram()
2608
+ sage: CD
2609
+ LaTeX example for testing display of a commutative diagram...
2610
+ """
2611
+
2612
+ def _repr_(self):
2613
+ """
2614
+ String representation.
2615
+
2616
+ EXAMPLES::
2617
+
2618
+ sage: from sage.misc.latex import latex_examples
2619
+ sage: len(latex_examples.diagram()._repr_()) > 300
2620
+ True
2621
+ """
2622
+ return r"""LaTeX example for testing display of a commutative diagram produced
2623
+ by xypic.
2624
+
2625
+ To use, try to view this object -- it will not work. Now try
2626
+ 'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")',
2627
+ and try viewing again. You should get a picture (a part of the diagram arising
2628
+ from a filtered chain complex)."""
2629
+
2630
+ def _latex_(self):
2631
+ """
2632
+ LaTeX representation.
2633
+
2634
+ EXAMPLES::
2635
+
2636
+ sage: from sage.misc.latex import latex_examples
2637
+ sage: len(latex_examples.diagram()._latex_()) > 1000
2638
+ True
2639
+ """
2640
+ return r"""\xymatrix{
2641
+ & {} \ar[d] & & \ar[d] & & \ar[d] \\
2642
+ \ldots \ar[r] & H_{p+q}(K^{p-2}) \ar[r] \ar[d] &
2643
+ H_{p+q}(K^{p-2}/K^{p-3}) \ar[r] & H_{p+q-1}(K^{p-3}) \ar[r] \ar[d] &
2644
+ H_{p+q-1}(K^{p-3}/K^{p-4}) \ar[r] & H_{p+q-2}(K^{p-4}) \ar[r] \ar[d] &
2645
+ \ldots \\
2646
+ \ldots \ar[r]^{k \quad \quad } & H_{p+q}(K^{p-1}) \ar[r] \ar[d]^{i} &
2647
+ H_{p+q}(K^{p-1}/K^{p-2}) \ar[r] & H_{p+q-1}(K^{p-2}) \ar[r] \ar[d] &
2648
+ H_{p+q-1}(K^{p-2}/K^{p-3}) \ar[r] & H_{p+q-2}(K^{p-3}) \ar[r] \ar[d] &
2649
+ \ldots \\
2650
+ \ldots \ar[r] & H_{p+q}(K^{p}) \ar[r]^{j} \ar[d] &
2651
+ H_{p+q}(K^{p}/K^{p-1}) \ar[r]^{k} & H_{p+q-1}(K^{p-1}) \ar[r] \ar[d]^{i} &
2652
+ H_{p+q-1}(K^{p-1}/K^{p-2}) \ar[r] & H_{p+q-2}(K^{p-2}) \ar[r] \ar[d] &
2653
+ \ldots \\
2654
+ \ldots \ar[r] & H_{p+q}(K^{p+1}) \ar[r] \ar[d] &
2655
+ H_{p+q}(K^{p+1}/K^{p}) \ar[r] & H_{p+q-1}(K^{p}) \ar[r]^{j} \ar[d] &
2656
+ H_{p+q-1}(K^{p}/K^{p-1}) \ar[r]^{k} & H_{p+q-2}(K^{p-1}) \ar[r] \ar[d]^{i} &
2657
+ \ldots \\
2658
+ & {} & {} & {} & {} & {} \\
2659
+ {} \\
2660
+ \save "3,1"+DL \PATH ~={**@{-}}
2661
+ '+<0pc,-1pc> '+<4pc,0pc> '+<0pc,-4pc> '+<16pc,0pc>
2662
+ '+<0pc,-3pc> '+<19pc,0pc>
2663
+ '+<0pc,-1pc>
2664
+ \restore
2665
+ \save "3,1"+DL \PATH ~={**@{-}}
2666
+ '+<0pc,2pc> '+<9pc,0pc> '+<0pc,-3pc> '+<18pc,0pc>
2667
+ '+<0pc,-4pc> '+<18pc,0pc>
2668
+ '+<0pc,-4pc>
2669
+ \restore
2670
+ }"""
2671
+
2672
+
2673
+ latex_examples = LatexExamples()