passagemath-singular 10.6.31rc3__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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.

Potentially problematic release.


This version of passagemath-singular might be problematic. Click here for more details.

Files changed (491) hide show
  1. PySingular.cpython-314-x86_64-linux-gnu.so +0 -0
  2. passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
  3. passagemath_singular-10.6.31rc3.dist-info/RECORD +491 -0
  4. passagemath_singular-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
  6. passagemath_singular.libs/libSingular-4-20aec911.4.1.so +0 -0
  7. passagemath_singular.libs/libcddgmp-21acf0c6.so.0.1.3 +0 -0
  8. passagemath_singular.libs/libfactory-4-fcee31da.4.1.so +0 -0
  9. passagemath_singular.libs/libflint-66e12231.so.21.0.0 +0 -0
  10. passagemath_singular.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
  11. passagemath_singular.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
  12. passagemath_singular.libs/libgmp-6e109695.so.10.5.0 +0 -0
  13. passagemath_singular.libs/libgsl-cda90e79.so.28.0.0 +0 -0
  14. passagemath_singular.libs/libmpfr-82690d50.so.6.2.1 +0 -0
  15. passagemath_singular.libs/libntl-e6f0d543.so.44.0.1 +0 -0
  16. passagemath_singular.libs/libomalloc-0-5c9e866e.9.6.so +0 -0
  17. passagemath_singular.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
  18. passagemath_singular.libs/libpolys-4-5c0a87e0.4.1.so +0 -0
  19. passagemath_singular.libs/libquadmath-2284e583.so.0.0.0 +0 -0
  20. passagemath_singular.libs/libreadline-ea270e21.so.8.2 +0 -0
  21. passagemath_singular.libs/libsingular_resources-4-a1aafc6d.4.1.so +0 -0
  22. passagemath_singular.libs/libtinfo-ceb117d9.so.6.3 +0 -0
  23. sage/algebras/all__sagemath_singular.py +3 -0
  24. sage/algebras/fusion_rings/all.py +19 -0
  25. sage/algebras/fusion_rings/f_matrix.py +2448 -0
  26. sage/algebras/fusion_rings/fast_parallel_fmats_methods.cpython-314-x86_64-linux-gnu.so +0 -0
  27. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pxd +5 -0
  28. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pyx +538 -0
  29. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.cpython-314-x86_64-linux-gnu.so +0 -0
  30. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pxd +3 -0
  31. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pyx +331 -0
  32. sage/algebras/fusion_rings/fusion_double.py +899 -0
  33. sage/algebras/fusion_rings/fusion_ring.py +1580 -0
  34. sage/algebras/fusion_rings/poly_tup_engine.cpython-314-x86_64-linux-gnu.so +0 -0
  35. sage/algebras/fusion_rings/poly_tup_engine.pxd +24 -0
  36. sage/algebras/fusion_rings/poly_tup_engine.pyx +579 -0
  37. sage/algebras/fusion_rings/shm_managers.cpython-314-x86_64-linux-gnu.so +0 -0
  38. sage/algebras/fusion_rings/shm_managers.pxd +24 -0
  39. sage/algebras/fusion_rings/shm_managers.pyx +780 -0
  40. sage/algebras/letterplace/all.py +1 -0
  41. sage/algebras/letterplace/free_algebra_element_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
  42. sage/algebras/letterplace/free_algebra_element_letterplace.pxd +18 -0
  43. sage/algebras/letterplace/free_algebra_element_letterplace.pyx +755 -0
  44. sage/algebras/letterplace/free_algebra_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
  45. sage/algebras/letterplace/free_algebra_letterplace.pxd +35 -0
  46. sage/algebras/letterplace/free_algebra_letterplace.pyx +914 -0
  47. sage/algebras/letterplace/letterplace_ideal.cpython-314-x86_64-linux-gnu.so +0 -0
  48. sage/algebras/letterplace/letterplace_ideal.pyx +408 -0
  49. sage/algebras/quatalg/all.py +2 -0
  50. sage/algebras/quatalg/quaternion_algebra.py +4778 -0
  51. sage/algebras/quatalg/quaternion_algebra_cython.cpython-314-x86_64-linux-gnu.so +0 -0
  52. sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
  53. sage/algebras/quatalg/quaternion_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
  54. sage/algebras/quatalg/quaternion_algebra_element.pxd +29 -0
  55. sage/algebras/quatalg/quaternion_algebra_element.pyx +2176 -0
  56. sage/all__sagemath_singular.py +11 -0
  57. sage/ext_data/all__sagemath_singular.py +1 -0
  58. sage/ext_data/singular/function_field/core.lib +98 -0
  59. sage/interfaces/all__sagemath_singular.py +1 -0
  60. sage/interfaces/singular.py +2835 -0
  61. sage/libs/all__sagemath_singular.py +1 -0
  62. sage/libs/singular/__init__.py +1 -0
  63. sage/libs/singular/decl.pxd +1168 -0
  64. sage/libs/singular/function.cpython-314-x86_64-linux-gnu.so +0 -0
  65. sage/libs/singular/function.pxd +87 -0
  66. sage/libs/singular/function.pyx +1901 -0
  67. sage/libs/singular/function_factory.py +61 -0
  68. sage/libs/singular/groebner_strategy.cpython-314-x86_64-linux-gnu.so +0 -0
  69. sage/libs/singular/groebner_strategy.pxd +22 -0
  70. sage/libs/singular/groebner_strategy.pyx +582 -0
  71. sage/libs/singular/option.cpython-314-x86_64-linux-gnu.so +0 -0
  72. sage/libs/singular/option.pyx +671 -0
  73. sage/libs/singular/polynomial.cpython-314-x86_64-linux-gnu.so +0 -0
  74. sage/libs/singular/polynomial.pxd +39 -0
  75. sage/libs/singular/polynomial.pyx +661 -0
  76. sage/libs/singular/ring.cpython-314-x86_64-linux-gnu.so +0 -0
  77. sage/libs/singular/ring.pxd +58 -0
  78. sage/libs/singular/ring.pyx +893 -0
  79. sage/libs/singular/singular.cpython-314-x86_64-linux-gnu.so +0 -0
  80. sage/libs/singular/singular.pxd +72 -0
  81. sage/libs/singular/singular.pyx +1944 -0
  82. sage/libs/singular/standard_options.py +145 -0
  83. sage/matrix/all__sagemath_singular.py +1 -0
  84. sage/matrix/matrix_mpolynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
  85. sage/matrix/matrix_mpolynomial_dense.pxd +7 -0
  86. sage/matrix/matrix_mpolynomial_dense.pyx +615 -0
  87. sage/rings/all__sagemath_singular.py +1 -0
  88. sage/rings/function_field/all__sagemath_singular.py +1 -0
  89. sage/rings/function_field/derivations_polymod.py +911 -0
  90. sage/rings/function_field/element_polymod.cpython-314-x86_64-linux-gnu.so +0 -0
  91. sage/rings/function_field/element_polymod.pyx +406 -0
  92. sage/rings/function_field/function_field_polymod.py +2611 -0
  93. sage/rings/function_field/ideal_polymod.py +1775 -0
  94. sage/rings/function_field/order_polymod.py +1475 -0
  95. sage/rings/function_field/place_polymod.py +681 -0
  96. sage/rings/polynomial/all__sagemath_singular.py +1 -0
  97. sage/rings/polynomial/multi_polynomial_ideal_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
  98. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pxd +5 -0
  99. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +339 -0
  100. sage/rings/polynomial/multi_polynomial_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
  101. sage/rings/polynomial/multi_polynomial_libsingular.pxd +30 -0
  102. sage/rings/polynomial/multi_polynomial_libsingular.pyx +6277 -0
  103. sage/rings/polynomial/plural.cpython-314-x86_64-linux-gnu.so +0 -0
  104. sage/rings/polynomial/plural.pxd +48 -0
  105. sage/rings/polynomial/plural.pyx +3171 -0
  106. sage/symbolic/all__sagemath_singular.py +1 -0
  107. sage/symbolic/comparison_impl.pxi +428 -0
  108. sage/symbolic/constants_c_impl.pxi +178 -0
  109. sage/symbolic/expression.cpython-314-x86_64-linux-gnu.so +0 -0
  110. sage/symbolic/expression.pxd +7 -0
  111. sage/symbolic/expression.pyx +14200 -0
  112. sage/symbolic/getitem_impl.pxi +202 -0
  113. sage/symbolic/pynac.pxi +572 -0
  114. sage/symbolic/pynac_constant_impl.pxi +133 -0
  115. sage/symbolic/pynac_function_impl.pxi +206 -0
  116. sage/symbolic/pynac_impl.pxi +2576 -0
  117. sage/symbolic/pynac_wrap.h +124 -0
  118. sage/symbolic/series_impl.pxi +272 -0
  119. sage/symbolic/substitution_map_impl.pxi +94 -0
  120. sage_wheels/bin/ESingular +0 -0
  121. sage_wheels/bin/Singular +0 -0
  122. sage_wheels/bin/TSingular +0 -0
  123. sage_wheels/lib/singular/MOD/cohomo.la +41 -0
  124. sage_wheels/lib/singular/MOD/cohomo.so +0 -0
  125. sage_wheels/lib/singular/MOD/customstd.la +41 -0
  126. sage_wheels/lib/singular/MOD/customstd.so +0 -0
  127. sage_wheels/lib/singular/MOD/freealgebra.la +41 -0
  128. sage_wheels/lib/singular/MOD/freealgebra.so +0 -0
  129. sage_wheels/lib/singular/MOD/gfanlib.la +41 -0
  130. sage_wheels/lib/singular/MOD/gfanlib.so +0 -0
  131. sage_wheels/lib/singular/MOD/gitfan.la +41 -0
  132. sage_wheels/lib/singular/MOD/gitfan.so +0 -0
  133. sage_wheels/lib/singular/MOD/interval.la +41 -0
  134. sage_wheels/lib/singular/MOD/interval.so +0 -0
  135. sage_wheels/lib/singular/MOD/loctriv.la +41 -0
  136. sage_wheels/lib/singular/MOD/loctriv.so +0 -0
  137. sage_wheels/lib/singular/MOD/machinelearning.la +41 -0
  138. sage_wheels/lib/singular/MOD/machinelearning.so +0 -0
  139. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.la +41 -0
  140. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.so +0 -0
  141. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.la +41 -0
  142. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.so +0 -0
  143. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.la +41 -0
  144. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.so +0 -0
  145. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.la +41 -0
  146. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.so +0 -0
  147. sage_wheels/lib/singular/MOD/partialgb.la +41 -0
  148. sage_wheels/lib/singular/MOD/partialgb.so +0 -0
  149. sage_wheels/lib/singular/MOD/pyobject.la +41 -0
  150. sage_wheels/lib/singular/MOD/pyobject.so +0 -0
  151. sage_wheels/lib/singular/MOD/singmathic.la +41 -0
  152. sage_wheels/lib/singular/MOD/singmathic.so +0 -0
  153. sage_wheels/lib/singular/MOD/sispasm.la +41 -0
  154. sage_wheels/lib/singular/MOD/sispasm.so +0 -0
  155. sage_wheels/lib/singular/MOD/subsets.la +41 -0
  156. sage_wheels/lib/singular/MOD/subsets.so +0 -0
  157. sage_wheels/lib/singular/MOD/systhreads.la +41 -0
  158. sage_wheels/lib/singular/MOD/systhreads.so +0 -0
  159. sage_wheels/lib/singular/MOD/syzextra.la +41 -0
  160. sage_wheels/lib/singular/MOD/syzextra.so +0 -0
  161. sage_wheels/libexec/singular/MOD/change_cost +0 -0
  162. sage_wheels/libexec/singular/MOD/singularsurf +11 -0
  163. sage_wheels/libexec/singular/MOD/singularsurf_jupyter +9 -0
  164. sage_wheels/libexec/singular/MOD/singularsurf_win +10 -0
  165. sage_wheels/libexec/singular/MOD/solve_IP +0 -0
  166. sage_wheels/libexec/singular/MOD/surfex +16 -0
  167. sage_wheels/libexec/singular/MOD/toric_ideal +0 -0
  168. sage_wheels/share/factory/gftables/10201 +342 -0
  169. sage_wheels/share/factory/gftables/1024 +37 -0
  170. sage_wheels/share/factory/gftables/10609 +356 -0
  171. sage_wheels/share/factory/gftables/11449 +384 -0
  172. sage_wheels/share/factory/gftables/11881 +398 -0
  173. sage_wheels/share/factory/gftables/121 +6 -0
  174. sage_wheels/share/factory/gftables/12167 +408 -0
  175. sage_wheels/share/factory/gftables/125 +7 -0
  176. sage_wheels/share/factory/gftables/12769 +428 -0
  177. sage_wheels/share/factory/gftables/128 +7 -0
  178. sage_wheels/share/factory/gftables/1331 +47 -0
  179. sage_wheels/share/factory/gftables/1369 +48 -0
  180. sage_wheels/share/factory/gftables/14641 +490 -0
  181. sage_wheels/share/factory/gftables/15625 +523 -0
  182. sage_wheels/share/factory/gftables/16 +3 -0
  183. sage_wheels/share/factory/gftables/16129 +540 -0
  184. sage_wheels/share/factory/gftables/16384 +549 -0
  185. sage_wheels/share/factory/gftables/16807 +563 -0
  186. sage_wheels/share/factory/gftables/1681 +58 -0
  187. sage_wheels/share/factory/gftables/169 +8 -0
  188. sage_wheels/share/factory/gftables/17161 +574 -0
  189. sage_wheels/share/factory/gftables/1849 +64 -0
  190. sage_wheels/share/factory/gftables/18769 +628 -0
  191. sage_wheels/share/factory/gftables/19321 +646 -0
  192. sage_wheels/share/factory/gftables/19683 +659 -0
  193. sage_wheels/share/factory/gftables/2048 +71 -0
  194. sage_wheels/share/factory/gftables/2187 +75 -0
  195. sage_wheels/share/factory/gftables/2197 +76 -0
  196. sage_wheels/share/factory/gftables/2209 +76 -0
  197. sage_wheels/share/factory/gftables/22201 +742 -0
  198. sage_wheels/share/factory/gftables/22801 +762 -0
  199. sage_wheels/share/factory/gftables/2401 +82 -0
  200. sage_wheels/share/factory/gftables/243 +11 -0
  201. sage_wheels/share/factory/gftables/24389 +815 -0
  202. sage_wheels/share/factory/gftables/24649 +824 -0
  203. sage_wheels/share/factory/gftables/25 +3 -0
  204. sage_wheels/share/factory/gftables/256 +11 -0
  205. sage_wheels/share/factory/gftables/26569 +888 -0
  206. sage_wheels/share/factory/gftables/27 +3 -0
  207. sage_wheels/share/factory/gftables/27889 +932 -0
  208. sage_wheels/share/factory/gftables/2809 +96 -0
  209. sage_wheels/share/factory/gftables/28561 +954 -0
  210. sage_wheels/share/factory/gftables/289 +12 -0
  211. sage_wheels/share/factory/gftables/29791 +995 -0
  212. sage_wheels/share/factory/gftables/29929 +1000 -0
  213. sage_wheels/share/factory/gftables/3125 +107 -0
  214. sage_wheels/share/factory/gftables/32 +4 -0
  215. sage_wheels/share/factory/gftables/32041 +1070 -0
  216. sage_wheels/share/factory/gftables/32761 +1094 -0
  217. sage_wheels/share/factory/gftables/32768 +1095 -0
  218. sage_wheels/share/factory/gftables/343 +14 -0
  219. sage_wheels/share/factory/gftables/3481 +118 -0
  220. sage_wheels/share/factory/gftables/361 +14 -0
  221. sage_wheels/share/factory/gftables/36481 +1218 -0
  222. sage_wheels/share/factory/gftables/3721 +126 -0
  223. sage_wheels/share/factory/gftables/37249 +1244 -0
  224. sage_wheels/share/factory/gftables/38809 +1296 -0
  225. sage_wheels/share/factory/gftables/39601 +1322 -0
  226. sage_wheels/share/factory/gftables/4 +3 -0
  227. sage_wheels/share/factory/gftables/4096 +139 -0
  228. sage_wheels/share/factory/gftables/44521 +1486 -0
  229. sage_wheels/share/factory/gftables/4489 +152 -0
  230. sage_wheels/share/factory/gftables/49 +4 -0
  231. sage_wheels/share/factory/gftables/4913 +166 -0
  232. sage_wheels/share/factory/gftables/49729 +1660 -0
  233. sage_wheels/share/factory/gftables/5041 +170 -0
  234. sage_wheels/share/factory/gftables/50653 +1691 -0
  235. sage_wheels/share/factory/gftables/512 +20 -0
  236. sage_wheels/share/factory/gftables/51529 +1720 -0
  237. sage_wheels/share/factory/gftables/52441 +1750 -0
  238. sage_wheels/share/factory/gftables/529 +20 -0
  239. sage_wheels/share/factory/gftables/5329 +180 -0
  240. sage_wheels/share/factory/gftables/54289 +1812 -0
  241. sage_wheels/share/factory/gftables/57121 +1906 -0
  242. sage_wheels/share/factory/gftables/58081 +1938 -0
  243. sage_wheels/share/factory/gftables/59049 +1971 -0
  244. sage_wheels/share/factory/gftables/6241 +210 -0
  245. sage_wheels/share/factory/gftables/625 +23 -0
  246. sage_wheels/share/factory/gftables/63001 +2102 -0
  247. sage_wheels/share/factory/gftables/64 +5 -0
  248. sage_wheels/share/factory/gftables/6561 +221 -0
  249. sage_wheels/share/factory/gftables/6859 +231 -0
  250. sage_wheels/share/factory/gftables/6889 +232 -0
  251. sage_wheels/share/factory/gftables/729 +27 -0
  252. sage_wheels/share/factory/gftables/7921 +266 -0
  253. sage_wheels/share/factory/gftables/8 +3 -0
  254. sage_wheels/share/factory/gftables/81 +5 -0
  255. sage_wheels/share/factory/gftables/8192 +276 -0
  256. sage_wheels/share/factory/gftables/841 +30 -0
  257. sage_wheels/share/factory/gftables/9 +3 -0
  258. sage_wheels/share/factory/gftables/9409 +316 -0
  259. sage_wheels/share/factory/gftables/961 +34 -0
  260. sage_wheels/share/info/singular.info +191898 -0
  261. sage_wheels/share/singular/LIB/GND.lib +1359 -0
  262. sage_wheels/share/singular/LIB/JMBTest.lib +976 -0
  263. sage_wheels/share/singular/LIB/JMSConst.lib +1363 -0
  264. sage_wheels/share/singular/LIB/KVequiv.lib +699 -0
  265. sage_wheels/share/singular/LIB/SingularityDBM.lib +491 -0
  266. sage_wheels/share/singular/LIB/VecField.lib +1542 -0
  267. sage_wheels/share/singular/LIB/absfact.lib +959 -0
  268. sage_wheels/share/singular/LIB/ainvar.lib +730 -0
  269. sage_wheels/share/singular/LIB/aksaka.lib +419 -0
  270. sage_wheels/share/singular/LIB/alexpoly.lib +2542 -0
  271. sage_wheels/share/singular/LIB/algebra.lib +1193 -0
  272. sage_wheels/share/singular/LIB/all.lib +136 -0
  273. sage_wheels/share/singular/LIB/arcpoint.lib +514 -0
  274. sage_wheels/share/singular/LIB/arnold.lib +4553 -0
  275. sage_wheels/share/singular/LIB/arnoldclassify.lib +2058 -0
  276. sage_wheels/share/singular/LIB/arr.lib +3486 -0
  277. sage_wheels/share/singular/LIB/assprimeszerodim.lib +755 -0
  278. sage_wheels/share/singular/LIB/autgradalg.lib +3361 -0
  279. sage_wheels/share/singular/LIB/bfun.lib +1964 -0
  280. sage_wheels/share/singular/LIB/bimodules.lib +774 -0
  281. sage_wheels/share/singular/LIB/brillnoether.lib +226 -0
  282. sage_wheels/share/singular/LIB/brnoeth.lib +5017 -0
  283. sage_wheels/share/singular/LIB/central.lib +2169 -0
  284. sage_wheels/share/singular/LIB/chern.lib +4162 -0
  285. sage_wheels/share/singular/LIB/cimonom.lib +571 -0
  286. sage_wheels/share/singular/LIB/cisimplicial.lib +1835 -0
  287. sage_wheels/share/singular/LIB/classify.lib +3239 -0
  288. sage_wheels/share/singular/LIB/classify2.lib +1462 -0
  289. sage_wheels/share/singular/LIB/classifyMapGerms.lib +1515 -0
  290. sage_wheels/share/singular/LIB/classify_aeq.lib +3253 -0
  291. sage_wheels/share/singular/LIB/classifyceq.lib +2092 -0
  292. sage_wheels/share/singular/LIB/classifyci.lib +1133 -0
  293. sage_wheels/share/singular/LIB/combinat.lib +91 -0
  294. sage_wheels/share/singular/LIB/compregb.lib +276 -0
  295. sage_wheels/share/singular/LIB/control.lib +1636 -0
  296. sage_wheels/share/singular/LIB/crypto.lib +3795 -0
  297. sage_wheels/share/singular/LIB/curveInv.lib +667 -0
  298. sage_wheels/share/singular/LIB/curvepar.lib +1817 -0
  299. sage_wheels/share/singular/LIB/customstd.lib +100 -0
  300. sage_wheels/share/singular/LIB/deRham.lib +5979 -0
  301. sage_wheels/share/singular/LIB/decodegb.lib +2134 -0
  302. sage_wheels/share/singular/LIB/decomp.lib +1655 -0
  303. sage_wheels/share/singular/LIB/deflation.lib +872 -0
  304. sage_wheels/share/singular/LIB/deform.lib +925 -0
  305. sage_wheels/share/singular/LIB/difform.lib +3055 -0
  306. sage_wheels/share/singular/LIB/divisors.lib +750 -0
  307. sage_wheels/share/singular/LIB/dmod.lib +5817 -0
  308. sage_wheels/share/singular/LIB/dmodapp.lib +3269 -0
  309. sage_wheels/share/singular/LIB/dmodideal.lib +1211 -0
  310. sage_wheels/share/singular/LIB/dmodloc.lib +2645 -0
  311. sage_wheels/share/singular/LIB/dmodvar.lib +818 -0
  312. sage_wheels/share/singular/LIB/dummy.lib +17 -0
  313. sage_wheels/share/singular/LIB/elim.lib +1009 -0
  314. sage_wheels/share/singular/LIB/ellipticcovers.lib +548 -0
  315. sage_wheels/share/singular/LIB/enumpoints.lib +146 -0
  316. sage_wheels/share/singular/LIB/equising.lib +2127 -0
  317. sage_wheels/share/singular/LIB/ffmodstd.lib +2384 -0
  318. sage_wheels/share/singular/LIB/ffsolve.lib +1289 -0
  319. sage_wheels/share/singular/LIB/findifs.lib +778 -0
  320. sage_wheels/share/singular/LIB/finitediff.lib +1768 -0
  321. sage_wheels/share/singular/LIB/finvar.lib +7989 -0
  322. sage_wheels/share/singular/LIB/fpadim.lib +2429 -0
  323. sage_wheels/share/singular/LIB/fpalgebras.lib +1666 -0
  324. sage_wheels/share/singular/LIB/fpaprops.lib +1462 -0
  325. sage_wheels/share/singular/LIB/freegb.lib +3853 -0
  326. sage_wheels/share/singular/LIB/general.lib +1350 -0
  327. sage_wheels/share/singular/LIB/gfan.lib +1768 -0
  328. sage_wheels/share/singular/LIB/gitfan.lib +3130 -0
  329. sage_wheels/share/singular/LIB/gkdim.lib +99 -0
  330. sage_wheels/share/singular/LIB/gmspoly.lib +589 -0
  331. sage_wheels/share/singular/LIB/gmssing.lib +1739 -0
  332. sage_wheels/share/singular/LIB/goettsche.lib +909 -0
  333. sage_wheels/share/singular/LIB/graal.lib +1366 -0
  334. sage_wheels/share/singular/LIB/gradedModules.lib +2541 -0
  335. sage_wheels/share/singular/LIB/graphics.lib +360 -0
  336. sage_wheels/share/singular/LIB/grobcov.lib +7706 -0
  337. sage_wheels/share/singular/LIB/groups.lib +1123 -0
  338. sage_wheels/share/singular/LIB/grwalk.lib +507 -0
  339. sage_wheels/share/singular/LIB/hdepth.lib +194 -0
  340. sage_wheels/share/singular/LIB/help.cnf +57 -0
  341. sage_wheels/share/singular/LIB/hess.lib +1946 -0
  342. sage_wheels/share/singular/LIB/hnoether.lib +4292 -0
  343. sage_wheels/share/singular/LIB/hodge.lib +400 -0
  344. sage_wheels/share/singular/LIB/homolog.lib +1965 -0
  345. sage_wheels/share/singular/LIB/hyperel.lib +975 -0
  346. sage_wheels/share/singular/LIB/inout.lib +679 -0
  347. sage_wheels/share/singular/LIB/integralbasis.lib +6224 -0
  348. sage_wheels/share/singular/LIB/interval.lib +1418 -0
  349. sage_wheels/share/singular/LIB/intprog.lib +778 -0
  350. sage_wheels/share/singular/LIB/invar.lib +443 -0
  351. sage_wheels/share/singular/LIB/involut.lib +980 -0
  352. sage_wheels/share/singular/LIB/jacobson.lib +1215 -0
  353. sage_wheels/share/singular/LIB/kskernel.lib +534 -0
  354. sage_wheels/share/singular/LIB/latex.lib +3146 -0
  355. sage_wheels/share/singular/LIB/lejeune.lib +651 -0
  356. sage_wheels/share/singular/LIB/linalg.lib +2040 -0
  357. sage_wheels/share/singular/LIB/locnormal.lib +212 -0
  358. sage_wheels/share/singular/LIB/lrcalc.lib +526 -0
  359. sage_wheels/share/singular/LIB/makedbm.lib +294 -0
  360. sage_wheels/share/singular/LIB/mathml.lib +813 -0
  361. sage_wheels/share/singular/LIB/matrix.lib +1372 -0
  362. sage_wheels/share/singular/LIB/maxlike.lib +1132 -0
  363. sage_wheels/share/singular/LIB/methods.lib +212 -0
  364. sage_wheels/share/singular/LIB/moddiq.lib +322 -0
  365. sage_wheels/share/singular/LIB/modfinduni.lib +181 -0
  366. sage_wheels/share/singular/LIB/modnormal.lib +218 -0
  367. sage_wheels/share/singular/LIB/modprimdec.lib +1278 -0
  368. sage_wheels/share/singular/LIB/modquotient.lib +269 -0
  369. sage_wheels/share/singular/LIB/modstd.lib +1024 -0
  370. sage_wheels/share/singular/LIB/modular.lib +545 -0
  371. sage_wheels/share/singular/LIB/modules.lib +2561 -0
  372. sage_wheels/share/singular/LIB/modwalk.lib +609 -0
  373. sage_wheels/share/singular/LIB/mondromy.lib +1016 -0
  374. sage_wheels/share/singular/LIB/monomialideal.lib +3851 -0
  375. sage_wheels/share/singular/LIB/mprimdec.lib +2353 -0
  376. sage_wheels/share/singular/LIB/mregular.lib +1863 -0
  377. sage_wheels/share/singular/LIB/multigrading.lib +5629 -0
  378. sage_wheels/share/singular/LIB/ncHilb.lib +777 -0
  379. sage_wheels/share/singular/LIB/ncModslimgb.lib +791 -0
  380. sage_wheels/share/singular/LIB/ncalg.lib +16311 -0
  381. sage_wheels/share/singular/LIB/ncall.lib +31 -0
  382. sage_wheels/share/singular/LIB/ncdecomp.lib +468 -0
  383. sage_wheels/share/singular/LIB/ncfactor.lib +13371 -0
  384. sage_wheels/share/singular/LIB/ncfrac.lib +1023 -0
  385. sage_wheels/share/singular/LIB/nchilbert.lib +448 -0
  386. sage_wheels/share/singular/LIB/nchomolog.lib +759 -0
  387. sage_wheels/share/singular/LIB/ncloc.lib +361 -0
  388. sage_wheels/share/singular/LIB/ncpreim.lib +795 -0
  389. sage_wheels/share/singular/LIB/ncrat.lib +2849 -0
  390. sage_wheels/share/singular/LIB/nctools.lib +1887 -0
  391. sage_wheels/share/singular/LIB/nets.lib +1456 -0
  392. sage_wheels/share/singular/LIB/nfmodstd.lib +1000 -0
  393. sage_wheels/share/singular/LIB/nfmodsyz.lib +732 -0
  394. sage_wheels/share/singular/LIB/noether.lib +1106 -0
  395. sage_wheels/share/singular/LIB/normal.lib +8700 -0
  396. sage_wheels/share/singular/LIB/normaliz.lib +2226 -0
  397. sage_wheels/share/singular/LIB/ntsolve.lib +362 -0
  398. sage_wheels/share/singular/LIB/numerAlg.lib +560 -0
  399. sage_wheels/share/singular/LIB/numerDecom.lib +2261 -0
  400. sage_wheels/share/singular/LIB/olga.lib +1933 -0
  401. sage_wheels/share/singular/LIB/orbitparam.lib +351 -0
  402. sage_wheels/share/singular/LIB/parallel.lib +319 -0
  403. sage_wheels/share/singular/LIB/paraplanecurves.lib +3110 -0
  404. sage_wheels/share/singular/LIB/perron.lib +202 -0
  405. sage_wheels/share/singular/LIB/pfd.lib +2223 -0
  406. sage_wheels/share/singular/LIB/phindex.lib +642 -0
  407. sage_wheels/share/singular/LIB/pointid.lib +673 -0
  408. sage_wheels/share/singular/LIB/polybori.lib +1430 -0
  409. sage_wheels/share/singular/LIB/polyclass.lib +525 -0
  410. sage_wheels/share/singular/LIB/polylib.lib +1174 -0
  411. sage_wheels/share/singular/LIB/polymake.lib +1902 -0
  412. sage_wheels/share/singular/LIB/presolve.lib +1533 -0
  413. sage_wheels/share/singular/LIB/primdec.lib +9576 -0
  414. sage_wheels/share/singular/LIB/primdecint.lib +1782 -0
  415. sage_wheels/share/singular/LIB/primitiv.lib +401 -0
  416. sage_wheels/share/singular/LIB/puiseuxexpansions.lib +1631 -0
  417. sage_wheels/share/singular/LIB/purityfiltration.lib +960 -0
  418. sage_wheels/share/singular/LIB/qhmoduli.lib +1561 -0
  419. sage_wheels/share/singular/LIB/qmatrix.lib +293 -0
  420. sage_wheels/share/singular/LIB/random.lib +455 -0
  421. sage_wheels/share/singular/LIB/ratgb.lib +489 -0
  422. sage_wheels/share/singular/LIB/realclassify.lib +5759 -0
  423. sage_wheels/share/singular/LIB/realizationMatroids.lib +772 -0
  424. sage_wheels/share/singular/LIB/realrad.lib +1197 -0
  425. sage_wheels/share/singular/LIB/recover.lib +2628 -0
  426. sage_wheels/share/singular/LIB/redcgs.lib +3984 -0
  427. sage_wheels/share/singular/LIB/reesclos.lib +465 -0
  428. sage_wheels/share/singular/LIB/resbinomial.lib +2802 -0
  429. sage_wheels/share/singular/LIB/resgraph.lib +789 -0
  430. sage_wheels/share/singular/LIB/resjung.lib +820 -0
  431. sage_wheels/share/singular/LIB/resolve.lib +5110 -0
  432. sage_wheels/share/singular/LIB/resources.lib +170 -0
  433. sage_wheels/share/singular/LIB/reszeta.lib +5473 -0
  434. sage_wheels/share/singular/LIB/ring.lib +1328 -0
  435. sage_wheels/share/singular/LIB/ringgb.lib +343 -0
  436. sage_wheels/share/singular/LIB/rinvar.lib +1153 -0
  437. sage_wheels/share/singular/LIB/rootisolation.lib +1481 -0
  438. sage_wheels/share/singular/LIB/rootsmr.lib +709 -0
  439. sage_wheels/share/singular/LIB/rootsur.lib +886 -0
  440. sage_wheels/share/singular/LIB/rstandard.lib +607 -0
  441. sage_wheels/share/singular/LIB/rwalk.lib +336 -0
  442. sage_wheels/share/singular/LIB/sagbi.lib +1353 -0
  443. sage_wheels/share/singular/LIB/sagbiNormaliz.lib +1622 -0
  444. sage_wheels/share/singular/LIB/sagbiNormaliz0.lib +1498 -0
  445. sage_wheels/share/singular/LIB/sagbigrob.lib +449 -0
  446. sage_wheels/share/singular/LIB/schreyer.lib +321 -0
  447. sage_wheels/share/singular/LIB/schubert.lib +2551 -0
  448. sage_wheels/share/singular/LIB/sets.lib +524 -0
  449. sage_wheels/share/singular/LIB/sheafcoh.lib +1663 -0
  450. sage_wheels/share/singular/LIB/signcond.lib +437 -0
  451. sage_wheels/share/singular/LIB/sing.lib +1094 -0
  452. sage_wheels/share/singular/LIB/sing4ti2.lib +419 -0
  453. sage_wheels/share/singular/LIB/solve.lib +2243 -0
  454. sage_wheels/share/singular/LIB/spcurve.lib +1077 -0
  455. sage_wheels/share/singular/LIB/spectrum.lib +62 -0
  456. sage_wheels/share/singular/LIB/sresext.lib +757 -0
  457. sage_wheels/share/singular/LIB/ssi.lib +143 -0
  458. sage_wheels/share/singular/LIB/standard.lib +2769 -0
  459. sage_wheels/share/singular/LIB/stanleyreisner.lib +473 -0
  460. sage_wheels/share/singular/LIB/stdmodule.lib +547 -0
  461. sage_wheels/share/singular/LIB/stratify.lib +1070 -0
  462. sage_wheels/share/singular/LIB/surf.lib +506 -0
  463. sage_wheels/share/singular/LIB/surf_jupyter.lib +223 -0
  464. sage_wheels/share/singular/LIB/surfacesignature.lib +522 -0
  465. sage_wheels/share/singular/LIB/surfex.lib +1462 -0
  466. sage_wheels/share/singular/LIB/swalk.lib +877 -0
  467. sage_wheels/share/singular/LIB/symodstd.lib +1570 -0
  468. sage_wheels/share/singular/LIB/systhreads.lib +74 -0
  469. sage_wheels/share/singular/LIB/tasks.lib +1324 -0
  470. sage_wheels/share/singular/LIB/tateProdCplxNegGrad.lib +2412 -0
  471. sage_wheels/share/singular/LIB/teachstd.lib +858 -0
  472. sage_wheels/share/singular/LIB/template.lib +116 -0
  473. sage_wheels/share/singular/LIB/toric.lib +1119 -0
  474. sage_wheels/share/singular/LIB/transformation.lib +116 -0
  475. sage_wheels/share/singular/LIB/triang.lib +1197 -0
  476. sage_wheels/share/singular/LIB/tropical.lib +8741 -0
  477. sage_wheels/share/singular/LIB/tropicalEllipticCovers.lib +2922 -0
  478. sage_wheels/share/singular/LIB/tropicalNewton.lib +1128 -0
  479. sage_wheels/share/singular/LIB/tst.lib +1108 -0
  480. sage_wheels/share/singular/LIB/weierstr.lib +241 -0
  481. sage_wheels/share/singular/LIB/zeroset.lib +1478 -0
  482. sage_wheels/share/singular/emacs/.emacs-general +184 -0
  483. sage_wheels/share/singular/emacs/.emacs-singular +234 -0
  484. sage_wheels/share/singular/emacs/COPYING +44 -0
  485. sage_wheels/share/singular/emacs/cmd-cmpl.el +241 -0
  486. sage_wheels/share/singular/emacs/ex-cmpl.el +1681 -0
  487. sage_wheels/share/singular/emacs/hlp-cmpl.el +4318 -0
  488. sage_wheels/share/singular/emacs/lib-cmpl.el +179 -0
  489. sage_wheels/share/singular/emacs/singular.el +4273 -0
  490. sage_wheels/share/singular/emacs/singular.xpm +39 -0
  491. sage_wheels/share/singular/singular.idx +5002 -0
@@ -0,0 +1,5017 @@
1
+ ////////////////////////////////////////////////////////////////
2
+ version="version brnoeth.lib 4.3.1.3 Jan_2023 "; // $Id: 9380be79d36e0f2336d5a4acafdab944af9a44ff $
3
+ category="Coding theory";
4
+ info="
5
+ LIBRARY: brnoeth.lib Brill-Noether Algorithm, Weierstrass-SG and AG-codes
6
+ AUTHORS: Jose Ignacio Farran Martin, ignfar@eis.uva.es
7
+ Christoph Lossen, lossen@mathematik.uni-kl.de
8
+
9
+ OVERVIEW:
10
+ Implementation of the Brill-Noether algorithm for solving the
11
+ Riemann-Roch problem and applications to Algebraic Geometry codes.
12
+ The computation of Weierstrass semigroups is also implemented.@*
13
+ The procedures are intended only for plane (singular) curves defined over
14
+ a prime field of positive characteristic.@*
15
+ For more information about the library see the end of the file brnoeth.lib.
16
+
17
+ PROCEDURES:
18
+ Adj_div(f) computes the conductor of a curve
19
+ NSplaces(h,A) computes non-singular places with given degrees
20
+ BrillNoether(D,C) computes a vector space basis of the linear system L(D)
21
+ Weierstrass(P,m,C) computes the Weierstrass semigroup of C at P up to m
22
+ extcurve(d,C) extends the curve C to an extension of degree d
23
+ AGcode_L(G,D,E) computes the evaluation AG code with divisors G and D
24
+ AGcode_Omega(G,D,E) computes the residual AG code with divisors G and D
25
+ prepSV(G,D,F,E) preprocessing for the basic decoding algorithm
26
+ decodeSV(y,K) decoding of a word with the basic decoding algorithm
27
+ closed_points(I) computes the zero-set of a zero-dim. ideal in 2 vars
28
+ dual_code(C) computes the dual code
29
+ sys_code(C) computes an equivalent systematic code
30
+ permute_L(L,P) applies a permutation to a list
31
+
32
+ KEYWORDS: Weierstrass semigroup; Algebraic Geometry codes;
33
+ Brill-Noether algorithm
34
+ ";
35
+
36
+ LIB "matrix.lib";
37
+ LIB "triang.lib";
38
+ LIB "hnoether.lib";
39
+ LIB "inout.lib";
40
+
41
+ ///////////////////////////////////////////////////////////////////////////////
42
+
43
+ // **********************************************************
44
+ // * POINTS, PLACES AND DIVISORS OF (SINGULAR) PLANE CURVES *
45
+ // **********************************************************
46
+
47
+ proc closed_points (ideal I)
48
+ "USAGE: closed_points(I); I an ideal
49
+ RETURN: list of prime ideals (each a Groebner basis), corresponding to
50
+ the (distinct affine closed) points of V(I)
51
+ NOTE: The ideal must have dimension 0, the basering must have 2
52
+ variables, the ordering must be lp, and the base field must
53
+ be finite and prime.@*
54
+ It might be convenient to set the option(redSB) in advance.
55
+ SEE ALSO: triang_lib
56
+ EXAMPLE: example closed_points; shows an example
57
+ "
58
+ {
59
+ ideal II;
60
+ if (attrib(I,"isSB")) { II=I; } else { II=std(I); }
61
+ if (II[1]==1)
62
+ {
63
+ return(list());
64
+ }
65
+ list TL=triangMH(II);
66
+ int s=size(TL);
67
+ list L=list();
68
+ int i,j,k;
69
+ ideal Facts;
70
+ poly G2;
71
+ for (i=1;i<=s;i=i+1)
72
+ {
73
+ Facts=factorize(TL[i][1],1);
74
+ k=size(Facts);
75
+ G2=TL[i][2];
76
+ for (j=1;j<=k;j=j+1)
77
+ {
78
+ L=L+pd2(Facts[j],G2);
79
+ }
80
+ }
81
+ // eliminate possible repetitions
82
+ s=size(L);
83
+ list LP=list();
84
+ LP[1]=std(L[1]);
85
+ int counter=1;
86
+ for (i=2;i<=s;i=i+1)
87
+ {
88
+ if (isPinL(L[i],LP)==0)
89
+ {
90
+ counter=counter+1;
91
+ LP[counter]=std(L[i]);
92
+ }
93
+ }
94
+ return(LP);
95
+ }
96
+ example
97
+ {
98
+ "EXAMPLE:"; echo = 2;
99
+ ring s=2,(x,y),lp;
100
+ // this is just the affine plane over F_4 :
101
+ ideal I=x4+x,y4+y;
102
+ list L=closed_points(I);
103
+ // and here you have all the points :
104
+ L;
105
+ }
106
+ ///////////////////////////////////////////////////////////////////////////////
107
+
108
+ static proc pd2 (poly g1,poly g2)
109
+ {
110
+ // If g1,g2 is a std. resp. lex. in (x,y) then the procedure
111
+ // factorizes g2 in the "extension given by g1"
112
+ // (then g1 must be irreducible) and returns a list of
113
+ // ideals with always g1 as first component and the
114
+ // distinct factors of g2 as second components
115
+ list L=list();
116
+ ideal J=g1;
117
+ int i,s;
118
+ if (deg(g1)==1)
119
+ {
120
+ poly A=-subst(g1,var(2),0);
121
+ poly B=subst(g2,var(2),A);
122
+ ideal facts=factorize(B,1);
123
+ s=size(facts);
124
+ for (i=1;i<=s;i=i+1)
125
+ {
126
+ J[2]=facts[i];
127
+ L[i]=J;
128
+ }
129
+ }
130
+ else
131
+ {
132
+ def BR=basering;
133
+ poly A=g1;
134
+ poly B=g2;
135
+ ring raux1=char(basering),(x,y,@a),lp;
136
+ poly G;
137
+ ring raux2=(char(basering),@a),(x,y),lp;
138
+ map psi=BR,x,@a; minpoly=number(psi(A)); if(!defined(psi)){ map psi=BR,x,@a; }
139
+ poly f=psi(B);
140
+ ideal facts=factorize(f,1);
141
+ s=size(facts);
142
+ poly g;
143
+ for (i=1;i<=s;i=i+1)
144
+ {
145
+ g=facts[i];
146
+ setring raux1;
147
+ G=imap(raux2,g);
148
+ G=subst(G,@a,y);
149
+ setring BR;
150
+ map ppssii=raux1,var(1),var(2),0;
151
+ J[2]=ppssii(G);
152
+ L[i]=J;
153
+ kill ppssii;
154
+ setring raux2;
155
+ }
156
+ setring BR;
157
+ kill raux1,raux2;
158
+ }
159
+ return(L);
160
+ }
161
+ ///////////////////////////////////////////////////////////////////////////////
162
+ static proc isPinL (ideal P,list L)
163
+ {
164
+ // checks if a (plane) point P is in a list of (plane) points L
165
+ // by just comparing generators
166
+ // it works only if all (prime) ideals are given in a "canonical way",
167
+ // namely:
168
+ // the first generator is monic and irreducible,
169
+ // and depends only on the second variable,
170
+ // and the second one is monic in the first variable
171
+ // and irreducible over the field extension determined by
172
+ // the second variable and the first generator as minpoly
173
+ int s=size(L);
174
+ int i;
175
+ for (i=1;i<=s;i=i+1)
176
+ {
177
+ if ( P[1]==L[i][1] && P[2]==L[i][2] )
178
+ {
179
+ return(1);
180
+ }
181
+ }
182
+ return(0);
183
+ }
184
+ ///////////////////////////////////////////////////////////////////////////////
185
+ static proc s_locus (poly f)
186
+ {
187
+ // computes : ideal of affine singular locus
188
+ // the equation f must be affine
189
+ // warning : if there is an error message then the output is "none"
190
+ // option(redSB) is convenient to be set in advance
191
+ ideal I=f,jacob(f);
192
+ I=std(I);
193
+ if (dim(I)>0)
194
+ {
195
+ // dimension check (has to be 0)
196
+ ERROR("something was wrong; possibly non-reduced curve");
197
+ }
198
+ else
199
+ {
200
+ return(I);
201
+ }
202
+ }
203
+ ///////////////////////////////////////////////////////////////////////////////
204
+ static proc curve (poly f)
205
+ "USAGE: curve(f), where f is a polynomial (affine or projective)
206
+ CREATE: poly CHI in both rings aff_r=p,(x,y),lp and Proj_R=p,(x,y,z),lp
207
+ also ideal (std) Aff_SLocus of affine singular locus in the ring
208
+ aff_r
209
+ RETURN: list (size 3) with two rings aff_r,Proj_R and an integer deg(f)
210
+ NOTE: f must be absolutely irreducible, but this is not checked
211
+ it is not implemented yet for extensions of prime fields
212
+ "
213
+ {
214
+ def base_r=basering;
215
+ ring aff_r=char(basering),(x,y),lp;
216
+ ring Proj_R=char(basering),(x,y,z),lp;
217
+ setring base_r;
218
+ int degX=deg(f);
219
+ if (nvars(basering)==2)
220
+ {
221
+ setring aff_r;
222
+ map embpol=base_r,x,y;
223
+ poly CHI=embpol(f);
224
+ export(CHI);
225
+ kill embpol;
226
+ ideal Aff_SLocus=s_locus(CHI);
227
+ export(Aff_SLocus);
228
+ setring Proj_R;
229
+ poly CHI=homog(imap(aff_r,CHI),z);
230
+ export(CHI);
231
+ setring base_r;
232
+ list L=list();
233
+ L[1]=aff_r;
234
+ L[2]=Proj_R;
235
+ L[3]=degX;
236
+ kill aff_r,Proj_R;
237
+ return(L);
238
+ }
239
+ if (nvars(basering)==3)
240
+ {
241
+ setring Proj_R;
242
+ map embpol=base_r,x,y,z;
243
+ poly CHI=embpol(f);
244
+ export(CHI);
245
+ kill embpol;
246
+ poly s=subst(CHI,z,1);
247
+ setring aff_r;
248
+ poly CHI=imap(Proj_R,s);
249
+ export(CHI);
250
+ ideal Aff_SLocus=s_locus(CHI);
251
+ export(Aff_SLocus);
252
+ setring base_r;
253
+ list L=list();
254
+ L[1]=aff_r;
255
+ L[2]=Proj_R;
256
+ L[3]=degX;
257
+ kill aff_r,Proj_R;
258
+ return(L);
259
+ }
260
+ ERROR("basering must have 2 or 3 variables");
261
+ }
262
+ ///////////////////////////////////////////////////////////////////////////////
263
+ static proc Aff_SL (ideal ISL)
264
+ {
265
+ // computes : affine singular (closed) points as a list of lists of
266
+ // prime ideals and intvec (for storing the places over each point)
267
+ // the ideal ISL=s_locus(CHI) is assumed to be computed in advance for
268
+ // a plane curve CHI, and it must be given by a standard basis
269
+ // for our purpose the function must called with the "global" ideal
270
+ // "Aff_SLocus"
271
+ list SL=list();
272
+ ideal I=ISL;
273
+ if ( I[1] != 1 )
274
+ {
275
+ list L=list();
276
+ ideal aux;
277
+ intvec iv;
278
+ int i,s;
279
+ L=closed_points(I);
280
+ s=size(L);
281
+ for (i=1;i<=s;i=i+1)
282
+ {
283
+ aux=std(L[i]);
284
+ SL[i]=list(aux,iv);
285
+ }
286
+ }
287
+ return(SL);
288
+ }
289
+ ///////////////////////////////////////////////////////////////////////////////
290
+ static proc inf_P (poly f)
291
+ {
292
+ // computes : all (closed) points at infinity as homogeneous polynomials
293
+ // output : two lists with respectively singular and non-singular points
294
+ intvec iv;
295
+ def base_r=basering;
296
+ ring r_auxz=char(basering),(x,y,z),lp;
297
+ poly f=imap(base_r,f);
298
+ poly F=homog(f,z); // equation of projective curve
299
+ poly f_inf=subst(F,z,0);
300
+ setring base_r;
301
+ poly f_inf=imap(r_auxz,f_inf);
302
+ ideal I=factorize(f_inf,1); // points at infinity as homogeneous
303
+ // polynomials
304
+ int s=size(I);
305
+ int i;
306
+ list IP_S=list(); // for singular points at infinity
307
+ list IP_NS=list(); // for non-singular points at infinity
308
+ int counter_S;
309
+ int counter_NS;
310
+ poly aux;
311
+ for (i=1;i<=s;i=i+1)
312
+ {
313
+ aux=subst(I[i],y,1);
314
+ if (aux==1)
315
+ {
316
+ // the point is (1:0:0)
317
+ setring r_auxz;
318
+ poly f_yz=subst(F,x,1);
319
+ if ( subst(subst(diff(f_yz,y),y,0),z,0)==0 &&
320
+ subst(subst(diff(f_yz,z),y,0),z,0)==0 )
321
+ {
322
+ // the point is singular
323
+ counter_S=counter_S+1;
324
+ kill f_yz;
325
+ setring base_r;
326
+ IP_S[counter_S]=list(I[i],iv);
327
+ }
328
+ else
329
+ {
330
+ // the point is non-singular
331
+ counter_NS=counter_NS+1;
332
+ kill f_yz;
333
+ setring base_r;
334
+ IP_NS[counter_NS]=list(I[i],iv);
335
+ }
336
+ }
337
+ else
338
+ {
339
+ // the point is (a:1:0) | a is root of aux
340
+ if (deg(aux)==1)
341
+ {
342
+ // the point is rational and no field extension is needed
343
+ setring r_auxz;
344
+ poly f_xz=subst(F,y,1);
345
+ poly aux=imap(base_r,aux);
346
+ number A=-number(subst(aux,x,0));
347
+ map phi=r_auxz,x+A,0,z;
348
+ poly f_origin=phi(f_xz);
349
+ if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 &&
350
+ subst(subst(diff(f_origin,z),x,0),z,0)==0 )
351
+ {
352
+ // the point is singular
353
+ counter_S=counter_S+1;
354
+ kill f_xz,aux,A,phi,f_origin;
355
+ setring base_r;
356
+ IP_S[counter_S]=list(I[i],iv);
357
+ }
358
+ else
359
+ {
360
+ // the point is non-singular
361
+ counter_NS=counter_NS+1;
362
+ kill f_xz,aux,A,phi,f_origin;
363
+ setring base_r;
364
+ IP_NS[counter_NS]=list(I[i],iv);
365
+ }
366
+ }
367
+ else
368
+ {
369
+ // the point is non-rational and a field extension with minpoly=aux
370
+ // is needed
371
+ ring r_ext=(char(basering),@a),(x,y,z),lp;
372
+ poly aux=imap(base_r,aux);
373
+ minpoly=number(subst(aux,x,@a));
374
+ poly F=imap(r_auxz,F);
375
+ poly f_xz=subst(F,y,1);
376
+ map phi=r_ext,x+@a,0,z;
377
+ poly f_origin=phi(f_xz);
378
+ if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 &&
379
+ subst(subst(diff(f_origin,z),x,0),z,0)==0 )
380
+ {
381
+ // the point is singular
382
+ counter_S=counter_S+1;
383
+ setring base_r;
384
+ kill r_ext;
385
+ IP_S[counter_S]=list(I[i],iv);
386
+ }
387
+ else
388
+ {
389
+ // the point is non-singular
390
+ counter_NS=counter_NS+1;
391
+ setring base_r;
392
+ kill r_ext;
393
+ IP_NS[counter_NS]=list(I[i],iv);
394
+ }
395
+ }
396
+ }
397
+ }
398
+ kill r_auxz;
399
+ return(list(IP_S,IP_NS));
400
+ }
401
+ ///////////////////////////////////////////////////////////////////////////////
402
+ static proc closed_points_ext (poly f,int d,ideal SL)
403
+ {
404
+ // computes : (closed affine non-singular) points over an extension of
405
+ // degree d
406
+ // remark(1) : singular points are supposed to be listed apart
407
+ // remark(2) : std SL=s_locus(f) is supposed to be computed in advance
408
+ // remark(3) : ideal SL is used to remove those points which are singular
409
+ // output : list of list of prime ideals with an intvec for storing the
410
+ // places
411
+ int Q=char(basering)^d; // cardinality of the extension field
412
+ ideal I=f,x^Q-x,y^Q-y; // ideal of the searched points
413
+ I=std(I);
414
+ if (I==1)
415
+ {
416
+ return(list());
417
+ }
418
+ list LP=list();
419
+ int m=size(SL);
420
+ list L=list();
421
+ ideal aux;
422
+ intvec iv;
423
+ int i,s,j,counter;
424
+ L=closed_points(I);
425
+ s=size(L);
426
+ for (i=1;i<=s;i=i+1)
427
+ {
428
+ aux=std(L[i]);
429
+ for (j=1;j<=m;j=j+1)
430
+ {
431
+ // check if singular i.e. if SL is contained in aux
432
+ if ( size(NF(SL[j],aux,5)) != 0 )
433
+ {
434
+ counter=counter+1;
435
+ LP[counter]=list(aux,iv);
436
+ break;
437
+ }
438
+ }
439
+ }
440
+ return(LP);
441
+ }
442
+ ///////////////////////////////////////////////////////////////////////////////
443
+ static proc degree_P (list P)
444
+ "USAGE: degree_P(P), where P is either a polynomial or an ideal
445
+ RETURN: integer with the degree of the closed point given by P
446
+ SEE ALSO: closed_points
447
+ NOTE: If P is a (homogeneous irreducible) polynomial the point is at
448
+ infinity, and if P is a (prime) ideal the points is affine, and
449
+ the ideal must be given by 2 generators: the first one irreducible
450
+ and depending only on y, and the second one irreducible over the
451
+ extension given by y with the first generator as minimal polynomial
452
+ "
453
+ {
454
+ // computes : the degree of a given point
455
+ // remark(1) : if the input is (irreducible homogeneous) polynomial => the point
456
+ // is at infinity
457
+ // remark(2) : it the input is (std. resp. lp. prime) ideal => the point is
458
+ // affine
459
+ if (typeof(P[1])=="ideal")
460
+ {
461
+ if (size(P[1])==2)
462
+ {
463
+ int d=deg(P[1][1]);
464
+ poly aux=subst(P[1][2],y,1);
465
+ d=d*deg(aux);
466
+ return(d);
467
+ }
468
+ else
469
+ {
470
+ // this should not happen in principle
471
+ ERROR("non-valid parameter");
472
+ }
473
+ }
474
+ else
475
+ {
476
+ if (typeof(P[1])=="poly")
477
+ {
478
+ return(deg(P[1]));
479
+ }
480
+ else
481
+ {
482
+ ERROR("parameter must have a polynomial or ideal in the first component");
483
+ }
484
+ }
485
+ }
486
+ ///////////////////////////////////////////////////////////////////////////////
487
+ static proc closed_points_deg (poly f,int d,ideal SL)
488
+ {
489
+ // computes : (closed affine non-singular) points of degree d
490
+ // remark(1) : singular points are supposed to be listed apart
491
+ // remark(2) : std SL=s_locus(f) is supposed to be computed in advance
492
+ list L=closed_points_ext(f,d,SL);
493
+ int s=size(L);
494
+ int i,counter;
495
+ list LP=list();
496
+ for (i=1;i<=s;i=i+1)
497
+ {
498
+ if (degree_P(L[i])==d)
499
+ {
500
+ counter++;
501
+ LP[counter]=L[i];
502
+ }
503
+ }
504
+ return(LP);
505
+ }
506
+ ///////////////////////////////////////////////////////////////////////////////
507
+ static proc idealSubset (ideal I,ideal J)
508
+ {
509
+ // checks whether I is contained in J and returns a boolean
510
+ int s=ncols(I);
511
+ int i;
512
+ if (!attrib(J,"isSB")) { J=std(J);}
513
+ for (i=1;i<=s;i=i+1)
514
+ {
515
+ if ( size(NF(I[i],J,5)) != 0 )
516
+ {
517
+ return(0);
518
+ }
519
+ }
520
+ return(1);
521
+ }
522
+ ///////////////////////////////////////////////////////////////////////////////
523
+ static proc belongs (list P,ideal I)
524
+ {
525
+ // checks if affine point P is contained in V(I) and returns a boolean
526
+ // remark : P[1] is assumed to be an ideal given by a standard basis
527
+ if (typeof(P[1])=="ideal")
528
+ {
529
+ return(idealSubset(I,P[1]));
530
+ }
531
+ else
532
+ {
533
+ ERROR("first argument must be an affine point");
534
+ }
535
+ }
536
+ ///////////////////////////////////////////////////////////////////////////////
537
+ static proc equals (ideal I,ideal J)
538
+ {
539
+ // checks if I is equal to J and returns a boolean
540
+ // remark : I and J are assumed to be given by a standard basis
541
+ int answer=0;
542
+ if (idealSubset(I,J)==1)
543
+ {
544
+ if (idealSubset(J,I)==1)
545
+ {
546
+ answer=1;
547
+ }
548
+ }
549
+ return(answer);
550
+ }
551
+ ///////////////////////////////////////////////////////////////////////////////
552
+ static proc isInLP (ideal P,list LP)
553
+ {
554
+ // checks if affine point P is a list LP and returns either its position or
555
+ // zero
556
+ // remark : all points in LP and P itself are assumed to be given by a
557
+ // standard basis
558
+ // warning : the procedure does not check whether the points are affine or
559
+ // not
560
+ int s=size(LP);
561
+ if (s==0)
562
+ {
563
+ return(0);
564
+ }
565
+ int i;
566
+ for (i=1;i<=s;i=i+1)
567
+ {
568
+ if (equals(P,LP[i][1])==1)
569
+ {
570
+ return(i);
571
+ }
572
+ }
573
+ return(0);
574
+ }
575
+ ///////////////////////////////////////////////////////////////////////////////
576
+ static proc res_deg ()
577
+ {
578
+ // computes the residual degree of the basering with respect to its prime
579
+ // field
580
+ int ext;
581
+ string s_m=string(minpoly);
582
+ if (s_m=="0")
583
+ {
584
+ ext=1;
585
+ }
586
+ else
587
+ {
588
+ ext=pardeg(minpoly);
589
+ }
590
+ return(ext);
591
+ }
592
+ ///////////////////////////////////////////////////////////////////////////////
593
+ static proc Frobenius (def etwas,int r)
594
+ {
595
+ // applies the Frobenius map over F_{p^r} to an object defined over an
596
+ // extension of such field
597
+ // usually it is called with r=1, i.e. the Frobenius map over the prime
598
+ // field F_p
599
+ // returns always an object of the same type, and works correctly on
600
+ // numbers, polynomials, ideals, matrices or lists of the above types
601
+ // maybe : types vector and module should be added in the future, but they
602
+ // are not needed now
603
+ int q=char(basering)^r;
604
+ if (typeof(etwas)=="number")
605
+ {
606
+ return(etwas^q);
607
+ }
608
+ if (typeof(etwas)=="poly")
609
+ {
610
+ int s=size(etwas);
611
+ poly f;
612
+ int i;
613
+ for (i=1;i<=s;i=i+1)
614
+ {
615
+ f=f+(leadcoef(etwas[i])^q)*leadmonom(etwas[i]);
616
+ }
617
+ return(f);
618
+ }
619
+ if (typeof(etwas)=="ideal")
620
+ {
621
+ int s=ncols(etwas);
622
+ ideal I;
623
+ int i;
624
+ for (i=1;i<=s;i=i+1)
625
+ {
626
+ I[i]=Frobenius(etwas[i],r);
627
+ }
628
+ return(I);
629
+ }
630
+ if (typeof(etwas)=="matrix")
631
+ {
632
+ int m=nrows(etwas);
633
+ int n=ncols(etwas);
634
+ matrix A[m][n];
635
+ int i,j;
636
+ for (i=1;i<=m;i=i+1)
637
+ {
638
+ for (j=1;j<=n;j=j+1)
639
+ {
640
+ A[i,j]=Frobenius(etwas[i,j],r);
641
+ }
642
+ }
643
+ return(A);
644
+ }
645
+ if (typeof(etwas)=="list")
646
+ {
647
+ int s=size(etwas);
648
+ list L=list();
649
+ int i;
650
+ for (i=1;i<=s;i=i+1)
651
+ {
652
+ if (typeof(etwas[i])<>"none")
653
+ {
654
+ L[i]=Frobenius(etwas[i],r);
655
+ }
656
+ }
657
+ return(L);
658
+ }
659
+ return(etwas);
660
+ }
661
+ ///////////////////////////////////////////////////////////////////////////////
662
+ static proc conj_b (list L,int r)
663
+ {
664
+ // applies the Frobenius map over F_{p^r} to a list of type HNE defined over
665
+ // a larger extension
666
+ // when r=1 it turns to be the Frobenius map over the prime field F_{p}
667
+ // returns : a list of type HNE which is either conjugate of the input or
668
+ // the same list in case of L being actually defined over the base field
669
+ // F_{p^r}
670
+ int p=char(basering);
671
+ int Q=p^r;
672
+ list LL=list();
673
+ int m=nrows(L[1]);
674
+ int n=ncols(L[1]);
675
+ matrix A[m][n];
676
+ poly f;
677
+ poly aux;
678
+ int i,j;
679
+ for (i=1;i<=m;i=i+1)
680
+ {
681
+ for (j=1;j<=n;j=j+1)
682
+ {
683
+ aux=L[1][i,j];
684
+ if (aux<>x)
685
+ {
686
+ A[i,j]=aux^Q;
687
+ }
688
+ else
689
+ {
690
+ A[i,j]=aux;
691
+ break;
692
+ }
693
+ }
694
+ }
695
+ m=size(L[4]);
696
+ for (i=1;i<=m;i=i+1)
697
+ {
698
+ f=f+(leadcoef(L[4][i])^Q)*leadmonom(L[4][i]);
699
+ }
700
+ LL[1]=A;
701
+ LL[2]=L[2];
702
+ LL[3]=L[3];
703
+ LL[4]=f;
704
+ return(LL);
705
+ }
706
+ ///////////////////////////////////////////////////////////////////////////////
707
+ static proc grad_b (list L,int r)
708
+ {
709
+ // computes the degree of a list of type HNE which is actually defined over
710
+ // F_{p^r} even though it is given in an extension of such field
711
+ int gr=1;
712
+ int rd=res_deg() div r;
713
+ list LL=L;
714
+ int i;
715
+ for (i=1;i<=rd;i=i+1)
716
+ {
717
+ LL=conj_b(LL,r);
718
+ if ( LL[1]==L[1] && LL[4]==L[4] )
719
+ {
720
+ break;
721
+ }
722
+ else
723
+ {
724
+ gr=gr+1;
725
+ }
726
+ }
727
+ return(gr);
728
+ }
729
+ ///////////////////////////////////////////////////////////////////////////////
730
+ static proc conj_bs (list L,int r)
731
+ {
732
+ // computes all the conjugates over F_{p^r} of a list of type HNE defined
733
+ // over an extension
734
+ // returns : a list of lists of type HNE, where the first one is the input
735
+ // list
736
+ // remark : notice that the degree of the branch is then the size of the
737
+ // output
738
+ list branches=list();
739
+ int gr=1;
740
+ branches[1]=L;
741
+ int rd=res_deg() div r;
742
+ list LL=L;
743
+ int i;
744
+ for (i=1;i<=rd;i=i+1)
745
+ {
746
+ LL=conj_b(LL,r);
747
+ if ( LL[1]==L[1] && LL[4]==L[4] )
748
+ {
749
+ break;
750
+ }
751
+ else
752
+ {
753
+ gr=gr+1;
754
+ branches[gr]=LL;
755
+ }
756
+ }
757
+ return(branches);
758
+ }
759
+ ///////////////////////////////////////////////////////////////////////////////
760
+ static proc subfield (def sf)
761
+ {
762
+ // writes the generator "a" of a subfield of the coefficients field of
763
+ // basering in terms of the current generator (also called "a") as a
764
+ // string sf is an existing ring whose coefficient field is such a subfield
765
+ // warning : in basering there must be a variable called "x" and subfield
766
+ // must not be prime
767
+ def base_r=basering;
768
+ string new_m=string(minpoly);
769
+ setring sf;
770
+ string old_m=string(minpoly);
771
+ if (old_m==new_m)
772
+ {
773
+ setring base_r;
774
+ return("a");
775
+ }
776
+ else
777
+ {
778
+ if (old_m<>"0")
779
+ {
780
+ ring auxring=char(basering),(a,x),lp;
781
+ execute("poly mpol="+old_m+";");
782
+ mpol=subst(mpol,a,x);
783
+ setring base_r;
784
+ poly mpol=imap(auxring,mpol);
785
+ kill auxring;
786
+ string answer="? error : non-primitive element";
787
+ int r=res_deg();
788
+ int q=char(basering)^r;
789
+ int i;
790
+ number b;
791
+ for (i=1;i<=q-2;i=i+1)
792
+ {
793
+ b=a^i;
794
+ if (subst(mpol,x,b)==0)
795
+ {
796
+ answer=string(b);
797
+ break;
798
+ }
799
+ }
800
+ if (answer<>"? error : non-primitive element")
801
+ {
802
+ return(answer);
803
+ }
804
+ else
805
+ {
806
+ // list all the elements of the finite field F_q
807
+ int p=char(basering);
808
+ list FF1,FF2;
809
+ for (i=0;i<p;i=i+1)
810
+ {
811
+ FF1[i+1]=number(i);
812
+ }
813
+ int s,j,k;
814
+ for (i=1;i<r;i=i+1)
815
+ {
816
+ s=size(FF1);
817
+ for (j=1;j<=s;j=j+1)
818
+ {
819
+ FF1[j]=FF1[j]*a;
820
+ }
821
+ FF2=FF1;
822
+ for (k=1;k<p;k=k+1)
823
+ {
824
+ for (j=1;j<=s;j=j+1)
825
+ {
826
+ FF1[j]=FF1[j]+number(1);
827
+ }
828
+ FF2=FF2+FF1;
829
+ }
830
+ FF1=FF2;
831
+ FF2=list();
832
+ }
833
+ kill FF2;
834
+ for (i=1;i<=q-1;i=i+1)
835
+ {
836
+ b=FF1[i];
837
+ if (subst(mpol,x,b)==0)
838
+ {
839
+ answer=string(b);
840
+ break;
841
+ }
842
+ }
843
+ }
844
+ kill FF1;
845
+ return(answer);
846
+ }
847
+ else
848
+ {
849
+ dbprint(printlevel+1,"warning : minpoly=0 in the subfield;
850
+ you should check that nothing is wrong");
851
+ return(string(1));
852
+ }
853
+ }
854
+ }
855
+ ///////////////////////////////////////////////////////////////////////////////
856
+ static proc importdatum (def sf,string datum,string rel)
857
+ {
858
+ // fetches a poly with name "datum" to the current basering from the ring sf
859
+ // such that the generator is given by string "rel"
860
+ // warning : ring sf must have only variables (x,y) and basering must have
861
+ // at least (x,y)
862
+ // warning : the case of minpoly=0 is not regarded; there you can use "imap"
863
+ // instead
864
+ def base_r=basering;
865
+ if (rel=="a")
866
+ {
867
+ setring sf;
868
+ execute("poly pdatum="+datum+";");
869
+ setring base_r;
870
+ poly pdatum=imap(sf,pdatum);
871
+ return(pdatum);
872
+ }
873
+ else
874
+ {
875
+ setring sf;
876
+ execute("string sdatum=string("+datum+");");
877
+ ring auxring=char(basering),(a,x,y),lp;
878
+ execute("poly pdatum="+sdatum+";");
879
+ execute("map phi=basering,"+rel+",x,y;");
880
+ pdatum=phi(pdatum);
881
+ string snewdatum=string(pdatum);
882
+ setring base_r;
883
+ execute("poly pdatum="+snewdatum+";");
884
+ kill auxring;
885
+ return(pdatum);
886
+ }
887
+ }
888
+ ///////////////////////////////////////////////////////////////////////////////
889
+ static proc rationalize (def lf,string datum,string rel)
890
+ {
891
+ // fetches a poly with name "datum" to the current basering from the ring lf
892
+ // and larger coefficients field, where the generator of current ring is
893
+ // given by string "rel" and "datum" is actually defined over the small
894
+ // field
895
+ // warning : ring lf must have only variables (x,y) and basering must have
896
+ // at least (x,y)
897
+ // warning : the case of minpoly=0 is supposed unnecessary, since then
898
+ // "datum" should be already written in the right way, i.e. in
899
+ // terms of the prime field
900
+ def base_r=basering;
901
+ if (rel=="a")
902
+ {
903
+ setring lf;
904
+ execute("poly pdatum="+datum+";");
905
+ setring base_r;
906
+ poly pdatum=imap(lf,pdatum);
907
+ return(pdatum);
908
+ }
909
+ else
910
+ {
911
+ setring lf;
912
+ execute("string sdatum=string("+datum+");");
913
+ ring auxring=char(basering),(a,b,x,y,t),lp;
914
+ execute("poly pdatum="+sdatum+";");
915
+ execute("poly prel=b-("+rel+");");
916
+ // was before:
917
+ // ideal I=pdatum,prel;
918
+ // I=eliminate(I,a);
919
+ // if (size(I)<=1){ poly newdatum=I[1]; }
920
+ // else { ERROR("Elimination error"); }
921
+ // CL 09/05 new:
922
+ poly newdatum=reduce(pdatum,std(prel));
923
+ newdatum;
924
+ //
925
+ newdatum=subst(newdatum,b,a);
926
+ string snewdatum=string(newdatum);
927
+ setring base_r;
928
+ execute("poly newdatum="+snewdatum+";");
929
+ kill auxring;
930
+ return(newdatum);
931
+ }
932
+ }
933
+ ///////////////////////////////////////////////////////////////////////////////
934
+ static proc place (intvec Pp,int sing,list CURVE)
935
+ {
936
+ // computes the "rational" places which are defined over a (closed) point
937
+ // Pp points to an appropriate point of the given curve
938
+ // creates : local rings (if they do not exist yet) and then add the
939
+ // places to a list
940
+ // each place is given basically by the coordinates of the point and a
941
+ // list HNdevelop
942
+ // returns : list with all updated data of the curve
943
+ // if the places already exist they are not computed again
944
+ // if sing==1 the point is assumed singular and computes the local conductor
945
+ // for all places using the local invariants of the branches
946
+ // if sing==2 the point is assumed singular and computes the local conductor
947
+ // for all places using the Dedekind formula and local parametrizations
948
+ // of the branches
949
+ // if sing<>1&2 the point is assumed non-singular and the local conductor
950
+ // should be zero
951
+ list PP=list();
952
+ if (Pp[1]==0)
953
+ {
954
+ if (Pp[2]==0)
955
+ {
956
+ PP=Aff_SPoints[Pp[3]];
957
+ }
958
+ if (Pp[2]==1)
959
+ {
960
+ PP=Inf_Points[1][Pp[3]];
961
+ }
962
+ if (Pp[2]==2)
963
+ {
964
+ PP=Inf_Points[2][Pp[3]];
965
+ }
966
+ }
967
+ else
968
+ {
969
+ PP=Aff_Points(Pp[2])[Pp[3]];
970
+ }
971
+ if (PP[2]<>0)
972
+ {
973
+ return(CURVE);
974
+ }
975
+ intvec PtoPl;
976
+ def base_r=basering;
977
+ int ext1;
978
+ list Places=CURVE[3];
979
+ intvec Conductor=CURVE[4];
980
+ list update_CURVE=CURVE;
981
+ if (typeof(PP[1])=="ideal")
982
+ {
983
+ ideal P=PP[1];
984
+ if (size(P)==2)
985
+ {
986
+ int d=deg(P[1]);
987
+ poly aux=subst(P[2],y,1);
988
+ d=d*deg(aux);
989
+ ext1=d;
990
+ // the point is (A:B:1) but one must distinguish several cases
991
+ // P is assumed to be a std. resp. "(x,y),lp" and thus P[1] depends
992
+ // only on "y"
993
+ if (d==1)
994
+ {
995
+ // the point is rational
996
+ number B=-number(subst(P[1],y,0));
997
+ poly aux2=subst(P[2],y,B);
998
+ number A=-number(subst(aux2,x,0));
999
+ // the point is (A:B:1)
1000
+ ring local_aux=char(basering),(x,y),ls;
1001
+ number coord@1=imap(base_r,A);
1002
+ number coord@2=imap(base_r,B);
1003
+ number coord@3=number(1);
1004
+ map phi=base_r,x+coord@1,y+coord@2;
1005
+ poly CHI=phi(CHI);
1006
+ }
1007
+ else
1008
+ {
1009
+ if (deg(P[1])==1)
1010
+ {
1011
+ // the point is non-rational but the second component needs no
1012
+ // field extension
1013
+ number B=-number(subst(P[1],y,0));
1014
+ poly aux2=subst(P[2],y,B);
1015
+ // the point has degree d>1
1016
+ // careful : the parameter will be called "a" anyway
1017
+ ring local_aux=(char(basering),a),(x,y),ls;
1018
+ map psi=base_r,a,0;
1019
+ minpoly=number(psi(aux2));
1020
+ number coord@1=a;
1021
+ number coord@2=imap(base_r,B);
1022
+ number coord@3=number(1);
1023
+ // the point is (a:B:1)
1024
+ map phi=base_r,x+a,y+coord@2;
1025
+ poly CHI=phi(CHI);
1026
+ }
1027
+ else
1028
+ {
1029
+ if (deg(subst(P[2],y,1))==1)
1030
+ {
1031
+ // the point is non-rational but the needed minpoly is just P[1]
1032
+ // careful : the parameter will be called "a" anyway
1033
+ poly P1=P[1];
1034
+ poly P2=P[2];
1035
+ ring local_aux=(char(basering),a),(x,y),ls;
1036
+ map psi=base_r,0,a;
1037
+ minpoly=number(psi(P1));
1038
+ // the point looks like (A:a:1)
1039
+ // A is computed by substituting y=a in P[2]
1040
+ poly aux1=imap(base_r,P2);
1041
+ poly aux2=subst(aux1,y,a);
1042
+ number coord@1=-number(subst(aux2,x,0));
1043
+ number coord@2=a;
1044
+ number coord@3=number(1);
1045
+ map phi=base_r,x+coord@1,y+a;
1046
+ poly CHI=phi(CHI);
1047
+ }
1048
+ else
1049
+ {
1050
+ // this is the most complicated case of non-rational point
1051
+ // firstly : construct an extension of degree d and guess the
1052
+ // minpoly
1053
+ poly P1=P[1];
1054
+ poly P2=P[2];
1055
+ int p=char(basering);
1056
+ int Q=p^d;
1057
+ ring aux_r=(Q,a),(x,y,t),ls;
1058
+ string minpoly_string=string(minpoly);
1059
+ ring local_aux=(char(basering),a),(x,y),ls;
1060
+ execute("minpoly="+minpoly_string+";");
1061
+ // secondly : compute one root of P[1]
1062
+ poly P_1=imap(base_r,P1);
1063
+ poly P_2=imap(base_r,P2);
1064
+ ideal factors1=factorize(P_1,1); // hopefully this works !!!!
1065
+ number coord@2=-number(subst(factors1[1],y,0));
1066
+ // thirdly : compute one of the first components for the above root
1067
+ poly P_0=subst(P_2,y,coord@2);
1068
+ ideal factors2=factorize(P_0,1); // hopefully this works !!!!
1069
+ number coord@1=-number(subst(factors2[1],x,0));
1070
+ number coord@3=number(1);
1071
+ map phi=base_r,x+coord@1,y+coord@2;
1072
+ poly CHI=phi(CHI);
1073
+ kill aux_r;
1074
+ }
1075
+ }
1076
+ }
1077
+ }
1078
+ else
1079
+ {
1080
+ // this should not happen in principle
1081
+ ERROR("non-valid parameter");
1082
+ }
1083
+ }
1084
+ else
1085
+ {
1086
+ if (typeof(PP[1])=="poly")
1087
+ {
1088
+ poly P=PP[1];
1089
+ ring r_auxz=char(basering),(x,y,z),lp;
1090
+ poly CHI=imap(base_r,CHI);
1091
+ CHI=homog(CHI,z);
1092
+ setring base_r;
1093
+ poly aux=subst(P,y,1);
1094
+ if (aux==1)
1095
+ {
1096
+ // the point is (1:0:0)
1097
+ ring local_aux=char(basering),(x,y),ls;
1098
+ number coord@1=number(1);
1099
+ number coord@2=number(0);
1100
+ number coord@3=number(0);
1101
+ map Phi=r_auxz,1,x,y;
1102
+ poly CHI=Phi(CHI);
1103
+ ext1=1;
1104
+ }
1105
+ else
1106
+ {
1107
+ // the point is (A:1:0) where A is a root of aux
1108
+ int d=deg(aux);
1109
+ ext1=d;
1110
+ if (d==1)
1111
+ {
1112
+ // the point is rational
1113
+ number A=-number(subst(aux,x,0));
1114
+ ring local_aux=char(basering),(x,y),ls;
1115
+ number coord@1=imap(base_r,A);
1116
+ number coord@2=number(1);
1117
+ number coord@3=number(0);
1118
+ map Phi=r_auxz,x+coord@1,1,y;
1119
+ poly CHI=Phi(CHI);
1120
+ }
1121
+ else
1122
+ {
1123
+ // the point has degree d>1
1124
+ // careful : the parameter will be called "a" anyway
1125
+ ring local_aux=(char(basering),a),(x,y),ls;
1126
+ map psi=base_r,a,1;
1127
+ minpoly=number(psi(P));
1128
+ number coord@1=a;
1129
+ number coord@2=number(1);
1130
+ number coord@3=number(0);
1131
+ map Phi=r_auxz,x+a,1,y;
1132
+ poly CHI=Phi(CHI);
1133
+ }
1134
+ }
1135
+ kill r_auxz;
1136
+ }
1137
+ else
1138
+ {
1139
+ ERROR("a point must have a polynomial or ideal in the first component");
1140
+ }
1141
+ }
1142
+ export(coord@1);
1143
+ export(coord@2);
1144
+ export(coord@3);
1145
+ export(CHI);
1146
+ int i,j,k;
1147
+ int m,n;
1148
+ list LLL=ratdevelop(CHI);
1149
+ // list LLL=hnexpansion(CHI,"ess");
1150
+ if (typeof(LLL[1])=="ring") {
1151
+ def altring=basering;
1152
+ def HNEring = LLL[1]; setring HNEring;
1153
+ def L@HNE = HND;
1154
+ kill HND;
1155
+ // def L@HNE = hne;
1156
+ // kill hne;
1157
+
1158
+ }
1159
+ else {
1160
+ def L@HNE=LLL;
1161
+ // def L@HNE=LLL[1];
1162
+ def HNEring=basering;
1163
+ setring HNEring;
1164
+ }
1165
+ kill LLL;
1166
+ export(L@HNE);
1167
+ int n_branches=size(L@HNE);
1168
+ list Li_aux=list();
1169
+ int N_branches;
1170
+ int N=size(Places);
1171
+ if (sing==1)
1172
+ {
1173
+ list delta2=list();
1174
+ for (i=1;i<=n_branches;i=i+1)
1175
+ {
1176
+ delta2[i]=invariants(L@HNE[i])[5];
1177
+ }
1178
+ int dq;
1179
+ }
1180
+ int ext2=res_deg();
1181
+ list dgs=list();
1182
+ int ext_0;
1183
+ int check;
1184
+ string sss,olda,newa;
1185
+ if (defined(Q)==0)
1186
+ {
1187
+ int Q;
1188
+ }
1189
+ if (ext1==1)
1190
+ {
1191
+ if (ext2==1)
1192
+ {
1193
+ if (sing==1)
1194
+ {
1195
+ intmat I_mult[n_branches][n_branches];
1196
+ if (n_branches>1)
1197
+ {
1198
+ for (i=1;i<=n_branches-1;i=i+1)
1199
+ {
1200
+ for (j=i+1;j<=n_branches;j=j+1)
1201
+ {
1202
+ I_mult[i,j]=intersection(L@HNE[i],L@HNE[j]);
1203
+ I_mult[j,i]=I_mult[i,j];
1204
+ }
1205
+ }
1206
+ }
1207
+ }
1208
+ ////////
1209
+ check=0;
1210
+ ////////
1211
+ if (size(update_CURVE[5])>0)
1212
+ {
1213
+ if (typeof(update_CURVE[5][1])=="list")
1214
+ {
1215
+ check=1;
1216
+ }
1217
+ }
1218
+ if (check==0)
1219
+ {
1220
+ intvec dgs_points(1);
1221
+ ring S(1)=char(basering),(x,y,t),ls;
1222
+ list BRANCHES=list();
1223
+ list POINTS=list();
1224
+ list LOC_EQS=list();
1225
+ list PARAMETRIZATIONS=list();
1226
+ export(BRANCHES);
1227
+ export(POINTS);
1228
+ export(LOC_EQS);
1229
+ export(PARAMETRIZATIONS);
1230
+ }
1231
+ else
1232
+ {
1233
+ intvec dgs_points(1)=update_CURVE[5][1][2];
1234
+ def S1=update_CURVE[5][1][1];
1235
+ execute("ring S(1)="+string(update_CURVE[5][1][1])+";");
1236
+ fetchall(S1);
1237
+ kill S1;
1238
+ }
1239
+ N_branches=size(BRANCHES);
1240
+ for (i=1;i<=n_branches;i=i+1)
1241
+ {
1242
+ dgs_points(1)[N_branches+i]=1;
1243
+ POINTS[N_branches+i]=list();
1244
+ POINTS[N_branches+i][1]=imap(local_aux,coord@1);
1245
+ POINTS[N_branches+i][2]=imap(local_aux,coord@2);
1246
+ POINTS[N_branches+i][3]=imap(local_aux,coord@3);
1247
+ LOC_EQS[N_branches+i]=imap(local_aux,CHI);
1248
+ setring HNEring;
1249
+ Li_aux=L@HNE[i];
1250
+ setring S(1);
1251
+ BRANCHES=insert(BRANCHES,imap(HNEring,Li_aux),N_branches+i-1);
1252
+ PARAMETRIZATIONS[N_branches+i]=param(BRANCHES[N_branches+i],0);
1253
+ N=N+1;
1254
+ intvec iw=1,N_branches+i;
1255
+ Places[N]=iw;
1256
+ if (sing==1)
1257
+ {
1258
+ dq=delta2[i];
1259
+ for (j=1;j<=n_branches;j=j+1)
1260
+ {
1261
+ dq=dq+I_mult[i,j];
1262
+ }
1263
+ Conductor[N]=dq;
1264
+ }
1265
+ if (sing==2)
1266
+ {
1267
+ Conductor[N]=local_conductor(iw[2],S(1));
1268
+ }
1269
+ kill iw;
1270
+ PtoPl[i]=N;
1271
+ }
1272
+ setring base_r;
1273
+ update_CURVE[5][1]=list();
1274
+ update_CURVE[5][1][1]=S(1);
1275
+ update_CURVE[5][1][2]=dgs_points(1);
1276
+ }
1277
+ else
1278
+ {
1279
+ // we start with a rational point but we get non-rational branches
1280
+ // they may have different degrees and then we may need to reduce the
1281
+ // field extensions for each one, and finally check if the minpoly
1282
+ // fetches with S(i) or not
1283
+ // if one of the branches is rational, we may trust that it is written
1284
+ // correctly
1285
+ if (sing==1)
1286
+ {
1287
+ int n_geobrs;
1288
+ int counter_c;
1289
+ list auxgb=list();
1290
+ list geobrs=list();
1291
+ for (i=1;i<=n_branches;i=i+1)
1292
+ {
1293
+ auxgb=conj_bs(L@HNE[i],1);
1294
+ dgs[i]=size(auxgb);
1295
+ n_geobrs=n_geobrs+dgs[i];
1296
+ for (j=1;j<=dgs[i];j=j+1)
1297
+ {
1298
+ counter_c=counter_c+1;
1299
+ geobrs[counter_c]=auxgb[j];
1300
+ }
1301
+ }
1302
+ intmat I_mult[n_geobrs][n_geobrs];
1303
+ for (i=1;i<n_geobrs;i=i+1)
1304
+ {
1305
+ for (j=i+1;j<=n_geobrs;j=j+1)
1306
+ {
1307
+ I_mult[i,j]=intersection(geobrs[i],geobrs[j]);
1308
+ I_mult[j,i]=I_mult[i,j];
1309
+ }
1310
+ }
1311
+ kill auxgb,geobrs;
1312
+ }
1313
+ else
1314
+ {
1315
+ for (i=1;i<=n_branches;i=i+1)
1316
+ {
1317
+ dgs[i]=grad_b(L[i],1);
1318
+ }
1319
+ }
1320
+ // the actual degree of each branch is computed and now check if the
1321
+ // local ring exists
1322
+ for (i=1;i<=n_branches;i=i+1)
1323
+ {
1324
+ ext_0=dgs[i];
1325
+ ////////
1326
+ check=0;
1327
+ ////////
1328
+ if (size(update_CURVE[5])>=ext_0)
1329
+ {
1330
+ if (typeof(update_CURVE[5][ext_0])=="list")
1331
+ {
1332
+ check=1;
1333
+ }
1334
+ }
1335
+ if (check==0)
1336
+ {
1337
+ if (ext_0>1)
1338
+ {
1339
+ if (ext_0==ext2)
1340
+ {
1341
+ sss=string(minpoly);
1342
+ }
1343
+ else
1344
+ {
1345
+ Q=char(basering)^ext_0;
1346
+ ring auxxx=(Q,a),z,lp;
1347
+ sss=string(minpoly);
1348
+ setring base_r;
1349
+ kill auxxx;
1350
+ }
1351
+ ring S(ext_0)=(char(basering),a),(x,y,t),ls;
1352
+ execute("minpoly="+sss+";");
1353
+ }
1354
+ else
1355
+ {
1356
+ ring S(ext_0)=char(basering),(x,y,t),ls;
1357
+ }
1358
+ intvec dgs_points(ext_0);
1359
+ list BRANCHES=list();
1360
+ list POINTS=list();
1361
+ list LOC_EQS=list();
1362
+ list PARAMETRIZATIONS=list();
1363
+ export(BRANCHES);
1364
+ export(POINTS);
1365
+ export(LOC_EQS);
1366
+ export(PARAMETRIZATIONS);
1367
+ }
1368
+ else
1369
+ {
1370
+ intvec dgs_points(ext_0)=update_CURVE[5][ext_0][2];
1371
+ def Sext_0=update_CURVE[5][ext_0][1];
1372
+ setring Sext_0;
1373
+ string SM=string(minpoly);
1374
+ string SR=string(update_CURVE[5][ext_0][1]);
1375
+ execute("ring S("+string(ext_0)+")="+SR+";");
1376
+ execute("minpoly="+SM+";");
1377
+ kill SM,SR;
1378
+ fetchall(Sext_0);
1379
+ kill Sext_0;
1380
+ }
1381
+ N_branches=size(BRANCHES);
1382
+ dgs_points(ext_0)[N_branches+1]=1;
1383
+ POINTS[N_branches+1]=list();
1384
+ POINTS[N_branches+1][1]=imap(local_aux,coord@1);
1385
+ POINTS[N_branches+1][2]=imap(local_aux,coord@2);
1386
+ POINTS[N_branches+1][3]=imap(local_aux,coord@3);
1387
+ LOC_EQS[N_branches+1]=imap(local_aux,CHI);
1388
+ // now fetch the branches into the new local ring
1389
+ if (ext_0==1)
1390
+ {
1391
+ setring HNEring;
1392
+ Li_aux=L@HNE[i];
1393
+ setring S(1);
1394
+ BRANCHES=insert(BRANCHES,imap(HNEring,Li_aux),N_branches);
1395
+ }
1396
+ else
1397
+ {
1398
+ // rationalize branch
1399
+ setring HNEring;
1400
+ newa=subfield(S(ext_0));
1401
+ m=nrows(L@HNE[i][1]);
1402
+ n=ncols(L@HNE[i][1]);
1403
+ setring S(ext_0);
1404
+ list Laux=list();
1405
+ poly paux=rationalize(HNEring,"L@HNE["+string(i)+"][4]",newa);
1406
+ matrix Maux[m][n];
1407
+ for (j=1;j<=m;j=j+1)
1408
+ {
1409
+ for (k=1;k<=n;k=k+1)
1410
+ {
1411
+ Maux[j,k]=rationalize(HNEring,"L@HNE["+string(i)+"][1]["+
1412
+ string(j)+","+string(k)+"]",newa);
1413
+ }
1414
+ }
1415
+ setring HNEring;
1416
+ intvec Li2=L@HNE[i][2];
1417
+ int Li3=L@HNE[i][3];
1418
+ setring S(ext_0);
1419
+ Laux[1]=Maux;
1420
+ Laux[2]=Li2;
1421
+ Laux[3]=Li3;
1422
+ Laux[4]=paux;
1423
+ BRANCHES=insert(BRANCHES,Laux,N_branches);
1424
+ kill Laux,Maux,paux,Li2,Li3;
1425
+ }
1426
+ PARAMETRIZATIONS[N_branches+1]=param(BRANCHES[N_branches+1],0);
1427
+ N=N+1;
1428
+ intvec iw=ext_0,N_branches+1;
1429
+ Places[N]=iw;
1430
+ if (sing==2)
1431
+ {
1432
+ Conductor[N]=local_conductor(iw[2],S(ext_0));
1433
+ }
1434
+ kill iw;
1435
+ PtoPl[i]=N;
1436
+ setring HNEring;
1437
+ update_CURVE[5][ext_0]=list();
1438
+ update_CURVE[5][ext_0][1]=S(ext_0);
1439
+ update_CURVE[5][ext_0][2]=dgs_points(ext_0);
1440
+ }
1441
+ if (sing==1)
1442
+ {
1443
+ int N_ini=N-n_branches;
1444
+ counter_c=1;
1445
+ for (i=1;i<=n_branches;i=i+1)
1446
+ {
1447
+ dq=delta2[i];
1448
+ for (j=1;j<=n_geobrs;j=j+1)
1449
+ {
1450
+ dq=dq+I_mult[counter_c,j];
1451
+ }
1452
+ Conductor[N_ini+i]=dq;
1453
+ counter_c=counter_c+dgs[i];
1454
+ }
1455
+ }
1456
+ setring base_r;
1457
+ }
1458
+ }
1459
+ else
1460
+ {
1461
+ if (ext1==ext2)
1462
+ {
1463
+ // the degree of the point equals to the degree of all branches
1464
+ // one must just fetch the minpoly's of local_aux, HNEring and S(ext2)
1465
+ if (sing==1)
1466
+ {
1467
+ intmat I_mult[n_branches][n_branches];
1468
+ if (n_branches>1)
1469
+ {
1470
+ for (i=1;i<=n_branches-1;i=i+1)
1471
+ {
1472
+ for (j=i+1;j<=n_branches;j=j+1)
1473
+ {
1474
+ I_mult[i,j]=intersection(L@HNE[i],L@HNE[j]);
1475
+ I_mult[j,i]=I_mult[i,j];
1476
+ }
1477
+ }
1478
+ }
1479
+ }
1480
+ ////////
1481
+ check=0;
1482
+ ////////
1483
+ if (size(update_CURVE[5])>=ext2)
1484
+ {
1485
+ if (typeof(update_CURVE[5][ext2])=="list")
1486
+ {
1487
+ check=1;
1488
+ }
1489
+ }
1490
+ if (check==0)
1491
+ {
1492
+ sss=string(minpoly);
1493
+ ring S(ext2)=(char(basering),a),(x,y,t),ls;
1494
+ execute("minpoly="+sss+";");
1495
+ intvec dgs_points(ext2);
1496
+ list BRANCHES=list();
1497
+ list POINTS=list();
1498
+ list LOC_EQS=list();
1499
+ list PARAMETRIZATIONS=list();
1500
+ export(BRANCHES);
1501
+ export(POINTS);
1502
+ export(LOC_EQS);
1503
+ export(PARAMETRIZATIONS);
1504
+ }
1505
+ else
1506
+ {
1507
+ intvec dgs_points(ext2)=update_CURVE[5][ext2][2];
1508
+ def Sext2=update_CURVE[5][ext2][1];
1509
+ setring Sext2;
1510
+ string SM=string(minpoly);
1511
+ string SR=string(update_CURVE[5][ext2][1]);
1512
+ execute("ring S("+string(ext2)+")="+SR+";");
1513
+ execute("minpoly="+SM+";");
1514
+ kill SM,SR;
1515
+ fetchall(Sext2);
1516
+ kill Sext2;
1517
+ }
1518
+ N_branches=size(BRANCHES);
1519
+ for (i=1;i<=n_branches;i=i+1)
1520
+ {
1521
+ // fetch all the data into the new local ring
1522
+ olda=subfield(local_aux);
1523
+ dgs_points(ext2)[N_branches+i]=ext1;
1524
+ POINTS[N_branches+i]=list();
1525
+ POINTS[N_branches+i][1]=number(importdatum(local_aux,"coord@1",olda));
1526
+ POINTS[N_branches+i][2]=number(importdatum(local_aux,"coord@2",olda));
1527
+ POINTS[N_branches+i][3]=number(importdatum(local_aux,"coord@3",olda));
1528
+ LOC_EQS[N_branches+i]=importdatum(local_aux,"CHI",olda);
1529
+ newa=subfield(HNEring);
1530
+ setring HNEring;
1531
+ m=nrows(L@HNE[i][1]);
1532
+ n=ncols(L@HNE[i][1]);
1533
+ setring S(ext2);
1534
+ list Laux=list();
1535
+ poly paux=importdatum(HNEring,"L@HNE["+string(i)+"][4]",newa);
1536
+ matrix Maux[m][n];
1537
+ for (j=1;j<=m;j=j+1)
1538
+ {
1539
+ for (k=1;k<=n;k=k+1)
1540
+ {
1541
+ Maux[j,k]=importdatum(HNEring,"L@HNE["+string(i)+"][1]["+
1542
+ string(j)+","+string(k)+"]",newa);
1543
+ }
1544
+ }
1545
+ setring HNEring;
1546
+ intvec Li2=L@HNE[i][2];
1547
+ int Li3=L@HNE[i][3];
1548
+ setring S(ext2);
1549
+ Laux[1]=Maux;
1550
+ Laux[2]=Li2;
1551
+ Laux[3]=Li3;
1552
+ Laux[4]=paux;
1553
+ BRANCHES=insert(BRANCHES,Laux,N_branches+i-1);
1554
+ kill Laux,Maux,paux,Li2,Li3;
1555
+ PARAMETRIZATIONS[N_branches+i]=param(BRANCHES[N_branches+i],0);
1556
+ N=N+1;
1557
+ intvec iw=ext2,N_branches+i;
1558
+ Places[N]=iw;
1559
+ if (sing==1)
1560
+ {
1561
+ dq=delta2[i];
1562
+ for (j=1;j<=n_branches;j=j+1)
1563
+ {
1564
+ dq=dq+I_mult[i,j];
1565
+ }
1566
+ Conductor[N]=dq;
1567
+ }
1568
+ if (sing==2)
1569
+ {
1570
+ Conductor[N]=local_conductor(iw[2],S(ext2));
1571
+ }
1572
+ kill iw;
1573
+ PtoPl[i]=N;
1574
+ }
1575
+ setring base_r;
1576
+ update_CURVE[5][ext2]=list();
1577
+ update_CURVE[5][ext2][1]=S(ext2);
1578
+ update_CURVE[5][ext2][2]=dgs_points(ext2);
1579
+ }
1580
+ else
1581
+ {
1582
+ // this is the most complicated case
1583
+ if (sing==1)
1584
+ {
1585
+ int n_geobrs;
1586
+ int counter_c;
1587
+ list auxgb=list();
1588
+ list geobrs=list();
1589
+ for (i=1;i<=n_branches;i=i+1)
1590
+ {
1591
+ auxgb=conj_bs(L@HNE[i],ext1);
1592
+ dgs[i]=size(auxgb);
1593
+ n_geobrs=n_geobrs+dgs[i];
1594
+ for (j=1;j<=dgs[i];j=j+1)
1595
+ {
1596
+ counter_c=counter_c+1;
1597
+ geobrs[counter_c]=auxgb[j];
1598
+ }
1599
+ }
1600
+ intmat I_mult[n_geobrs][n_geobrs];
1601
+ for (i=1;i<n_geobrs;i=i+1)
1602
+ {
1603
+ for (j=i+1;j<=n_geobrs;j=j+1)
1604
+ {
1605
+ I_mult[i,j]=intersection(geobrs[i],geobrs[j]);
1606
+ I_mult[j,i]=I_mult[i,j];
1607
+ }
1608
+ }
1609
+ kill auxgb,geobrs;
1610
+ }
1611
+ else
1612
+ {
1613
+ for (i=1;i<=n_branches;i=i+1)
1614
+ {
1615
+ dgs[i]=grad_b(L@HNE[i],ext1);
1616
+ }
1617
+ }
1618
+ for (i=1;i<=n_branches;i=i+1)
1619
+ {
1620
+ // first compute the actual degree of each branch and check if the
1621
+ // local ring exists
1622
+ ext_0=ext1*dgs[i];
1623
+ ////////
1624
+ check=0;
1625
+ ////////
1626
+ if (size(update_CURVE[5])>=ext_0)
1627
+ {
1628
+ if (typeof(update_CURVE[5][ext_0])=="list")
1629
+ {
1630
+ check=1;
1631
+ }
1632
+ }
1633
+ if (check==0)
1634
+ {
1635
+ if (ext_0>ext1)
1636
+ {
1637
+ if (ext_0==ext2)
1638
+ {
1639
+ sss=string(minpoly);
1640
+ }
1641
+ else
1642
+ {
1643
+ Q=char(basering)^ext_0;
1644
+ ring auxxx=(Q,a),z,lp;
1645
+ sss=string(minpoly);
1646
+ setring base_r;
1647
+ kill auxxx;
1648
+ }
1649
+ }
1650
+ else
1651
+ {
1652
+ setring local_aux;
1653
+ sss=string(minpoly);
1654
+ }
1655
+ ring S(ext_0)=(char(basering),a),(x,y,t),ls;
1656
+ execute("minpoly="+sss+";");
1657
+ intvec dgs_points(ext_0);
1658
+ list BRANCHES=list();
1659
+ list POINTS=list();
1660
+ list LOC_EQS=list();
1661
+ list PARAMETRIZATIONS=list();
1662
+ export(BRANCHES);
1663
+ export(POINTS);
1664
+ export(LOC_EQS);
1665
+ export(PARAMETRIZATIONS);
1666
+ }
1667
+ else
1668
+ {
1669
+ intvec dgs_points(ext_0)=update_CURVE[5][ext_0][2];
1670
+ def Sext_0=update_CURVE[5][ext_0][1];
1671
+ setring Sext_0;
1672
+ string SM=string(minpoly);
1673
+ string SR=string(update_CURVE[5][ext_0][1]);
1674
+ execute("ring S("+string(ext_0)+")="+SR+";");
1675
+ execute("minpoly="+SM+";");
1676
+ kill SM,SR;
1677
+ fetchall(badring);
1678
+ kill badring;
1679
+ }
1680
+ N_branches=size(BRANCHES);
1681
+ // now fetch all the data into the new local ring
1682
+ olda=subfield(local_aux);
1683
+ dgs_points(ext_0)[N_branches+1]=ext1;
1684
+ POINTS[N_branches+1]=list();
1685
+ POINTS[N_branches+1][1]=number(importdatum(local_aux,"coord@1",olda));
1686
+ POINTS[N_branches+1][2]=number(importdatum(local_aux,"coord@2",olda));
1687
+ POINTS[N_branches+1][3]=number(importdatum(local_aux,"coord@3",olda));
1688
+ LOC_EQS[N_branches+1]=importdatum(local_aux,"CHI",olda);
1689
+ setring HNEring;
1690
+ newa=subfield(S(ext_0));
1691
+ m=nrows(L@HNE[i][1]);
1692
+ n=ncols(L@HNE[i][1]);
1693
+ setring S(ext_0);
1694
+ list Laux=list();
1695
+ poly paux=rationalize(HNEring,"L@HNE["+string(i)+"][4]",newa);
1696
+ matrix Maux[m][n];
1697
+ for (j=1;j<=m;j=j+1)
1698
+ {
1699
+ for (k=1;k<=n;k=k+1)
1700
+ {
1701
+ Maux[j,k]=rationalize(HNEring,"L@HNE["+string(i)+"][1]["+
1702
+ string(j)+","+string(k)+"]",newa);
1703
+ }
1704
+ }
1705
+ setring HNEring;
1706
+ intvec Li2=L@HNE[i][2];
1707
+ int Li3=L@HNE[i][3];
1708
+ setring S(ext_0);
1709
+ Laux[1]=Maux;
1710
+ Laux[2]=Li2;
1711
+ Laux[3]=Li3;
1712
+ Laux[4]=paux;
1713
+ BRANCHES=insert(BRANCHES,Laux,N_branches);
1714
+ kill Laux,Maux,paux,Li2,Li3;
1715
+ PARAMETRIZATIONS[N_branches+1]=param(BRANCHES[N_branches+1],0);
1716
+ N=N+1;
1717
+ intvec iw=ext_0,N_branches+1;
1718
+ Places[N]=iw;
1719
+ if (sing==2)
1720
+ {
1721
+ Conductor[N]=local_conductor(iw[2],S(ext_0));
1722
+ }
1723
+ kill iw;
1724
+ PtoPl[i]=N;
1725
+ setring HNEring;
1726
+ update_CURVE[5][ext_0]=list();
1727
+ update_CURVE[5][ext_0][1]=S(ext_0);
1728
+ update_CURVE[5][ext_0][2]=dgs_points(ext_0);
1729
+ }
1730
+ if (sing==1)
1731
+ {
1732
+ int N_ini=N-n_branches;
1733
+ counter_c=1;
1734
+ for (i=1;i<=n_branches;i=i+1)
1735
+ {
1736
+ dq=delta2[i];
1737
+ for (j=1;j<=n_geobrs;j=j+1)
1738
+ {
1739
+ dq=dq+I_mult[counter_c,j];
1740
+ }
1741
+ Conductor[N_ini+i]=dq;
1742
+ counter_c=counter_c+dgs[i];
1743
+ }
1744
+ }
1745
+ setring base_r;
1746
+ }
1747
+ }
1748
+ update_CURVE[3]=Places;
1749
+ update_CURVE[4]=Conductor;
1750
+ PP[2]=PtoPl;
1751
+ if (Pp[1]==0)
1752
+ {
1753
+ if (Pp[2]==0)
1754
+ {
1755
+ Aff_SPoints[Pp[3]]=PP;
1756
+ }
1757
+ if (Pp[2]==1)
1758
+ {
1759
+ Inf_Points[1][Pp[3]]=PP;
1760
+ }
1761
+ if (Pp[2]==2)
1762
+ {
1763
+ Inf_Points[2][Pp[3]]=PP;
1764
+ }
1765
+ }
1766
+ else
1767
+ {
1768
+ Aff_Points(Pp[2])[Pp[3]]=PP;
1769
+ }
1770
+ update_CURVE[1][1]=base_r;
1771
+ kill HNEring;
1772
+ kill local_aux;
1773
+ return(update_CURVE);
1774
+ }
1775
+ ///////////////////////////////////////////////////////////////////////////////
1776
+ static proc local_conductor (int k,def SS)
1777
+ {
1778
+ // computes the degree of the local conductor at a place of a plane curve
1779
+ // if the point is non-singular the result will be zero
1780
+ // the computation is carried out with the "Dedekind formula" via
1781
+ // parametrizations
1782
+ int a,b,Cq;
1783
+ def b_ring=basering;
1784
+ setring SS;
1785
+ poly fx=diff(LOC_EQS[k],x);
1786
+ poly fy=diff(LOC_EQS[k],y);
1787
+ int nr=ncols(BRANCHES[k][1]);
1788
+ poly xt=PARAMETRIZATIONS[k][1][1];
1789
+ poly yt=PARAMETRIZATIONS[k][1][2];
1790
+ int ordx=PARAMETRIZATIONS[k][2][1];
1791
+ int ordy=PARAMETRIZATIONS[k][2][2];
1792
+ map phi_t=basering,xt,yt,1;
1793
+ poly derf;
1794
+ if (fx<>0)
1795
+ {
1796
+ derf=fx;
1797
+ poly tt=diff(yt,t);
1798
+ b=mindeg(tt);
1799
+ if (ordy>-1)
1800
+ {
1801
+ while (b>=ordy)
1802
+ {
1803
+ BRANCHES[k]=extdevelop(BRANCHES[k],2*nr);
1804
+ nr=ncols(BRANCHES[k][1]);
1805
+ PARAMETRIZATIONS[k]=param(BRANCHES[k],0);
1806
+ ordy=PARAMETRIZATIONS[k][2][2];
1807
+ yt=PARAMETRIZATIONS[k][1][2];
1808
+ tt=diff(yt,t);
1809
+ b=mindeg(tt);
1810
+ }
1811
+ xt=PARAMETRIZATIONS[k][1][1];
1812
+ ordx=PARAMETRIZATIONS[k][2][1];
1813
+ }
1814
+ poly ft=phi_t(derf);
1815
+ }
1816
+ else
1817
+ {
1818
+ derf=fy;
1819
+ poly tt=diff(xt,t);
1820
+ b=mindeg(tt);
1821
+ if (ordx>-1)
1822
+ {
1823
+ while (b>=ordx)
1824
+ {
1825
+ BRANCHES[k]=extdevelop(BRANCHES[k],2*nr);
1826
+ nr=ncols(BRANCHES[k][1]);
1827
+ PARAMETRIZATIONS[k]=param(BRANCHES[k],0);
1828
+ ordx=PARAMETRIZATIONS[k][2][1];
1829
+ xt=PARAMETRIZATIONS[k][1][1];
1830
+ tt=diff(xt,t);
1831
+ b=mindeg(tt);
1832
+ }
1833
+ yt=PARAMETRIZATIONS[k][1][2];
1834
+ ordy=PARAMETRIZATIONS[k][2][2];
1835
+ }
1836
+ poly ft=phi_t(derf);
1837
+ }
1838
+ a=mindeg(ft);
1839
+ if ( ordx>-1 || ordy>-1 )
1840
+ {
1841
+ if (ordy==-1)
1842
+ {
1843
+ while (a>ordx)
1844
+ {
1845
+ BRANCHES[k]=extdevelop(BRANCHES[k],2*nr);
1846
+ nr=ncols(BRANCHES[k][1]);
1847
+ PARAMETRIZATIONS[k]=param(BRANCHES[k],0);
1848
+ ordx=PARAMETRIZATIONS[k][2][1];
1849
+ xt=PARAMETRIZATIONS[k][1][1];
1850
+ ft=phi_t(derf);
1851
+ a=mindeg(ft);
1852
+ }
1853
+ }
1854
+ else
1855
+ {
1856
+ if (ordx==-1)
1857
+ {
1858
+ while (a>ordy)
1859
+ {
1860
+ BRANCHES[k]=extdevelop(BRANCHES[k],2*nr);
1861
+ nr=ncols(BRANCHES[k][1]);
1862
+ PARAMETRIZATIONS[k]=param(BRANCHES[k],0);
1863
+ ordy=PARAMETRIZATIONS[k][2][2];
1864
+ yt=PARAMETRIZATIONS[k][1][2];
1865
+ ft=phi_t(derf);
1866
+ a=mindeg(ft);
1867
+ }
1868
+ }
1869
+ else
1870
+ {
1871
+ int ordf=ordx;
1872
+ if (ordx>ordy)
1873
+ {
1874
+ ordf=ordy;
1875
+ }
1876
+ while (a>ordf)
1877
+ {
1878
+ BRANCHES[k]=extdevelop(BRANCHES[k],2*nr);
1879
+ nr=ncols(BRANCHES[k][1]);
1880
+ PARAMETRIZATIONS[k]=param(BRANCHES[k],0);
1881
+ ordx=PARAMETRIZATIONS[k][2][1];
1882
+ ordy=PARAMETRIZATIONS[k][2][2];
1883
+ ordf=ordx;
1884
+ if (ordx>ordy)
1885
+ {
1886
+ ordf=ordy;
1887
+ }
1888
+ xt=PARAMETRIZATIONS[k][1][1];
1889
+ yt=PARAMETRIZATIONS[k][1][2];
1890
+ ft=phi_t(derf);
1891
+ a=mindeg(ft);
1892
+ }
1893
+ }
1894
+ }
1895
+ }
1896
+ Cq=a-b;
1897
+ setring b_ring;
1898
+ return(Cq);
1899
+ }
1900
+ ///////////////////////////////////////////////////////////////////////////////
1901
+ static proc max_D (intvec D1,intvec D2)
1902
+ {
1903
+ // computes the maximum of two divisors (intvec)
1904
+ int s1=size(D1);
1905
+ int s2=size(D2);
1906
+ int i;
1907
+ if (s1>s2)
1908
+ {
1909
+ for (i=1;i<=s2;i=i+1)
1910
+ {
1911
+ if (D2[i]>D1[i])
1912
+ {
1913
+ D1[i]=D2[i];
1914
+ }
1915
+ }
1916
+ for (i=s2+1;i<=s1;i=i+1)
1917
+ {
1918
+ if (D1[i]<0)
1919
+ {
1920
+ D1[i]=0;
1921
+ }
1922
+ }
1923
+ return(D1);
1924
+ }
1925
+ else
1926
+ {
1927
+ for (i=1;i<=s1;i=i+1)
1928
+ {
1929
+ if (D1[i]>D2[i])
1930
+ {
1931
+ D2[i]=D1[i];
1932
+ }
1933
+ }
1934
+ for (i=s1+1;i<=s2;i=i+1)
1935
+ {
1936
+ if (D2[i]<0)
1937
+ {
1938
+ D2[i]=0;
1939
+ }
1940
+ }
1941
+ return(D2);
1942
+ }
1943
+ }
1944
+ ///////////////////////////////////////////////////////////////////////////////
1945
+ static proc deg_D (intvec D,list PP)
1946
+ {
1947
+ // computes the degree of a divisor (intvec or list of integers)
1948
+ int i;
1949
+ int d=0;
1950
+ int s=size(D);
1951
+ for (i=1;i<=s;i=i+1)
1952
+ {
1953
+ d=d+D[i]*PP[i][1];
1954
+ }
1955
+ return(d);
1956
+ }
1957
+ ///////////////////////////////////////////////////////////////////////////////
1958
+
1959
+ // ============================================================================
1960
+ // ******* MAIN PROCEDURES for the "preprocessing" of Brill-Noether ********
1961
+ // ============================================================================
1962
+
1963
+ proc Adj_div (poly f,list #)
1964
+ "USAGE: Adj_div( f [,l] ); f a poly, [l a list]
1965
+ RETURN: list L with the computed data:
1966
+ @format
1967
+ L[1] a list of rings: L[1][1]=aff_r (affine), L[1][2]=Proj_R (projective),
1968
+ L[2] an intvec with 2 entries (degree, genus),
1969
+ L[3] a list of intvec (closed places),
1970
+ L[4] an intvec (conductor),
1971
+ L[5] a list of lists:
1972
+ L[5][d][1] a (local) ring over an extension of degree d,
1973
+ L[5][d][2] an intvec (degrees of base points of places of degree d)
1974
+ @end format
1975
+ NOTE: @code{Adj_div(f);} computes and stores the fundamental data of the
1976
+ plane curve defined by f as needed for AG codes.
1977
+ In the affine ring you can find the following data:
1978
+ @format
1979
+ poly CHI: affine equation of the curve,
1980
+ ideal Aff_SLocus: affine singular locus (std),
1981
+ list Inf_Points: points at infinity
1982
+ Inf_Points[1]: singular points
1983
+ Inf_Points[2]: non-singular points,
1984
+ list Aff_SPoints: affine singular points (if not empty).
1985
+ @end format
1986
+ In the projective ring you can find the projective equation
1987
+ CHI of the curve (poly).
1988
+ In the local rings L[5][d][1] you find:
1989
+ @format
1990
+ list POINTS: base points of the places of degree d,
1991
+ list LOC_EQS: local equations of the curve at the base points,
1992
+ list BRANCHES: Hamburger-Noether developments of the places,
1993
+ list PARAMETRIZATIONS: local parametrizations of the places,
1994
+ @end format
1995
+ Each entry of the list L[3] corresponds to one closed place (i.e.,
1996
+ a place and all its conjugates) which is represented by an intvec
1997
+ of size two, the first entry is the degree of the place (in
1998
+ particular, it tells the local ring where to find the data
1999
+ describing one representative of the closed place), and the
2000
+ second one is the position of those data in the lists POINTS, etc.,
2001
+ inside this local ring.@*
2002
+ In the intvec L[4] (conductor) the i-th entry corresponds to the
2003
+ i-th entry in the list of places L[3].
2004
+
2005
+ With no optional arguments, the conductor is computed by
2006
+ local invariants of the singularities; otherwise it is computed
2007
+ by the Dedekind formula. @*
2008
+ An affine point is represented by a list P where P[1] is std
2009
+ of a prime ideal and P[2] is an intvec containing the position
2010
+ of the places above P in the list of closed places L[3]. @*
2011
+ If the point is at infinity, P[1] is a homogeneous irreducible
2012
+ polynomial in two variables.
2013
+
2014
+ If @code{printlevel>=0} additional comments are displayed (default:
2015
+ @code{printlevel=0}).
2016
+ WARNING: The parameter of the needed field extensions is called 'a'. Thus,
2017
+ there should be no global object named 'a' when executing Adj_div.
2018
+ KEYWORDS: Hamburger-Noether expansions; adjunction divisor
2019
+ SEE ALSO: closed_points, NSplaces
2020
+ EXAMPLE: example Adj_div; shows an example
2021
+ "
2022
+ {
2023
+ // computes the adjunction divisor and the genus of a (singular) plane curve
2024
+ // as a byproduct, it computes all the singular points with the corresponding
2025
+ // places and the genus of the curve
2026
+ // the adjunction divisor is stored in an intvec
2027
+ // also the non-singular places at infinity are computed
2028
+ // returns a list with all the computed data
2029
+ if (char(basering)==0)
2030
+ {
2031
+ ERROR("Base field not implemented");
2032
+ }
2033
+ if (npars(basering)>0)
2034
+ {
2035
+ ERROR("Base field not implemented");
2036
+ }
2037
+ if (defined(a)==1)
2038
+ {
2039
+ if ((typeof(a)=="int") or (typeof(a)=="intvec") or (typeof(a)=="intmat") or
2040
+ (typeof(a)=="string") or (typeof(a)=="proc") or (typeof(a)=="list"))
2041
+ {
2042
+ print("WARNING: There is an object named 'a' of the global type "
2043
+ + typeof(a)+".");
2044
+ print("This will cause problems when "
2045
+ + "executing Adj_div, as 'a' is used for "
2046
+ + "the name of the parameter of the field extensions needed.");
2047
+ ERROR("Please rename or kill the object named 'a'");
2048
+ }
2049
+ }
2050
+ intvec opgt=option(get);
2051
+ option(redSB);
2052
+ def Base_R=basering;
2053
+ list CURVE=curve(f);
2054
+ def aff_r=CURVE[1];
2055
+ def Proj_R=CURVE[2];
2056
+ int degX=CURVE[3];
2057
+ int genusX=(degX-1)*(degX-2);
2058
+ genusX = genusX div 2;
2059
+ intvec iivv=degX,genusX;
2060
+ intvec Conductor;
2061
+ setring aff_r;
2062
+ dbprint(printlevel+1,"Computing affine singular points ... ");
2063
+ list Aff_SPoints=Aff_SL(Aff_SLocus);
2064
+ int s=size(Aff_SPoints);
2065
+ if (s>0)
2066
+ {
2067
+ export(Aff_SPoints);
2068
+ }
2069
+ dbprint(printlevel+1,"Computing all points at infinity ... ");
2070
+ list Inf_Points=inf_P(CHI);
2071
+ export(Inf_Points);
2072
+ list update_CURVE=list();
2073
+ update_CURVE[1]=list();
2074
+ update_CURVE[1][1]=aff_r;
2075
+ update_CURVE[1][2]=Proj_R;
2076
+ update_CURVE[2]=iivv;
2077
+ update_CURVE[3]=list();
2078
+ update_CURVE[4]=Conductor;
2079
+ update_CURVE[5]=list();
2080
+ int i;
2081
+ intvec pP=0,0,0;
2082
+ if (size(#)==0)
2083
+ {
2084
+ dbprint(printlevel+1,"Computing affine singular places ... ");
2085
+ if (s>0)
2086
+ {
2087
+ for (i=1;i<=s;i=i+1)
2088
+ {
2089
+ pP[3]=i;
2090
+ update_CURVE=place(pP,1,update_CURVE);
2091
+ }
2092
+ }
2093
+ dbprint(printlevel+1,"Computing singular places at infinity ... ");
2094
+ s=size(Inf_Points[1]);
2095
+ if (s>0)
2096
+ {
2097
+ pP[2]=1;
2098
+ for (i=1;i<=s;i=i+1)
2099
+ {
2100
+ pP[3]=i;
2101
+ update_CURVE=place(pP,1,update_CURVE);
2102
+ }
2103
+ }
2104
+ }
2105
+ else
2106
+ {
2107
+ dbprint(printlevel+1,"Computing affine singular places ... ");
2108
+ s=size(Aff_SPoints);
2109
+ if (s>0)
2110
+ {
2111
+ for (i=1;i<=s;i=i+1)
2112
+ {
2113
+ pP[3]=i;
2114
+ update_CURVE=place(pP,2,update_CURVE);
2115
+ }
2116
+ }
2117
+ dbprint(printlevel+1,"Computing singular places at infinity ... ");
2118
+ s=size(Inf_Points[1]);
2119
+ if (s>0)
2120
+ {
2121
+ pP[2]=1;
2122
+ for (i=1;i<=s;i=i+1)
2123
+ {
2124
+ pP[3]=i;
2125
+ update_CURVE=place(pP,2,update_CURVE);
2126
+ }
2127
+ }
2128
+ }
2129
+ dbprint(printlevel+1,"Computing non-singular places at infinity ... ");
2130
+ s=size(Inf_Points[2]);
2131
+ if (s>0)
2132
+ {
2133
+ pP[2]=2;
2134
+ for (i=1;i<=s;i=i+1)
2135
+ {
2136
+ pP[3]=i;
2137
+ update_CURVE=place(pP,0,update_CURVE);
2138
+ }
2139
+ }
2140
+ dbprint(printlevel+1,"Adjunction divisor computed successfully");
2141
+ list Places=update_CURVE[3];
2142
+ Conductor=update_CURVE[4];
2143
+ genusX = genusX - (deg_D(Conductor,Places) div 2);
2144
+ update_CURVE[2][2]=genusX;
2145
+ setring Base_R;
2146
+ dbprint(printlevel+1," ");
2147
+ dbprint(printlevel+2,"The genus of the curve is "+string(genusX));
2148
+ option(set,opgt);
2149
+ return(update_CURVE);
2150
+ }
2151
+ example
2152
+ {
2153
+ "EXAMPLE:"; echo = 2;
2154
+ int plevel=printlevel;
2155
+ printlevel=-1;
2156
+ ring s=2,(x,y),lp;
2157
+ list C=Adj_div(y9+y8+xy6+x2y3+y2+x3);
2158
+ def aff_R=C[1][1]; // the affine ring
2159
+ setring aff_R;
2160
+ listvar(aff_R); // data in the affine ring
2161
+ CHI; // affine equation of the curve
2162
+ Aff_SLocus; // ideal of the affine singular locus
2163
+ Aff_SPoints[1]; // 1st affine singular point: (1:1:1), no.1
2164
+ Inf_Points[1]; // singular point(s) at infinity: (1:0:0), no.4
2165
+ Inf_Points[2]; // list of non-singular points at infinity
2166
+ //
2167
+ pause("press RETURN");
2168
+ def proj_R=C[1][2]; // the projective ring
2169
+ setring proj_R;
2170
+ CHI; // projective equation of the curve
2171
+ C[2][1]; // degree of the curve
2172
+ C[2][2]; // genus of the curve
2173
+ C[3]; // list of computed places
2174
+ C[4]; // adjunction divisor (all points are singular!)
2175
+ //
2176
+ pause("press RETURN");
2177
+ // we look at the place(s) of degree 2 by changing to the ring
2178
+ C[5][2][1];
2179
+ def S(2)=C[5][2][1];
2180
+ setring S(2);
2181
+ POINTS; // base point(s) of place(s) of degree 2: (1:a:1)
2182
+ LOC_EQS; // local equation(s)
2183
+ PARAMETRIZATIONS; // parametrization(s) and exactness
2184
+ BRANCHES; // Hamburger-Noether development
2185
+ printlevel=plevel;
2186
+ }
2187
+ ///////////////////////////////////////////////////////////////////////////////
2188
+
2189
+ proc NSplaces (intvec h,list CURVE)
2190
+ "USAGE: NSplaces( h, CURVE ), where h is an intvec and CURVE is a list
2191
+ RETURN: list L with updated data of CURVE after computing all non-singular
2192
+ affine closed places whose degrees are in the intvec h: @*
2193
+ @format
2194
+ in L[1][1]: (affine ring) lists Aff_Points(d) with affine non-singular
2195
+ (closed) points of degree d (if non-empty),
2196
+ in L[3]: the newly computed closed places are added,
2197
+ in L[5]: local rings created/updated to store (repres. of) new places.
2198
+ @end format
2199
+ See @ref{Adj_div} for a description of the entries in L.
2200
+ NOTE: The list_expression should be the output of the procedure Adj_div.@*
2201
+ Raising @code{printlevel}, additional comments are displayed
2202
+ (default: @code{printlevel=0}).
2203
+ WARNING: The parameter of the needed field extensions is called 'a'. Thus,
2204
+ there should be no global object named 'a' when executing NSplaces.
2205
+ SEE ALSO: closed_points, Adj_div
2206
+ EXAMPLE: example NSplaces; shows an example
2207
+ "
2208
+ {
2209
+ // computes all the non-singular affine (closed) places with fixed degrees
2210
+ // creates lists of points and the corresponding places
2211
+ // list CURVE must be the output of the procedure "Adj_div"
2212
+ // notice : if h==0 then nothing is done
2213
+ // warning : non-positive entries are forgotten
2214
+ if (defined(a)==1)
2215
+ {
2216
+ if ((typeof(a)=="int") or (typeof(a)=="intvec") or (typeof(a)=="intmat") or
2217
+ (typeof(a)=="string") or (typeof(a)=="proc") or (typeof(a)=="list"))
2218
+ {
2219
+ print("WARNING: There is an object named 'a' of the global type "
2220
+ + typeof(a)+".");
2221
+ print("This will cause problems when "
2222
+ + "executing Adj_div, as 'a' is used for "
2223
+ + "the name of the parameter of the field extensions needed.");
2224
+ ERROR("Please rename or kill the object named 'a'");
2225
+ }
2226
+ }
2227
+ if (h==0)
2228
+ {
2229
+ return(CURVE);
2230
+ }
2231
+ intvec opgt=option(get);
2232
+ option(redSB);
2233
+ def Base_R=basering;
2234
+ def aff_r=CURVE[1][1];
2235
+ int M=size(h);
2236
+ list update_CURVE=CURVE;
2237
+ int i,j,l,s;
2238
+ setring aff_r;
2239
+ intvec pP=1,0,0;
2240
+ for (i=1;i<=M;i=i+1)
2241
+ {
2242
+ l=h[i];
2243
+ if (l>0)
2244
+ {
2245
+ dbprint(printlevel+1,"Computing non-singular affine places of degree "
2246
+ +string(l)+" ... ");
2247
+ if (defined(Aff_Points(l))==0)
2248
+ {
2249
+ list Aff_Points(l)=closed_points_deg(CHI,l,Aff_SLocus);
2250
+ s=size(Aff_Points(l));
2251
+ if (s>0)
2252
+ {
2253
+ export(Aff_Points(l));
2254
+ pP[2]=l;
2255
+ for (j=1;j<=s;j=j+1)
2256
+ {
2257
+ dbprint(printlevel-voice-2,"Place No.\ "+string(j));
2258
+ pP[3]=j;
2259
+ update_CURVE=place(pP,0,update_CURVE);
2260
+ }
2261
+ }
2262
+ }
2263
+ }
2264
+ }
2265
+ setring Base_R;
2266
+ option(set,opgt);
2267
+ return(update_CURVE);
2268
+ }
2269
+ example
2270
+ {
2271
+ "EXAMPLE:"; echo = 2;
2272
+ int plevel=printlevel;
2273
+ printlevel=-1;
2274
+ ring s=2,(x,y),lp;
2275
+ list C=Adj_div(x3y+y3+x);
2276
+ // The list of computed places:
2277
+ C[3];
2278
+ // create places up to degree 4
2279
+ list L=NSplaces(1..4,C);
2280
+ // The list of computed places is now:
2281
+ L[3];
2282
+ // e.g., affine non-singular points of degree 4 :
2283
+ def aff_r=L[1][1];
2284
+ setring aff_r;
2285
+ Aff_Points(4);
2286
+ // e.g., base point of the 1st place of degree 4 :
2287
+ def S(4)=L[5][4][1];
2288
+ setring S(4);
2289
+ POINTS[1];
2290
+ printlevel=plevel;
2291
+ }
2292
+ ///////////////////////////////////////////////////////////////////////////////
2293
+
2294
+ // ** SPECIAL PROCEDURES FOR LINEAR ALGEBRA **
2295
+
2296
+ static proc Ker (matrix A)
2297
+ {
2298
+ // warning : "lp" ordering is necessary
2299
+ intvec opgt=option(get);
2300
+ option(redSB);
2301
+ matrix M=transpose(syz(A));
2302
+ option(set,opgt);
2303
+ return(M);
2304
+ }
2305
+ ///////////////////////////////////////////////////////////////////////////////
2306
+ static proc get_NZsol (matrix A)
2307
+ {
2308
+ matrix sol=Ker(A);
2309
+ return(submat(sol,1..1,1..ncols(sol)));
2310
+ }
2311
+ ///////////////////////////////////////////////////////////////////////////////
2312
+ static proc supplement (matrix W,matrix V)
2313
+ "USAGE: supplement(W,V), where W,V are matrices of numbers such that the
2314
+ vector space generated by the rows of W is contained in that
2315
+ generated by the rows of V
2316
+ RETURN: matrix whose rows generate a supplementary vector space of W in V,
2317
+ or a zero row-matrix if <W>==<V>
2318
+ NOTE: W,V must be given with maximal rank
2319
+ "
2320
+ {
2321
+ // W and V represent independent sets of vectors and <W> is assumed to be
2322
+ // contained in <V>
2323
+ // computes matrix S whose rows are l.i. vectors s.t. <W> union <S> is a
2324
+ // basis of <V>
2325
+ // careful : the size of all vectors is assumed to be the same but it is
2326
+ // not checked and neither the linear independence of the vectors is checked
2327
+ // the trivial case W=0 is not covered by this procedure (and thus V<>0)
2328
+ // if <W>=<V> then a zero row-matrix is returned
2329
+ // warning : option(redSB) must be set in advance
2330
+ int n1=nrows(W);
2331
+ int n2=nrows(V);
2332
+ int s=n2-n1;
2333
+ if (s==0)
2334
+ {
2335
+ int n=ncols(W);
2336
+ matrix HH[1][n];
2337
+ return(HH);
2338
+ }
2339
+ matrix H=transpose(lift(transpose(V),transpose(W)));
2340
+ H=supplem(H);
2341
+ return(H*V);
2342
+ }
2343
+ ///////////////////////////////////////////////////////////////////////////////
2344
+ static proc supplem (matrix M)
2345
+ "USAGE: supplem(M), where M is a matrix of numbers with maximal rank
2346
+ RETURN: matrix whose rows generate a supplementary vector space of <M> in
2347
+ k^n, where k is the base field and n is the number of columns
2348
+ SEE ALSO: supplement
2349
+ NOTE: The rank r is assumed to be 1<r<n.
2350
+ "
2351
+ {
2352
+ // warning : the linear independence of the rows is not checked
2353
+ int r=nrows(M);
2354
+ int n=ncols(M);
2355
+ int s=n-r;
2356
+ matrix A=M;
2357
+ matrix supl[s][n];
2358
+ int counter=0;
2359
+ int h=r+1;
2360
+ int i;
2361
+ for (i=1;i<=n;i=i+1)
2362
+ {
2363
+ matrix TT[1][n];
2364
+ TT[1,i]=1;
2365
+ A=transpose(concat(transpose(A),transpose(TT)));
2366
+ r=mat_rank(A);
2367
+ if (r==h)
2368
+ {
2369
+ h=h+1;
2370
+ counter=counter+1;
2371
+ supl=transpose(concat(transpose(supl),transpose(TT)));
2372
+ if (counter==s)
2373
+ {
2374
+ break;
2375
+ }
2376
+ }
2377
+ kill TT;
2378
+ }
2379
+ supl=transpose(compress(transpose(supl)));
2380
+ return(supl);
2381
+ }
2382
+ ///////////////////////////////////////////////////////////////////////////////
2383
+ static proc mat_rank (matrix A)
2384
+ {
2385
+ // warning : "lp" ordering is necessary
2386
+ intvec opgt=option(get);
2387
+ option(redSB);
2388
+ int r=size(std(module(transpose(A))));
2389
+ option(set,opgt);
2390
+ return(r);
2391
+ }
2392
+ ///////////////////////////////////////////////////////////////////////////////
2393
+
2394
+ // ***************************************************************
2395
+ // * PROCEDURES FOR INTERPOLATION, INTERSECTION AND EXTRA PLACES *
2396
+ // ***************************************************************
2397
+
2398
+ static proc estim_n (intvec Dplus,int dgX,list PL)
2399
+ {
2400
+ // computes an estimate for the degree n in the Brill-Noether algorithm
2401
+ int estim=2*deg_D(Dplus,PL)+dgX*(dgX-3);
2402
+ estim=estim div (2*dgX);
2403
+ estim=estim+1;
2404
+ if (estim<dgX)
2405
+ {
2406
+ estim=dgX;
2407
+ }
2408
+ return(estim);
2409
+ }
2410
+ ///////////////////////////////////////////////////////////////////////////////
2411
+ static proc nforms (int n)
2412
+ {
2413
+ // computes the list of all homogeneous monomials of degree n>=0
2414
+ // exports ideal nFORMS(n) whose generators are ranged with lp order
2415
+ // in Proj_R and returns size(nFORMS(n))
2416
+ // warning : it is supposed to be called inside Proj_R
2417
+ // if n<=0 then nFORMS(0) is "computed fast"
2418
+ ideal nFORMS(n);
2419
+ int N;
2420
+ if (n>0)
2421
+ {
2422
+ N=(n+1)*(n+2);
2423
+ N=N div 2;
2424
+ N=N+1;
2425
+ int i,j,k;
2426
+ for (i=0;i<=n;i=i+1)
2427
+ {
2428
+ for (j=0;j<=n-i;j=j+1)
2429
+ {
2430
+ k=k+1;
2431
+ nFORMS(n)[N-k]=x^i*y^j*z^(n-i-j);
2432
+ }
2433
+ }
2434
+ export(nFORMS(n));
2435
+ }
2436
+ else
2437
+ {
2438
+ N=2;
2439
+ nFORMS(0)=1;
2440
+ export(nFORMS(0));
2441
+ }
2442
+ return(N-1);
2443
+ }
2444
+ ///////////////////////////////////////////////////////////////////////////////
2445
+ static proc nmultiples (int n,int dgX,poly f)
2446
+ {
2447
+ // computes a basis of the space of forms of degree n which are multiple of
2448
+ // CHI
2449
+ // returns a matrix whose rows are the coordinates (related to nFORMS(n))
2450
+ // of such a basis
2451
+ // warning : it is supposed to be called inside Proj_R
2452
+ // warning : nFORMS(n) is created in the way, together with nFORMS(n-degX)
2453
+ // warning : n must be greater or equal than the degree of the curve
2454
+ if (defined(nFORMS(n))==0)
2455
+ {
2456
+ dbprint(printlevel+1,string(nforms(n)));
2457
+ }
2458
+ int m=n-dgX;
2459
+ if (defined(nFORMS(m))==0)
2460
+ {
2461
+ int k=nforms(m);
2462
+ }
2463
+ else
2464
+ {
2465
+ int k=size(nFORMS(m));
2466
+ }
2467
+ ideal nmults;
2468
+ int i;
2469
+ for (i=1;i<=k;i=i+1)
2470
+ {
2471
+ nmults[i]=f*nFORMS(m)[i];
2472
+ }
2473
+ return(transpose(lift(nFORMS(n),nmults)));
2474
+ }
2475
+ ///////////////////////////////////////////////////////////////////////////////
2476
+ static proc interpolating_forms (intvec D,int n,list CURVE)
2477
+ {
2478
+ // computes a vector basis of the space of forms of degree n whose
2479
+ // intersection divisor with the curve is greater or equal than D>=0
2480
+ // the procedure is supposed to be called inside the ring Proj_R and
2481
+ // assumes that the forms nFORMS(n) are previously computed
2482
+ // the output is a matrix whose rows are the coordinates in nFORMS(n) of
2483
+ // such a basis
2484
+ // remark : the support of D may contain "extra" places
2485
+ def BR=basering;
2486
+ def aff_r=CURVE[1][1];
2487
+ int N=size(nFORMS(n));
2488
+ matrix totalM[1][N];
2489
+ int s=size(D);
2490
+ list Places=CURVE[3];
2491
+ int NPls=size(Places);
2492
+ int i,j,k,kk,id,ip,RR,ordx,ordy,nr,NR;
2493
+ if (s<=NPls)
2494
+ {
2495
+ for (i=1;i<=s;i=i+1)
2496
+ {
2497
+ if (D[i]>0)
2498
+ {
2499
+ id=Places[i][1];
2500
+ ip=Places[i][2];
2501
+ RR=D[i];
2502
+ def SS=CURVE[5][id][1];
2503
+ setring SS;
2504
+ poly xt=PARAMETRIZATIONS[ip][1][1];
2505
+ poly yt=PARAMETRIZATIONS[ip][1][2];
2506
+ ordx=PARAMETRIZATIONS[ip][2][1];
2507
+ ordy=PARAMETRIZATIONS[ip][2][2];
2508
+ nr=ncols(BRANCHES[ip][1]);
2509
+ if ( ordx>-1 || ordy>-1 )
2510
+ {
2511
+ while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) )
2512
+ {
2513
+ BRANCHES[ip]=extdevelop(BRANCHES[ip],2*nr);
2514
+ nr=ncols(BRANCHES[ip][1]);
2515
+ PARAMETRIZATIONS[ip]=param(BRANCHES[ip],0);
2516
+ xt=PARAMETRIZATIONS[ip][1][1];
2517
+ yt=PARAMETRIZATIONS[ip][1][2];
2518
+ ordx=PARAMETRIZATIONS[ip][2][1];
2519
+ ordy=PARAMETRIZATIONS[ip][2][2];
2520
+ }
2521
+ }
2522
+ if (POINTS[ip][3]==number(1))
2523
+ {
2524
+ number A=POINTS[ip][1];
2525
+ number B=POINTS[ip][2];
2526
+ map Mt=BR,A+xt,B+yt,1;
2527
+ kill A,B;
2528
+ }
2529
+ else
2530
+ {
2531
+ if (POINTS[ip][2]==number(1))
2532
+ {
2533
+ number A=POINTS[ip][1];
2534
+ map Mt=BR,A+xt,1,yt;
2535
+ kill A;
2536
+ }
2537
+ else
2538
+ {
2539
+ map Mt=BR,1,xt,yt;
2540
+ }
2541
+ }
2542
+ ideal nFORMS(n)=Mt(nFORMS(n));
2543
+ // rewrite properly the above conditions to obtain the local equations
2544
+ matrix partM[RR][N];
2545
+ matrix auxMC=coeffs(nFORMS(n),t);
2546
+ NR=nrows(auxMC);
2547
+ if (RR<=NR)
2548
+ {
2549
+ for (j=1;j<=RR;j=j+1)
2550
+ {
2551
+ for (k=1;k<=N;k=k+1)
2552
+ {
2553
+ partM[j,k]=number(auxMC[j,k]);
2554
+ }
2555
+ }
2556
+ }
2557
+ else
2558
+ {
2559
+ for (j=1;j<=NR;j=j+1)
2560
+ {
2561
+ for (k=1;k<=N;k=k+1)
2562
+ {
2563
+ partM[j,k]=number(auxMC[j,k]);
2564
+ }
2565
+ }
2566
+ for (j=NR+1;j<=RR;j=j+1)
2567
+ {
2568
+ for (k=1;k<=N;k=k+1)
2569
+ {
2570
+ partM[j,k]=number(0);
2571
+ }
2572
+ }
2573
+ }
2574
+ matrix localM=partM;
2575
+ matrix conjM=partM;
2576
+ for (j=2;j<=id;j=j+1)
2577
+ {
2578
+ conjM=Frobenius(conjM,1);
2579
+ localM=transpose(concat(transpose(localM),transpose(conjM)));
2580
+ }
2581
+ localM=gauss_row(localM);
2582
+ setring BR;
2583
+ totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM))));
2584
+ totalM=transpose(compress(transpose(totalM)));
2585
+ setring SS;
2586
+ kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM;
2587
+ setring BR;
2588
+ kill SS;
2589
+ }
2590
+ }
2591
+ }
2592
+ else
2593
+ {
2594
+ // distinguish between "standard" places and "extra" places
2595
+ for (i=1;i<=NPls;i=i+1)
2596
+ {
2597
+ if (D[i]>0)
2598
+ {
2599
+ id=Places[i][1];
2600
+ ip=Places[i][2];
2601
+ RR=D[i];
2602
+ def SS=CURVE[5][id][1];
2603
+ setring SS;
2604
+ poly xt=PARAMETRIZATIONS[ip][1][1];
2605
+ poly yt=PARAMETRIZATIONS[ip][1][2];
2606
+ ordx=PARAMETRIZATIONS[ip][2][1];
2607
+ ordy=PARAMETRIZATIONS[ip][2][2];
2608
+ nr=ncols(BRANCHES[ip][1]);
2609
+ if ( ordx>-1 || ordy>-1 )
2610
+ {
2611
+ while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) )
2612
+ {
2613
+ BRANCHES[ip]=extdevelop(BRANCHES[ip],2*nr);
2614
+ nr=ncols(BRANCHES[ip][1]);
2615
+ PARAMETRIZATIONS[ip]=param(BRANCHES[ip],0);
2616
+ xt=PARAMETRIZATIONS[ip][1][1];
2617
+ yt=PARAMETRIZATIONS[ip][1][2];
2618
+ ordx=PARAMETRIZATIONS[ip][2][1];
2619
+ ordy=PARAMETRIZATIONS[ip][2][2];
2620
+ }
2621
+ }
2622
+ if (POINTS[ip][3]==number(1))
2623
+ {
2624
+ number A=POINTS[ip][1];
2625
+ number B=POINTS[ip][2];
2626
+ map Mt=BR,A+xt,B+yt,1;
2627
+ kill A,B;
2628
+ }
2629
+ else
2630
+ {
2631
+ if (POINTS[ip][2]==number(1))
2632
+ {
2633
+ number A=POINTS[ip][1];
2634
+ map Mt=BR,A+xt,1,yt;
2635
+ kill A;
2636
+ }
2637
+ else
2638
+ {
2639
+ map Mt=BR,1,xt,yt;
2640
+ }
2641
+ }
2642
+ ideal nFORMS(n)=Mt(nFORMS(n));
2643
+ // rewrite properly the above conditions to obtain the local equations
2644
+ matrix partM[RR][N];
2645
+ matrix auxMC=coeffs(nFORMS(n),t);
2646
+ NR=nrows(auxMC);
2647
+ if (RR<=NR)
2648
+ {
2649
+ for (j=1;j<=RR;j=j+1)
2650
+ {
2651
+ for (k=1;k<=N;k=k+1)
2652
+ {
2653
+ partM[j,k]=number(auxMC[j,k]);
2654
+ }
2655
+ }
2656
+ }
2657
+ else
2658
+ {
2659
+ for (j=1;j<=NR;j=j+1)
2660
+ {
2661
+ for (k=1;k<=N;k=k+1)
2662
+ {
2663
+ partM[j,k]=number(auxMC[j,k]);
2664
+ }
2665
+ }
2666
+ for (j=NR+1;j<=RR;j=j+1)
2667
+ {
2668
+ for (k=1;k<=N;k=k+1)
2669
+ {
2670
+ partM[j,k]=number(0);
2671
+ }
2672
+ }
2673
+ }
2674
+ matrix localM=partM;
2675
+ matrix conjM=partM;
2676
+ for (j=2;j<=id;j=j+1)
2677
+ {
2678
+ conjM=Frobenius(conjM,1);
2679
+ localM=transpose(concat(transpose(localM),transpose(conjM)));
2680
+ }
2681
+ localM=gauss_row(localM);
2682
+ setring BR;
2683
+ totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM))));
2684
+ totalM=transpose(compress(transpose(totalM)));
2685
+ setring SS;
2686
+ kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM;
2687
+ setring BR;
2688
+ kill SS;
2689
+ }
2690
+ }
2691
+ k=s-NPls;
2692
+ int l;
2693
+ for (i=1;i<=k;i=i+1)
2694
+ {
2695
+ // in this case D[NPls+i]>0 is assumed to be true during the
2696
+ // Brill-Noether algorithm
2697
+ RR=D[NPls+i];
2698
+ setring aff_r;
2699
+ def SS=@EXTRA@[2][i];
2700
+ def extra_dgs=@EXTRA@[3];
2701
+ setring SS;
2702
+ poly xt=PARAMETRIZATION[1][1];
2703
+ poly yt=PARAMETRIZATION[1][2];
2704
+ ordx=PARAMETRIZATION[2][1];
2705
+ ordy=PARAMETRIZATION[2][2];
2706
+ nr=ncols(BRANCH[1]);
2707
+ if ( ordx>-1 || ordy>-1 )
2708
+ {
2709
+ while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) )
2710
+ {
2711
+ BRANCH=extdevelop(BRANCH,2*nr);
2712
+ nr=ncols(BRANCH[1]);
2713
+ PARAMETRIZATION=param(BRANCH,0);
2714
+ xt=PARAMETRIZATION[1][1];
2715
+ yt=PARAMETRIZATION[1][2];
2716
+ ordx=PARAMETRIZATION[2][1];
2717
+ ordy=PARAMETRIZATION[2][2];
2718
+ }
2719
+ }
2720
+ number A=POINT[1];
2721
+ number B=POINT[2];
2722
+ map Mt=BR,A+xt,B+yt,1;
2723
+ kill A,B;
2724
+ ideal nFORMS(n)=Mt(nFORMS(n));
2725
+ // rewrite properly the above conditions to obtain the local equations
2726
+ matrix partM[RR][N];
2727
+ matrix auxMC=coeffs(nFORMS(n),t);
2728
+ NR=nrows(auxMC);
2729
+ if (RR<=NR)
2730
+ {
2731
+ for (j=1;j<=RR;j=j+1)
2732
+ {
2733
+ for (kk=1;kk<=N;kk=kk+1)
2734
+ {
2735
+ partM[j,kk]=number(auxMC[j,kk]);
2736
+ }
2737
+ }
2738
+ }
2739
+ else
2740
+ {
2741
+ for (j=1;j<=NR;j=j+1)
2742
+ {
2743
+ for (kk=1;kk<=N;kk=kk+1)
2744
+ {
2745
+ partM[j,kk]=number(auxMC[j,kk]);
2746
+ }
2747
+ }
2748
+ for (j=NR+1;j<=RR;j=j+1)
2749
+ {
2750
+ for (kk=1;kk<=N;kk=kk+1)
2751
+ {
2752
+ partM[j,kk]=number(0);
2753
+ }
2754
+ }
2755
+ }
2756
+ matrix localM=partM;
2757
+ matrix conjM=partM;
2758
+ l=extra_dgs[i];
2759
+ for (j=2;j<=l;j=j+1)
2760
+ {
2761
+ conjM=Frobenius(conjM,1);
2762
+ localM=transpose(concat(transpose(localM),transpose(conjM)));
2763
+ }
2764
+ localM=gauss_row(localM);
2765
+ setring BR;
2766
+ totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM))));
2767
+ totalM=transpose(compress(transpose(totalM)));
2768
+ setring SS;
2769
+ kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM;
2770
+ setring BR;
2771
+ kill SS;
2772
+ }
2773
+ }
2774
+ return(Ker(totalM));
2775
+ }
2776
+ ///////////////////////////////////////////////////////////////////////////////
2777
+ static proc local_IN (poly h,int m)
2778
+ {
2779
+ // computes the intersection number of h and the curve CHI at a certain place
2780
+ // returns a list with the intersection number and the "leading coefficient"
2781
+ // the procedure must be called inside a local ring, h must be a local
2782
+ // equation with respect to the desired place, and m indicates the
2783
+ // number of place inside that local ring, containing lists
2784
+ // POINT(S)/BRANCH(ES)/PARAMETRIZATION(S) when m=0 an "extra place" is
2785
+ // considered
2786
+ def BR=basering;
2787
+ if (m>0)
2788
+ {
2789
+ int nr=ncols(BRANCHES[m][1]);
2790
+ poly xt=PARAMETRIZATIONS[m][1][1];
2791
+ poly yt=PARAMETRIZATIONS[m][1][2];
2792
+ int ordx=PARAMETRIZATIONS[m][2][1];
2793
+ int ordy=PARAMETRIZATIONS[m][2][2];
2794
+ map phi=BR,xt,yt,1;
2795
+ poly ht=phi(h);
2796
+ int inum=mindeg(ht);
2797
+ if ( ordx>-1 || ordy>-1 )
2798
+ {
2799
+ while (((inum>ordx||inum==-1) && ordx>-1) || ((inum>ordy||inum==-1) && ordy>-1))
2800
+ {
2801
+ BRANCHES[m]=extdevelop(BRANCHES[m],2*nr);
2802
+ nr=ncols(BRANCHES[m][1]);
2803
+ PARAMETRIZATIONS[m]=param(BRANCHES[m],0);
2804
+ xt=PARAMETRIZATIONS[m][1][1];
2805
+ yt=PARAMETRIZATIONS[m][1][2];
2806
+ ordx=PARAMETRIZATIONS[m][2][1];
2807
+ ordy=PARAMETRIZATIONS[m][2][2];
2808
+ phi=BR,xt,yt,1;
2809
+ ht=phi(h);
2810
+ inum=mindeg(ht);
2811
+ }
2812
+ }
2813
+ }
2814
+ else
2815
+ {
2816
+ int nr=ncols(BRANCH[1]);
2817
+ poly xt=PARAMETRIZATION[1][1];
2818
+ poly yt=PARAMETRIZATION[1][2];
2819
+ int ordx=PARAMETRIZATION[2][1];
2820
+ int ordy=PARAMETRIZATION[2][2];
2821
+ map phi=basering,xt,yt,1;
2822
+ poly ht=phi(h);
2823
+ int inum=mindeg(ht);
2824
+ if ( ordx>-1 || ordy>-1 )
2825
+ {
2826
+ while (((inum>ordx||inum==-1) && ordx>-1) || ((inum>ordy||inum==-1) && ordy>-1))
2827
+ {
2828
+ BRANCH=extdevelop(BRANCH,2*nr);
2829
+ nr=ncols(BRANCH[1]);
2830
+ PARAMETRIZATION=param(BRANCH,0);
2831
+ xt=PARAMETRIZATION[1][1];
2832
+ yt=PARAMETRIZATION[1][2];
2833
+ ordx=PARAMETRIZATION[2][1];
2834
+ ordy=PARAMETRIZATION[2][2];
2835
+ phi=BR,xt,yt,1;
2836
+ ht=phi(h);
2837
+ inum=mindeg(ht);
2838
+ }
2839
+ }
2840
+ }
2841
+ list answer=list();
2842
+ answer[1]=inum;
2843
+ number AA=number(coeffs(ht,t)[inum+1,1]);
2844
+ answer[2]=AA;
2845
+ return(answer);
2846
+ }
2847
+ ///////////////////////////////////////////////////////////////////////////////
2848
+ static proc extra_place (ideal P)
2849
+ {
2850
+ // computes the "rational" place which is defined over a (closed) "extra"
2851
+ // point
2852
+ // an "extra" point will be necessarily affine, non-singular and non-rational
2853
+ // creates : a specific local ring to deal with the (unique) place above it
2854
+ // returns : list with the above local ring and the degree of the point/place
2855
+ // warning : the procedure must be called inside the affine ring aff_r
2856
+ def base_r=basering;
2857
+ int ext=deg(P[1]);
2858
+ poly aux=subst(P[2],y,1);
2859
+ ext=ext*deg(aux);
2860
+ // P is assumed to be a std. resp. "(x,y),lp" and thus P[1] depends only
2861
+ // on "y"
2862
+ if (deg(P[1])==1)
2863
+ {
2864
+ // the point is non-rational but the second component needs no field
2865
+ // extension
2866
+ number B=-number(subst(P[1],y,0));
2867
+ poly aux2=subst(P[2],y,B);
2868
+ // careful : the parameter will be called "a" anyway
2869
+ ring ES=(char(basering),a),(x,y,t),ls;
2870
+ map psi=base_r,a,0;
2871
+ minpoly=number(psi(aux2));
2872
+ if (defined (psi))
2873
+ {
2874
+ kill psi;
2875
+ }
2876
+ number A=a;
2877
+ number B=imap(base_r,B);
2878
+ }
2879
+ else
2880
+ {
2881
+ if (deg(subst(P[2],y,1))==1)
2882
+ {
2883
+ // the point is non-rational but the needed minpoly is just P[1]
2884
+ // careful : the parameter will be called "a" anyway
2885
+ poly P1=P[1];
2886
+ poly P2=P[2];
2887
+ ring ES=(char(basering),a),(x,y,t),ls;
2888
+ map psi=base_r,0,a;
2889
+ minpoly=number(psi(P1));
2890
+ if (defined (psi))
2891
+ {
2892
+ kill psi;
2893
+ }
2894
+ poly aux1=imap(base_r,P2);
2895
+ poly aux2=subst(aux1,y,a);
2896
+ number A=-number(subst(aux2,x,0));
2897
+ number B=a;
2898
+ }
2899
+ else
2900
+ {
2901
+ // this is the most complicated case of non-rational point
2902
+ poly P1=P[1];
2903
+ poly P2=P[2];
2904
+ int p=char(basering);
2905
+ int Q=p^ext;
2906
+ ring aux_r=(Q,a),(x,y,t),ls;
2907
+ string minpoly_string=string(minpoly);
2908
+ ring ES=(char(basering),a),(x,y,t),ls;
2909
+ execute("minpoly="+minpoly_string+";");
2910
+ poly P_1=imap(base_r,P1);
2911
+ poly P_2=imap(base_r,P2);
2912
+ ideal factors1=factorize(P_1,1);
2913
+ number B=-number(subst(factors1[1],y,0));
2914
+ poly P_0=subst(P_2,y,B);
2915
+ ideal factors2=factorize(P_0,1);
2916
+ number A=-number(subst(factors2[1],x,0));
2917
+ kill aux_r;
2918
+ }
2919
+ }
2920
+ list POINT=list();
2921
+ POINT[1]=A;
2922
+ POINT[2]=B;
2923
+ export(POINT);
2924
+ map phi=base_r,x+A,y+B;
2925
+ poly LOC_EQ=phi(CHI);
2926
+ kill A,B,phi;
2927
+ list LLL=hnexpansion(LOC_EQ,"ess");
2928
+ if (typeof(LLL[1])=="ring") {
2929
+ def altring=basering;
2930
+ def HNEring = LLL[1];
2931
+ setring HNEring;
2932
+ def L@HNE = hne[1];
2933
+ kill hne;
2934
+ export(L@HNE);
2935
+ int m=nrows(L@HNE[1]);
2936
+ int n=ncols(L@HNE[1]);
2937
+ intvec Li2=L@HNE[2];
2938
+ int Li3=L@HNE[3];
2939
+ setring ES;
2940
+ string newa=subfield(HNEring);
2941
+ poly paux=importdatum(HNEring,"L@HNE[4]",newa);
2942
+ matrix Maux[m][n];
2943
+ int i,j;
2944
+ for (i=1;i<=m;i=i+1)
2945
+ {
2946
+ for (j=1;j<=n;j=j+1)
2947
+ {
2948
+ Maux[i,j]=importdatum(HNEring,"L@HNE[1]["+string(i)+","+
2949
+ string(j)+"]",newa);
2950
+ }
2951
+ }
2952
+ }
2953
+ else {
2954
+ def L@HNE=LLL[1][1];
2955
+ matrix Maux=L@HNE[1];
2956
+ intvec Li2=L@HNE[2];
2957
+ int Li3=L@HNE[3];
2958
+ poly paux=L@HNE[4];
2959
+ def HNEring=basering;
2960
+ setring HNEring;
2961
+ }
2962
+ kill LLL;
2963
+
2964
+ list BRANCH=list();
2965
+ BRANCH[1]=Maux;
2966
+ BRANCH[2]=Li2;
2967
+ BRANCH[3]=Li3;
2968
+ BRANCH[4]=paux;
2969
+ export(BRANCH);
2970
+ list PARAMETRIZATION=param(BRANCH,0);
2971
+ export(PARAMETRIZATION);
2972
+ kill HNEring;
2973
+ setring base_r;
2974
+ list answer=list();
2975
+ answer[1]=ES;
2976
+ answer[2]=ext;
2977
+ kill ES;
2978
+ return(answer);
2979
+ }
2980
+ ///////////////////////////////////////////////////////////////////////////////
2981
+ static proc intersection_div (poly H,list CURVE)
2982
+ "USAGE: intersection_div(H,CURVE), where H is a homogeneous polynomial
2983
+ in ring Proj_R=p,(x,y,z),lp and CURVE is the list of data for
2984
+ the given curve
2985
+ CREATE: new places which had not been computed in advance if necessary
2986
+ those places are stored each one in a local ring where you find
2987
+ lists POINT,BRANCH,PARAMETRIZATION for the place living in that
2988
+ ring; the degree of the point/place in such a ring is stored in
2989
+ an intvec, and the base points in the remaining list
2990
+ Everything is exported in a list @EXTRA@ inside the ring
2991
+ aff_r=CURVE[1][1] and returned with the updated CURVE
2992
+ RETURN: list with the intersection divisor (intvec) between the underlying
2993
+ curve and H=0, and the list CURVE updated
2994
+ SEE ALSO: Adj_div, NSplaces, closed_points
2995
+ NOTE: The procedure must be called from the ring Proj_R=CURVE[1][2]
2996
+ (projective).
2997
+ If @EXTRA@ already exists, the new places are added to the
2998
+ previous data.
2999
+ "
3000
+ {
3001
+ // computes the intersection divisor of H and the curve CHI
3002
+ // returns a list with (possibly) "extra places" and it must be called
3003
+ // inside Proj_R
3004
+ // in case of extra places, some local rings ES(1) ... ES(m) are created
3005
+ // together with an integer list "extra_dgs" containing the degrees of
3006
+ // those places
3007
+ intvec opgt=option(get);
3008
+ option(redSB);
3009
+ intvec interdiv;
3010
+ def BRing=basering;
3011
+ int Tz1=deg(H);
3012
+ list Places=CURVE[3];
3013
+ int N=size(Places);
3014
+ def aff_r=CURVE[1][1];
3015
+ setring aff_r;
3016
+ if (defined(@EXTRA@)==0)
3017
+ {
3018
+ list @EXTRA@=list();
3019
+ list EP=list();
3020
+ list ES=list();
3021
+ list extra_dgs=list();
3022
+ }
3023
+ else
3024
+ {
3025
+ list EP=@EXTRA@[1];
3026
+ list ES=@EXTRA@[2];
3027
+ list extra_dgs=@EXTRA@[3];
3028
+ }
3029
+ int NN=size(extra_dgs);
3030
+ int counterEPl=0;
3031
+ setring BRing;
3032
+ poly h=subst(H,z,1);
3033
+ int Tz2=deg(h);
3034
+ int Tz3=Tz1-Tz2;
3035
+ int i,j,k,l,m,n,s,np,NP,I_N;
3036
+ if (Tz3==0)
3037
+ {
3038
+ // if this still does not work -> try always with ALL points in
3039
+ // Inf_Points !!!!
3040
+ poly Hinf=subst(H,z,0);
3041
+ setring aff_r;
3042
+ // compute the points at infinity of H and see which of them are in
3043
+ // Inf_Points
3044
+ poly h=imap(BRing,h);
3045
+ poly hinf=imap(BRing,Hinf);
3046
+ ideal pinf=factorize(hinf,1);
3047
+ list TIP=Inf_Points[1]+Inf_Points[2];
3048
+ s=size(TIP);
3049
+ NP=size(pinf);
3050
+ for (i=1;i<=NP;i=i+1)
3051
+ {
3052
+ for (j=1;j<=s;j=j+1)
3053
+ {
3054
+ if (pinf[i]==TIP[j][1])
3055
+ {
3056
+ np=size(TIP[j][2]);
3057
+ for (k=1;k<=np;k=k+1)
3058
+ {
3059
+ n=TIP[j][2][k];
3060
+ l=Places[n][1];
3061
+ m=Places[n][2];
3062
+ def SS=CURVE[5][l][1];
3063
+ setring SS;
3064
+ // local equation h of H
3065
+ if (POINTS[m][2]==number(1))
3066
+ {
3067
+ number A=POINTS[m][1];
3068
+ map psi=BRing,x+A,1,y;
3069
+ kill A;
3070
+ }
3071
+ else
3072
+ {
3073
+ map psi=BRing,1,x,y;
3074
+ }
3075
+ poly h=psi(H);
3076
+ I_N=local_IN(h,m)[1];
3077
+ interdiv[n]=I_N;
3078
+ kill h,psi;
3079
+ setring aff_r;
3080
+ kill SS;
3081
+ }
3082
+ break;
3083
+ }
3084
+ }
3085
+ }
3086
+ kill hinf,pinf;
3087
+ }
3088
+ else
3089
+ {
3090
+ // H is a multiple of z and hence all the points in Inf_Points intersect
3091
+ // with H
3092
+ setring aff_r;
3093
+ poly h=imap(BRing,h);
3094
+ list TIP=Inf_Points[1]+Inf_Points[2];
3095
+ s=size(TIP);
3096
+ for (j=1;j<=s;j=j+1)
3097
+ {
3098
+ np=size(TIP[j][2]);
3099
+ for (k=1;k<=np;k=k+1)
3100
+ {
3101
+ n=TIP[j][2][k];
3102
+ l=Places[n][1];
3103
+ m=Places[n][2];
3104
+ def SS=CURVE[5][l][1];
3105
+ setring SS;
3106
+ // local equation h of H
3107
+ if (POINTS[m][2]==number(1))
3108
+ {
3109
+ number A=POINTS[m][1];
3110
+ map psi=BRing,x+A,1,y;
3111
+ kill A;
3112
+ }
3113
+ else
3114
+ {
3115
+ map psi=BRing,1,x,y;
3116
+ }
3117
+ poly h=psi(H);
3118
+ I_N=local_IN(h,m)[1];
3119
+ interdiv[n]=I_N;
3120
+ kill h,psi;
3121
+ setring aff_r;
3122
+ kill SS;
3123
+ }
3124
+ }
3125
+ }
3126
+ // compute common affine points of H and CHI
3127
+ ideal CAL=h,CHI;
3128
+ CAL=std(CAL);
3129
+ if (CAL<>1)
3130
+ {
3131
+ list TAP=list();
3132
+ TAP=closed_points(CAL);
3133
+ NP=size(TAP);
3134
+ list auxP=list();
3135
+ int dP;
3136
+ for (i=1;i<=NP;i=i+1)
3137
+ {
3138
+ if (belongs(TAP[i],Aff_SLocus)==1)
3139
+ {
3140
+ // search the point in the list Aff_SPoints
3141
+ j=isInLP(TAP[i],Aff_SPoints);
3142
+ np=size(Aff_SPoints[j][2]);
3143
+ for (k=1;k<=np;k=k+1)
3144
+ {
3145
+ n=Aff_SPoints[j][2][k];
3146
+ l=Places[n][1];
3147
+ m=Places[n][2];
3148
+ def SS=CURVE[5][l][1];
3149
+ setring SS;
3150
+ // local equation h of H
3151
+ number A=POINTS[m][1];
3152
+ number B=POINTS[m][2];
3153
+ map psi=BRing,x+A,y+B,1;
3154
+ poly h=psi(H);
3155
+ I_N=local_IN(h,m)[1];
3156
+ interdiv[n]=I_N;
3157
+ kill A,B,h,psi;
3158
+ setring aff_r;
3159
+ kill SS;
3160
+ }
3161
+ }
3162
+ else
3163
+ {
3164
+ auxP=list();
3165
+ auxP[1]=TAP[i];
3166
+ dP=degree_P(auxP);
3167
+ if (defined(Aff_Points(dP))<>0)
3168
+ {
3169
+ // search the point in the list Aff_Points(dP)
3170
+ j=isInLP(TAP[i],Aff_Points(dP));
3171
+ n=Aff_Points(dP)[j][2][1];
3172
+ l=Places[n][1];
3173
+ m=Places[n][2];
3174
+ def SS=CURVE[5][l][1];
3175
+ setring SS;
3176
+ // local equation h of H
3177
+ number A=POINTS[m][1];
3178
+ number B=POINTS[m][2];
3179
+ map psi=BRing,x+A,y+B,1;
3180
+ poly h=psi(H);
3181
+ I_N=local_IN(h,m)[1];
3182
+ interdiv[n]=I_N;
3183
+ kill A,B,h,psi;
3184
+ setring aff_r;
3185
+ kill SS;
3186
+ }
3187
+ else
3188
+ {
3189
+ // previously check if it is an existing "extra place"
3190
+ j=isInLP(TAP[i],EP);
3191
+ if (j>0)
3192
+ {
3193
+ def SS=ES[j];
3194
+ setring SS;
3195
+ // local equation h of H
3196
+ number A=POINT[1];
3197
+ number B=POINT[2];
3198
+ map psi=BRing,x+A,y+B,1;
3199
+ poly h=psi(H);
3200
+ I_N=local_IN(h,0)[1];
3201
+ interdiv[N+j]=I_N;
3202
+ setring aff_r;
3203
+ kill SS;
3204
+ }
3205
+ else
3206
+ {
3207
+ // then we must create a new "extra place"
3208
+ counterEPl=counterEPl+1;
3209
+ list EXTRA_PLACE=extra_place(TAP[i]);
3210
+ def SS=EXTRA_PLACE[1];
3211
+ ES[NN+counterEPl]=SS;
3212
+ extra_dgs[NN+counterEPl]=EXTRA_PLACE[2];
3213
+ EP[NN+counterEPl]=list();
3214
+ EP[NN+counterEPl][1]=TAP[i];
3215
+ EP[NN+counterEPl][2]=0;
3216
+ setring SS;
3217
+ // local equation h of H
3218
+ number A=POINT[1];
3219
+ number B=POINT[2];
3220
+ map psi=BRing,x+A,y+B,1;
3221
+ poly h=psi(H);
3222
+ I_N=local_IN(h,0)[1];
3223
+ kill A,B,h,psi;
3224
+ interdiv[N+NN+counterEPl]=I_N;
3225
+ setring aff_r;
3226
+ kill SS;
3227
+ }
3228
+ }
3229
+ }
3230
+ }
3231
+ kill TAP,auxP;
3232
+ }
3233
+ kill h,CAL,TIP;
3234
+ @EXTRA@[1]=EP;
3235
+ @EXTRA@[2]=ES;
3236
+ @EXTRA@[3]=extra_dgs;
3237
+ kill EP;
3238
+ list update_CURVE=CURVE;
3239
+ if (size(extra_dgs)>0)
3240
+ {
3241
+ export(@EXTRA@);
3242
+ update_CURVE[1][1]=basering;
3243
+ }
3244
+ else
3245
+ {
3246
+ kill @EXTRA@;
3247
+ }
3248
+ setring BRing;
3249
+ kill h;
3250
+ kill aff_r;
3251
+ list answer=list();
3252
+ answer[1]=interdiv;
3253
+ answer[2]=update_CURVE;
3254
+ option(set,opgt);
3255
+ return(answer);
3256
+ }
3257
+ ///////////////////////////////////////////////////////////////////////////////
3258
+ static proc local_eq (poly H,def SS,int m)
3259
+ {
3260
+ // computes a local equation of polynomial H in the ring SS related to the place
3261
+ // "m"
3262
+ // list POINT/POINTS is searched depending on whether m=0 or m>0 respectively
3263
+ // warning : the procedure must be called from ring "Proj_R" and returns a
3264
+ // string
3265
+ def BRing=basering;
3266
+ setring SS;
3267
+ if (m>0)
3268
+ {
3269
+ if (POINTS[m][3]==number(1))
3270
+ {
3271
+ number A=POINTS[m][1];
3272
+ number B=POINTS[m][2];
3273
+ map psi=BRing,x+A,y+B,1;
3274
+ }
3275
+ else
3276
+ {
3277
+ if (POINTS[m][2]==number(1))
3278
+ {
3279
+ number A=POINTS[m][1];
3280
+ map psi=BRing,x+A,1,y;
3281
+ }
3282
+ else
3283
+ {
3284
+ map psi=BRing,1,x,y;
3285
+ }
3286
+ }
3287
+ }
3288
+ else
3289
+ {
3290
+ number A=POINT[1];
3291
+ number B=POINT[2];
3292
+ map psi=BRing,x+A,y+B,1;
3293
+ }
3294
+ poly h=psi(H);
3295
+ string str_h=string(h);
3296
+ setring BRing;
3297
+ return(str_h);
3298
+ }
3299
+ ///////////////////////////////////////////////////////////////////////////////
3300
+ static proc min_wt_rmat (matrix M)
3301
+ {
3302
+ // finds the row of M with minimum non-zero entries, i.e. minimum
3303
+ // "Hamming-weight"
3304
+ int m=nrows(M);
3305
+ int n=ncols(M);
3306
+ int i,j;
3307
+ int Hwt=0;
3308
+ for (j=1;j<=n;j=j+1)
3309
+ {
3310
+ if (M[1,j]<>0)
3311
+ {
3312
+ Hwt=Hwt+1;
3313
+ }
3314
+ }
3315
+ int minHwt=Hwt;
3316
+ int k=1;
3317
+ for (i=2;i<=m;i=i+1)
3318
+ {
3319
+ Hwt=0;
3320
+ for (j=1;j<=n;j=j+1)
3321
+ {
3322
+ if (M[i,j]<>0)
3323
+ {
3324
+ Hwt=Hwt+1;
3325
+ }
3326
+ }
3327
+ if (Hwt<minHwt)
3328
+ {
3329
+ minHwt=Hwt;
3330
+ k=i;
3331
+ }
3332
+ }
3333
+ return(k);
3334
+ }
3335
+ ///////////////////////////////////////////////////////////////////////////////
3336
+
3337
+ // ============================================================================
3338
+ // ******* MAIN PROCEDURE : the Brill-Noether algorithm ********
3339
+ // ============================================================================
3340
+
3341
+ proc BrillNoether (intvec G,list CURVE)
3342
+ "USAGE: BrillNoether(G,CURVE); G an intvec, CURVE a list
3343
+ RETURN: list of ideals (each of them with two homogeneous generators,
3344
+ which represent the numerator, resp. denominator, of a rational
3345
+ function).@*
3346
+ The corresponding rational functions form a vector space basis of the
3347
+ linear system L(G), G a rational divisor over a non-singular curve.
3348
+ NOTE: The procedure must be called from the ring CURVE[1][2], where
3349
+ CURVE is the output of the procedure @code{NSplaces}. @*
3350
+ The intvec G represents a rational divisor supported on the closed
3351
+ places of CURVE[3] (e.g. @code{G=2,0,-1;} means 2 times the closed
3352
+ place 1 minus 1 times the closed place 3).
3353
+ SEE ALSO: Adj_div, NSplaces, Weierstrass
3354
+ EXAMPLE: example BrillNoether; shows an example
3355
+ "
3356
+ {
3357
+ // computes a vector basis for the space L(G),
3358
+ // where G is a given rational divisor over the non-singular curve
3359
+ // returns : list of ideals in R each with 2 elements H,Ho such that
3360
+ // the set of functions {H/Ho} is the searched basis
3361
+ // warning : the conductor and sufficiently many points of the plane
3362
+ // curve should be computed in advance, in list CURVE
3363
+ // the algorithm of Brill-Noether is carried out in the procedure
3364
+ def BRing=basering;
3365
+ int degX=CURVE[2][1];
3366
+ list Places=CURVE[3];
3367
+ intvec Conductor=CURVE[4];
3368
+ if (deg_D(G,Places)<0)
3369
+ {
3370
+ return(list());
3371
+ }
3372
+ intvec nuldiv;
3373
+ if (G==nuldiv)
3374
+ {
3375
+ list quickL=list();
3376
+ ideal quickId;
3377
+ quickId[1]=1;
3378
+ quickId[2]=1;
3379
+ quickL[1]=quickId;
3380
+ return(quickL);
3381
+ }
3382
+ intvec J=max_D(G,nuldiv)+Conductor;
3383
+ int n=estim_n(J,degX,Places);
3384
+ dbprint(printlevel+1,"Forms of degree "+string(n)+" : ");
3385
+ matrix W=nmultiples(n,degX,CHI);
3386
+ kill nFORMS(n-degX);
3387
+ list update_CURVE=CURVE;
3388
+ matrix V=interpolating_forms(J,n,update_CURVE);
3389
+ matrix VmW=supplement(W,V);
3390
+ int k=min_wt_rmat(VmW);
3391
+ int N=size(nFORMS(n));
3392
+ matrix H0[1][N];
3393
+ int i,j;
3394
+ for (i=1;i<=N;i=i+1) { H0[1,i]=VmW[k,i]; }
3395
+ poly Ho;
3396
+ for (i=1;i<=N;i=i+1) { Ho=Ho+(H0[1,i]*nFORMS(n)[i]); }
3397
+ list INTERD=intersection_div(Ho,update_CURVE);
3398
+ intvec NHo=INTERD[1];
3399
+ update_CURVE=INTERD[2];
3400
+ intvec AR=NHo-G;
3401
+ matrix V2=interpolating_forms(AR,n,update_CURVE);
3402
+ def aux_RING=update_CURVE[1][1];
3403
+ setring aux_RING;
3404
+ if (defined(@EXTRA@)<>0)
3405
+ {
3406
+ kill @EXTRA@;
3407
+ }
3408
+ setring BRing;
3409
+ update_CURVE[1][1]=aux_RING;
3410
+ kill aux_RING;
3411
+ matrix B0=supplement(W,V2);
3412
+ if (Hamming_wt(B0)==0)
3413
+ {
3414
+ return(list());
3415
+ }
3416
+ int ld=nrows(B0);
3417
+ list Bres=list();
3418
+ ideal HH;
3419
+ poly H;
3420
+ for (j=1;j<=ld;j=j+1)
3421
+ {
3422
+ H=0;
3423
+ for (i=1;i<=N;i=i+1)
3424
+ {
3425
+ H=H+(B0[j,i]*nFORMS(n)[i]);
3426
+ }
3427
+ HH=H,Ho;
3428
+ Bres[j]=simplifyRF(HH);
3429
+ }
3430
+ kill nFORMS(n);
3431
+ dbprint(printlevel+1," ");
3432
+ dbprint(printlevel+2,"Vector basis successfully computed ");
3433
+ dbprint(printlevel+1," ");
3434
+ return(Bres);
3435
+ }
3436
+ example
3437
+ {
3438
+ "EXAMPLE:"; echo = 2;
3439
+ int plevel=printlevel;
3440
+ printlevel=-1;
3441
+ ring s=2,(x,y),lp;
3442
+ list C=Adj_div(x3y+y3+x);
3443
+ C=NSplaces(1..4,C);
3444
+ // the first 3 Places in C[3] are of degree 1.
3445
+ // we define the rational divisor G = 4*C[3][1]+4*C[3][3] (of degree 8):
3446
+ intvec G=4,0,4;
3447
+ def R=C[1][2];
3448
+ setring R;
3449
+ list LG=BrillNoether(G,C);
3450
+ // here is the vector basis of L(G):
3451
+ LG;
3452
+ printlevel=plevel;
3453
+ }
3454
+ ///////////////////////////////////////////////////////////////////////////////
3455
+
3456
+ // *** procedures for dealing with "RATIONAL FUNCTIONS" over a plane curve ***
3457
+ // a rational function F may be given by (homogeneous) ideal or (affine) poly
3458
+ // (or number)
3459
+
3460
+ static proc polytoRF (F)
3461
+ {
3462
+ // converts a polynomial (or number) into a "rational function" of type "ideal"
3463
+ // warning : it must be called inside "R" and the polynomial is expected to be affine
3464
+ ideal RF;
3465
+ RF[1]=homog(F,z);
3466
+ RF[2]=z^(deg(F));
3467
+ return(RF);
3468
+ }
3469
+ ///////////////////////////////////////////////////////////////////////////////
3470
+ static proc simplifyRF (ideal F)
3471
+ {
3472
+ // simplifies a rational function f/g extracting the gcd(f,g)
3473
+ // maybe add a "restriction" to the curve "CHI" but it is not easy to
3474
+ // program
3475
+ poly auxp=gcd(F[1],F[2]);
3476
+ return(ideal(division(F,auxp)[1]));
3477
+ }
3478
+ ///////////////////////////////////////////////////////////////////////////////
3479
+ static proc sumRF (def F,def G)
3480
+ {
3481
+ // sum of two "rational functions" F,G given by either a pair
3482
+ // numerator/denominator or a poly
3483
+ if ( typeof(F)=="ideal" && typeof(G)=="ideal" )
3484
+ {
3485
+ ideal FG;
3486
+ FG[1]=F[1]*G[2]+F[2]*G[1];
3487
+ FG[2]=F[2]*G[2];
3488
+ return(simplifyRF(FG));
3489
+ }
3490
+ else
3491
+ {
3492
+ if (typeof(F)=="ideal")
3493
+ {
3494
+ ideal GG=polytoRF(G);
3495
+ ideal FG;
3496
+ FG[1]=F[1]*GG[2]+F[2]*GG[1];
3497
+ FG[2]=F[2]*GG[2];
3498
+ return(simplifyRF(FG));
3499
+ }
3500
+ else
3501
+ {
3502
+ if (typeof(G)=="ideal")
3503
+ {
3504
+ ideal FF=polytoRF(F);
3505
+ ideal FG;
3506
+ FG[1]=FF[1]*G[2]+FF[2]*G[1];
3507
+ FG[2]=FF[2]*G[2];
3508
+ return(simplifyRF(FG));
3509
+ }
3510
+ else
3511
+ {
3512
+ return(F+G);
3513
+ }
3514
+ }
3515
+ }
3516
+ }
3517
+ ///////////////////////////////////////////////////////////////////////////////
3518
+ static proc negRF (def F)
3519
+ {
3520
+ // returns -F as rational function
3521
+ if (typeof(F)=="ideal")
3522
+ {
3523
+ ideal FF=F;
3524
+ FF[1]=-F[1];
3525
+ return(FF);
3526
+ }
3527
+ else
3528
+ {
3529
+ return(-F);
3530
+ }
3531
+ }
3532
+ ///////////////////////////////////////////////////////////////////////////////
3533
+ static proc escprodRF (def l,def F)
3534
+ {
3535
+ // computes l*F as rational function
3536
+ // l should be either a number or a polynomial of degree zero
3537
+ if (typeof(F)=="ideal")
3538
+ {
3539
+ ideal lF=F;
3540
+ lF[1]=l*F[1];
3541
+ return(lF);
3542
+ }
3543
+ else
3544
+ {
3545
+ return(l*F);
3546
+ }
3547
+ }
3548
+ ///////////////////////////////////////////////////////////////////////////////
3549
+
3550
+ // ******** procedures to compute Weierstrass semigroups ********
3551
+
3552
+ static proc orderRF (ideal F,def SS,int m)
3553
+ "USAGE: orderRF(F,SS,m); F an ideal, SS a ring and m an integer
3554
+ RETURN: list with the order (int) and the leading coefficient (number)
3555
+ NOTE: F represents a rational function, thus the procedure must be
3556
+ called from global ring R or R(d).
3557
+ SS contains the name of a local ring where rational places are
3558
+ stored, and then we take that which is in position m in the
3559
+ corresponding lists of data.
3560
+ The order of F at the place given by SS,m is returned together
3561
+ with the coefficient of minimum degree in the corresponding power
3562
+ series.
3563
+ "
3564
+ {
3565
+ // computes the order of a rational function F at a RATIONAL place given by
3566
+ // a local ring SS and a position "m" inside SS
3567
+ // warning : the procedure must be called from global projective ring "R" or
3568
+ // "R(i)"
3569
+ // returns a list with the order (int) and the "leading coefficient" (number)
3570
+ def BR=basering;
3571
+ poly f=F[1];
3572
+ string sf=local_eq(f,SS,m);
3573
+ poly g=F[2];
3574
+ string sg=local_eq(g,SS,m);
3575
+ setring SS;
3576
+ execute("poly ff="+sf+";");
3577
+ execute("poly gg="+sg+";");
3578
+ list o1=local_IN(ff,m);
3579
+ list o2=local_IN(gg,m);
3580
+ int oo=o1[1]-o2[1];
3581
+ number lc=o1[2]/o2[2];
3582
+ setring BR;
3583
+ number LC=number(imap(SS,lc));
3584
+ return(list(oo,LC));
3585
+ }
3586
+ ///////////////////////////////////////////////////////////////////////////////
3587
+
3588
+ proc Weierstrass (int P,int m,list CURVE)
3589
+ "USAGE: Weierstrass( i, m, CURVE ); i,m integers and CURVE a list
3590
+ RETURN: list WS of two lists:
3591
+ @format
3592
+ WS[1] list of integers (Weierstr. semigroup of the curve at place i up to m)
3593
+ WS[2] list of ideals (the associated rational functions)
3594
+ @end format
3595
+ NOTE: The procedure must be called from the ring CURVE[1][2],
3596
+ where CURVE is the output of the procedure @code{NSplaces}.
3597
+ @* i represents the place CURVE[3][i].
3598
+ @* Rational functions are represented by numerator/denominator
3599
+ in form of ideals with two homogeneous generators.
3600
+ WARNING: The place must be rational, i.e., necessarily CURVE[3][i][1]=1. @*
3601
+ SEE ALSO: Adj_div, NSplaces, BrillNoether
3602
+ EXAMPLE: example Weierstrass; shows an example
3603
+ "
3604
+ {
3605
+ // computes the Weierstrass semigroup at a RATIONAL place P up to a bound "m"
3606
+ // together with the functions achieving each value up to m, via
3607
+ // Brill-Noether
3608
+ // returns 2 lists : the first consists of all the poles up to m in
3609
+ // increasing order and the second consists of the corresponding rational
3610
+ // functions
3611
+ list Places=CURVE[3];
3612
+ intvec pl=Places[P];
3613
+ int dP=pl[1];
3614
+ int nP=pl[2];
3615
+ if (dP<>1)
3616
+ {
3617
+ ERROR("the given place is not defined over the prime field");
3618
+ }
3619
+ if (m<=0)
3620
+ {
3621
+ if (m==0)
3622
+ {
3623
+ list semig=list();
3624
+ int auxint=0;
3625
+ semig[1]=auxint;
3626
+ list funcs=list();
3627
+ ideal auxF;
3628
+ auxF[1]=1;
3629
+ auxF[2]=1;
3630
+ funcs[1]=auxF;
3631
+ return(list(semig,funcs));
3632
+ }
3633
+ else
3634
+ {
3635
+ ERROR("second argument must be non-negative");
3636
+ }
3637
+ }
3638
+ int auxint=0;
3639
+ ideal auxF;
3640
+ auxF[1]=1;
3641
+ auxF[2]=1;
3642
+ // Brill-Noether algorithm
3643
+ intvec mP;
3644
+ mP[P]=m;
3645
+ list LmP=BrillNoether(mP,CURVE);
3646
+ int lmP=size(LmP);
3647
+ if (lmP==1)
3648
+ {
3649
+ list semig=list();
3650
+ semig[1]=auxint;
3651
+ list funcs=list();
3652
+ funcs[1]=auxF;
3653
+ return(list(semig,funcs));
3654
+ }
3655
+ def SS=CURVE[5][dP][1];
3656
+ list ordLmP=list();
3657
+ list polLmP=list();
3658
+ list sortpol=list();
3659
+ int maxpol;
3660
+ int i,j,k;
3661
+ for (i=1;i<=lmP-1;i=i+1)
3662
+ {
3663
+ for (j=1;j<=lmP-i+1;j=j+1)
3664
+ {
3665
+ ordLmP[j]=orderRF(LmP[j],SS,nP);
3666
+ polLmP[j]=-ordLmP[j][1];
3667
+ }
3668
+ sortpol=sort(polLmP);
3669
+ polLmP=sortpol[1];
3670
+ maxpol=polLmP[lmP-i+1];
3671
+ LmP=permute_L(LmP,sortpol[2]);
3672
+ ordLmP=permute_L(ordLmP,sortpol[2]);
3673
+ // triangulate LmP
3674
+ for (k=1;k<=lmP-i;k=k+1)
3675
+ {
3676
+ if (polLmP[lmP-i+1-k]==maxpol)
3677
+ {
3678
+ LmP[lmP-i+1-k]=sumRF(LmP[lmP-i+1-k],negRF(escprodRF(
3679
+ ordLmP[lmP-i+1-k][2]/ordLmP[lmP-i+1][2],LmP[lmP-i+1])));
3680
+ }
3681
+ else
3682
+ {
3683
+ break;
3684
+ }
3685
+ }
3686
+ }
3687
+ polLmP[1]=auxint;
3688
+ LmP[1]=auxF;
3689
+ return(list(polLmP,LmP));
3690
+ }
3691
+ example
3692
+ {
3693
+ "EXAMPLE:"; echo = 2;
3694
+ int plevel=printlevel;
3695
+ printlevel=-1;
3696
+ ring s=2,(x,y),lp;
3697
+ list C=Adj_div(x3y+y3+x);
3698
+ C=NSplaces(1..4,C);
3699
+ def R=C[1][2];
3700
+ setring R;
3701
+ // Place C[3][1] has degree 1 (i.e it is rational);
3702
+ list WS=Weierstrass(1,7,C);
3703
+ // the first part of the list is the Weierstrass semigroup up to 7 :
3704
+ WS[1];
3705
+ // and the second part are the corresponding functions :
3706
+ WS[2];
3707
+ printlevel=plevel;
3708
+ }
3709
+ ///////////////////////////////////////////////////////////////////////////////
3710
+
3711
+ // axiliary procedure for permuting a list or intvec
3712
+
3713
+ proc permute_L (def L,def P)
3714
+ "USAGE: permute_L( L, P ); L,P either intvecs or lists
3715
+ RETURN: list obtained from L by applying the permutation given by P.
3716
+ NOTE: If P is a list, all entries must be integers.
3717
+ SEE ALSO: sys_code, AGcode_Omega, prepSV
3718
+ EXAMPLE: example permute_L; shows an example
3719
+ "
3720
+ {
3721
+ // permutes the list L according to the permutation P (both intvecs or
3722
+ // lists of integers)
3723
+ int s=size(L);
3724
+ int n=size(P);
3725
+ int i;
3726
+ if (s<n)
3727
+ {
3728
+ for (i=s+1;i<=n;i=i+1)
3729
+ {
3730
+ L[i]=0;
3731
+ }
3732
+ s=size(L);
3733
+ }
3734
+ list auxL=L;
3735
+ for (i=1;i<=n;i=i+1)
3736
+ {
3737
+ auxL[i]=L[P[i]];
3738
+ }
3739
+ return(auxL);
3740
+ }
3741
+ example
3742
+ {
3743
+ "EXAMPLE:"; echo = 2;
3744
+ list L=list();
3745
+ L[1]="a";
3746
+ L[2]="b";
3747
+ L[3]="c";
3748
+ L[4]="d";
3749
+ intvec P=1,3,4,2;
3750
+ // the list L is permuted according to P :
3751
+ permute_L(L,P);
3752
+ }
3753
+ ///////////////////////////////////////////////////////////////////////////////
3754
+ static proc evalRF (ideal F,def SS,int m)
3755
+ "USAGE: evalRF(F,SS,m), where F is an ideal, SS is a ring and m is an
3756
+ integer
3757
+ RETURN: the evaluation (number) of F at the place given by SS,m if it is
3758
+ well-defined
3759
+ NOTE: F represents a rational function, thus the procedure must be
3760
+ called from R or R(d).
3761
+ SS contains the name of a local ring where rational places are
3762
+ stored, and then we take that which is in position m in the
3763
+ corresponding lists of data.
3764
+ "
3765
+ {
3766
+ // evaluates a rational function F at a RATIONAL place given by
3767
+ // a local ring SS and a position "m" inside SS
3768
+ list olc=orderRF(F,SS,m);
3769
+ int oo=olc[1];
3770
+ if (oo==0)
3771
+ {
3772
+ return(olc[2]);
3773
+ }
3774
+ else
3775
+ {
3776
+ if (oo>0)
3777
+ {
3778
+ return(number(0));
3779
+ }
3780
+ else
3781
+ {
3782
+ ERROR("the function is not well-defined at the given place");
3783
+ }
3784
+ }
3785
+ }
3786
+ ///////////////////////////////////////////////////////////////////////////////
3787
+ //
3788
+ // ******** procedures for constructing AG codes ********
3789
+ //
3790
+ ///////////////////////////////////////////////////////////////////////////////
3791
+
3792
+ static proc gen_mat (list LF,intvec LP,def RP)
3793
+ "USAGE: gen_mat(LF,LP,RP); LF list of rational functions,
3794
+ LP intvec of rational places and RP a local ring
3795
+ RETURN: a generator matrix of the evaluation code given by LF and LP
3796
+ SEE ALSO: extcurve
3797
+ KEYWORDS: evaluation codes
3798
+ NOTE: Rational places are searched in local ring RP
3799
+ The procedure must be called from R or R(d) fromlist CURVE
3800
+ after having executed extcurve(d,CURVE)
3801
+ "
3802
+ {
3803
+ // computes a generator matrix (with numbers) of the evaluation code given
3804
+ // by a list of rational functions LF and a list of RATIONAL places LP
3805
+ int m=size(LF);
3806
+ int n=size(LP);
3807
+ matrix GM[m][n];
3808
+ int i,j;
3809
+ for (i=1;i<=m;i=i+1)
3810
+ {
3811
+ for (j=1;j<=n;j=j+1)
3812
+ {
3813
+ GM[i,j]=evalRF(LF[i],RP,LP[j]);
3814
+ }
3815
+ }
3816
+ return(GM);
3817
+ }
3818
+ ///////////////////////////////////////////////////////////////////////////////
3819
+
3820
+ proc dual_code (matrix G)
3821
+ "USAGE: dual_code(G); G a matrix of numbers
3822
+ RETURN: a generator matrix of the dual code generated by G
3823
+ NOTE: The input should be a matrix G of numbers. @*
3824
+ The output is also a parity check matrix for the code defined by G
3825
+ KEYWORDS: linear code, dual
3826
+ EXAMPLE: example dual_code; shows an example
3827
+ "
3828
+ {
3829
+ // computes the dual code of C given by a generator matrix G
3830
+ // i.e. computes a parity-check matrix H of C
3831
+ // conversely : computes also G if H is given
3832
+ return(Ker(G));
3833
+ }
3834
+ example
3835
+ {
3836
+ "EXAMPLE:"; echo = 2;
3837
+ ring s=2,T,lp;
3838
+ // here is the Hamming code of length 7 and dimension 3
3839
+ matrix G[3][7]=1,0,1,0,1,0,1,0,1,1,0,0,1,1,0,0,0,1,1,1,1;
3840
+ print(G);
3841
+ matrix H=dual_code(G);
3842
+ print(H);
3843
+ }
3844
+ ///////////////////////////////////////////////////////////////////////////////
3845
+
3846
+ // ======================================================================
3847
+ // *********** initial test for disjointness ***************
3848
+ // ======================================================================
3849
+
3850
+ static proc disj_divs (intvec H,intvec P,list EC)
3851
+ {
3852
+ int s1=size(H);
3853
+ int s2=size(P);
3854
+ list PLACES=EC[3];
3855
+ def BRing=basering;
3856
+ def auxR=EC[1][5];
3857
+ setring auxR;
3858
+ int s=res_deg();
3859
+ setring BRing;
3860
+ kill auxR;
3861
+ int i,j,k,d,l,N,M;
3862
+ intvec auxIV,iw;
3863
+ for (i=1;i<=s;i=i+1)
3864
+ {
3865
+ if ( (s mod i) == 0 )
3866
+ {
3867
+ if (typeof(EC[5][i])=="list")
3868
+ {
3869
+ def auxR=EC[5][i][1];
3870
+ setring auxR;
3871
+ auxIV[i]=size(POINTS);
3872
+ setring BRing;
3873
+ kill auxR;
3874
+ }
3875
+ else
3876
+ {
3877
+ auxIV[i]=0;
3878
+ }
3879
+ }
3880
+ else
3881
+ {
3882
+ auxIV[i]=0;
3883
+ }
3884
+ }
3885
+ for (i=1;i<=s1;i=i+1)
3886
+ {
3887
+ if (H[i]<>0)
3888
+ {
3889
+ iw=PLACES[i];
3890
+ d=iw[1];
3891
+ if ( (s mod d) == 0 )
3892
+ {
3893
+ l=iw[2];
3894
+ // check that this place(s) is/are not in sup(D)
3895
+ if (d==1)
3896
+ {
3897
+ for (j=1;j<=s2;j=j+1)
3898
+ {
3899
+ if (l==P[j])
3900
+ {
3901
+ return(0);
3902
+ }
3903
+ }
3904
+ }
3905
+ else
3906
+ {
3907
+ N=0;
3908
+ for (j=1;j<d;j=j+1)
3909
+ {
3910
+ N=N+j*auxIV[j];
3911
+ }
3912
+ N=N+d*(l-1);
3913
+ M=N+d;
3914
+ for (k=N+1;k<=M;k=k+1)
3915
+ {
3916
+ for (j=1;j<=s2;j=j+1)
3917
+ {
3918
+ if (k==P[j])
3919
+ {
3920
+ return(0);
3921
+ }
3922
+ }
3923
+ }
3924
+ }
3925
+ }
3926
+ }
3927
+ }
3928
+ kill auxIV,iw;
3929
+ return(1);
3930
+ }
3931
+ ///////////////////////////////////////////////////////////////////////////////
3932
+
3933
+ proc AGcode_L (intvec G,intvec D,list EC)
3934
+ "USAGE: AGcode_L( G, D, EC ); G,D intvec, EC a list
3935
+ RETURN: a generator matrix for the evaluation AG code defined by the
3936
+ divisors G and D.
3937
+ NOTE: The procedure must be called within the ring EC[1][4],
3938
+ where EC is the output of @code{extcurve(d)} (or within
3939
+ the ring EC[1][2] if d=1). @*
3940
+ The entry i in the intvec D refers to the i-th rational
3941
+ place in EC[1][5] (i.e., to POINTS[i], etc., see @ref{extcurve}).@*
3942
+ The intvec G represents a rational divisor (see @ref{BrillNoether}
3943
+ for more details).@*
3944
+ The code evaluates the vector space basis of L(G) at the rational
3945
+ places given by D.
3946
+ WARNINGS: G should satisfy @math{ 2*genus-2 < deg(G) < size(D) }, which is
3947
+ not checked by the algorithm.
3948
+ G and D should have disjoint supports (checked by the algorithm).
3949
+ SEE ALSO: Adj_div, BrillNoether, extcurve, AGcode_Omega
3950
+ EXAMPLE: example AGcode_L; shows an example
3951
+ "
3952
+ {
3953
+ // returns a generator matrix for the evaluation AG code given by G and D
3954
+ // G must be a divisor defined over the prime field and D an intvec of
3955
+ // "rational places"
3956
+ // it must be called inside R or R(d) and requires previously "extcurve(d)"
3957
+ def BR=basering;
3958
+ if (disj_divs(G,D,EC)==0)
3959
+ {
3960
+ dbprint(printlevel+3,"? the divisors do not have disjoint supports,
3961
+ 0-matrix returned ?");
3962
+ matrix answer;
3963
+ return(answer);
3964
+ }
3965
+ if (res_deg()>1)
3966
+ {
3967
+ def R=EC[1][2];
3968
+ setring R;
3969
+ list LG=BrillNoether(G,EC);
3970
+ setring BR;
3971
+ list LG=imap(R,LG);
3972
+ setring R;
3973
+ kill LG;
3974
+ setring BR;
3975
+ kill R;
3976
+ }
3977
+ else
3978
+ {
3979
+ list LG=BrillNoether(G,EC);
3980
+ }
3981
+ def RP=EC[1][5];
3982
+ matrix M=gen_mat(LG,D,RP);
3983
+ kill LG;
3984
+ return(M);
3985
+ }
3986
+ example
3987
+ {
3988
+ "EXAMPLE:"; echo = 2;
3989
+ int plevel=printlevel;
3990
+ printlevel=-1;
3991
+ ring s=2,(x,y),lp;
3992
+ list HC=Adj_div(x3+y2+y);
3993
+ HC=NSplaces(1..2,HC);
3994
+ HC=extcurve(2,HC);
3995
+ def ER=HC[1][4];
3996
+ setring ER;
3997
+ intvec G=5; // the rational divisor G = 5*HC[3][1]
3998
+ intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4
3999
+ // let us construct the corresponding evaluation AG code :
4000
+ matrix C=AGcode_L(G,D,HC);
4001
+ // here is a linear code of type [8,5,>=3] over F_4
4002
+ print(C);
4003
+ printlevel=plevel;
4004
+ }
4005
+ ///////////////////////////////////////////////////////////////////////////////
4006
+
4007
+ proc AGcode_Omega (intvec G,intvec D,list EC)
4008
+ "USAGE: AGcode_Omega( G, D, EC ); G,D intvec, EC a list
4009
+ RETURN: a generator matrix for the residual AG code defined by the
4010
+ divisors G and D.
4011
+ NOTE: The procedure must be called within the ring EC[1][4],
4012
+ where EC is the output of @code{extcurve(d)} (or within
4013
+ the ring EC[1][2] if d=1). @*
4014
+ The entry i in the intvec D refers to the i-th rational
4015
+ place in EC[1][5] (i.e., to POINTS[i], etc., see @ref{extcurve}).@*
4016
+ The intvec G represents a rational divisor (see @ref{BrillNoether}
4017
+ for more details).@*
4018
+ The code computes the residues of a vector space basis of
4019
+ @math{\Omega(G-D)} at the rational places given by D.
4020
+ WARNINGS: G should satisfy @math{ 2*genus-2 < deg(G) < size(D) }, which is
4021
+ not checked by the algorithm.
4022
+ G and D should have disjoint supports (checked by the algorithm).
4023
+ SEE ALSO: Adj_div, BrillNoether, extcurve, AGcode_L
4024
+ EXAMPLE: example AGcode_Omega; shows an example
4025
+ "
4026
+ {
4027
+ // returns a generator matrix for the residual AG code given by G and D
4028
+ // G must be a divisor defined over the prime field and D an intvec or
4029
+ // "rational places"
4030
+ // it must be called inside R or R(d) and requires previously "extcurve(d)"
4031
+ return(dual_code(AGcode_L(G,D,EC)));
4032
+ }
4033
+ example
4034
+ {
4035
+ "EXAMPLE:"; echo = 2;
4036
+ int plevel=printlevel;
4037
+ printlevel=-1;
4038
+ ring s=2,(x,y),lp;
4039
+ list HC=Adj_div(x3+y2+y);
4040
+ HC=NSplaces(1..2,HC);
4041
+ HC=extcurve(2,HC);
4042
+ def ER=HC[1][4];
4043
+ setring ER;
4044
+ intvec G=5; // the rational divisor G = 5*HC[3][1]
4045
+ intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4
4046
+ // let us construct the corresponding residual AG code :
4047
+ matrix C=AGcode_Omega(G,D,HC);
4048
+ // here is a linear code of type [8,3,>=5] over F_4
4049
+ print(C);
4050
+ printlevel=plevel;
4051
+ }
4052
+ ///////////////////////////////////////////////////////////////////////////////
4053
+
4054
+ // ============================================================================
4055
+ // ******* auxiliary procedure to define AG codes over extensions ********
4056
+ // ============================================================================
4057
+
4058
+ proc extcurve (int d,list CURVE)
4059
+ "USAGE: extcurve( d, CURVE ); d an integer, CURVE a list
4060
+ RETURN: list L which is the update of the list CURVE with additional entries
4061
+ @format
4062
+ L[1][3]: ring (p,a),(x,y),lp (affine),
4063
+ L[1][4]: ring (p,a),(x,y,z),lp (projective),
4064
+ L[1][5]: ring (p,a),(x,y,t),ls (local),
4065
+ L[2][3]: int (the number of rational places),
4066
+ @end format
4067
+ the rings being defined over a field extension of degree d. @*
4068
+ If d<2 then @code{extcurve(d,CURVE);} creates a list L which
4069
+ is the update of the list CURVE with additional entries
4070
+ @format
4071
+ L[1][5]: ring p,(x,y,t),ls,
4072
+ L[2][3]: int (the number of computed places over the base field).
4073
+ @end format
4074
+ In both cases, in the ring L[1][5] lists with the data for all the
4075
+ computed rational places (after a field extension of degree d) are
4076
+ created (see @ref{Adj_div}):
4077
+ @format
4078
+ lists POINTS, LOC_EQS, BRANCHES, PARAMETRIZATIONS.
4079
+ @end format
4080
+ NOTE: The list CURVE should be the output of @code{NSplaces},
4081
+ and must contain (at least) one place of degree d. @*
4082
+ You actually need all the places with degree dividing d.
4083
+ Otherwise, not all the places are computed, but only part of them. @*
4084
+ This procedure must be executed before constructing AG codes,
4085
+ even if no extension is needed. The ring L[1][4] must be active
4086
+ when constructing codes over the field extension.@*
4087
+ SEE ALSO: closed_points, Adj_div, NSplaces, AGcode_L, AGcode_Omega
4088
+ EXAMPLE: example extcurve; shows an example
4089
+ "
4090
+ {
4091
+ // extends the underlying curve and all its associated objects to a larger
4092
+ // base field in order to evaluate points over such a extension
4093
+ // if d<2 then the only change is that a local ring "RatPl" (which is a
4094
+ // copy of "S(1)") is created in order to store the rational places
4095
+ // where we can do evaluations
4096
+ // otherwise, such a ring contains all places which are rational over the
4097
+ // extension
4098
+ // warning : list Places does not change so that only divisors which are
4099
+ // "rational over the prime field" are allowed; this probably will
4100
+ // change in the future
4101
+ // warning : the places in RatPl are ranged in increasing degree, respecting
4102
+ // the order from list Places and placing the conjugate branches all
4103
+ // together
4104
+ def BR=basering;
4105
+ list ext_CURVE=CURVE;
4106
+ if (d<2)
4107
+ {
4108
+ def SS=CURVE[5][1][1];
4109
+ ring RatPl=char(basering),(x,y,t),ls;
4110
+ list POINTS=imap(SS,POINTS);
4111
+ list LOC_EQS=imap(SS,LOC_EQS);
4112
+ list BRANCHES=imap(SS,BRANCHES);
4113
+ list PARAMETRIZATIONS=imap(SS,PARAMETRIZATIONS);
4114
+ export(POINTS);
4115
+ export(LOC_EQS);
4116
+ export(BRANCHES);
4117
+ export(PARAMETRIZATIONS);
4118
+ int NrRatPl=size(POINTS);
4119
+ ext_CURVE[2][3]=NrRatPl;
4120
+ setring BR;
4121
+ ext_CURVE[1][5]=RatPl;
4122
+ dbprint(printlevel+1,"");
4123
+ dbprint(printlevel+2,"Total number of rational places : "+string(NrRatPl));
4124
+ dbprint(printlevel+1,"");
4125
+ kill RatPl;
4126
+ return(ext_CURVE);
4127
+ }
4128
+ else
4129
+ {
4130
+ // exclude the case when no place of degree d was previously computed/found
4131
+ int dd=size(CURVE[5]);
4132
+ if (dd<d)
4133
+ {
4134
+ ERROR("you did not compute/find any place of degree "+string(d));
4135
+ }
4136
+ if (typeof(CURVE[5][d])<>"list")
4137
+ {
4138
+ ERROR("you did not compute/find any place of degree "+string(d));
4139
+ }
4140
+
4141
+ // Define the ring "RatPl" :
4142
+ def S(d)=CURVE[5][d][1];
4143
+ setring S(d);
4144
+ string smin=string(minpoly);
4145
+ setring BR;
4146
+ ring RatPl=(char(basering),a),(x,y,t),ls;
4147
+ execute("minpoly="+smin+";");
4148
+
4149
+ // import data from local ring S(d)
4150
+ list POINTS=imap(S(d),POINTS);
4151
+ list LOC_EQS=imap(S(d),LOC_EQS);
4152
+ list BRANCHES=imap(S(d),BRANCHES);
4153
+ list PARAMETRIZATIONS=imap(S(d),PARAMETRIZATIONS);
4154
+ kill S(d);
4155
+
4156
+ // conjugate data from S(d)
4157
+ int s=size(POINTS);
4158
+ int counter=0;
4159
+ int piv=0;
4160
+ int i,j,k;
4161
+ for (j=1;j<=s;j=j+1)
4162
+ {
4163
+ counter=counter+1;
4164
+ piv=counter;
4165
+ for (k=1;k<d;k=k+1)
4166
+ {
4167
+ POINTS=insert(POINTS,Frobenius(POINTS[piv],1),counter);
4168
+ LOC_EQS=insert(LOC_EQS,Frobenius(LOC_EQS[piv],1),counter);
4169
+ BRANCHES=insert(BRANCHES,conj_b(BRANCHES[piv],1),counter);
4170
+ PARAMETRIZATIONS=insert(PARAMETRIZATIONS,Frobenius(
4171
+ PARAMETRIZATIONS[piv],1),counter);
4172
+ counter=counter+1;
4173
+ piv=counter;
4174
+ }
4175
+ }
4176
+
4177
+ // now the same thing for smaller base fields
4178
+ string olda;
4179
+ poly paux;
4180
+ intvec iv,iw;
4181
+ int ii,jj,kk,m,n;
4182
+ for (i=d-1;i>=2;i=i-1)
4183
+ {
4184
+ if ( (d mod i)==0 )
4185
+ {
4186
+ if (typeof(CURVE[5][i])=="list")
4187
+ {
4188
+ def S(i)=CURVE[5][i][1];
4189
+ // embed S(i) inside basering == RatPl " ==S(d) "
4190
+ olda=subfield(S(i));
4191
+ setring S(i);
4192
+ s=size(POINTS);
4193
+ setring RatPl;
4194
+ // import data from S(i)
4195
+ for (j=s;j>=1;j=j-1)
4196
+ {
4197
+ counter=0;
4198
+ POINTS=insert(POINTS,list(),0);
4199
+ POINTS[1][1]=number(importdatum(S(i),"POINTS["+string(j)
4200
+ +"][1]",olda));
4201
+ POINTS[1][2]=number(importdatum(S(i),"POINTS["+string(j)
4202
+ +"][2]",olda));
4203
+ POINTS[1][3]=number(importdatum(S(i),"POINTS["+string(j)
4204
+ +"][3]",olda));
4205
+ LOC_EQS=insert(LOC_EQS,importdatum(S(i),"LOC_EQS["+string(j)
4206
+ +"]",olda),0);
4207
+ BRANCHES=insert(BRANCHES,list(),0);
4208
+ setring S(i);
4209
+ m=nrows(BRANCHES[j][1]);
4210
+ n=ncols(BRANCHES[j][1]);
4211
+ iv=BRANCHES[j][2];
4212
+ kk=BRANCHES[j][3];
4213
+ poly par@1=subst(PARAMETRIZATIONS[j][1][1],t,x);
4214
+ poly par@2=subst(PARAMETRIZATIONS[j][1][2],t,x);
4215
+ export(par@1);
4216
+ export(par@2);
4217
+ iw=PARAMETRIZATIONS[j][2];
4218
+ setring RatPl;
4219
+ paux=importdatum(S(i),"BRANCHES["+string(j)+"][4]",olda);
4220
+ matrix Maux[m][n];
4221
+ for (ii=1;ii<=m;ii=ii+1)
4222
+ {
4223
+ for (jj=1;jj<=n;jj=jj+1)
4224
+ {
4225
+ Maux[ii,jj]=importdatum(S(i),"BRANCHES["+string(j)
4226
+ +"][1]["+string(ii)+","+string(jj)+"]",olda);
4227
+ }
4228
+ }
4229
+ BRANCHES[1][1]=Maux;
4230
+ BRANCHES[1][2]=iv;
4231
+ BRANCHES[1][3]=kk;
4232
+ BRANCHES[1][4]=paux;
4233
+ kill Maux;
4234
+ PARAMETRIZATIONS=insert(PARAMETRIZATIONS,list(),0);
4235
+ PARAMETRIZATIONS[1][1]=ideal(0);
4236
+ PARAMETRIZATIONS[1][1][1]=importdatum(S(i),"par@1",olda);
4237
+ PARAMETRIZATIONS[1][1][2]=importdatum(S(i),"par@2",olda);
4238
+ PARAMETRIZATIONS[1][1][1]=subst(PARAMETRIZATIONS[1][1][1],x,t);
4239
+ PARAMETRIZATIONS[1][1][2]=subst(PARAMETRIZATIONS[1][1][2],x,t);
4240
+ PARAMETRIZATIONS[1][2]=iw;
4241
+ for (k=1;k<i;k=k+1)
4242
+ {
4243
+ counter=counter+1;
4244
+ piv=counter;
4245
+ POINTS=insert(POINTS,Frobenius(POINTS[piv],1),counter);
4246
+ LOC_EQS=insert(LOC_EQS,Frobenius(LOC_EQS[piv],1),counter);
4247
+ BRANCHES=insert(BRANCHES,conj_b(BRANCHES[piv],1),counter);
4248
+ PARAMETRIZATIONS=insert(PARAMETRIZATIONS,Frobenius(
4249
+ PARAMETRIZATIONS[piv],1),counter);
4250
+ }
4251
+ setring S(i);
4252
+ kill par@1,par@2;
4253
+ setring RatPl;
4254
+ }
4255
+ kill S(i);
4256
+ }
4257
+ }
4258
+ }
4259
+ kill iw;
4260
+ kill paux;
4261
+
4262
+ // finally add points from S(1)
4263
+ if (typeof(CURVE[5][1])=="list")
4264
+ {
4265
+ def S(1)=CURVE[5][1][1];
4266
+ POINTS=imap(S(1),POINTS)+POINTS;
4267
+ LOC_EQS=imap(S(1),LOC_EQS)+LOC_EQS;
4268
+ BRANCHES=imap(S(1),BRANCHES)+BRANCHES;
4269
+ PARAMETRIZATIONS=imap(S(1),PARAMETRIZATIONS)+PARAMETRIZATIONS;
4270
+ }
4271
+
4272
+ // prepare data for output
4273
+ export(POINTS);
4274
+ export(LOC_EQS);
4275
+ export(BRANCHES);
4276
+ export(PARAMETRIZATIONS);
4277
+ int NrRatPl=size(POINTS);
4278
+ ext_CURVE[2][3]=NrRatPl;
4279
+ setring BR;
4280
+ ext_CURVE[1][5]=RatPl;
4281
+ ring r(d)=(char(basering),a),(x,y),lp;
4282
+ execute("minpoly="+smin+";");
4283
+ setring BR;
4284
+ ext_CURVE[1][3]=r(d);
4285
+ ring R(d)=(char(basering),a),(x,y,z),lp;
4286
+ execute("minpoly="+smin+";");
4287
+ setring BR;
4288
+ ext_CURVE[1][4]=R(d);
4289
+ dbprint(printlevel+1,"");
4290
+ dbprint(printlevel+2,"Total number of rational places : NrRatPl = "
4291
+ +string(NrRatPl));
4292
+ dbprint(printlevel+1,"");
4293
+ kill S(1);
4294
+ kill R(d);
4295
+ kill RatPl;
4296
+ return(ext_CURVE);
4297
+ }
4298
+ }
4299
+ example
4300
+ {
4301
+ "EXAMPLE:"; echo = 2;
4302
+ int plevel=printlevel;
4303
+ printlevel=-1;
4304
+ ring s=2,(x,y),lp;
4305
+ list C=Adj_div(x5+y2+y);
4306
+ C=NSplaces(1..4,C);
4307
+ // since we have all points up to degree 4, we can extend the curve
4308
+ // to that extension, in order to get rational points over F_16;
4309
+ C=extcurve(4,C);
4310
+ // e.g., display the basepoint of place no. 32:
4311
+ def R=C[1][5];
4312
+ setring R;
4313
+ POINTS[32];
4314
+ printlevel=plevel;
4315
+ }
4316
+ ///////////////////////////////////////////////////////////////////////////////
4317
+
4318
+ // specific procedures for linear/AG codes
4319
+
4320
+ static proc Hamming_wt (matrix A)
4321
+ "USAGE: Hamming_wt(A), where A is any matrix
4322
+ RETURN: the Hamming weight (number of non-zero entries) of the matrix A
4323
+ "
4324
+ {
4325
+ // computes the Hamming weight (number of non-zero entries) of any matrix
4326
+ // notice that "words" are represented by matrices of size 1xn
4327
+ // computing the Hamming distance between two matrices can be done by
4328
+ // Hamming_wt(A-B)
4329
+ int m=nrows(A);
4330
+ int n=ncols(A);
4331
+ int i,j;
4332
+ int w=0;
4333
+ for (i=1;i<=m;i=i+1)
4334
+ {
4335
+ for (j=1;j<=n;j=j+1)
4336
+ {
4337
+ if (A[i,j]<>0)
4338
+ {
4339
+ w=w+1;
4340
+ }
4341
+ }
4342
+ }
4343
+ return(w);
4344
+ }
4345
+ ///////////////////////////////////////////////////////////////////////////////
4346
+
4347
+ // Basic Algorithm of Skorobogatov and Vladut for decoding AG codes
4348
+ // warning : the user must choose carefully the parameters for the code and
4349
+ // the decoding since they will never be checked by the procedures
4350
+
4351
+ proc prepSV (intvec G,intvec D,intvec F,list EC)
4352
+ "USAGE: prepSV( G, D, F, EC ); G,D,F intvecs and EC a list
4353
+ RETURN: list E of size n+3, where n=size(D). All its entries but E[n+3]
4354
+ are matrices:
4355
+ @format
4356
+ E[1]: parity check matrix for the current AG code
4357
+ E[2] ... E[n+2]: matrices used in the procedure decodeSV
4358
+ E[n+3]: intvec with
4359
+ E[n+3][1]: correction capacity @math{epsilon} of the algorithm
4360
+ E[n+3][2]: designed Goppa distance @math{delta} of the current AG code
4361
+ @end format
4362
+ NOTE: Computes the preprocessing for the basic (Skorobogatov-Vladut)
4363
+ decoding algorithm.@*
4364
+ The procedure must be called within the ring EC[1][4], where EC is
4365
+ the output of @code{extcurve(d)} (or in the ring EC[1][2] if d=1) @*
4366
+ The intvec G and F represent rational divisors (see
4367
+ @ref{BrillNoether} for more details).@*
4368
+ The intvec D refers to rational places (see @ref{AGcode_Omega}
4369
+ for more details.).
4370
+ The current AG code is @code{AGcode_Omega(G,D,EC)}.@*
4371
+ If you know the exact minimum distance d and you want to use it in
4372
+ @code{decodeSV} instead of @math{delta}, you can change the value
4373
+ of E[n+3][2] to d before applying decodeSV.
4374
+ If you have a systematic encoding for the current code and want to
4375
+ keep it during the decoding, you must previously permute D (using
4376
+ @code{permute_L(D,P);}), e.g., according to the permutation
4377
+ P=L[3], L being the output of @code{sys_code}.
4378
+ WARNINGS: F must be a divisor with support disjoint from the support of D and
4379
+ with degree @math{epsilon + genus}, where
4380
+ @math{epsilon:=[(deg(G)-3*genus+1)/2]}.@*
4381
+ G should satisfy @math{ 2*genus-2 < deg(G) < size(D) }, which is
4382
+ not checked by the algorithm.
4383
+ G and D should also have disjoint supports (checked by the
4384
+ algorithm).
4385
+ KEYWORDS: SV-decoding algorithm, preprocessing
4386
+ SEE ALSO: extcurve, AGcode_Omega, decodeSV, sys_code, permute_L
4387
+ EXAMPLE: example prepSV; shows an example
4388
+ "
4389
+ {
4390
+ if (disj_divs(F,D,EC)==0)
4391
+ {
4392
+ dbprint(printlevel+3,"? the divisors do not have disjoint supports,
4393
+ empty list returned ?");
4394
+ return(list());
4395
+ }
4396
+ list E=list();
4397
+ list Places=EC[3];
4398
+ int m=deg_D(G,Places);
4399
+ int genusX=EC[2][2];
4400
+ int e=(m+1-3*genusX) div 2;
4401
+ if (e<1)
4402
+ {
4403
+ dbprint(printlevel+3,"? the correction capacity of the basic algorithm
4404
+ is zero, empty list returned ?");
4405
+ return(list());
4406
+ }
4407
+ // deg(F)==e+genusX should be satisfied, and sup(D),sup(F) should be
4408
+ // disjoint !!!!
4409
+ int n=size(D);
4410
+ // 2*genusX-2<m<n should also be satisfied !!!!
4411
+ matrix EE=AGcode_L(G,D,EC);
4412
+ int l=nrows(EE);
4413
+ E[1]=EE;
4414
+ matrix GP=AGcode_L(F,D,EC);
4415
+ int r=nrows(GP);
4416
+ intvec H=G-F;
4417
+ matrix HP=AGcode_L(H,D,EC);
4418
+ int s=nrows(HP);
4419
+ int i,j,k;
4420
+ kill EE;
4421
+ for (k=1;k<=n;k=k+1)
4422
+ {
4423
+ E[k+1]=GP[1,k]*submat(HP,1..s,k..k);
4424
+ for (i=2;i<=r;i=i+1)
4425
+ {
4426
+ E[k+1]=concat(E[k+1],GP[i,k]*submat(HP,1..s,k..k));
4427
+ }
4428
+ }
4429
+ E[n+2]=GP;
4430
+ intvec IW=e,m+2-2*genusX;
4431
+ E[n+3]=IW;
4432
+ kill IW;
4433
+ return(E);
4434
+ }
4435
+ example
4436
+ {
4437
+ "EXAMPLE:"; echo = 2;
4438
+ int plevel=printlevel;
4439
+ printlevel=-1;
4440
+ ring s=2,(x,y),lp;
4441
+ list HC=Adj_div(x3+y2+y);
4442
+ HC=NSplaces(1..2,HC);
4443
+ HC=extcurve(2,HC);
4444
+ def ER=HC[1][4];
4445
+ setring ER;
4446
+ intvec G=5; // the rational divisor G = 5*HC[3][1]
4447
+ intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4
4448
+ // construct the corresp. residual AG code of type [8,3,>=5] over F_4:
4449
+ matrix C=AGcode_Omega(G,D,HC);
4450
+ // we can correct 1 error and the genus is 1, thus F must have degree 2
4451
+ // and support disjoint from that of D;
4452
+ intvec F=2;
4453
+ list SV=prepSV(G,D,F,HC);
4454
+ // now everything is prepared to decode with the basic algorithm;
4455
+ // for example, here is a parity check matrix to compute the syndrome :
4456
+ print(SV[1]);
4457
+ // and here you have the correction capacity of the algorithm :
4458
+ int epsilon=SV[size(D)+3][1];
4459
+ epsilon;
4460
+ printlevel=plevel;
4461
+ }
4462
+ ///////////////////////////////////////////////////////////////////////////////
4463
+
4464
+ proc decodeSV (matrix y,list K)
4465
+ "USAGE: decodeSV( y, K ); y a row-matrix and K a list
4466
+ RETURN: a codeword (row-matrix) if possible, resp. the 0-matrix (of size
4467
+ 1) if decoding is impossible.
4468
+ For decoding the basic (Skorobogatov-Vladut) decoding algorithm
4469
+ is applied.
4470
+ NOTE: The list_expression should be the output K of the procedure
4471
+ @code{prepSV}.@*
4472
+ The matrix_expression should be a (1 x n)-matrix, where
4473
+ n = ncols(K[1]).@*
4474
+ The decoding may fail if the number of errors is greater than
4475
+ the correction capacity of the algorithm.
4476
+ KEYWORDS: SV-decoding algorithm
4477
+ SEE ALSO: extcurve, AGcode_Omega, prepSV
4478
+ EXAMPLE: example decodeSV; shows an example
4479
+ "
4480
+ {
4481
+ // decodes y with the "basic decoding algorithm", if possible
4482
+ // requires the preprocessing done by the procedure "prepSV"
4483
+ // the procedure must be called from ring R or R(d)
4484
+ // returns either a codeword (matrix) of none (in case of too many errors)
4485
+ matrix syndr=K[1]*transpose(y);
4486
+ if (Hamming_wt(syndr)==0)
4487
+ {
4488
+ return(y);
4489
+ }
4490
+ matrix Ey=y[1,1]*K[2];
4491
+ int n=ncols(y);
4492
+ int i;
4493
+ for (i=2;i<=n;i=i+1)
4494
+ {
4495
+ Ey=Ey+y[1,i]*K[i+1];
4496
+ }
4497
+ matrix Ky=get_NZsol(Ey);
4498
+ if (Hamming_wt(Ky)==0)
4499
+ {
4500
+ dbprint(printlevel+3,"? no error-locator found ?");
4501
+ dbprint(printlevel+3,"? too many errors occur, 0-matrix returned ?");
4502
+ matrix answer;
4503
+ return(answer);
4504
+ }
4505
+ int r=nrows(K[n+2]);
4506
+ matrix ErrLoc[1][n];
4507
+ list Z=list();
4508
+ list NZ=list();
4509
+ int j;
4510
+ for (j=1;j<=n;j=j+1)
4511
+ {
4512
+ for (i=1;i<=r;i=i+1)
4513
+ {
4514
+ ErrLoc[1,j]=ErrLoc[1,j]+K[n+2][i,j]*Ky[1,i];
4515
+ }
4516
+ if (ErrLoc[1,j]==0)
4517
+ {
4518
+ Z=insert(Z,j,size(Z));
4519
+ }
4520
+ else
4521
+ {
4522
+ NZ=insert(NZ,j,size(NZ));
4523
+ }
4524
+ }
4525
+ int k=size(NZ);
4526
+ int l=nrows(K[1]);
4527
+ int s=l+k;
4528
+ matrix A[s][n];
4529
+ matrix b[s][1];
4530
+ for (i=1;i<=l;i=i+1)
4531
+ {
4532
+ for (j=1;j<=n;j=j+1)
4533
+ {
4534
+ A[i,j]=K[1][i,j];
4535
+ }
4536
+ b[i,1]=syndr[i,1];
4537
+ }
4538
+ for (i=1;i<=k;i=i+1)
4539
+ {
4540
+ A[l+i,NZ[i]]=number(1);
4541
+ }
4542
+ intvec opgt=option(get);
4543
+ option(redSB);
4544
+ matrix L=transpose(syz(concat(A,-b)));
4545
+ if (nrows(L)==1)
4546
+ {
4547
+ if (L[1,n+1]<>0)
4548
+ {
4549
+ poly pivote=L[1,n+1];
4550
+ matrix sol=submat(L,1..1,1..n);
4551
+ if (pivote<>1)
4552
+ {
4553
+ sol=(number(1)/number(pivote))*sol;
4554
+ }
4555
+ // check at least that the number of committed errors is less than half
4556
+ // the Goppa distance
4557
+ // imposing Hamming_wt(sol)<=K[n+3][1] would be more correct, but maybe
4558
+ // is too strong
4559
+ // on the other hand, if Hamming_wt(sol) is too large the decoding may
4560
+ // not be acceptable
4561
+ if ( Hamming_wt(sol) <= (K[n+3][2]-1) div 2 )
4562
+ {
4563
+ option(set,opgt);
4564
+ return(y-sol);
4565
+ }
4566
+ else
4567
+ {
4568
+ dbprint(printlevel+3,"? non-acceptable decoding ?");
4569
+ }
4570
+ }
4571
+ else
4572
+ {
4573
+ dbprint(printlevel+3,"? no solution found ?");
4574
+ }
4575
+ }
4576
+ else
4577
+ {
4578
+ dbprint(printlevel+3,"? non-unique solution ?");
4579
+ }
4580
+ option(set,opgt);
4581
+ dbprint(printlevel+3,"? too many errors occur, 0-matrix returned ?");
4582
+ matrix answer;
4583
+ return(answer);
4584
+ }
4585
+ example
4586
+ {
4587
+ "EXAMPLE:"; echo = 2;
4588
+ int plevel=printlevel;
4589
+ printlevel=-1;
4590
+ ring s=2,(x,y),lp;
4591
+ list HC=Adj_div(x3+y2+y);
4592
+ HC=NSplaces(1..2,HC);
4593
+ HC=extcurve(2,HC);
4594
+ def ER=HC[1][4];
4595
+ setring ER;
4596
+ intvec G=5; // the rational divisor G = 5*HC[3][1]
4597
+ intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4
4598
+ // construct the corresp. residual AG code of type [8,3,>=5] over F_4:
4599
+ matrix C=AGcode_Omega(G,D,HC);
4600
+ // we can correct 1 error and the genus is 1, thus F must have degree 2
4601
+ // and support disjoint from that of D
4602
+ intvec F=2;
4603
+ list SV=prepSV(G,D,F,HC);
4604
+ // now we produce 1 error on the zero-codeword :
4605
+ matrix y[1][8];
4606
+ y[1,3]=a;
4607
+ // and then we decode :
4608
+ print(decodeSV(y,SV));
4609
+ printlevel=plevel;
4610
+ }
4611
+ ///////////////////////////////////////////////////////////////////////////////
4612
+
4613
+ proc sys_code (matrix C)
4614
+ "USAGE: sys_code(C); C is a matrix of constants
4615
+ RETURN: list L with:
4616
+ @format
4617
+ L[1] is the generator matrix in standard form of an equivalent code,
4618
+ L[2] is the parity check matrix in standard form of such code,
4619
+ L[3] is an intvec which represents the needed permutation.
4620
+ @end format
4621
+ NOTE: Computes a systematic code which is equivalent to the given one.@*
4622
+ The input should be a matrix of numbers.@*
4623
+ The output has to be interpreted as follows: if the input was
4624
+ the generator matrix of an AG code then one should apply the
4625
+ permutation L[3] to the divisor D of rational points by means
4626
+ of @code{permute_L(D,L[3]);} before continuing to work with the
4627
+ code (for instance, if you want to use the systematic encoding
4628
+ together with a decoding algorithm).
4629
+ KEYWORDS: linear code, systematic
4630
+ SEE ALSO: permute_L, AGcode_Omega, prepSV
4631
+ EXAMPLE: example sys_code; shows an example
4632
+ "
4633
+ {
4634
+ // computes a systematic code which is equivalent to that given by C
4635
+ int i,j,k,l,h,r;
4636
+ int m=nrows(C);
4637
+ int n=ncols(C);
4638
+ int mr=m;
4639
+ matrix A[m][n]=C;
4640
+ poly c,p;
4641
+ list corners=list();
4642
+ if(m>n)
4643
+ {
4644
+ mr=n;
4645
+ }
4646
+ // first the matrix A will be reduced with elementary operations by rows
4647
+ for(i=1;i<=mr;i=i+1)
4648
+ {
4649
+ if((i+l)>n)
4650
+ {
4651
+ // the process is finished
4652
+ break;
4653
+ }
4654
+ // look for a non-zero element
4655
+ if(A[i,i+l]==0)
4656
+ {
4657
+ h=i;
4658
+ p=0;
4659
+ for (j=i+1;j<=m;j=j+1)
4660
+ {
4661
+ c=A[j,i+l];
4662
+ if (c!=0)
4663
+ {
4664
+ p=c;
4665
+ h=j;
4666
+ break;
4667
+ }
4668
+ }
4669
+ if (h!=i)
4670
+ {
4671
+ // permutation of rows i and h
4672
+ for (j=1;j<=n;j=j+1)
4673
+ {
4674
+ c=A[i,j];
4675
+ A[i,j]=A[h,j];
4676
+ A[h,j]=c;
4677
+ }
4678
+ }
4679
+ if(p==0)
4680
+ {
4681
+ // non-zero element not found in the current column
4682
+ l=l+1;
4683
+ continue;
4684
+ }
4685
+ }
4686
+ // non-zero element was found in "strategic" position
4687
+ corners[i]=i+l;
4688
+ // make zeros below that position
4689
+ for(j=i+1;j<=m;j=j+1)
4690
+ {
4691
+ c=A[j,i+l]/A[i,i+l];
4692
+ for(k=i+l+1;k<=n;k=k+1)
4693
+ {
4694
+ A[j,k]=A[j,k]-A[i,k]*c;
4695
+ }
4696
+ A[j,i+l]=0;
4697
+ A[j,i]=0;
4698
+ }
4699
+ // the rank is at least r
4700
+ // when the process stops the last r is actually the true rank of A=a
4701
+ r=i;
4702
+ }
4703
+ if (r<m)
4704
+ {
4705
+ ERROR("the given matrix does not have maximum rank");
4706
+ }
4707
+ // set the corners to the beginning and construct the permutation
4708
+ intvec PCols=1..n;
4709
+ for (j=1;j<=m;j=j+1)
4710
+ {
4711
+ if (corners[j]>j)
4712
+ {
4713
+ // interchange columns j and corners[j]
4714
+ for (i=1;i<=m;i=i+1)
4715
+ {
4716
+ c=A[i,j];
4717
+ A[i,j]=A[i,corners[j]];
4718
+ A[i,corners[j]]=c;
4719
+ }
4720
+ k=PCols[j];
4721
+ PCols[j]=PCols[corners[j]];
4722
+ PCols[corners[j]]=k;
4723
+ }
4724
+ }
4725
+ // convert the diagonal into ones
4726
+ for (i=1;i<=m;i=i+1)
4727
+ {
4728
+ for (j=i+1;j<=n;j=j+1)
4729
+ {
4730
+ A[i,j]=A[i,j]/A[i,i];
4731
+ }
4732
+ A[i,i]=1;
4733
+ }
4734
+ // complete a block with the identity matrix
4735
+ for (k=1;k<m;k=k+1)
4736
+ {
4737
+ for (i=k+1;i<=m;i=i+1)
4738
+ {
4739
+ for (j=i+1;j<=n;j=j+1)
4740
+ {
4741
+ A[k,j]=A[k,j]-A[i,j]*A[k,i];
4742
+ }
4743
+ A[k,i]=0;
4744
+ }
4745
+ }
4746
+ // compute a parity-check matrix in standard form
4747
+ matrix B=concat(-transpose(submat(A,1..m,m+1..n)),diag(1,n-m));
4748
+ list L=list();
4749
+ L[1]=A;
4750
+ L[2]=B;
4751
+ L[3]=PCols;
4752
+ return(L);
4753
+ }
4754
+ example
4755
+ {
4756
+ "EXAMPLE:"; echo = 2;
4757
+ ring s=3,T,lp;
4758
+ matrix C[2][5]=0,1,0,1,1,0,1,0,0,1;
4759
+ print(C);
4760
+ list L=sys_code(C);
4761
+ L[3];
4762
+ // here is the generator matrix in standard form
4763
+ print(L[1]);
4764
+ // here is the control matrix in standard form
4765
+ print(L[2]);
4766
+ // we can check that both codes are dual to each other
4767
+ print(L[1]*transpose(L[2]));
4768
+ }
4769
+
4770
+ ////////////// this procedure should be moved to hnoether.lib /////////
4771
+ static proc ratdevelop (poly chi)
4772
+ {
4773
+ int ring_is_changed;
4774
+ int k1=res_deg();
4775
+ list L=hnexpansion(chi,"ess");
4776
+ if (typeof(L[1])=="ring") {
4777
+ def altring=basering;
4778
+ def HNring = L[1]; setring HNring;
4779
+ def HND = hne;
4780
+ kill hne;
4781
+ ring_is_changed=1;
4782
+ }
4783
+ else {
4784
+ def HND=L[1];
4785
+ }
4786
+ int k2=res_deg();
4787
+ if (k1<k2)
4788
+ {
4789
+ int N=size(HND);
4790
+ list CB=list();
4791
+ int i,j,k,d;
4792
+ intvec dgs;
4793
+ list auxL=list();
4794
+ intvec auxiv;
4795
+ for (i=1;i<=N;i++)
4796
+ {
4797
+ CB[i]=conj_bs(HND[i],k1);
4798
+ dgs[i]=size(CB[i]);
4799
+ }
4800
+ for (i=1;i<N;i++)
4801
+ {
4802
+ for (j=i+1;j<=N;j++)
4803
+ {
4804
+ if (dgs[i]==dgs[j])
4805
+ {
4806
+ d=dgs[i];
4807
+ for (k=1;k<=d;k++)
4808
+ {
4809
+ if (intersection(CB[i][1],CB[j][k])==-1)
4810
+ {
4811
+ HND=delete(HND,j);
4812
+ CB=delete(CB,j);
4813
+ // dgs=delete(dgs,j);
4814
+ execute("auxL="+string(dgs)+";");
4815
+ auxL=delete(auxL,j);
4816
+ execute("dgs="+string(auxL)+";");
4817
+ N=N-1;
4818
+ j=j-1;
4819
+ break;
4820
+ }
4821
+ }
4822
+ }
4823
+ }
4824
+ }
4825
+ }
4826
+ if (ring_is_changed==0) { return(HND); }
4827
+ else { export HND; setring altring; return(HNring); }
4828
+ }
4829
+
4830
+
4831
+
4832
+ ///////////////////////////////////////////////////////////////////////////////
4833
+
4834
+ /*
4835
+ // ============================================================================
4836
+ // ******* ADDITIONAL INFORMATION ABOUT THE LIBRARY ********
4837
+ // ============================================================================
4838
+
4839
+ A SINGULAR library for plane curves, Weierstrass semigroups and AG codes
4840
+ Also available via http://wmatem.eis.uva.es/~ignfar/singular/
4841
+
4842
+ PREVIOUS WARNINGS :
4843
+
4844
+ (1) The procedures will work only in positive characteristic
4845
+ (2) The base field must be prime (this may change in the future)
4846
+ This limitation is not too serious, since in coding theory
4847
+ the used curves are usually (if not always) defined over a
4848
+ prime field, and extensions are only considered for
4849
+ evaluating functions in a field with many points;
4850
+ by the same reason, auxiliary divisors are usually defined
4851
+ over the prime field,
4852
+ with the exception of that consisting of "rational points"
4853
+ (3) The curve must be absolutely irreducible (but it is not checked)
4854
+ (4) Only (algebraic projective) plane curves are considered
4855
+
4856
+ GENERAL CONCEPTS :
4857
+
4858
+ (1) An affine point P is represented by a std of a prime ideal,
4859
+ and an intvec containing the position of the places above P
4860
+ in the list of Places; if the point is at infinity, the ideal is
4861
+ changed by a homogeneous irreducible polynomial in two variables
4862
+ (2) A place is represented by :
4863
+ a base point (list of homogeneous coordinates),
4864
+ a local equation for the curve at the base point,
4865
+ a Hamburger-Noether expansion of the corresponding branch,
4866
+ and a local parametrization (in "t") of such branch; everything is
4867
+ stored in a local ring "_[5][d][1]", d being the degree of the place,
4868
+ by means of lists "POINTS,LOC_EQS,BRANCHES,PARAMETRIZATIONS", and
4869
+ the degrees of the base points corresponding to the places in the
4870
+ ring "_[5][d][1]" are stored in an intvec "_[5][d][2]"
4871
+ (3) A divisor is represented by an intvec, where the integer at the
4872
+ position i means the coefficient of the i-th place in the divisor
4873
+ (4) Rational functions are represented by numerator/denominator
4874
+ in form of ideals with two homogeneous generators
4875
+
4876
+ OUTLINE/EXAMPLE OF THE USE OF THE LIBRARY :
4877
+
4878
+ Plane curves :
4879
+
4880
+ (1.0) ring s=p,(x,y[,z]),lp;
4881
+
4882
+ Notice that if you use 3 variables, then the equation
4883
+ of the curve is assumed to be a homogeneous polynomial.
4884
+
4885
+ (1.1) list CURVE=Adj_div(equation);
4886
+
4887
+ In CURVE[3] are listed all the (singular closed) places
4888
+ with their corresponding degrees; thus, you can now decide
4889
+ how many other points you want to compute with NSplaces.
4890
+
4891
+ (1.2) CURVE=NSplaces(degrees,CURVE);
4892
+
4893
+ "degrees" is an intvec with the degrees we want to compute
4894
+
4895
+ (1.3) CURVE=extcurve(extension,CURVE);
4896
+
4897
+ The rational places over the extension are ranged in
4898
+ the ring CURVE[1][5] with the following rules:
4899
+
4900
+ (i) all the representatives of the same closed point
4901
+ are listed in consecutive positions;
4902
+ (ii) if deg(P)<deg(Q), then the representatives of P
4903
+ are listed before those of Q;
4904
+ (iii) if two closed points P,Q have the same degree,
4905
+ then the representatives of P are listed before
4906
+ if P appears before in the list CURVE[3].
4907
+
4908
+ Rational functions :
4909
+
4910
+ (2.0) def R=CURVE[1][2];
4911
+ setring R;
4912
+ (2.1) list LG=BrillNoether(intvec divisor,CURVE);
4913
+ (2.2) list WS=Weierstrass(int place,int bound,CURVE);
4914
+
4915
+ Algebraic Geometry codes :
4916
+
4917
+ (3.0) def ER=CURVE[1][4]; // if extension>1; else use R instead
4918
+ setring ER;
4919
+
4920
+ Now you have to decide the divisor G and the sequence of
4921
+ rational points D to use for constructing the codes;
4922
+ first notice that the syntax for G and D is different:
4923
+
4924
+ (a) G is a divisor supported on the closed places of
4925
+ CURVE[3], and you must say just the coefficient
4926
+ of each such a point; for example, G=2,0,-1 means
4927
+ 2 times the place 1 minus 1 times the place 3.
4928
+
4929
+ (b) D is a sequence of rational points (all different
4930
+ and counted 1 time each one), whose data are read
4931
+ from the lists inside CURVE[1][5] and now you must
4932
+ say just the order how you range the chosen point;
4933
+ for example, D=2,4,1 means that you choose the
4934
+ rational places 1,2,4 and you range them as 2,4,1.
4935
+
4936
+ (3.1) matrix C=AGcode_L(divisor,places,CURVE);
4937
+
4938
+ (3.2) AGcode_Omega(divisor,places,CURVE);
4939
+
4940
+ In the same way as for defining the codes, the auxiliary
4941
+ divisor F must have disjoint support to that of D, and
4942
+ its degree has to be given by a formula (see help prepSV).
4943
+
4944
+ (3.3) list SV=prepSV(divisor,places,auxiliary_divisor,CURVE);
4945
+
4946
+ (3.4) decodeSV(word,SV);
4947
+
4948
+ Special Issues :
4949
+
4950
+ (I) AG codes with systematic encoding :
4951
+
4952
+ matrix C=AGcode_Omega(G,D,CURVE);
4953
+ list CODE=sys_code(G);
4954
+ C=CODE[1]; // generator matrix in standard form
4955
+ D=permute_L(D,CODE[3]); // suitable permutation of coordinates
4956
+ list SV=prepSV(G,D,F,CURVE);
4957
+ SV[1]=CODE[2]; // parity-check matrix in standard form
4958
+
4959
+ (II) Using the true minimum distance d for decoding :
4960
+
4961
+ matrix C=AGcode_Omega(G,D,CURVE);
4962
+ int n=size(D);
4963
+ list SV=prepSV(G,D,F,CURVE);
4964
+ SV[n+3][2]=d; // then use decodeSV(y,SV);
4965
+
4966
+
4967
+ // ============================================================================
4968
+ // *** Some "macros" with typical examples of curves in Coding Theory ****
4969
+ // ============================================================================
4970
+
4971
+
4972
+ proc Klein ()
4973
+ {
4974
+ list KLEIN=Adj_div(x3y+y3+x);
4975
+ KLEIN=NSplaces(1..3,KLEIN);
4976
+ KLEIN=extcurve(3,KLEIN);
4977
+ dbprint(printlevel+1,"Klein quartic over F_8 successfully constructed");
4978
+ return(KLEIN);
4979
+ }
4980
+
4981
+ proc Hermite (int m)
4982
+ {
4983
+ int p=char(basering);
4984
+ int r=p^m;
4985
+ list HERMITE=Adj_div(y^r+y-x^(r+1));
4986
+ HERMITE=NSplaces(1..2*m,HERMITE);
4987
+ HERMITE=extcurve(2*m,HERMITE);
4988
+ dbprint(printlevel+1,"Hermitian curve over F_("+string(r)+"^2)
4989
+ successfully constructed");
4990
+ return(HERMITE);
4991
+ }
4992
+
4993
+ proc Suzuki ()
4994
+ {
4995
+ list SUZUKI=Adj_div(x10+x3+y8+y);
4996
+ SUZUKI=NSplaces(1..3,SUZUKI);
4997
+ SUZUKI=extcurve(3,SUZUKI);
4998
+ dbprint(printlevel+1,"Suzuki curve over F_8 successfully constructed");
4999
+ return(SUZUKI);
5000
+ }
5001
+
5002
+ // **** Other interesting examples :
5003
+
5004
+ // A hyperelliptic curve with 33 rational points over F_16
5005
+
5006
+ list CURVE=Adj_div(x5+y2+y);
5007
+ CURVE=NSplaces(1..4,CURVE);
5008
+ CURVE=extcurve(4,CURVE);
5009
+
5010
+ // A nice curve with 113 rational points over F_64
5011
+
5012
+ list CURVE=Adj_div(y9+y8+xy6+x2y3+y2+x3);
5013
+ intvec ww=1,2,3,6;
5014
+ CURVE=NSplaces(ww,CURVE);
5015
+ CURVE=extcurve(6,CURVE);
5016
+
5017
+ */