passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (807) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
  3. passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
  12. sage/algebras/all__sagemath_modules.py +20 -0
  13. sage/algebras/catalog.py +148 -0
  14. sage/algebras/clifford_algebra.py +3107 -0
  15. sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  16. sage/algebras/clifford_algebra_element.pxd +16 -0
  17. sage/algebras/clifford_algebra_element.pyx +997 -0
  18. sage/algebras/commutative_dga.py +4252 -0
  19. sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
  20. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  21. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  22. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  23. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  29. sage/algebras/finite_gca.py +528 -0
  30. sage/algebras/group_algebra.py +232 -0
  31. sage/algebras/lie_algebras/abelian.py +197 -0
  32. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  33. sage/algebras/lie_algebras/all.py +25 -0
  34. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  35. sage/algebras/lie_algebras/bch.py +177 -0
  36. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  37. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  38. sage/algebras/lie_algebras/center_uea.py +767 -0
  39. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  40. sage/algebras/lie_algebras/examples.py +683 -0
  41. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  42. sage/algebras/lie_algebras/heisenberg.py +820 -0
  43. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  44. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  47. sage/algebras/lie_algebras/morphism.py +661 -0
  48. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  49. sage/algebras/lie_algebras/onsager.py +1324 -0
  50. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  51. sage/algebras/lie_algebras/quotient.py +462 -0
  52. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  53. sage/algebras/lie_algebras/representation.py +1040 -0
  54. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  55. sage/algebras/lie_algebras/subalgebra.py +967 -0
  56. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  57. sage/algebras/lie_algebras/verma_module.py +1630 -0
  58. sage/algebras/lie_algebras/virasoro.py +1186 -0
  59. sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
  60. sage/algebras/octonion_algebra.pxd +20 -0
  61. sage/algebras/octonion_algebra.pyx +987 -0
  62. sage/algebras/orlik_solomon.py +907 -0
  63. sage/algebras/orlik_terao.py +779 -0
  64. sage/algebras/steenrod/all.py +7 -0
  65. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  66. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  67. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  68. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  69. sage/algebras/weyl_algebra.py +1126 -0
  70. sage/all__sagemath_modules.py +62 -0
  71. sage/calculus/all__sagemath_modules.py +19 -0
  72. sage/calculus/expr.py +205 -0
  73. sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
  74. sage/calculus/integration.pyx +698 -0
  75. sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
  76. sage/calculus/interpolation.pxd +13 -0
  77. sage/calculus/interpolation.pyx +387 -0
  78. sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
  79. sage/calculus/interpolators.pyx +326 -0
  80. sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
  81. sage/calculus/ode.pxd +5 -0
  82. sage/calculus/ode.pyx +610 -0
  83. sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
  84. sage/calculus/riemann.pyx +1521 -0
  85. sage/calculus/test_sympy.py +201 -0
  86. sage/calculus/transforms/all.py +7 -0
  87. sage/calculus/transforms/dft.py +844 -0
  88. sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
  89. sage/calculus/transforms/dwt.pxd +7 -0
  90. sage/calculus/transforms/dwt.pyx +160 -0
  91. sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
  92. sage/calculus/transforms/fft.pxd +12 -0
  93. sage/calculus/transforms/fft.pyx +487 -0
  94. sage/calculus/wester.py +662 -0
  95. sage/coding/abstract_code.py +1108 -0
  96. sage/coding/ag_code.py +868 -0
  97. sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
  98. sage/coding/ag_code_decoders.pyx +2639 -0
  99. sage/coding/all.py +15 -0
  100. sage/coding/bch_code.py +494 -0
  101. sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
  102. sage/coding/binary_code.pxd +124 -0
  103. sage/coding/binary_code.pyx +4139 -0
  104. sage/coding/bounds_catalog.py +43 -0
  105. sage/coding/channel.py +819 -0
  106. sage/coding/channels_catalog.py +29 -0
  107. sage/coding/code_bounds.py +755 -0
  108. sage/coding/code_constructions.py +804 -0
  109. sage/coding/codes_catalog.py +111 -0
  110. sage/coding/cyclic_code.py +1329 -0
  111. sage/coding/databases.py +316 -0
  112. sage/coding/decoder.py +373 -0
  113. sage/coding/decoders_catalog.py +88 -0
  114. sage/coding/delsarte_bounds.py +709 -0
  115. sage/coding/encoder.py +390 -0
  116. sage/coding/encoders_catalog.py +64 -0
  117. sage/coding/extended_code.py +468 -0
  118. sage/coding/gabidulin_code.py +1058 -0
  119. sage/coding/golay_code.py +404 -0
  120. sage/coding/goppa_code.py +441 -0
  121. sage/coding/grs_code.py +2371 -0
  122. sage/coding/guava.py +107 -0
  123. sage/coding/guruswami_sudan/all.py +1 -0
  124. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  125. sage/coding/guruswami_sudan/interpolation.py +409 -0
  126. sage/coding/guruswami_sudan/utils.py +176 -0
  127. sage/coding/hamming_code.py +176 -0
  128. sage/coding/information_set_decoder.py +1032 -0
  129. sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
  130. sage/coding/kasami_codes.pyx +351 -0
  131. sage/coding/linear_code.py +3067 -0
  132. sage/coding/linear_code_no_metric.py +1354 -0
  133. sage/coding/linear_rank_metric.py +961 -0
  134. sage/coding/parity_check_code.py +353 -0
  135. sage/coding/punctured_code.py +719 -0
  136. sage/coding/reed_muller_code.py +999 -0
  137. sage/coding/self_dual_codes.py +942 -0
  138. sage/coding/source_coding/all.py +2 -0
  139. sage/coding/source_coding/huffman.py +553 -0
  140. sage/coding/subfield_subcode.py +423 -0
  141. sage/coding/two_weight_db.py +399 -0
  142. sage/combinat/all__sagemath_modules.py +7 -0
  143. sage/combinat/cartesian_product.py +347 -0
  144. sage/combinat/family.py +11 -0
  145. sage/combinat/free_module.py +1977 -0
  146. sage/combinat/root_system/all.py +147 -0
  147. sage/combinat/root_system/ambient_space.py +527 -0
  148. sage/combinat/root_system/associahedron.py +471 -0
  149. sage/combinat/root_system/braid_move_calculator.py +143 -0
  150. sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
  151. sage/combinat/root_system/braid_orbit.pyx +144 -0
  152. sage/combinat/root_system/branching_rules.py +2301 -0
  153. sage/combinat/root_system/cartan_matrix.py +1245 -0
  154. sage/combinat/root_system/cartan_type.py +3069 -0
  155. sage/combinat/root_system/coxeter_group.py +162 -0
  156. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  157. sage/combinat/root_system/coxeter_type.py +681 -0
  158. sage/combinat/root_system/dynkin_diagram.py +900 -0
  159. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  160. sage/combinat/root_system/fundamental_group.py +795 -0
  161. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  162. sage/combinat/root_system/integrable_representations.py +1227 -0
  163. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  164. sage/combinat/root_system/pieri_factors.py +1147 -0
  165. sage/combinat/root_system/plot.py +1615 -0
  166. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  167. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  168. sage/combinat/root_system/root_space.py +487 -0
  169. sage/combinat/root_system/root_system.py +882 -0
  170. sage/combinat/root_system/type_A.py +348 -0
  171. sage/combinat/root_system/type_A_affine.py +227 -0
  172. sage/combinat/root_system/type_A_infinity.py +241 -0
  173. sage/combinat/root_system/type_B.py +347 -0
  174. sage/combinat/root_system/type_BC_affine.py +287 -0
  175. sage/combinat/root_system/type_B_affine.py +216 -0
  176. sage/combinat/root_system/type_C.py +317 -0
  177. sage/combinat/root_system/type_C_affine.py +188 -0
  178. sage/combinat/root_system/type_D.py +357 -0
  179. sage/combinat/root_system/type_D_affine.py +208 -0
  180. sage/combinat/root_system/type_E.py +641 -0
  181. sage/combinat/root_system/type_E_affine.py +231 -0
  182. sage/combinat/root_system/type_F.py +387 -0
  183. sage/combinat/root_system/type_F_affine.py +137 -0
  184. sage/combinat/root_system/type_G.py +293 -0
  185. sage/combinat/root_system/type_G_affine.py +132 -0
  186. sage/combinat/root_system/type_H.py +105 -0
  187. sage/combinat/root_system/type_I.py +110 -0
  188. sage/combinat/root_system/type_Q.py +150 -0
  189. sage/combinat/root_system/type_affine.py +509 -0
  190. sage/combinat/root_system/type_dual.py +704 -0
  191. sage/combinat/root_system/type_folded.py +301 -0
  192. sage/combinat/root_system/type_marked.py +748 -0
  193. sage/combinat/root_system/type_reducible.py +601 -0
  194. sage/combinat/root_system/type_relabel.py +730 -0
  195. sage/combinat/root_system/type_super_A.py +837 -0
  196. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  197. sage/combinat/root_system/weight_space.py +639 -0
  198. sage/combinat/root_system/weyl_characters.py +2238 -0
  199. sage/crypto/__init__.py +4 -0
  200. sage/crypto/all.py +28 -0
  201. sage/crypto/block_cipher/all.py +7 -0
  202. sage/crypto/block_cipher/des.py +1065 -0
  203. sage/crypto/block_cipher/miniaes.py +2171 -0
  204. sage/crypto/block_cipher/present.py +909 -0
  205. sage/crypto/block_cipher/sdes.py +1527 -0
  206. sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
  207. sage/crypto/boolean_function.pxd +10 -0
  208. sage/crypto/boolean_function.pyx +1487 -0
  209. sage/crypto/cipher.py +78 -0
  210. sage/crypto/classical.py +3668 -0
  211. sage/crypto/classical_cipher.py +569 -0
  212. sage/crypto/cryptosystem.py +387 -0
  213. sage/crypto/key_exchange/all.py +7 -0
  214. sage/crypto/key_exchange/catalog.py +24 -0
  215. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  216. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  217. sage/crypto/lattice.py +312 -0
  218. sage/crypto/lfsr.py +295 -0
  219. sage/crypto/lwe.py +840 -0
  220. sage/crypto/mq/__init__.py +4 -0
  221. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  222. sage/crypto/mq/rijndael_gf.py +2345 -0
  223. sage/crypto/mq/sbox.py +7 -0
  224. sage/crypto/mq/sr.py +3344 -0
  225. sage/crypto/public_key/all.py +5 -0
  226. sage/crypto/public_key/blum_goldwasser.py +776 -0
  227. sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
  228. sage/crypto/sbox.pyx +2090 -0
  229. sage/crypto/sboxes.py +2090 -0
  230. sage/crypto/stream.py +390 -0
  231. sage/crypto/stream_cipher.py +297 -0
  232. sage/crypto/util.py +519 -0
  233. sage/ext/all__sagemath_modules.py +1 -0
  234. sage/ext/interpreters/__init__.py +1 -0
  235. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  236. sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
  237. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  238. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  239. sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
  240. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  241. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  242. sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
  243. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  244. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  245. sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
  246. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  247. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  248. sage/geometry/all__sagemath_modules.py +5 -0
  249. sage/geometry/toric_lattice.py +1745 -0
  250. sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
  251. sage/geometry/toric_lattice_element.pyx +432 -0
  252. sage/groups/abelian_gps/abelian_group.py +1925 -0
  253. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  254. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  255. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  256. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  257. sage/groups/abelian_gps/element_base.py +341 -0
  258. sage/groups/abelian_gps/values.py +488 -0
  259. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  260. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  261. sage/groups/additive_abelian/all.py +4 -0
  262. sage/groups/additive_abelian/qmodnz.py +231 -0
  263. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  264. sage/groups/affine_gps/affine_group.py +535 -0
  265. sage/groups/affine_gps/all.py +1 -0
  266. sage/groups/affine_gps/catalog.py +17 -0
  267. sage/groups/affine_gps/euclidean_group.py +246 -0
  268. sage/groups/affine_gps/group_element.py +562 -0
  269. sage/groups/all__sagemath_modules.py +12 -0
  270. sage/groups/galois_group.py +479 -0
  271. sage/groups/matrix_gps/all.py +4 -0
  272. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  273. sage/groups/matrix_gps/catalog.py +26 -0
  274. sage/groups/matrix_gps/coxeter_group.py +927 -0
  275. sage/groups/matrix_gps/finitely_generated.py +487 -0
  276. sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
  277. sage/groups/matrix_gps/group_element.pxd +11 -0
  278. sage/groups/matrix_gps/group_element.pyx +431 -0
  279. sage/groups/matrix_gps/linear.py +440 -0
  280. sage/groups/matrix_gps/matrix_group.py +617 -0
  281. sage/groups/matrix_gps/named_group.py +296 -0
  282. sage/groups/matrix_gps/orthogonal.py +544 -0
  283. sage/groups/matrix_gps/symplectic.py +251 -0
  284. sage/groups/matrix_gps/unitary.py +436 -0
  285. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  286. sage/groups/misc_gps/argument_groups.py +1905 -0
  287. sage/groups/misc_gps/imaginary_groups.py +479 -0
  288. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  289. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  293. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  296. sage/homology/algebraic_topological_model.py +595 -0
  297. sage/homology/all.py +2 -0
  298. sage/homology/all__sagemath_modules.py +8 -0
  299. sage/homology/chain_complex.py +2148 -0
  300. sage/homology/chain_complex_homspace.py +165 -0
  301. sage/homology/chain_complex_morphism.py +629 -0
  302. sage/homology/chain_homotopy.py +604 -0
  303. sage/homology/chains.py +653 -0
  304. sage/homology/free_resolution.py +923 -0
  305. sage/homology/graded_resolution.py +567 -0
  306. sage/homology/hochschild_complex.py +756 -0
  307. sage/homology/homology_group.py +188 -0
  308. sage/homology/homology_morphism.py +422 -0
  309. sage/homology/homology_vector_space_with_basis.py +1454 -0
  310. sage/homology/koszul_complex.py +169 -0
  311. sage/homology/matrix_utils.py +205 -0
  312. sage/libs/all__sagemath_modules.py +1 -0
  313. sage/libs/gsl/__init__.py +1 -0
  314. sage/libs/gsl/airy.pxd +56 -0
  315. sage/libs/gsl/all.pxd +66 -0
  316. sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
  317. sage/libs/gsl/array.pxd +5 -0
  318. sage/libs/gsl/array.pyx +102 -0
  319. sage/libs/gsl/bessel.pxd +208 -0
  320. sage/libs/gsl/blas.pxd +116 -0
  321. sage/libs/gsl/blas_types.pxd +34 -0
  322. sage/libs/gsl/block.pxd +52 -0
  323. sage/libs/gsl/chebyshev.pxd +37 -0
  324. sage/libs/gsl/clausen.pxd +12 -0
  325. sage/libs/gsl/combination.pxd +47 -0
  326. sage/libs/gsl/complex.pxd +151 -0
  327. sage/libs/gsl/coulomb.pxd +30 -0
  328. sage/libs/gsl/coupling.pxd +21 -0
  329. sage/libs/gsl/dawson.pxd +12 -0
  330. sage/libs/gsl/debye.pxd +24 -0
  331. sage/libs/gsl/dilog.pxd +14 -0
  332. sage/libs/gsl/eigen.pxd +46 -0
  333. sage/libs/gsl/elementary.pxd +12 -0
  334. sage/libs/gsl/ellint.pxd +48 -0
  335. sage/libs/gsl/elljac.pxd +8 -0
  336. sage/libs/gsl/erf.pxd +32 -0
  337. sage/libs/gsl/errno.pxd +26 -0
  338. sage/libs/gsl/exp.pxd +44 -0
  339. sage/libs/gsl/expint.pxd +44 -0
  340. sage/libs/gsl/fermi_dirac.pxd +44 -0
  341. sage/libs/gsl/fft.pxd +121 -0
  342. sage/libs/gsl/fit.pxd +50 -0
  343. sage/libs/gsl/gamma.pxd +94 -0
  344. sage/libs/gsl/gegenbauer.pxd +26 -0
  345. sage/libs/gsl/histogram.pxd +176 -0
  346. sage/libs/gsl/hyperg.pxd +52 -0
  347. sage/libs/gsl/integration.pxd +69 -0
  348. sage/libs/gsl/interp.pxd +109 -0
  349. sage/libs/gsl/laguerre.pxd +24 -0
  350. sage/libs/gsl/lambert.pxd +16 -0
  351. sage/libs/gsl/legendre.pxd +90 -0
  352. sage/libs/gsl/linalg.pxd +185 -0
  353. sage/libs/gsl/log.pxd +26 -0
  354. sage/libs/gsl/math.pxd +43 -0
  355. sage/libs/gsl/matrix.pxd +143 -0
  356. sage/libs/gsl/matrix_complex.pxd +130 -0
  357. sage/libs/gsl/min.pxd +67 -0
  358. sage/libs/gsl/monte.pxd +56 -0
  359. sage/libs/gsl/ntuple.pxd +32 -0
  360. sage/libs/gsl/odeiv.pxd +70 -0
  361. sage/libs/gsl/permutation.pxd +78 -0
  362. sage/libs/gsl/poly.pxd +40 -0
  363. sage/libs/gsl/pow_int.pxd +12 -0
  364. sage/libs/gsl/psi.pxd +28 -0
  365. sage/libs/gsl/qrng.pxd +29 -0
  366. sage/libs/gsl/random.pxd +257 -0
  367. sage/libs/gsl/rng.pxd +100 -0
  368. sage/libs/gsl/roots.pxd +72 -0
  369. sage/libs/gsl/sort.pxd +36 -0
  370. sage/libs/gsl/statistics.pxd +59 -0
  371. sage/libs/gsl/sum.pxd +55 -0
  372. sage/libs/gsl/synchrotron.pxd +16 -0
  373. sage/libs/gsl/transport.pxd +24 -0
  374. sage/libs/gsl/trig.pxd +58 -0
  375. sage/libs/gsl/types.pxd +137 -0
  376. sage/libs/gsl/vector.pxd +101 -0
  377. sage/libs/gsl/vector_complex.pxd +83 -0
  378. sage/libs/gsl/wavelet.pxd +49 -0
  379. sage/libs/gsl/zeta.pxd +28 -0
  380. sage/libs/mpc/__init__.pxd +114 -0
  381. sage/libs/mpc/types.pxd +28 -0
  382. sage/libs/mpfr/__init__.pxd +299 -0
  383. sage/libs/mpfr/types.pxd +26 -0
  384. sage/libs/mpmath/__init__.py +1 -0
  385. sage/libs/mpmath/all.py +27 -0
  386. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  387. sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
  388. sage/libs/mpmath/utils.pxd +4 -0
  389. sage/libs/mpmath/utils.pyx +319 -0
  390. sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
  391. sage/matrix/action.pxd +26 -0
  392. sage/matrix/action.pyx +596 -0
  393. sage/matrix/all.py +9 -0
  394. sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
  395. sage/matrix/args.pxd +144 -0
  396. sage/matrix/args.pyx +1668 -0
  397. sage/matrix/benchmark.py +1258 -0
  398. sage/matrix/berlekamp_massey.py +95 -0
  399. sage/matrix/compute_J_ideal.py +926 -0
  400. sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
  401. sage/matrix/constructor.pyx +750 -0
  402. sage/matrix/docs.py +430 -0
  403. sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  404. sage/matrix/echelon_matrix.pyx +155 -0
  405. sage/matrix/matrix.pxd +2 -0
  406. sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
  407. sage/matrix/matrix0.pxd +68 -0
  408. sage/matrix/matrix0.pyx +6324 -0
  409. sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
  410. sage/matrix/matrix1.pxd +8 -0
  411. sage/matrix/matrix1.pyx +2851 -0
  412. sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
  413. sage/matrix/matrix2.pxd +25 -0
  414. sage/matrix/matrix2.pyx +20181 -0
  415. sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
  416. sage/matrix/matrix_cdv.pxd +4 -0
  417. sage/matrix/matrix_cdv.pyx +93 -0
  418. sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  419. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  420. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  421. sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
  422. sage/matrix/matrix_dense.pxd +5 -0
  423. sage/matrix/matrix_dense.pyx +343 -0
  424. sage/matrix/matrix_domain_dense.pxd +5 -0
  425. sage/matrix/matrix_domain_sparse.pxd +5 -0
  426. sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  427. sage/matrix/matrix_double_dense.pxd +7 -0
  428. sage/matrix/matrix_double_dense.pyx +3906 -0
  429. sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  430. sage/matrix/matrix_double_sparse.pxd +6 -0
  431. sage/matrix/matrix_double_sparse.pyx +248 -0
  432. sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
  433. sage/matrix/matrix_generic_dense.pxd +7 -0
  434. sage/matrix/matrix_generic_dense.pyx +354 -0
  435. sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  436. sage/matrix/matrix_generic_sparse.pxd +7 -0
  437. sage/matrix/matrix_generic_sparse.pyx +461 -0
  438. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  441. sage/matrix/matrix_misc.py +313 -0
  442. sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  443. sage/matrix/matrix_numpy_dense.pxd +14 -0
  444. sage/matrix/matrix_numpy_dense.pyx +450 -0
  445. sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  446. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  447. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  448. sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  449. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  450. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  451. sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  452. sage/matrix/matrix_real_double_dense.pxd +7 -0
  453. sage/matrix/matrix_real_double_dense.pyx +122 -0
  454. sage/matrix/matrix_space.py +2848 -0
  455. sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  456. sage/matrix/matrix_sparse.pxd +5 -0
  457. sage/matrix/matrix_sparse.pyx +1222 -0
  458. sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
  459. sage/matrix/matrix_window.pxd +37 -0
  460. sage/matrix/matrix_window.pyx +242 -0
  461. sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  462. sage/matrix/misc_mpfr.pyx +80 -0
  463. sage/matrix/operation_table.py +1182 -0
  464. sage/matrix/special.py +3666 -0
  465. sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
  466. sage/matrix/strassen.pyx +851 -0
  467. sage/matrix/symplectic_basis.py +541 -0
  468. sage/matrix/template.pxd +6 -0
  469. sage/matrix/tests.py +71 -0
  470. sage/matroids/advanced.py +77 -0
  471. sage/matroids/all.py +13 -0
  472. sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  473. sage/matroids/basis_exchange_matroid.pxd +96 -0
  474. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  475. sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  476. sage/matroids/basis_matroid.pxd +45 -0
  477. sage/matroids/basis_matroid.pyx +1217 -0
  478. sage/matroids/catalog.py +44 -0
  479. sage/matroids/chow_ring.py +473 -0
  480. sage/matroids/chow_ring_ideal.py +849 -0
  481. sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  482. sage/matroids/circuit_closures_matroid.pxd +16 -0
  483. sage/matroids/circuit_closures_matroid.pyx +559 -0
  484. sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  485. sage/matroids/circuits_matroid.pxd +38 -0
  486. sage/matroids/circuits_matroid.pyx +947 -0
  487. sage/matroids/constructor.py +1086 -0
  488. sage/matroids/database_collections.py +365 -0
  489. sage/matroids/database_matroids.py +5338 -0
  490. sage/matroids/dual_matroid.py +583 -0
  491. sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
  492. sage/matroids/extension.pxd +34 -0
  493. sage/matroids/extension.pyx +519 -0
  494. sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  495. sage/matroids/flats_matroid.pxd +28 -0
  496. sage/matroids/flats_matroid.pyx +715 -0
  497. sage/matroids/gammoid.py +600 -0
  498. sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  499. sage/matroids/graphic_matroid.pxd +39 -0
  500. sage/matroids/graphic_matroid.pyx +2024 -0
  501. sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  502. sage/matroids/lean_matrix.pxd +126 -0
  503. sage/matroids/lean_matrix.pyx +3667 -0
  504. sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  505. sage/matroids/linear_matroid.pxd +180 -0
  506. sage/matroids/linear_matroid.pyx +6649 -0
  507. sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
  508. sage/matroids/matroid.pxd +243 -0
  509. sage/matroids/matroid.pyx +8759 -0
  510. sage/matroids/matroids_catalog.py +190 -0
  511. sage/matroids/matroids_plot_helpers.py +890 -0
  512. sage/matroids/minor_matroid.py +480 -0
  513. sage/matroids/minorfix.h +9 -0
  514. sage/matroids/named_matroids.py +5 -0
  515. sage/matroids/rank_matroid.py +268 -0
  516. sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
  517. sage/matroids/set_system.pxd +38 -0
  518. sage/matroids/set_system.pyx +800 -0
  519. sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  520. sage/matroids/transversal_matroid.pxd +14 -0
  521. sage/matroids/transversal_matroid.pyx +893 -0
  522. sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  523. sage/matroids/union_matroid.pxd +20 -0
  524. sage/matroids/union_matroid.pyx +331 -0
  525. sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
  526. sage/matroids/unpickling.pyx +843 -0
  527. sage/matroids/utilities.py +809 -0
  528. sage/misc/all__sagemath_modules.py +20 -0
  529. sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
  530. sage/misc/c3.pyx +238 -0
  531. sage/misc/compat.py +87 -0
  532. sage/misc/element_with_label.py +173 -0
  533. sage/misc/func_persist.py +79 -0
  534. sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
  535. sage/misc/pickle_old.pyx +19 -0
  536. sage/misc/proof.py +7 -0
  537. sage/misc/replace_dot_all.py +472 -0
  538. sage/misc/sagedoc_conf.py +168 -0
  539. sage/misc/sphinxify.py +167 -0
  540. sage/misc/test_class_pickling.py +85 -0
  541. sage/modules/all.py +42 -0
  542. sage/modules/complex_double_vector.py +25 -0
  543. sage/modules/diamond_cutting.py +380 -0
  544. sage/modules/fg_pid/all.py +1 -0
  545. sage/modules/fg_pid/fgp_element.py +456 -0
  546. sage/modules/fg_pid/fgp_module.py +2091 -0
  547. sage/modules/fg_pid/fgp_morphism.py +550 -0
  548. sage/modules/filtered_vector_space.py +1271 -0
  549. sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
  550. sage/modules/finite_submodule_iter.pxd +27 -0
  551. sage/modules/finite_submodule_iter.pyx +452 -0
  552. sage/modules/fp_graded/all.py +1 -0
  553. sage/modules/fp_graded/element.py +346 -0
  554. sage/modules/fp_graded/free_element.py +298 -0
  555. sage/modules/fp_graded/free_homspace.py +53 -0
  556. sage/modules/fp_graded/free_module.py +1060 -0
  557. sage/modules/fp_graded/free_morphism.py +217 -0
  558. sage/modules/fp_graded/homspace.py +563 -0
  559. sage/modules/fp_graded/module.py +1340 -0
  560. sage/modules/fp_graded/morphism.py +1990 -0
  561. sage/modules/fp_graded/steenrod/all.py +1 -0
  562. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  563. sage/modules/fp_graded/steenrod/module.py +477 -0
  564. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  565. sage/modules/fp_graded/steenrod/profile.py +241 -0
  566. sage/modules/free_module.py +8447 -0
  567. sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
  568. sage/modules/free_module_element.pxd +22 -0
  569. sage/modules/free_module_element.pyx +5445 -0
  570. sage/modules/free_module_homspace.py +369 -0
  571. sage/modules/free_module_integer.py +896 -0
  572. sage/modules/free_module_morphism.py +823 -0
  573. sage/modules/free_module_pseudohomspace.py +352 -0
  574. sage/modules/free_module_pseudomorphism.py +578 -0
  575. sage/modules/free_quadratic_module.py +1706 -0
  576. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  577. sage/modules/matrix_morphism.py +1745 -0
  578. sage/modules/misc.py +103 -0
  579. sage/modules/module_functors.py +192 -0
  580. sage/modules/multi_filtered_vector_space.py +719 -0
  581. sage/modules/ore_module.py +2208 -0
  582. sage/modules/ore_module_element.py +178 -0
  583. sage/modules/ore_module_homspace.py +147 -0
  584. sage/modules/ore_module_morphism.py +968 -0
  585. sage/modules/quotient_module.py +699 -0
  586. sage/modules/real_double_vector.py +22 -0
  587. sage/modules/submodule.py +255 -0
  588. sage/modules/tensor_operations.py +567 -0
  589. sage/modules/torsion_quadratic_module.py +1352 -0
  590. sage/modules/tutorial_free_modules.py +248 -0
  591. sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  592. sage/modules/vector_complex_double_dense.pxd +6 -0
  593. sage/modules/vector_complex_double_dense.pyx +117 -0
  594. sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  595. sage/modules/vector_double_dense.pxd +6 -0
  596. sage/modules/vector_double_dense.pyx +604 -0
  597. sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  598. sage/modules/vector_integer_dense.pxd +15 -0
  599. sage/modules/vector_integer_dense.pyx +361 -0
  600. sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  601. sage/modules/vector_integer_sparse.pxd +29 -0
  602. sage/modules/vector_integer_sparse.pyx +406 -0
  603. sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
  604. sage/modules/vector_modn_dense.pxd +12 -0
  605. sage/modules/vector_modn_dense.pyx +394 -0
  606. sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  607. sage/modules/vector_modn_sparse.pxd +21 -0
  608. sage/modules/vector_modn_sparse.pyx +298 -0
  609. sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  610. sage/modules/vector_numpy_dense.pxd +15 -0
  611. sage/modules/vector_numpy_dense.pyx +304 -0
  612. sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  613. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  614. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  615. sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
  616. sage/modules/vector_rational_dense.pxd +15 -0
  617. sage/modules/vector_rational_dense.pyx +387 -0
  618. sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  619. sage/modules/vector_rational_sparse.pxd +30 -0
  620. sage/modules/vector_rational_sparse.pyx +413 -0
  621. sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  622. sage/modules/vector_real_double_dense.pxd +6 -0
  623. sage/modules/vector_real_double_dense.pyx +126 -0
  624. sage/modules/vector_space_homspace.py +430 -0
  625. sage/modules/vector_space_morphism.py +989 -0
  626. sage/modules/with_basis/all.py +15 -0
  627. sage/modules/with_basis/cell_module.py +494 -0
  628. sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
  629. sage/modules/with_basis/indexed_element.pxd +13 -0
  630. sage/modules/with_basis/indexed_element.pyx +1058 -0
  631. sage/modules/with_basis/invariant.py +1075 -0
  632. sage/modules/with_basis/morphism.py +1636 -0
  633. sage/modules/with_basis/representation.py +2939 -0
  634. sage/modules/with_basis/subquotient.py +685 -0
  635. sage/numerical/all__sagemath_modules.py +6 -0
  636. sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
  637. sage/numerical/gauss_legendre.pyx +381 -0
  638. sage/numerical/optimize.py +910 -0
  639. sage/probability/all.py +10 -0
  640. sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
  641. sage/probability/probability_distribution.pyx +1242 -0
  642. sage/probability/random_variable.py +411 -0
  643. sage/quadratic_forms/all.py +4 -0
  644. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  645. sage/quadratic_forms/binary_qf.py +2042 -0
  646. sage/quadratic_forms/bqf_class_group.py +748 -0
  647. sage/quadratic_forms/constructions.py +93 -0
  648. sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
  649. sage/quadratic_forms/count_local_2.pyx +365 -0
  650. sage/quadratic_forms/extras.py +195 -0
  651. sage/quadratic_forms/quadratic_form.py +1753 -0
  652. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  653. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  654. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  656. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  657. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  658. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  659. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  660. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  661. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  662. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  663. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  664. sage/quadratic_forms/random_quadraticform.py +209 -0
  665. sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
  666. sage/quadratic_forms/ternary.pyx +1154 -0
  667. sage/quadratic_forms/ternary_qf.py +2027 -0
  668. sage/rings/all__sagemath_modules.py +28 -0
  669. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  670. sage/rings/asymptotic/misc.py +1252 -0
  671. sage/rings/cc.py +4 -0
  672. sage/rings/cfinite_sequence.py +1306 -0
  673. sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  674. sage/rings/complex_conversion.pxd +8 -0
  675. sage/rings/complex_conversion.pyx +23 -0
  676. sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
  677. sage/rings/complex_double.pxd +21 -0
  678. sage/rings/complex_double.pyx +2654 -0
  679. sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
  680. sage/rings/complex_mpc.pxd +21 -0
  681. sage/rings/complex_mpc.pyx +2576 -0
  682. sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  683. sage/rings/complex_mpfr.pxd +18 -0
  684. sage/rings/complex_mpfr.pyx +3602 -0
  685. sage/rings/derivation.py +2334 -0
  686. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  687. sage/rings/finite_rings/maps_finite_field.py +191 -0
  688. sage/rings/function_field/all__sagemath_modules.py +8 -0
  689. sage/rings/function_field/derivations.py +102 -0
  690. sage/rings/function_field/derivations_rational.py +132 -0
  691. sage/rings/function_field/differential.py +853 -0
  692. sage/rings/function_field/divisor.py +1107 -0
  693. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  694. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  695. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  696. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  697. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  698. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  699. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  700. sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
  701. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  702. sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
  703. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  704. sage/rings/invariants/all.py +4 -0
  705. sage/rings/invariants/invariant_theory.py +4597 -0
  706. sage/rings/invariants/reconstruction.py +395 -0
  707. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  708. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  709. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  712. sage/rings/polynomial/ore_function_element.py +952 -0
  713. sage/rings/polynomial/ore_function_field.py +1028 -0
  714. sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  715. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  716. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  717. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  718. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  720. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  721. sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  722. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  723. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  724. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  727. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  730. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  731. sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
  732. sage/rings/real_double_element_gsl.pxd +8 -0
  733. sage/rings/real_double_element_gsl.pyx +794 -0
  734. sage/rings/real_field.py +58 -0
  735. sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  736. sage/rings/real_mpfr.pxd +29 -0
  737. sage/rings/real_mpfr.pyx +6122 -0
  738. sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
  739. sage/rings/ring_extension.pxd +42 -0
  740. sage/rings/ring_extension.pyx +2779 -0
  741. sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  742. sage/rings/ring_extension_conversion.pxd +16 -0
  743. sage/rings/ring_extension_conversion.pyx +462 -0
  744. sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
  745. sage/rings/ring_extension_element.pxd +21 -0
  746. sage/rings/ring_extension_element.pyx +1635 -0
  747. sage/rings/ring_extension_homset.py +64 -0
  748. sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
  749. sage/rings/ring_extension_morphism.pxd +35 -0
  750. sage/rings/ring_extension_morphism.pyx +920 -0
  751. sage/schemes/all__sagemath_modules.py +1 -0
  752. sage/schemes/projective/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/coherent_sheaf.py +300 -0
  754. sage/schemes/projective/cohomology.py +510 -0
  755. sage/stats/all.py +15 -0
  756. sage/stats/basic_stats.py +489 -0
  757. sage/stats/distributions/all.py +7 -0
  758. sage/stats/distributions/catalog.py +34 -0
  759. sage/stats/distributions/dgs.h +50 -0
  760. sage/stats/distributions/dgs.pxd +111 -0
  761. sage/stats/distributions/dgs_bern.h +400 -0
  762. sage/stats/distributions/dgs_gauss.h +614 -0
  763. sage/stats/distributions/dgs_misc.h +104 -0
  764. sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
  765. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  767. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  768. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  769. sage/stats/hmm/all.py +15 -0
  770. sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
  771. sage/stats/hmm/chmm.pyx +1595 -0
  772. sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
  773. sage/stats/hmm/distributions.pxd +29 -0
  774. sage/stats/hmm/distributions.pyx +531 -0
  775. sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
  776. sage/stats/hmm/hmm.pxd +17 -0
  777. sage/stats/hmm/hmm.pyx +1388 -0
  778. sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
  779. sage/stats/hmm/util.pxd +7 -0
  780. sage/stats/hmm/util.pyx +165 -0
  781. sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
  782. sage/stats/intlist.pxd +14 -0
  783. sage/stats/intlist.pyx +588 -0
  784. sage/stats/r.py +49 -0
  785. sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
  786. sage/stats/time_series.pxd +6 -0
  787. sage/stats/time_series.pyx +2546 -0
  788. sage/tensor/all.py +2 -0
  789. sage/tensor/modules/all.py +8 -0
  790. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  791. sage/tensor/modules/comp.py +5598 -0
  792. sage/tensor/modules/ext_pow_free_module.py +824 -0
  793. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  794. sage/tensor/modules/format_utilities.py +333 -0
  795. sage/tensor/modules/free_module_alt_form.py +858 -0
  796. sage/tensor/modules/free_module_automorphism.py +1207 -0
  797. sage/tensor/modules/free_module_basis.py +1074 -0
  798. sage/tensor/modules/free_module_element.py +284 -0
  799. sage/tensor/modules/free_module_homset.py +652 -0
  800. sage/tensor/modules/free_module_linear_group.py +564 -0
  801. sage/tensor/modules/free_module_morphism.py +1581 -0
  802. sage/tensor/modules/free_module_tensor.py +3289 -0
  803. sage/tensor/modules/reflexive_module.py +386 -0
  804. sage/tensor/modules/tensor_free_module.py +780 -0
  805. sage/tensor/modules/tensor_free_submodule.py +538 -0
  806. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  807. sage/tensor/modules/tensor_with_indices.py +1043 -0
@@ -0,0 +1,4139 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ # sage.doctest: needs sage.modules sage.rings.finite_rings
3
+ r"""
4
+ Optimized low-level binary code representation
5
+
6
+ Some computations with linear binary codes. Fix a basis for `\GF{2}^n`.
7
+ A linear binary code is a linear subspace of `\GF{2}^n`, together with
8
+ this choice of basis. A permutation `g \in S_n` of the fixed basis
9
+ gives rise to a permutation of the vectors, or words, in `\GF{2}^n`,
10
+ sending `(w_i)` to `(w_{g(i)})`. The permutation automorphism group of
11
+ the code `C` is the set of permutations of the basis that bijectively
12
+ map `C` to itself. Note that if `g` is such a permutation, then
13
+
14
+ .. MATH::
15
+
16
+ g(a_i) + g(b_i) = (a_{g(i)} + b_{g(i)}) = g((a_i) + (b_i)).
17
+
18
+ Over other fields, it is also required that the map be linear, which
19
+ as per above boils down to scalar multiplication. However, over
20
+ `\GF{2},` the only scalars are 0 and 1, so the linearity condition has
21
+ trivial effect.
22
+
23
+ AUTHOR:
24
+
25
+ - Robert L Miller (Oct-Nov 2007)
26
+
27
+ * compiled code data structure
28
+ * union-find based orbit partition
29
+ * optimized partition stack class
30
+ * NICE-based partition refinement algorithm
31
+ * canonical generation function
32
+ """
33
+
34
+ # ***************************************************************************
35
+ # Copyright (C) 2007 Robert L. Miller <rlmillster@gmail.com>
36
+ #
37
+ # This program is free software: you can redistribute it and/or modify
38
+ # it under the terms of the GNU General Public License as published by
39
+ # the Free Software Foundation, either version 2 of the License, or
40
+ # (at your option) any later version.
41
+ # https://www.gnu.org/licenses/
42
+ # ***************************************************************************
43
+
44
+ from libc.string cimport memcpy
45
+ from cpython.mem cimport *
46
+ from cpython.object cimport PyObject_RichCompare
47
+ from cysignals.memory cimport sig_malloc, sig_free
48
+
49
+ from sage.structure.element cimport Matrix
50
+ from sage.misc.timing import cputime
51
+ from sage.rings.integer cimport Integer
52
+ from copy import copy
53
+ from sage.data_structures.bitset_base cimport *
54
+
55
+ WORD_SIZE = sizeof(codeword) << 3
56
+
57
+ cdef enum:
58
+ chunk_size = 8
59
+
60
+ cdef inline int min(int a, int b) noexcept:
61
+ if a > b:
62
+ return b
63
+ else:
64
+ return a
65
+
66
+ # NOTE - Since most of the functions are used from within the module, cdef'd
67
+ # functions come without an underscore, and the def'd equivalents, which are
68
+ # essentially only for doctesting and debugging, have underscores.
69
+
70
+ cdef int *hamming_weights() noexcept:
71
+ cdef int *ham_wts
72
+ cdef int i
73
+ ham_wts = <int *> sig_malloc(65536 * sizeof(int))
74
+ if ham_wts is NULL:
75
+ sig_free(ham_wts)
76
+ raise MemoryError("Memory.")
77
+ ham_wts[0] = 0
78
+ ham_wts[1] = 1
79
+ ham_wts[2] = 1
80
+ ham_wts[3] = 2
81
+ for i from 4 <= i < 16:
82
+ ham_wts[i] = ham_wts[i & 3] + ham_wts[(i>>2) & 3]
83
+ for i from 16 <= i < 256:
84
+ ham_wts[i] = ham_wts[i & 15] + ham_wts[(i>>4) & 15]
85
+ for i from 256 <= i < 65536:
86
+ ham_wts[i] = ham_wts[i & 255] + ham_wts[(i>>8) & 255]
87
+ return ham_wts
88
+
89
+
90
+ def weight_dist(M):
91
+ """
92
+ Compute the weight distribution of the row space of `M`.
93
+
94
+ EXAMPLES::
95
+
96
+ sage: from sage.coding.binary_code import weight_dist
97
+ sage: M = Matrix(GF(2), [
98
+ ....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0],
99
+ ....: [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
100
+ ....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
101
+ ....: [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
102
+ ....: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]])
103
+ sage: weight_dist(M)
104
+ [1, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1]
105
+ sage: M = Matrix(GF(2), [
106
+ ....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
107
+ ....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],
108
+ ....: [0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1],
109
+ ....: [0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1]])
110
+ sage: weight_dist(M)
111
+ [1, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 0, 0]
112
+ sage: M = Matrix(GF(2), [
113
+ ....: [1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
114
+ ....: [0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0],
115
+ ....: [0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0],
116
+ ....: [0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0],
117
+ ....: [0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0],
118
+ ....: [0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0],
119
+ ....: [0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0],
120
+ ....: [0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1]])
121
+ sage: weight_dist(M)
122
+ [1, 0, 0, 0, 0, 0, 68, 0, 85, 0, 68, 0, 34, 0, 0, 0, 0, 0]
123
+ """
124
+ cdef bitset_t word
125
+ cdef int i,j,k, dim=M.nrows(), deg=M.ncols()
126
+ cdef list L
127
+ cdef MemoryAllocator mem = MemoryAllocator()
128
+ cdef int *LL = <int *> mem.malloc((deg+1) * sizeof(int))
129
+ cdef bitset_s *basis = <bitset_s *> mem.malloc(dim * sizeof(bitset_s))
130
+ for i from 0 <= i < dim:
131
+ bitset_init(&basis[i], deg)
132
+ bitset_zero(&basis[i])
133
+ for j in M.row(i).nonzero_positions():
134
+ bitset_set(&basis[i], j)
135
+ for i in range(deg + 1):
136
+ LL[i] = 0
137
+ bitset_init(word, deg)
138
+ bitset_zero(word)
139
+ i = 0
140
+ j = 0
141
+ while True:
142
+ LL[bitset_hamming_weight(word)] += 1
143
+ i ^= 1
144
+ k = 0
145
+ if not i:
146
+ while not j & (1 << k):
147
+ k += 1
148
+ k += 1
149
+ if k == dim:
150
+ break
151
+ j ^= (1 << k)
152
+ bitset_xor(word, word, &basis[k])
153
+ bitset_free(word)
154
+ L = [int(LL[i]) for i from 0 <= i < deg+1]
155
+ for i from 0 <= i < dim:
156
+ bitset_free(&basis[i])
157
+ return L
158
+
159
+
160
+ def test_word_perms(t_limit=5.0):
161
+ r"""
162
+ Test the :class:`WordPermutation` structs for at least ``t_limit`` seconds.
163
+
164
+ These are structures written in pure C for speed, and are tested from this
165
+ function, which performs the following tests:
166
+
167
+ 1. Tests :func:`create_word_perm`, which creates a :class:`WordPermutation`
168
+ from a Python list `L` representing a permutation `i \mapsto
169
+ L[i]`. Takes a random word and permutes it by a random list permutation,
170
+ and tests that the result agrees with doing it the slow way.
171
+
172
+ 1b. Tests :func:`create_array_word_perm`, which creates a
173
+ :class:`WordPermutation` from a C array. Does the same as above.
174
+
175
+ 2. Tests :func:`create_comp_word_perm`, which creates a
176
+ :class:`WordPermutation` as a composition of two
177
+ :class:`WordPermutation` objects. Takes a random word and two random
178
+ permutations, and tests that the result of permuting by the composition
179
+ is correct.
180
+
181
+ 3. Tests :func:`create_inv_word_perm` and :func:`create_id_word_perm`,
182
+ which create a :class:`WordPermutation` as the inverse and identity
183
+ permutations, resp. Takes a random word and a random permutation, and
184
+ tests that the result permuting by the permutation and its inverse in
185
+ either order, and permuting by the identity both return the original
186
+ word.
187
+
188
+ .. NOTE::
189
+
190
+ The functions :func:`permute_word_by_wp` and :func:`dealloc_word_perm`
191
+ are implicitly involved in each of the above tests.
192
+
193
+ TESTS::
194
+
195
+ sage: from sage.coding.binary_code import test_word_perms
196
+ sage: test_word_perms() # long time (5s on sage.math, 2011)
197
+ """
198
+ cdef WordPermutation *g
199
+ cdef WordPermutation *h
200
+ cdef WordPermutation *i
201
+ cdef codeword cw1, cw2, cw3
202
+ cdef int n = sizeof(codeword) << 3
203
+ cdef int j
204
+ cdef int *arr = <int*> sig_malloc(n * sizeof(int))
205
+ if arr is NULL:
206
+ raise MemoryError("Error allocating memory.")
207
+ from sage.misc.prandom import randint
208
+ from sage.combinat.permutation import Permutations
209
+ S = Permutations(list(range(n)))
210
+ t = cputime()
211
+ while cputime(t) < t_limit:
212
+ word = [randint(0, 1) for _ in range(n)]
213
+ cw1 = 0
214
+ for j from 0 <= j < n:
215
+ cw1 += (<codeword>word[j]) << (<codeword>j)
216
+ # 1. test create_word_perm
217
+ gg = S.random_element()
218
+ g = create_word_perm(gg)
219
+ word2 = [0]*n
220
+ for j from 0 <= j < n:
221
+ word2[gg[j]] = word[j]
222
+ cw2 = permute_word_by_wp(g, cw1)
223
+ cw3 = 0
224
+ for j from 0 <= j < n:
225
+ cw3 += (<codeword>word2[j]) << (<codeword>j)
226
+ if cw3 != cw2:
227
+ print("ERROR1")
228
+ dealloc_word_perm(g)
229
+ # 1b. test create_array_word_perm
230
+ gg = S.random_element()
231
+ for j from 0 <= j < n:
232
+ arr[j] = gg[j]
233
+ g = create_array_word_perm(arr, 0, n)
234
+ word2 = [0]*n
235
+ for j from 0 <= j < n:
236
+ word2[gg[j]] = word[j]
237
+ cw2 = permute_word_by_wp(g, cw1)
238
+ cw3 = 0
239
+ for j from 0 <= j < n:
240
+ cw3 += (<codeword>word2[j]) << (<codeword>j)
241
+ if cw3 != cw2:
242
+ print("ERROR1b")
243
+ dealloc_word_perm(g)
244
+ # 2. test create_comp_word_perm
245
+ gg = S.random_element()
246
+ hh = S.random_element()
247
+ g = create_word_perm(gg)
248
+ h = create_word_perm(hh)
249
+ i = create_comp_word_perm(g, h)
250
+ word2 = [0]*n
251
+ for j from 0 <= j < n:
252
+ word2[gg[hh[j]]] = word[j]
253
+ cw2 = permute_word_by_wp(i, cw1)
254
+ cw3 = 0
255
+ for j from 0 <= j < n:
256
+ cw3 += (<codeword>word2[j]) << (<codeword>j)
257
+ if cw3 != cw2:
258
+ print("ERROR2")
259
+ dealloc_word_perm(g)
260
+ dealloc_word_perm(h)
261
+ dealloc_word_perm(i)
262
+ # 3. test create_inv_word_perm and create_id_word_perm
263
+ gg = S.random_element()
264
+ g = create_word_perm(gg)
265
+ h = create_inv_word_perm(g)
266
+ i = create_id_word_perm(n)
267
+ cw2 = permute_word_by_wp(g, cw1)
268
+ cw2 = permute_word_by_wp(h, cw2)
269
+ if cw1 != cw2:
270
+ print("ERROR3a")
271
+ cw2 = permute_word_by_wp(h, cw1)
272
+ cw2 = permute_word_by_wp(g, cw2)
273
+ if cw1 != cw2:
274
+ print("ERROR3b")
275
+ cw2 = permute_word_by_wp(i, cw1)
276
+ if cw1 != cw2:
277
+ print("ERROR3c")
278
+ dealloc_word_perm(g)
279
+ dealloc_word_perm(h)
280
+ dealloc_word_perm(i)
281
+ sig_free(arr)
282
+
283
+
284
+ cdef WordPermutation *create_word_perm(object list_perm) noexcept:
285
+ r"""
286
+ Create a word permutation from a Python list permutation L, i.e. such that
287
+ `i \mapsto L[i]`.
288
+ """
289
+ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
290
+ cdef codeword *images_i
291
+ cdef codeword image
292
+ cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
293
+ if word_perm is NULL:
294
+ raise RuntimeError("Error allocating memory.")
295
+ word_perm.degree = len(list_perm)
296
+ list_perm = copy(list_perm)
297
+ while num_chunks*chunk_size < word_perm.degree:
298
+ num_chunks += 1
299
+ word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
300
+ if word_perm.images is NULL:
301
+ sig_free(word_perm)
302
+ raise RuntimeError("Error allocating memory.")
303
+ word_perm.chunk_num = num_chunks
304
+ words_per_chunk = 1 << chunk_size
305
+ word_perm.gate = ((<codeword>1) << chunk_size) - 1
306
+ list_perm += list(range(len(list_perm), chunk_size*num_chunks))
307
+ word_perm.chunk_words = words_per_chunk
308
+ for i from 0 <= i < num_chunks:
309
+ images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
310
+ if images_i is NULL:
311
+ for j from 0 <= j < i:
312
+ sig_free(word_perm.images[j])
313
+ sig_free(word_perm.images)
314
+ sig_free(word_perm)
315
+ raise RuntimeError("Error allocating memory.")
316
+ word_perm.images[i] = images_i
317
+ for j from 0 <= j < chunk_size:
318
+ images_i[1 << j] = (<codeword>1) << list_perm[chunk_size*i + j]
319
+ image = <codeword> 0
320
+ parity = 0
321
+ comb = 0
322
+ while True:
323
+ images_i[comb] = image
324
+ parity ^= 1
325
+ j = 0
326
+ if not parity:
327
+ while not comb & (1 << j):
328
+ j += 1
329
+ j += 1
330
+ if j == chunk_size:
331
+ break
332
+ comb ^= (1 << j)
333
+ image ^= images_i[1 << j]
334
+ return word_perm
335
+
336
+ cdef WordPermutation *create_array_word_perm(int *array, int start, int degree) noexcept:
337
+ """
338
+ Create a word permutation of a given degree from a C array, starting at start.
339
+ """
340
+ cdef int i, j, cslim, parity, comb, words_per_chunk, num_chunks = 1
341
+ cdef codeword *images_i
342
+ cdef codeword image
343
+ cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
344
+ if word_perm is NULL:
345
+ raise RuntimeError("Error allocating memory.")
346
+ word_perm.degree = degree
347
+ while num_chunks*chunk_size < word_perm.degree:
348
+ num_chunks += 1
349
+ word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
350
+ if word_perm.images is NULL:
351
+ sig_free(word_perm)
352
+ raise RuntimeError("Error allocating memory.")
353
+ word_perm.chunk_num = num_chunks
354
+ words_per_chunk = 1 << chunk_size
355
+ word_perm.gate = ((<codeword>1) << chunk_size) - 1
356
+ word_perm.chunk_words = words_per_chunk
357
+ for i from 0 <= i < num_chunks:
358
+ images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
359
+ if images_i is NULL:
360
+ for j from 0 <= j < i:
361
+ sig_free(word_perm.images[j])
362
+ sig_free(word_perm.images)
363
+ sig_free(word_perm)
364
+ raise RuntimeError("Error allocating memory.")
365
+ word_perm.images[i] = images_i
366
+ cslim = min(chunk_size, degree - i*chunk_size)
367
+ for j from 0 <= j < cslim:
368
+ images_i[1 << j] = (<codeword>1) << array[start + chunk_size*i + j]
369
+ image = <codeword> 0
370
+ parity = 0
371
+ comb = 0
372
+ while True:
373
+ images_i[comb] = image
374
+ parity ^= 1
375
+ j = 0
376
+ if not parity:
377
+ while not comb & (1 << j):
378
+ j += 1
379
+ j += 1
380
+ if j == chunk_size:
381
+ break
382
+ comb ^= (1 << j)
383
+ image ^= images_i[1 << j]
384
+ return word_perm
385
+
386
+ cdef WordPermutation *create_id_word_perm(int degree) noexcept:
387
+ """
388
+ Create the identity word permutation of degree degree.
389
+ """
390
+ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
391
+ cdef codeword *images_i
392
+ cdef codeword image
393
+ cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
394
+ if word_perm is NULL:
395
+ raise RuntimeError("Error allocating memory.")
396
+ word_perm.degree = degree
397
+ while num_chunks*chunk_size < degree:
398
+ num_chunks += 1
399
+ word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
400
+ if word_perm.images is NULL:
401
+ sig_free(word_perm)
402
+ raise RuntimeError("Error allocating memory.")
403
+ word_perm.chunk_num = num_chunks
404
+ words_per_chunk = 1 << chunk_size
405
+ word_perm.gate = ((<codeword>1) << chunk_size) - 1
406
+ word_perm.chunk_words = words_per_chunk
407
+ for i from 0 <= i < num_chunks:
408
+ images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
409
+ if images_i is NULL:
410
+ for j from 0 <= j < i:
411
+ sig_free(word_perm.images[j])
412
+ sig_free(word_perm.images)
413
+ sig_free(word_perm)
414
+ raise RuntimeError("Error allocating memory.")
415
+ word_perm.images[i] = images_i
416
+ for j from 0 <= j < chunk_size:
417
+ images_i[1 << j] = (<codeword>1) << (chunk_size*i + j)
418
+ image = <codeword> 0
419
+ parity = 0
420
+ comb = 0
421
+ while True:
422
+ images_i[comb] = image
423
+ parity ^= 1
424
+ j = 0
425
+ if not parity:
426
+ while not comb & (1 << j):
427
+ j += 1
428
+ j += 1
429
+ if j == chunk_size:
430
+ break
431
+ comb ^= (1 << j)
432
+ image ^= images_i[1 << j]
433
+ return word_perm
434
+
435
+ cdef WordPermutation *create_comp_word_perm(WordPermutation *g, WordPermutation *h) noexcept:
436
+ r"""
437
+ Create the composition of word permutations `g \circ h`.
438
+ """
439
+ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
440
+ cdef codeword *images_i
441
+ cdef codeword image
442
+ cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
443
+ if word_perm is NULL:
444
+ raise RuntimeError("Error allocating memory.")
445
+ word_perm.degree = g.degree
446
+ while num_chunks*chunk_size < word_perm.degree:
447
+ num_chunks += 1
448
+ word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
449
+ if word_perm.images is NULL:
450
+ sig_free(word_perm)
451
+ raise RuntimeError("Error allocating memory.")
452
+ word_perm.chunk_num = num_chunks
453
+ words_per_chunk = 1 << chunk_size
454
+ word_perm.gate = ((<codeword>1) << chunk_size) - 1
455
+ word_perm.chunk_words = words_per_chunk
456
+ for i from 0 <= i < num_chunks:
457
+ images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
458
+ if images_i is NULL:
459
+ for j from 0 <= j < i:
460
+ sig_free(word_perm.images[j])
461
+ sig_free(word_perm.images)
462
+ sig_free(word_perm)
463
+ raise RuntimeError("Error allocating memory.")
464
+ word_perm.images[i] = images_i
465
+ for j in range(chunk_size):
466
+ image = (<codeword>1) << (chunk_size*i + j)
467
+ image = permute_word_by_wp(h, image)
468
+ image = permute_word_by_wp(g, image)
469
+ images_i[1 << j] = image
470
+ image = <codeword> 0
471
+ parity = 0
472
+ comb = 0
473
+ while True:
474
+ images_i[comb] = image
475
+ parity ^= 1
476
+ j = 0
477
+ if not parity:
478
+ while not comb & (1 << j):
479
+ j += 1
480
+ j += 1
481
+ if j == chunk_size:
482
+ break
483
+ comb ^= (1 << j)
484
+ image ^= images_i[1 << j]
485
+ return word_perm
486
+
487
+ cdef WordPermutation *create_inv_word_perm(WordPermutation *g) noexcept:
488
+ r"""
489
+ Create the inverse `g^{-1}` of the word permutation of `g`.
490
+ """
491
+ cdef int i, j
492
+ cdef int *array = <int *> sig_malloc(g.degree * sizeof(int))
493
+ cdef codeword temp
494
+ cdef WordPermutation *w
495
+ for i from 0 <= i < g.degree:
496
+ j = 0
497
+ temp = permute_word_by_wp(g, (<codeword>1) << i)
498
+ while not ((<codeword>1) << j) & temp:
499
+ j += 1
500
+ array[j] = i
501
+ w = create_array_word_perm(array, 0, g.degree)
502
+ sig_free(array)
503
+ return w
504
+
505
+ cdef int dealloc_word_perm(WordPermutation *wp) noexcept:
506
+ """
507
+ Free the memory used by a word permutation.
508
+ """
509
+ cdef int i
510
+ for i from 0 <= i < wp.chunk_num:
511
+ sig_free(wp.images[i])
512
+ sig_free(wp.images)
513
+ sig_free(wp)
514
+
515
+ cdef codeword permute_word_by_wp(WordPermutation *wp, codeword word) noexcept:
516
+ """
517
+ Return the codeword obtained by applying the permutation wp to word.
518
+ """
519
+ cdef int num_chunks = wp.chunk_num
520
+ cdef int i
521
+ cdef codeword gate = wp.gate
522
+ cdef codeword image = 0
523
+ cdef codeword **images = wp.images
524
+ for i from 0 <= i < num_chunks:
525
+ image += images[i][(word >> i*chunk_size) & gate]
526
+ return image
527
+
528
+
529
+ def test_expand_to_ortho_basis(B=None):
530
+ r"""
531
+ This function is written in pure C for speed, and is tested from this
532
+ function.
533
+
534
+ INPUT:
535
+
536
+ - ``B`` -- a :class:`BinaryCode` in standard form
537
+
538
+ OUTPUT:
539
+
540
+ An array of codewords which represent the expansion of a basis for `B` to a
541
+ basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1
542
+ is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees
543
+ that all the vectors in the span of the output have even weight).
544
+
545
+ TESTS::
546
+
547
+ sage: from sage.coding.binary_code import test_expand_to_ortho_basis, BinaryCode
548
+ sage: M = Matrix(GF(2), [[1,1,1,1,1,1,0,0,0,0], [0,0,1,1,1,1,1,1,1,1]])
549
+ sage: B = BinaryCode(M)
550
+ sage: B.put_in_std_form()
551
+ 0
552
+ sage: test_expand_to_ortho_basis(B=B)
553
+ INPUT CODE:
554
+ Binary [10,2] linear code, generator matrix
555
+ [1010001111]
556
+ [0101111111]
557
+ Expanding to the basis of an orthogonal complement...
558
+ Basis:
559
+ 0010000010
560
+ 0001000010
561
+ 0000100001
562
+ 0000010001
563
+ 0000001001
564
+ """
565
+ cdef codeword *output
566
+ cdef int k=0, i
567
+ cdef BinaryCode C
568
+ if not isinstance(B, BinaryCode):
569
+ raise TypeError()
570
+ C = B
571
+ print("INPUT CODE:")
572
+ print(C)
573
+ print("Expanding to the basis of an orthogonal complement...")
574
+ output = expand_to_ortho_basis(C, C.ncols)
575
+ print("Basis:")
576
+ while output[k]:
577
+ k += 1
578
+ for i from 0 <= i < k:
579
+ print(''.join(reversed(Integer(output[i]).binary().zfill(C.ncols))))
580
+ sig_free(output)
581
+
582
+
583
+ cdef codeword *expand_to_ortho_basis(BinaryCode B, int n) noexcept:
584
+ r"""
585
+ INPUT:
586
+
587
+ - ``B`` -- a BinaryCode in standard form
588
+ - ``n`` -- the degree
589
+
590
+ OUTPUT:
591
+
592
+ An array of codewords which represent the expansion of a basis for `B` to a
593
+ basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1
594
+ is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees
595
+ that all the vectors in the span of the output have even weight).
596
+ """
597
+ # assumes B is already in standard form
598
+ cdef codeword *basis
599
+ cdef codeword word = 0, temp, new, pivots = 0, combo, parity
600
+ cdef codeword n_gate = (~<codeword>0) >> ((sizeof(codeword)<<3) - n)
601
+ cdef int i, j, m, k = B.nrows
602
+ cdef WordPermutation *wp
603
+ basis = <codeword *> sig_malloc((n + 1) * sizeof(codeword))
604
+ if basis is NULL:
605
+ raise MemoryError()
606
+ for i from 0 <= i < k:
607
+ basis[i] = B.basis[i]
608
+ word ^= basis[i]
609
+ # If 11...1 is already a word of the code,
610
+ # then being orthogonal to the code guarantees
611
+ # being even weight. Otherwise, add this in.
612
+ word = (~word) & n_gate
613
+ if word:
614
+ basis[k] = word
615
+ temp = (<codeword>1) << k
616
+ i = k
617
+ while not word & temp:
618
+ temp = temp << 1
619
+ i += 1
620
+ for j from 0 <= j < k:
621
+ if temp & basis[j]:
622
+ basis[j] ^= word
623
+ temp += (<codeword>1 << k) - 1
624
+ i = k
625
+ word = <codeword>1 << k
626
+ k += 1
627
+ else: # NOTE THIS WILL NEVER HAPPEN AS CURRENTLY SET UP!
628
+ temp = (<codeword>1 << k) - 1
629
+ i = k
630
+ word = <codeword>1 << k
631
+ # Now:
632
+ # k is the length of the basis so far
633
+ j = k
634
+ while i < n:
635
+ # we are now looking at the ith free variable,
636
+ # word has a 1 in the ith place, and
637
+ # j is the current row we are putting in basis
638
+ new = 0
639
+ for m from 0 <= m < k:
640
+ if basis[m] & word:
641
+ new ^= basis[m]
642
+ basis[j] = (new & temp) + word
643
+ j += ((word ^ temp) >> i) & 1
644
+ i += 1
645
+ word = word << 1
646
+ temp = (<codeword>1 << B.nrows) - 1
647
+ for i from k <= i < n:
648
+ basis[i-k] = basis[i] ^ B.words[basis[i] & temp]
649
+ k = n-k
650
+ i = 0
651
+ word = (<codeword>1 << B.nrows)
652
+ while i < k and (word & n_gate):
653
+ m = i
654
+ while m < k and not basis[m] & word:
655
+ m += 1
656
+ if m < k:
657
+ pivots += word
658
+ if m != i:
659
+ new = basis[i]
660
+ basis[i] = basis[m]
661
+ basis[m] = new
662
+ for j from 0 <= j < i:
663
+ if basis[j] & word:
664
+ basis[j] ^= basis[i]
665
+ for j from i < j < k:
666
+ if basis[j] & word:
667
+ basis[j] ^= basis[i]
668
+ i += 1
669
+ word = word << 1
670
+ for j from i <= j < n:
671
+ basis[j] = 0
672
+ # now basis is length i
673
+ perm = list(range(B.nrows))
674
+ perm_c = []
675
+ for j from B.nrows <= j < B.ncols:
676
+ if (<codeword>1 << j) & pivots:
677
+ perm.append(j)
678
+ else:
679
+ perm_c.append(j)
680
+ perm.extend(perm_c)
681
+ perm.extend(list(range(B.ncols, n)))
682
+ perm_c = [0]*n
683
+ for j from 0 <= j < n:
684
+ perm_c[perm[j]] = j
685
+ wp = create_word_perm(perm_c)
686
+ for j from 0 <= j < i:
687
+ basis[j] = permute_word_by_wp(wp, basis[j])
688
+ for j from 0 <= j < B.nrows:
689
+ B.basis[j] = permute_word_by_wp(wp, B.basis[j])
690
+ dealloc_word_perm(wp)
691
+ word = 0
692
+ parity = 0
693
+ combo = 0
694
+ while True:
695
+ B.words[combo] = word
696
+ parity ^= 1
697
+ j = 0
698
+ if not parity:
699
+ while not combo & (1 << j):
700
+ j += 1
701
+ j += 1
702
+ if j == B.nrows:
703
+ break
704
+ else:
705
+ combo ^= (1 << j)
706
+ word ^= B.basis[j]
707
+ return basis
708
+
709
+ cdef class BinaryCode:
710
+ """
711
+ Minimal, but optimized, binary code object.
712
+
713
+ EXAMPLES::
714
+
715
+ sage: import sage.coding.binary_code
716
+ sage: from sage.coding.binary_code import *
717
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
718
+ sage: B = BinaryCode(M) # create from matrix
719
+ sage: C = BinaryCode(B, 60) # create using glue
720
+ sage: D = BinaryCode(C, 240)
721
+ sage: E = BinaryCode(D, 85)
722
+ sage: B
723
+ Binary [4,1] linear code, generator matrix
724
+ [1111]
725
+ sage: C
726
+ Binary [6,2] linear code, generator matrix
727
+ [111100]
728
+ [001111]
729
+ sage: D
730
+ Binary [8,3] linear code, generator matrix
731
+ [11110000]
732
+ [00111100]
733
+ [00001111]
734
+ sage: E
735
+ Binary [8,4] linear code, generator matrix
736
+ [11110000]
737
+ [00111100]
738
+ [00001111]
739
+ [10101010]
740
+
741
+ sage: M = Matrix(GF(2), [[1]*32])
742
+ sage: B = BinaryCode(M)
743
+ sage: B
744
+ Binary [32,1] linear code, generator matrix
745
+ [11111111111111111111111111111111]
746
+ """
747
+ def __cinit__(self, arg1, arg2=None):
748
+ """
749
+ Initialize.
750
+
751
+ TESTS::
752
+
753
+ sage: import sage.coding.binary_code
754
+ sage: from sage.coding.binary_code import *
755
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
756
+ sage: B = BinaryCode(M)
757
+ sage: TestSuite(B).run()
758
+ """
759
+ cdef int nrows, i, j, size
760
+ cdef int nwords, other_nwords, parity, combination
761
+ cdef codeword word, glue_word
762
+ cdef BinaryCode other
763
+ cdef codeword *self_words
764
+ cdef codeword *self_basis
765
+ cdef codeword *other_basis
766
+
767
+ self.radix = sizeof(int) << 3
768
+
769
+ if isinstance(arg1, Matrix):
770
+ self.ncols = arg1.ncols()
771
+ self.nrows = arg1.nrows()
772
+ nrows = self.nrows
773
+ self.nwords = 1 << nrows
774
+ nwords = self.nwords
775
+ elif isinstance(arg1, BinaryCode):
776
+ other = <BinaryCode> arg1
777
+ self.nrows = other.nrows + 1
778
+ glue_word = <codeword> arg2
779
+ size = 0
780
+ while 0 < ((<codeword> 1) << size) <= glue_word:
781
+ size += 1
782
+ if other.ncols > size:
783
+ self.ncols = other.ncols
784
+ else:
785
+ self.ncols = size
786
+ other_nwords = other.nwords
787
+ self.nwords = 2 * other_nwords
788
+ nrows = self.nrows
789
+ nwords = self.nwords
790
+ else:
791
+ raise NotImplementedError
792
+
793
+ if self.nrows >= self.radix or self.ncols > self.radix:
794
+ raise NotImplementedError("Columns and rows are stored as ints. This code is too big.")
795
+
796
+ self.mem = MemoryAllocator()
797
+ self.words = <codeword *> self.mem.malloc(nwords * sizeof(int))
798
+ self.basis = <codeword *> self.mem.malloc(nrows * sizeof(int))
799
+ self_words = self.words
800
+ self_basis = self.basis
801
+
802
+ if isinstance(arg1, Matrix):
803
+ rows = arg1.rows()
804
+ for i from 0 <= i < nrows:
805
+ word = <codeword> 0
806
+ for j in rows[i].nonzero_positions():
807
+ word += (1<<j)
808
+ self_basis[i] = word
809
+
810
+ word = <codeword> 0
811
+ parity = 0
812
+ combination = 0
813
+ while True:
814
+ self_words[combination] = word
815
+ parity ^= 1
816
+ j = 0
817
+ if not parity:
818
+ while not combination & (1 << j):
819
+ j += 1
820
+ j += 1
821
+ if j == nrows:
822
+ break
823
+ else:
824
+ combination ^= (1 << j)
825
+ word ^= self_basis[j]
826
+
827
+ else: # isinstance(arg1, BinaryCode)
828
+ other_basis = other.basis
829
+ for i from 0 <= i < nrows-1:
830
+ self_basis[i] = other_basis[i]
831
+ i = nrows - 1
832
+ self_basis[i] = glue_word
833
+
834
+ memcpy(self_words, other.words, other_nwords*(self.radix>>3))
835
+
836
+ for combination from 0 <= combination < other_nwords:
837
+ self_words[combination+other_nwords] = self_words[combination] ^ glue_word
838
+
839
+ def __reduce__(self):
840
+ """
841
+ Method for pickling and unpickling BinaryCodes.
842
+
843
+ TESTS::
844
+
845
+ sage: from sage.coding.binary_code import *
846
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
847
+ sage: B = BinaryCode(M)
848
+ sage: loads(dumps(B)) == B
849
+ True
850
+ """
851
+ return BinaryCode, (self.matrix(),)
852
+
853
+ def __richcmp__(self, other, int op):
854
+ """
855
+ Comparison of BinaryCodes.
856
+
857
+ TESTS::
858
+
859
+ sage: from sage.coding.binary_code import *
860
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
861
+ sage: B = BinaryCode(M)
862
+ sage: C = BinaryCode(B.matrix())
863
+ sage: B == C
864
+ True
865
+ """
866
+ if type(self) is not type(other):
867
+ return NotImplemented
868
+ return PyObject_RichCompare(self.matrix(), other.matrix(), op)
869
+
870
+ def matrix(self):
871
+ """
872
+ Return the generator matrix of the :class:`BinaryCode`, i.e. the code is
873
+ the rowspace of ``B.matrix()``.
874
+
875
+ EXAMPLES::
876
+
877
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0], [0,0,1,1,1,1]])
878
+ sage: from sage.coding.binary_code import *
879
+ sage: B = BinaryCode(M)
880
+ sage: B.matrix()
881
+ [1 1 1 1 0 0]
882
+ [0 0 1 1 1 1]
883
+ """
884
+ cdef int i, j
885
+ from sage.matrix.constructor import matrix
886
+ from sage.rings.finite_rings.finite_field_constructor import GF
887
+ rows = []
888
+ for i from 0 <= i < self.nrows:
889
+ row = [0]*self.ncols
890
+ for j from 0 <= j < self.ncols:
891
+ if self.basis[i] & ((<codeword>1) << j):
892
+ row[j] = 1
893
+ rows.append(row)
894
+ return matrix(GF(2), self.nrows, self.ncols, rows)
895
+
896
+ def print_data(self):
897
+ """
898
+ Print all data for ``self``.
899
+
900
+ EXAMPLES::
901
+
902
+ sage: # needs sage.graphs
903
+ sage: import sage.coding.binary_code
904
+ sage: from sage.coding.binary_code import *
905
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
906
+ sage: B = BinaryCode(M)
907
+ sage: C = BinaryCode(B, 60)
908
+ sage: D = BinaryCode(C, 240)
909
+ sage: E = BinaryCode(D, 85)
910
+ sage: B.print_data() # random - actually "print(P.print_data())"
911
+ ncols: 4
912
+ nrows: 1
913
+ nwords: 2
914
+ radix: 32
915
+ basis:
916
+ 1111
917
+ words:
918
+ 0000
919
+ 1111
920
+ sage: C.print_data() # random - actually "print(P.print_data())"
921
+ ncols: 6
922
+ nrows: 2
923
+ nwords: 4
924
+ radix: 32
925
+ basis:
926
+ 111100
927
+ 001111
928
+ words:
929
+ 000000
930
+ 111100
931
+ 001111
932
+ 110011
933
+ sage: D.print_data() # random - actually "print(P.print_data())"
934
+ ncols: 8
935
+ nrows: 3
936
+ nwords: 8
937
+ radix: 32
938
+ basis:
939
+ 11110000
940
+ 00111100
941
+ 00001111
942
+ words:
943
+ 00000000
944
+ 11110000
945
+ 00111100
946
+ 11001100
947
+ 00001111
948
+ 11111111
949
+ 00110011
950
+ 11000011
951
+ sage: E.print_data() # random - actually "print(P.print_data())"
952
+ ncols: 8
953
+ nrows: 4
954
+ nwords: 16
955
+ radix: 32
956
+ basis:
957
+ 11110000
958
+ 00111100
959
+ 00001111
960
+ 10101010
961
+ words:
962
+ 00000000
963
+ 11110000
964
+ 00111100
965
+ 11001100
966
+ 00001111
967
+ 11111111
968
+ 00110011
969
+ 11000011
970
+ 10101010
971
+ 01011010
972
+ 10010110
973
+ 01100110
974
+ 10100101
975
+ 01010101
976
+ 10011001
977
+ 01101001
978
+ """
979
+ from sage.graphs.generic_graph_pyx import int_to_binary_string
980
+ cdef int ui
981
+ cdef int i
982
+ s = ''
983
+ s += "ncols:" + str(self.ncols)
984
+ s += "\nnrows:" + str(self.nrows)
985
+ s += "\nnwords:" + str(self.nwords)
986
+ s += "\nradix:" + str(self.radix)
987
+ s += "\nbasis:\n"
988
+ for i from 0 <= i < self.nrows:
989
+ b = list(int_to_binary_string(self.basis[i]).zfill(self.ncols))
990
+ b.reverse()
991
+ b.append('\n')
992
+ s += ''.join(b)
993
+ s += "\nwords:\n"
994
+ for ui from 0 <= ui < self.nwords:
995
+ b = list(int_to_binary_string(self.words[ui]).zfill(self.ncols))
996
+ b.reverse()
997
+ b.append('\n')
998
+ s += ''.join(b)
999
+
1000
+ def __repr__(self) -> str:
1001
+ """
1002
+ String representation of ``self``.
1003
+
1004
+ EXAMPLES::
1005
+
1006
+ sage: import sage.coding.binary_code
1007
+ sage: from sage.coding.binary_code import *
1008
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
1009
+ sage: B = BinaryCode(M)
1010
+ sage: B
1011
+ Binary [8,4] linear code, generator matrix
1012
+ [11110000]
1013
+ [00111100]
1014
+ [00001111]
1015
+ [10101010]
1016
+ """
1017
+ cdef int i
1018
+ s = 'Binary [%d,%d] linear code, generator matrix\n' % (
1019
+ self.ncols, self.nrows)
1020
+ for i in range(self.nrows):
1021
+ s += '[' + self._word((<codeword> 1)<<i) + ']\n'
1022
+ return s
1023
+
1024
+ def _word(self, coords):
1025
+ """
1026
+ Considering ``coords`` as an integer in binary, think of the 0s and 1s
1027
+ as coefficients of the basis given by ``self.matrix()``. This function
1028
+ returns a string representation of that word.
1029
+
1030
+ EXAMPLES::
1031
+
1032
+ sage: from sage.coding.binary_code import *
1033
+ sage: M = Matrix(GF(2), [[1,1,1,1]])
1034
+ sage: B = BinaryCode(M)
1035
+ sage: B._word(0)
1036
+ '0000'
1037
+ sage: B._word(1)
1038
+ '1111'
1039
+
1040
+ Note that behavior under input which does not represent a word in
1041
+ the code is unspecified (gives nonsense).
1042
+ """
1043
+ return ''.join('%d' % self.is_one(coords, j)
1044
+ for j in range(self.ncols))
1045
+
1046
+ def _is_one(self, word, col):
1047
+ """
1048
+ Return the col-th letter of word, i.e. 0 or 1. Words are expressed
1049
+ as integers, which represent linear combinations of the rows of the
1050
+ generator matrix of the code.
1051
+
1052
+ EXAMPLES::
1053
+
1054
+ sage: import sage.coding.binary_code
1055
+ sage: from sage.coding.binary_code import *
1056
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
1057
+ sage: B = BinaryCode(M)
1058
+ sage: B
1059
+ Binary [8,4] linear code, generator matrix
1060
+ [11110000]
1061
+ [00111100]
1062
+ [00001111]
1063
+ [10101010]
1064
+ sage: B._is_one(7, 4)
1065
+ 0
1066
+ sage: B._is_one(8, 4)
1067
+ 1
1068
+ sage: B._is_automorphism([1,0,3,2,4,5,6,7], [0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 11, 10, 13, 12, 15, 14])
1069
+ 1
1070
+ """
1071
+ return self.is_one(word, col) != 0
1072
+
1073
+ cdef int is_one(self, int word, int column) noexcept:
1074
+ return (self.words[word] & (<codeword> 1 << column)) >> column
1075
+
1076
+ def _is_automorphism(self, col_gamma, word_gamma):
1077
+ """
1078
+ Check whether a given permutation is an automorphism of the code.
1079
+
1080
+ INPUT:
1081
+
1082
+ - ``col_gamma`` -- permutation sending i |--> col_gamma[i] acting
1083
+ on the columns
1084
+ - ``word_gamma`` -- permutation sending i |--> word_gamma[i] acting
1085
+ on the words
1086
+
1087
+ EXAMPLES::
1088
+
1089
+ sage: import sage.coding.binary_code
1090
+ sage: from sage.coding.binary_code import *
1091
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
1092
+ sage: B = BinaryCode(M)
1093
+ sage: B
1094
+ Binary [8,4] linear code, generator matrix
1095
+ [11110000]
1096
+ [00111100]
1097
+ [00001111]
1098
+ [10101010]
1099
+ sage: B._is_automorphism([1,0,3,2,4,5,6,7], [0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 11, 10, 13, 12, 15, 14])
1100
+ 1
1101
+ """
1102
+ cdef int i
1103
+ cdef int *_col_gamma
1104
+ cdef int *_word_gamma
1105
+ _word_gamma = <int *> sig_malloc(self.nwords * sizeof(int))
1106
+ _col_gamma = <int *> sig_malloc(self.ncols * sizeof(int))
1107
+ if _col_gamma is NULL or _word_gamma is NULL:
1108
+ if _word_gamma is not NULL:
1109
+ sig_free(_word_gamma)
1110
+ if _col_gamma is not NULL:
1111
+ sig_free(_col_gamma)
1112
+ raise MemoryError("Memory.")
1113
+ for i from 0 <= i < self.nwords:
1114
+ _word_gamma[i] = word_gamma[i]
1115
+ for i from 0 <= i < self.ncols:
1116
+ _col_gamma[i] = col_gamma[i]
1117
+ result = self.is_automorphism(_col_gamma, _word_gamma)
1118
+ sig_free(_col_gamma)
1119
+ sig_free(_word_gamma)
1120
+ return result
1121
+
1122
+ cdef int is_automorphism(self, int *col_gamma, int *word_gamma) noexcept:
1123
+ cdef int i, j, self_nwords = self.nwords, self_ncols = self.ncols
1124
+ i = 1
1125
+ while i < self_nwords:
1126
+ for j from 0 <= j < self_ncols:
1127
+ if self.is_one(i, j) != self.is_one(word_gamma[i], col_gamma[j]):
1128
+ return 0
1129
+ i = i << 1
1130
+ return 1
1131
+
1132
+ def apply_permutation(self, labeling):
1133
+ """
1134
+ Apply a column permutation to the code.
1135
+
1136
+ INPUT:
1137
+
1138
+ - ``labeling`` -- list permutation of the columns
1139
+
1140
+ EXAMPLES::
1141
+
1142
+ sage: from sage.coding.binary_code import *
1143
+ sage: B = BinaryCode(codes.GolayCode(GF(2)).generator_matrix())
1144
+ sage: B
1145
+ Binary [24,12] linear code, generator matrix
1146
+ [100000000000101011100011]
1147
+ [010000000000111110010010]
1148
+ [001000000000110100101011]
1149
+ [000100000000110001110110]
1150
+ [000010000000110011011001]
1151
+ [000001000000011001101101]
1152
+ [000000100000001100110111]
1153
+ [000000010000101101111000]
1154
+ [000000001000010110111100]
1155
+ [000000000100001011011110]
1156
+ [000000000010101110001101]
1157
+ [000000000001010111000111]
1158
+ sage: B.apply_permutation(list(range(11,-1,-1)) + list(range(12, 24)))
1159
+ sage: B
1160
+ Binary [24,12] linear code, generator matrix
1161
+ [000000000001101011100011]
1162
+ [000000000010111110010010]
1163
+ [000000000100110100101011]
1164
+ [000000001000110001110110]
1165
+ [000000010000110011011001]
1166
+ [000000100000011001101101]
1167
+ [000001000000001100110111]
1168
+ [000010000000101101111000]
1169
+ [000100000000010110111100]
1170
+ [001000000000001011011110]
1171
+ [010000000000101110001101]
1172
+ [100000000000010111000111]
1173
+ """
1174
+ # Tests for this function implicitly test _apply_permutation_to_basis
1175
+ # and _update_words_from_basis. These functions should not be used
1176
+ # individually by the user, so they remain cdef'd.
1177
+ self._apply_permutation_to_basis(labeling)
1178
+ self._update_words_from_basis()
1179
+
1180
+ cdef void _apply_permutation_to_basis(self, object labeling) noexcept:
1181
+ cdef WordPermutation *wp
1182
+ cdef int i
1183
+ wp = create_word_perm(labeling)
1184
+ for i from 0 <= i < self.nrows:
1185
+ self.basis[i] = permute_word_by_wp(wp, self.basis[i])
1186
+ dealloc_word_perm(wp)
1187
+
1188
+ cdef void _update_words_from_basis(self) noexcept:
1189
+ cdef codeword word
1190
+ cdef int j, parity, combination
1191
+ word = 0
1192
+ parity = 0
1193
+ combination = 0
1194
+ while True:
1195
+ self.words[combination] = word
1196
+ parity ^= 1
1197
+ j = 0
1198
+ if not parity:
1199
+ while not combination & (1 << j):
1200
+ j += 1
1201
+ j += 1
1202
+ if j == self.nrows:
1203
+ break
1204
+ else:
1205
+ combination ^= (1 << j)
1206
+ word ^= self.basis[j]
1207
+
1208
+ cpdef int put_in_std_form(self) noexcept:
1209
+ """
1210
+ Put the code in binary form, which is defined by an identity matrix on
1211
+ the left, augmented by a matrix of data.
1212
+
1213
+ EXAMPLES::
1214
+
1215
+ sage: from sage.coding.binary_code import *
1216
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0], [0,0,1,1,1,1]])
1217
+ sage: B = BinaryCode(M); B
1218
+ Binary [6,2] linear code, generator matrix
1219
+ [111100]
1220
+ [001111]
1221
+ sage: B.put_in_std_form(); B
1222
+ 0
1223
+ Binary [6,2] linear code, generator matrix
1224
+ [101011]
1225
+ [010111]
1226
+ """
1227
+ cdef codeword swap, current = 1, pivots = 0
1228
+ cdef int i, j, k, row = 0
1229
+ cdef object perm
1230
+ while row < self.nrows:
1231
+ i = row
1232
+ while i < self.nrows and not self.basis[i] & current:
1233
+ i += 1
1234
+ if i < self.nrows:
1235
+ pivots += current
1236
+ if i != row:
1237
+ swap = self.basis[row]
1238
+ self.basis[row] = self.basis[i]
1239
+ self.basis[i] = swap
1240
+ for j from 0 <= j < row:
1241
+ if self.basis[j] & current:
1242
+ self.basis[j] ^= self.basis[row]
1243
+ for j from row < j < self.nrows:
1244
+ if self.basis[j] & current:
1245
+ self.basis[j] ^= self.basis[row]
1246
+ row += 1
1247
+ current = current << 1
1248
+ perm = [0]*self.ncols
1249
+ j = 0
1250
+ k = self.nrows
1251
+ for i from 0 <= i < self.ncols:
1252
+ if ((<codeword>1) << i) & pivots:
1253
+ perm[i] = j
1254
+ j += 1
1255
+ else:
1256
+ perm[i] = k
1257
+ k += 1
1258
+ self._apply_permutation_to_basis(perm)
1259
+ self._update_words_from_basis()
1260
+
1261
+
1262
+ cdef class OrbitPartition:
1263
+ """
1264
+ Structure which keeps track of which vertices are equivalent
1265
+ under the part of the automorphism group that has already been
1266
+ seen, during search. Essentially a disjoint-set data structure*,
1267
+ which also keeps track of the minimum element and size of each
1268
+ cell of the partition, and the size of the partition.
1269
+
1270
+ See :wikipedia:`Disjoint-set_data_structure`
1271
+ """
1272
+ def __cinit__(self, int nrows, int ncols):
1273
+ """
1274
+ Initialize.
1275
+
1276
+ TESTS::
1277
+
1278
+ sage: import sage.coding.binary_code
1279
+ sage: from sage.coding.binary_code import *
1280
+ sage: O = OrbitPartition(4, 8)
1281
+ sage: TestSuite(O).run(skip='_test_pickling')
1282
+ """
1283
+ cdef int col
1284
+ cdef int nwords, word
1285
+ nwords = (1 << nrows)
1286
+ self.nwords = nwords
1287
+ self.ncols = ncols
1288
+ self.mem = MemoryAllocator()
1289
+ self.wd_parent = <int *> self.mem.malloc(nwords * sizeof(int))
1290
+ self.wd_rank = <int *> self.mem.malloc(nwords * sizeof(int))
1291
+ self.wd_min_cell_rep = <int *> self.mem.malloc(nwords * sizeof(int))
1292
+ self.wd_size = <int *> self.mem.malloc(nwords * sizeof(int))
1293
+ self.col_parent = <int *> self.mem.malloc(ncols * sizeof(int))
1294
+ self.col_rank = <int *> self.mem.malloc(ncols * sizeof(int))
1295
+ self.col_min_cell_rep = <int *> self.mem.malloc(ncols * sizeof(int))
1296
+ self.col_size = <int *> self.mem.malloc(ncols * sizeof(int))
1297
+ for word from 0 <= word < nwords:
1298
+ self.wd_parent[word] = word
1299
+ self.wd_rank[word] = 0
1300
+ self.wd_min_cell_rep[word] = word
1301
+ self.wd_size[word] = 1
1302
+ for col from 0 <= col < ncols:
1303
+ self.col_parent[col] = col
1304
+ self.col_rank[col] = 0
1305
+ self.col_min_cell_rep[col] = col
1306
+ self.col_size[col] = 1
1307
+
1308
+ def __repr__(self):
1309
+ """
1310
+ Return a string representation of the orbit partition.
1311
+
1312
+ EXAMPLES::
1313
+
1314
+ sage: import sage.coding.binary_code
1315
+ sage: from sage.coding.binary_code import *
1316
+ sage: O = OrbitPartition(4, 8)
1317
+ sage: O
1318
+ OrbitPartition on 16 words and 8 columns. Data:
1319
+ Words:
1320
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1321
+ Columns:
1322
+ 0,1,2,3,4,5,6,7
1323
+ """
1324
+ cdef int i
1325
+ cdef int j
1326
+ s = 'OrbitPartition on %d words and %d columns. Data:\n' % (self.nwords,
1327
+ self.ncols)
1328
+ # s += 'Parents::\n'
1329
+ s += 'Words:\n'
1330
+ for i from 0 <= i < self.nwords:
1331
+ s += '%d,' % self.wd_parent[i]
1332
+ s = s[:-1] + '\nColumns:\n'
1333
+ for j from 0 <= j < self.ncols:
1334
+ s += '%d,' % self.col_parent[j]
1335
+ # s = s[:-1] + '\n'
1336
+ # s += 'Min Cell Reps::\n'
1337
+ # s += 'Words:\n'
1338
+ # for i from 0 <= i < self.nwords:
1339
+ # s += '%d,' % self.wd_min_cell_rep[i]
1340
+ # s = s[:-1] + '\nColumns:\n'
1341
+ # for j from 0 <= j < self.ncols:
1342
+ # s += '%d,' % self.col_min_cell_rep[j]
1343
+ return s[:-1]
1344
+
1345
+ def _wd_find(self, word):
1346
+ """
1347
+ Return the root of word.
1348
+
1349
+ EXAMPLES::
1350
+
1351
+ sage: import sage.coding.binary_code
1352
+ sage: from sage.coding.binary_code import *
1353
+ sage: O = OrbitPartition(4, 8)
1354
+ sage: O
1355
+ OrbitPartition on 16 words and 8 columns. Data:
1356
+ Words:
1357
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1358
+ Columns:
1359
+ 0,1,2,3,4,5,6,7
1360
+ sage: O._wd_find(12)
1361
+ 12
1362
+ """
1363
+ return self.wd_find(word)
1364
+
1365
+ cdef int wd_find(self, int word) noexcept:
1366
+ if self.wd_parent[word] == word:
1367
+ return word
1368
+ else:
1369
+ self.wd_parent[word] = self.wd_find(self.wd_parent[word])
1370
+ return self.wd_parent[word]
1371
+
1372
+ def _wd_union(self, x, y):
1373
+ """
1374
+ Join the cells containing x and y.
1375
+
1376
+ EXAMPLES::
1377
+
1378
+ sage: import sage.coding.binary_code
1379
+ sage: from sage.coding.binary_code import *
1380
+ sage: O = OrbitPartition(4, 8)
1381
+ sage: O
1382
+ OrbitPartition on 16 words and 8 columns. Data:
1383
+ Words:
1384
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1385
+ Columns:
1386
+ 0,1,2,3,4,5,6,7
1387
+ sage: O._wd_union(1,10)
1388
+ sage: O
1389
+ OrbitPartition on 16 words and 8 columns. Data:
1390
+ Words:
1391
+ 0,1,2,3,4,5,6,7,8,9,1,11,12,13,14,15
1392
+ Columns:
1393
+ 0,1,2,3,4,5,6,7
1394
+ sage: O._wd_find(10)
1395
+ 1
1396
+ """
1397
+ self.wd_union(x, y)
1398
+
1399
+ cdef void wd_union(self, int x, int y) noexcept:
1400
+ cdef int x_root, y_root
1401
+ x_root = self.wd_find(x)
1402
+ y_root = self.wd_find(y)
1403
+ if self.wd_rank[x_root] > self.wd_rank[y_root]:
1404
+ self.wd_parent[y_root] = x_root
1405
+ self.wd_min_cell_rep[x_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
1406
+ self.wd_size[x_root] += self.wd_size[y_root]
1407
+ elif self.wd_rank[x_root] < self.wd_rank[y_root]:
1408
+ self.wd_parent[x_root] = y_root
1409
+ self.wd_min_cell_rep[y_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
1410
+ self.wd_size[y_root] += self.wd_size[x_root]
1411
+ elif x_root != y_root:
1412
+ self.wd_parent[y_root] = x_root
1413
+ self.wd_min_cell_rep[x_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
1414
+ self.wd_size[x_root] += self.wd_size[y_root]
1415
+ self.wd_rank[x_root] += 1
1416
+
1417
+ def _col_find(self, col):
1418
+ """
1419
+ Return the root of col.
1420
+
1421
+ EXAMPLES::
1422
+
1423
+ sage: import sage.coding.binary_code
1424
+ sage: from sage.coding.binary_code import *
1425
+ sage: O = OrbitPartition(4, 8)
1426
+ sage: O
1427
+ OrbitPartition on 16 words and 8 columns. Data:
1428
+ Words:
1429
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1430
+ Columns:
1431
+ 0,1,2,3,4,5,6,7
1432
+ sage: O._col_find(6)
1433
+ 6
1434
+ """
1435
+ return self.col_find(col)
1436
+
1437
+ cdef int col_find(self, int col) noexcept:
1438
+ if self.col_parent[col] == col:
1439
+ return col
1440
+ else:
1441
+ self.col_parent[col] = self.col_find(self.col_parent[col])
1442
+ return self.col_parent[col]
1443
+
1444
+ def _col_union(self, x, y):
1445
+ """
1446
+ Join the cells containing x and y.
1447
+
1448
+ EXAMPLES::
1449
+
1450
+ sage: import sage.coding.binary_code
1451
+ sage: from sage.coding.binary_code import *
1452
+ sage: O = OrbitPartition(4, 8)
1453
+ sage: O
1454
+ OrbitPartition on 16 words and 8 columns. Data:
1455
+ Words:
1456
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1457
+ Columns:
1458
+ 0,1,2,3,4,5,6,7
1459
+ sage: O._col_union(1,4)
1460
+ sage: O
1461
+ OrbitPartition on 16 words and 8 columns. Data:
1462
+ Words:
1463
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1464
+ Columns:
1465
+ 0,1,2,3,1,5,6,7
1466
+ sage: O._col_find(4)
1467
+ 1
1468
+ """
1469
+ self.col_union(x, y)
1470
+
1471
+ cdef void col_union(self, int x, int y) noexcept:
1472
+ cdef int x_root, y_root
1473
+ x_root = self.col_find(x)
1474
+ y_root = self.col_find(y)
1475
+ if self.col_rank[x_root] > self.col_rank[y_root]:
1476
+ self.col_parent[y_root] = x_root
1477
+ self.col_min_cell_rep[x_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
1478
+ self.col_size[x_root] += self.col_size[y_root]
1479
+ elif self.col_rank[x_root] < self.col_rank[y_root]:
1480
+ self.col_parent[x_root] = y_root
1481
+ self.col_min_cell_rep[y_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
1482
+ self.col_size[y_root] += self.col_size[x_root]
1483
+ elif x_root != y_root:
1484
+ self.col_parent[y_root] = x_root
1485
+ self.col_min_cell_rep[x_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
1486
+ self.col_size[x_root] += self.col_size[y_root]
1487
+ self.col_rank[x_root] += 1
1488
+
1489
+ def _merge_perm(self, col_gamma, wd_gamma):
1490
+ """
1491
+ Merges the cells of ``self`` under the given permutation. If gamma[a] = b,
1492
+ then after merge_perm, a and b will be in the same cell. Returns 0 if
1493
+ nothing was done, otherwise returns 1.
1494
+
1495
+ EXAMPLES::
1496
+
1497
+ sage: import sage.coding.binary_code
1498
+ sage: from sage.coding.binary_code import *
1499
+ sage: O = OrbitPartition(4, 8)
1500
+ sage: O
1501
+ OrbitPartition on 16 words and 8 columns. Data:
1502
+ Words:
1503
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1504
+ Columns:
1505
+ 0,1,2,3,4,5,6,7
1506
+ sage: O._merge_perm([1,0,3,2,4,5,6,7], [0,1,2,3,4,5,6,7,9,8,11,10,13,12,15,14])
1507
+ 1
1508
+ sage: O
1509
+ OrbitPartition on 16 words and 8 columns. Data:
1510
+ Words:
1511
+ 0,1,2,3,4,5,6,7,8,8,10,10,12,12,14,14
1512
+ Columns:
1513
+ 0,0,2,2,4,5,6,7
1514
+ """
1515
+ cdef int i
1516
+ cdef int *_col_gamma
1517
+ cdef int *_wd_gamma
1518
+ _wd_gamma = <int *> sig_malloc(self.nwords * sizeof(int))
1519
+ _col_gamma = <int *> sig_malloc(self.ncols * sizeof(int))
1520
+ if _col_gamma is NULL or _wd_gamma is NULL:
1521
+ if _wd_gamma is not NULL:
1522
+ sig_free(_wd_gamma)
1523
+ if _col_gamma is not NULL:
1524
+ sig_free(_col_gamma)
1525
+ raise MemoryError("Memory.")
1526
+ for i from 0 <= i < self.nwords:
1527
+ _wd_gamma[i] = wd_gamma[i]
1528
+ for i from 0 <= i < self.ncols:
1529
+ _col_gamma[i] = col_gamma[i]
1530
+ result = self.merge_perm(_col_gamma, _wd_gamma)
1531
+ sig_free(_col_gamma)
1532
+ sig_free(_wd_gamma)
1533
+ return result
1534
+
1535
+ cdef int merge_perm(self, int *col_gamma, int *wd_gamma) noexcept:
1536
+ cdef int i, gamma_i_root
1537
+ cdef int j, gamma_j_root, return_value = 0
1538
+ for i in range(self.nwords):
1539
+ gamma_i_root = self.wd_find(wd_gamma[i])
1540
+ if gamma_i_root != i:
1541
+ return_value = 1
1542
+ self.wd_union(i, gamma_i_root)
1543
+ for j in range(self.ncols):
1544
+ gamma_j_root = self.col_find(col_gamma[j])
1545
+ if gamma_j_root != j:
1546
+ return_value = 1
1547
+ self.col_union(j, gamma_j_root)
1548
+ return return_value
1549
+
1550
+ cdef class PartitionStack:
1551
+ """
1552
+ Partition stack structure for traversing the search tree during automorphism
1553
+ group computation.
1554
+ """
1555
+ def __cinit__(self, arg1, arg2=None):
1556
+ """
1557
+ Initialize.
1558
+
1559
+ TESTS::
1560
+
1561
+ sage: import sage.coding.binary_code
1562
+ sage: from sage.coding.binary_code import *
1563
+ sage: P = PartitionStack(2, 6)
1564
+ sage: TestSuite(P).run(skip='_test_pickling')
1565
+ """
1566
+ cdef int k, nwords, ncols, sizeof_int
1567
+ cdef PartitionStack other = None
1568
+ cdef int *wd_ents
1569
+ cdef int *wd_lvls
1570
+ cdef int *col_ents
1571
+ cdef int *col_lvls
1572
+ cdef int *col_degs
1573
+ cdef int *col_counts
1574
+ cdef int *col_output
1575
+ cdef int *wd_degs
1576
+ cdef int *wd_counts
1577
+ cdef int *wd_output
1578
+ sizeof_int = sizeof(int)
1579
+
1580
+ try:
1581
+ self.nrows = <int> arg1
1582
+ self.nwords = 1 << self.nrows
1583
+ self.ncols = <int> arg2
1584
+ except Exception:
1585
+ other = arg1
1586
+ self.nrows = other.nrows
1587
+ self.nwords = other.nwords
1588
+ self.ncols = other.ncols
1589
+
1590
+ self.radix = sizeof_int << 3
1591
+ self.flag = (1 << (self.radix-1))
1592
+
1593
+ # data
1594
+ self.mem = MemoryAllocator()
1595
+ self.wd_ents = <int *> self.mem.malloc(self.nwords * sizeof_int)
1596
+ self.wd_lvls = <int *> self.mem.malloc(self.nwords * sizeof_int)
1597
+ self.col_ents = <int *> self.mem.malloc(self.ncols * sizeof_int)
1598
+ self.col_lvls = <int *> self.mem.malloc(self.ncols * sizeof_int)
1599
+
1600
+ # scratch space
1601
+ self.col_degs = <int *> self.mem.malloc(self.ncols * sizeof_int)
1602
+ self.col_counts = <int *> self.mem.malloc(self.nwords * sizeof_int)
1603
+ self.col_output = <int *> self.mem.malloc(self.ncols * sizeof_int)
1604
+ self.wd_degs = <int *> self.mem.malloc(self.nwords * sizeof_int)
1605
+ self.wd_counts = <int *> self.mem.malloc((self.ncols + 1) * sizeof_int)
1606
+ self.wd_output = <int *> self.mem.malloc(self.nwords * sizeof_int)
1607
+
1608
+ nwords = self.nwords
1609
+ ncols = self.ncols
1610
+
1611
+ if other:
1612
+ memcpy(self.wd_ents, other.wd_ents, self.nwords * sizeof_int)
1613
+ memcpy(self.wd_lvls, other.wd_lvls, self.nwords * sizeof_int)
1614
+ memcpy(self.col_ents, other.col_ents, self.ncols * sizeof_int)
1615
+ memcpy(self.col_lvls, other.col_lvls, self.ncols * sizeof_int)
1616
+ else:
1617
+ wd_ents = self.wd_ents
1618
+ wd_lvls = self.wd_lvls
1619
+ col_ents = self.col_ents
1620
+ col_lvls = self.col_lvls
1621
+ for k from 0 <= k < nwords-1:
1622
+ wd_ents[k] = k
1623
+ wd_lvls[k] = 2*ncols
1624
+ for k from 0 <= k < ncols-1:
1625
+ col_ents[k] = k
1626
+ col_lvls[k] = 2*ncols
1627
+ wd_ents[nwords-1] = nwords-1
1628
+ wd_lvls[nwords-1] = -1
1629
+ col_ents[ncols-1] = ncols-1
1630
+ col_lvls[ncols-1] = -1
1631
+
1632
+ col_degs = self.col_degs
1633
+ col_counts = self.col_counts
1634
+ col_output = self.col_output
1635
+ wd_degs = self.wd_degs
1636
+ wd_counts = self.wd_counts
1637
+ wd_output = self.wd_output
1638
+ for k from 0 <= k < ncols:
1639
+ col_degs[k]=0
1640
+ col_output[k]=0
1641
+ wd_counts[k]=0
1642
+ wd_counts[ncols]=0
1643
+ for k from 0 <= k < nwords:
1644
+ col_counts[k]=0
1645
+ wd_degs[k]=0
1646
+ wd_output[k]=0
1647
+
1648
+ def __dealloc__(self):
1649
+ if self.basis_locations:
1650
+ sig_free(self.basis_locations)
1651
+
1652
+ def print_data(self):
1653
+ """
1654
+ Print all data for ``self``.
1655
+
1656
+ EXAMPLES::
1657
+
1658
+ sage: import sage.coding.binary_code
1659
+ sage: from sage.coding.binary_code import *
1660
+ sage: P = PartitionStack(2, 6)
1661
+ sage: print(P.print_data())
1662
+ nwords:4
1663
+ nrows:2
1664
+ ncols:6
1665
+ radix:32
1666
+ wd_ents:
1667
+ 0
1668
+ 1
1669
+ 2
1670
+ 3
1671
+ wd_lvls:
1672
+ 12
1673
+ 12
1674
+ 12
1675
+ -1
1676
+ col_ents:
1677
+ 0
1678
+ 1
1679
+ 2
1680
+ 3
1681
+ 4
1682
+ 5
1683
+ col_lvls:
1684
+ 12
1685
+ 12
1686
+ 12
1687
+ 12
1688
+ 12
1689
+ -1
1690
+ col_degs:
1691
+ 0
1692
+ 0
1693
+ 0
1694
+ 0
1695
+ 0
1696
+ 0
1697
+ col_counts:
1698
+ 0
1699
+ 0
1700
+ 0
1701
+ 0
1702
+ col_output:
1703
+ 0
1704
+ 0
1705
+ 0
1706
+ 0
1707
+ 0
1708
+ 0
1709
+ wd_degs:
1710
+ 0
1711
+ 0
1712
+ 0
1713
+ 0
1714
+ wd_counts:
1715
+ 0
1716
+ 0
1717
+ 0
1718
+ 0
1719
+ 0
1720
+ 0
1721
+ 0
1722
+ wd_output:
1723
+ 0
1724
+ 0
1725
+ 0
1726
+ 0
1727
+ """
1728
+ cdef int i, j
1729
+ s = ''
1730
+ s += "nwords:" + str(self.nwords) + '\n'
1731
+ s += "nrows:" + str(self.nrows) + '\n'
1732
+ s += "ncols:" + str(self.ncols) + '\n'
1733
+ s += "radix:" + str(self.radix) + '\n'
1734
+ s += "wd_ents:" + '\n'
1735
+ for i from 0 <= i < self.nwords:
1736
+ s += str(self.wd_ents[i]) + '\n'
1737
+ s += "wd_lvls:" + '\n'
1738
+ for i from 0 <= i < self.nwords:
1739
+ s += str(self.wd_lvls[i]) + '\n'
1740
+ s += "col_ents:" + '\n'
1741
+ for i from 0 <= i < self.ncols:
1742
+ s += str(self.col_ents[i]) + '\n'
1743
+ s += "col_lvls:" + '\n'
1744
+ for i from 0 <= i < self.ncols:
1745
+ s += str(self.col_lvls[i]) + '\n'
1746
+ s += "col_degs:" + '\n'
1747
+ for i from 0 <= i < self.ncols:
1748
+ s += str(self.col_degs[i]) + '\n'
1749
+ s += "col_counts:" + '\n'
1750
+ for i from 0 <= i < self.nwords:
1751
+ s += str(self.col_counts[i]) + '\n'
1752
+ s += "col_output:" + '\n'
1753
+ for i from 0 <= i < self.ncols:
1754
+ s += str(self.col_output[i]) + '\n'
1755
+ s += "wd_degs:" + '\n'
1756
+ for i from 0 <= i < self.nwords:
1757
+ s += str(self.wd_degs[i]) + '\n'
1758
+ s += "wd_counts:" + '\n'
1759
+ for i from 0 <= i < self.ncols + 1:
1760
+ s += str(self.wd_counts[i]) + '\n'
1761
+ s += "wd_output:" + '\n'
1762
+ for i from 0 <= i < self.nwords:
1763
+ s += str(self.wd_output[i]) + '\n'
1764
+ if self.basis_locations:
1765
+ s += "basis_locations:" + '\n'
1766
+ j = 1
1767
+ while (1 << j) < self.nwords:
1768
+ j += 1
1769
+ for i from 0 <= i < j:
1770
+ s += str(self.basis_locations[i]) + '\n'
1771
+ return s
1772
+
1773
+ def __repr__(self) -> str:
1774
+ """
1775
+ Return a string representation of ``self``.
1776
+
1777
+ EXAMPLES::
1778
+
1779
+ sage: import sage.coding.binary_code
1780
+ sage: from sage.coding.binary_code import *
1781
+ sage: P = PartitionStack(2, 6)
1782
+ sage: P
1783
+ ({0,1,2,3}) ({0,1,2,3,4,5})
1784
+ """
1785
+ cdef int k
1786
+ s = ''
1787
+ last = ''
1788
+ current = ''
1789
+ for k in range(2 * self.ncols):
1790
+ current = self._repr_at_k(k)
1791
+ if current == last:
1792
+ break
1793
+ s += current
1794
+ last = current
1795
+ return s
1796
+
1797
+ def _repr_at_k(self, k) -> str:
1798
+ """
1799
+ Give a string representing the partition at level k.
1800
+
1801
+ EXAMPLES::
1802
+
1803
+ sage: from sage.coding.binary_code import *
1804
+ sage: P = PartitionStack(2, 6); P
1805
+ ({0,1,2,3}) ({0,1,2,3,4,5})
1806
+ sage: P._repr_at_k(0)
1807
+ '({0,1,2,3}) ({0,1,2,3,4,5})\n'
1808
+ """
1809
+ cdef int j
1810
+ s = '({'
1811
+ for j in range(self.nwords):
1812
+ s += str(self.wd_ents[j])
1813
+ if self.wd_lvls[j] <= k:
1814
+ s += '},{'
1815
+ else:
1816
+ s += ','
1817
+ s = s[:-2] + ') '
1818
+ s += '({'
1819
+ for j in range(self.ncols):
1820
+ s += str(self.col_ents[j])
1821
+ if self.col_lvls[j] <= k:
1822
+ s += '},{'
1823
+ else:
1824
+ s += ','
1825
+ s = s[:-2] + ')\n'
1826
+ return s
1827
+
1828
+ def _is_discrete(self, k):
1829
+ """
1830
+ Return whether the partition at level k is discrete.
1831
+
1832
+ EXAMPLES::
1833
+
1834
+ sage: import sage.coding.binary_code
1835
+ sage: from sage.coding.binary_code import *
1836
+ sage: P = PartitionStack(2, 6)
1837
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
1838
+ [0, 1, 2, 3, 4]
1839
+ sage: P._sort_wds(0, [0,2,3,1], 5)
1840
+ 0
1841
+ sage: P
1842
+ ({0,3,1,2}) ({0,1,2,3,4,5})
1843
+ ({0,3,1,2}) ({0},{1,2,3,4,5})
1844
+ ({0,3,1,2}) ({0},{1},{2,3,4,5})
1845
+ ({0,3,1,2}) ({0},{1},{2},{3,4,5})
1846
+ ({0,3,1,2}) ({0},{1},{2},{3},{4,5})
1847
+ ({0},{3},{1},{2}) ({0},{1},{2},{3},{4},{5})
1848
+ sage: P._is_discrete(4)
1849
+ 0
1850
+ sage: P._is_discrete(5)
1851
+ 1
1852
+ """
1853
+ return self.is_discrete(k)
1854
+
1855
+ cdef int is_discrete(self, int k) noexcept:
1856
+ cdef int i, self_ncols = self.ncols, self_nwords = self.nwords
1857
+ cdef int *self_col_lvls = self.col_lvls
1858
+ cdef int *self_wd_lvls = self.wd_lvls
1859
+ for i from 0 <= i < self_ncols:
1860
+ if self_col_lvls[i] > k:
1861
+ return 0
1862
+ for i from 0 <= i < self_nwords:
1863
+ if self_wd_lvls[i] > k:
1864
+ return 0
1865
+ return 1
1866
+
1867
+ def _num_cells(self, k):
1868
+ """
1869
+ Return the number of cells in the partition at level k.
1870
+
1871
+ EXAMPLES::
1872
+
1873
+ sage: import sage.coding.binary_code
1874
+ sage: from sage.coding.binary_code import *
1875
+ sage: P = PartitionStack(2, 6)
1876
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
1877
+ [0, 1, 2, 3, 4]
1878
+ sage: P
1879
+ ({0,1,2,3}) ({0,1,2,3,4,5})
1880
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
1881
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
1882
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
1883
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
1884
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
1885
+ sage: P._num_cells(3)
1886
+ 5
1887
+ """
1888
+ return self.num_cells(k)
1889
+
1890
+ cdef int num_cells(self, int k) noexcept:
1891
+ cdef int i, j = 0
1892
+ cdef int *self_wd_lvls = self.wd_lvls
1893
+ cdef int *self_col_lvls = self.col_lvls
1894
+ for i from 0 <= i < self.nwords:
1895
+ if self_wd_lvls[i] <= k:
1896
+ j += 1
1897
+ for i from 0 <= i < self.ncols:
1898
+ if self_col_lvls[i] <= k:
1899
+ j += 1
1900
+ return j
1901
+
1902
+ def _sat_225(self, k):
1903
+ """
1904
+ Return whether the partition at level k satisfies the hypotheses of
1905
+ Lemma 2.25 in Brendan McKay's Practical Graph Isomorphism paper (see
1906
+ sage/graphs/graph_isom.pyx.
1907
+
1908
+ EXAMPLES::
1909
+
1910
+ sage: import sage.coding.binary_code
1911
+ sage: from sage.coding.binary_code import *
1912
+ sage: P = PartitionStack(2, 6)
1913
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
1914
+ [0, 1, 2, 3, 4]
1915
+ sage: P._sat_225(3)
1916
+ 0
1917
+ sage: P._sat_225(4)
1918
+ 1
1919
+ sage: P
1920
+ ({0,1,2,3}) ({0,1,2,3,4,5})
1921
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
1922
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
1923
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
1924
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
1925
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
1926
+ """
1927
+ return self.sat_225(k)
1928
+
1929
+ cdef int sat_225(self, int k) noexcept:
1930
+ cdef int i, n = self.nwords + self.ncols, in_cell = 0
1931
+ cdef int nontrivial_cells = 0, total_cells = self.num_cells(k)
1932
+ cdef int *self_wd_lvls = self.wd_lvls
1933
+ cdef int *self_col_lvls = self.col_lvls
1934
+ if n <= total_cells + 4:
1935
+ return 1
1936
+ for i from 0 <= i < self.nwords:
1937
+ if self_wd_lvls[i] <= k:
1938
+ if in_cell:
1939
+ nontrivial_cells += 1
1940
+ in_cell = 0
1941
+ else:
1942
+ in_cell = 1
1943
+ in_cell = 0
1944
+ for i from 0 <= i < self.ncols:
1945
+ if self_col_lvls[i] <= k:
1946
+ if in_cell:
1947
+ nontrivial_cells += 1
1948
+ in_cell = 0
1949
+ else:
1950
+ in_cell = 1
1951
+ if n == total_cells + nontrivial_cells:
1952
+ return 1
1953
+ if n == total_cells + nontrivial_cells + 1:
1954
+ return 1
1955
+ return 0
1956
+
1957
+ # def _new_min_cell_reps(self, k): #TODO
1958
+ # """
1959
+ # Returns an integer whose bits represent which columns are minimal cell
1960
+ # representatives.
1961
+ #
1962
+ # EXAMPLES::
1963
+ #
1964
+ # sage: import sage.coding.binary_code
1965
+ # sage: from sage.coding.binary_code import *
1966
+ # sage: P = PartitionStack(2, 6)
1967
+ # sage: [P._split_column(i,i+1) for i in range(5)]
1968
+ # [0, 1, 2, 3, 4]
1969
+ # sage: a = P._min_cell_reps(2)
1970
+ # sage: Integer(a).binary()
1971
+ # '111'
1972
+ # sage: P
1973
+ # ({0,1,2,3})
1974
+ # ({0,1,2,3})
1975
+ # ({0,1,2,3})
1976
+ # ({0,1,2,3})
1977
+ # ({0,1,2,3,4,5})
1978
+ # ({0},{1,2,3,4,5})
1979
+ # ({0},{1},{2,3,4,5})
1980
+ # ({0},{1},{2},{3,4,5})
1981
+ # ({0},{1},{2},{3},{4,5})
1982
+ # ({0},{1},{2},{3},{4},{5})
1983
+ #
1984
+ # """
1985
+ # return self.min_cell_reps(k)
1986
+ #
1987
+ # cdef int min_cell_reps(self, int k):
1988
+ # cdef int i
1989
+ # cdef int reps = 1
1990
+ # cdef int *self_col_lvls = self.col_lvls
1991
+ # for i from 0 < i < self.ncols:
1992
+ # if self_col_lvls[i-1] <= k:
1993
+ # reps += (1 << i)
1994
+ # return reps
1995
+ #
1996
+ cdef void new_min_cell_reps(self, int k, unsigned int *Omega, int start) noexcept:
1997
+ cdef int i
1998
+ cdef int *self_col_lvls = self.col_lvls
1999
+ cdef int *self_wd_lvls = self.wd_lvls
2000
+ cdef int *self_col_ents = self.col_ents
2001
+ cdef int *self_wd_ents = self.wd_ents
2002
+ cdef int length, word
2003
+ cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols
2004
+ length = 1 + nwords/radix
2005
+ if nwords % radix:
2006
+ length += 1
2007
+ for i in range(length):
2008
+ Omega[start+i] = 0
2009
+ for i in range(1, ncols):
2010
+ Omega[start] += ((self_col_lvls[i-1] <= k) << self_col_ents[i])
2011
+ Omega[start+1] = (1 << self_wd_ents[0])
2012
+ for i in range(1, nwords):
2013
+ if self_wd_lvls[i-1] <= k:
2014
+ word = self_wd_lvls[i-1]
2015
+ Omega[start+1+word/radix] += (1 << word % radix)
2016
+
2017
+ # def _fixed_cols(self, mcrs, k): #TODO
2018
+ # """
2019
+ # Returns an integer whose bits represent which columns are fixed. For
2020
+ # efficiency, mcrs is the output of min_cell_reps.
2021
+ #
2022
+ # EXAMPLES::
2023
+ #
2024
+ # sage: import sage.coding.binary_code
2025
+ # sage: from sage.coding.binary_code import *
2026
+ # sage: P = PartitionStack(2, 6)
2027
+ # sage: [P._split_column(i,i+1) for i in range(5)]
2028
+ # [0, 1, 2, 3, 4]
2029
+ # sage: a = P._fixed_cols(7, 2)
2030
+ # sage: Integer(a).binary()
2031
+ # '11'
2032
+ # sage: P
2033
+ # ({0,1,2,3})
2034
+ # ({0,1,2,3})
2035
+ # ({0,1,2,3})
2036
+ # ({0,1,2,3})
2037
+ # ({0,1,2,3,4,5})
2038
+ # ({0},{1,2,3,4,5})
2039
+ # ({0},{1},{2,3,4,5})
2040
+ # ({0},{1},{2},{3,4,5})
2041
+ # ({0},{1},{2},{3},{4,5})
2042
+ # ({0},{1},{2},{3},{4},{5})
2043
+ #
2044
+ # """
2045
+ # return self.fixed_cols(mcrs, k)
2046
+ #
2047
+ # cdef int fixed_cols(self, int mcrs, int k):
2048
+ # cdef int i
2049
+ # cdef int fixed = 0
2050
+ # cdef int *self_col_lvls = self.col_lvls
2051
+ # for i from 0 <= i < self.ncols:
2052
+ # if self_col_lvls[i] <= k:
2053
+ # fixed += (1 << i)
2054
+ # return fixed & mcrs
2055
+ #
2056
+ cdef void fixed_vertices(self, int k, unsigned int *Phi, unsigned int *Omega, int start) noexcept:
2057
+ cdef int i, length, ell, fixed = 0
2058
+ cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols
2059
+ cdef int *self_col_lvls = self.col_lvls
2060
+ cdef int *self_wd_lvls = self.wd_lvls
2061
+ cdef int *self_col_ents = self.col_ents
2062
+ cdef int *self_wd_ents = self.wd_ents
2063
+ for i from 0 <= i < ncols:
2064
+ fixed += ((self_col_lvls[i] <= k) << self_col_ents[i])
2065
+ Phi[start] = fixed & Omega[start]
2066
+ # zero out the rest of Phi
2067
+ length = 1 + nwords/self.radix
2068
+ if nwords % self.radix:
2069
+ length += 1
2070
+ for i from 0 < i < length:
2071
+ Phi[start+i] = 0
2072
+ for i from 0 <= i < nwords:
2073
+ ell = self_wd_ents[i]
2074
+ Phi[start+1+ell/radix] = ((self_wd_lvls[i] <= k) << ell % radix)
2075
+ for i from 0 < i < length:
2076
+ Phi[i] &= Omega[i]
2077
+
2078
+ # def _first_smallest_nontrivial(self, k): #TODO
2079
+ # """
2080
+ # Returns an integer representing the first, smallest nontrivial cell of columns.
2081
+ #
2082
+ # EXAMPLES::
2083
+ #
2084
+ # sage: import sage.coding.binary_code
2085
+ # sage: from sage.coding.binary_code import *
2086
+ # sage: P = PartitionStack(2, 6)
2087
+ # sage: [P._split_column(i,i+1) for i in range(5)]
2088
+ # [0, 1, 2, 3, 4]
2089
+ # sage: a = P._first_smallest_nontrivial(2)
2090
+ # sage: Integer(a).binary().zfill(32)
2091
+ # '00000000000000000000000000111100'
2092
+ # sage: P
2093
+ # ({0,1,2,3})
2094
+ # ({0,1,2,3})
2095
+ # ({0,1,2,3})
2096
+ # ({0,1,2,3})
2097
+ # ({0,1,2,3,4,5})
2098
+ # ({0},{1,2,3,4,5})
2099
+ # ({0},{1},{2,3,4,5})
2100
+ # ({0},{1},{2},{3,4,5})
2101
+ # ({0},{1},{2},{3},{4,5})
2102
+ # ({0},{1},{2},{3},{4},{5})
2103
+ #
2104
+ # """
2105
+ # return self.first_smallest_nontrivial(k)
2106
+ #
2107
+ # cdef int first_smallest_nontrivial(self, int k):
2108
+ # cdef int cell
2109
+ # cdef int i = 0, j = 0, location = 0, ncols = self.ncols
2110
+ # cdef int *self_col_lvls = self.col_lvls
2111
+ # while True:
2112
+ # if self_col_lvls[i] <= k:
2113
+ # if i != j and ncols > i - j + 1:
2114
+ # ncols = i - j + 1
2115
+ # location = j
2116
+ # j = i + 1
2117
+ # if self_col_lvls[i] == -1: break
2118
+ # i += 1
2119
+ # # location now points to the beginning of the first, smallest,
2120
+ # # nontrivial cell
2121
+ # j = location
2122
+ # self.v = self.col_ents[j]
2123
+ # while True:
2124
+ # if self_col_lvls[j] <= k: break
2125
+ # j += 1
2126
+ # # j now points to the last element of the cell
2127
+ # i = self.radix - j - 1 # the cell is represented in binary, reading from the right:
2128
+ # cell = (~0 << location) ^ (~0 << j+1) # <------- self.radix ----->
2129
+ # return cell # [0]*(radix-j-1) + [1]*(j-location+1) + [0]*location
2130
+ #
2131
+ cdef int new_first_smallest_nontrivial(self, int k, unsigned int *W, int start) noexcept:
2132
+ cdef int ell
2133
+ cdef int i = 0, j = 0, location = 0, min = self.ncols, nwords = self.nwords
2134
+ cdef int min_is_col = 1, radix = self.radix
2135
+ cdef int *self_col_lvls = self.col_lvls
2136
+ cdef int *self_wd_lvls = self.wd_lvls
2137
+ cdef int *self_col_ents = self.col_ents
2138
+ cdef int *self_wd_ents = self.wd_ents
2139
+ while True:
2140
+ if self_col_lvls[i] <= k:
2141
+ if i != j and min > i - j + 1:
2142
+ min = i - j + 1
2143
+ location = j
2144
+ j = i + 1
2145
+ if self_col_lvls[i] == -1:
2146
+ break
2147
+ i += 1
2148
+ # i = 0; j = 0
2149
+ # while True:
2150
+ # if self_wd_lvls[i] <= k:
2151
+ # if i != j and min > i - j + 1:
2152
+ # min = i - j + 1
2153
+ # min_is_col = 0
2154
+ # location = j
2155
+ # j = i + 1
2156
+ # if self_wd_lvls[i] == -1:
2157
+ # break
2158
+ # i += 1
2159
+ # location now points to the beginning of the first, smallest,
2160
+ # nontrivial cell
2161
+ j = location
2162
+ # zero out this level of W:
2163
+ ell = 1 + nwords/radix
2164
+ if nwords % radix:
2165
+ ell += 1
2166
+ for i from 0 <= i < ell:
2167
+ W[start+i] = 0
2168
+ if min_is_col:
2169
+ while True:
2170
+ if self_col_lvls[j] <= k:
2171
+ break
2172
+ j += 1
2173
+ # j now points to the last element of the cell
2174
+ i = location
2175
+ while i <= j:
2176
+ W[start] ^= (1 << self_col_ents[i])
2177
+ i += 1
2178
+ return self_col_ents[location]
2179
+ else:
2180
+ while True:
2181
+ if self_wd_lvls[j] <= k:
2182
+ break
2183
+ j += 1
2184
+ # j now points to the last element of the cell
2185
+ i = location
2186
+ while i <= j:
2187
+ ell = self_wd_ents[i]
2188
+ W[start+1+ell/radix] ^= (1 << ell % radix)
2189
+ i += 1
2190
+ return self_wd_ents[location] ^ self.flag
2191
+
2192
+ def _dangerous_dont_use_set_ents_lvls(self, col_ents, col_lvls, wd_ents, wd_lvls):
2193
+ """
2194
+ For debugging only.
2195
+
2196
+ EXAMPLES::
2197
+
2198
+ sage: import sage.coding.binary_code
2199
+ sage: from sage.coding.binary_code import *
2200
+ sage: P = PartitionStack(2, 6)
2201
+ sage: P
2202
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2203
+ sage: P._dangerous_dont_use_set_ents_lvls([99]*6, [0,3,2,3,5,-1], [4,3,5,6], [3,2,1,-1])
2204
+ sage: P
2205
+ ({4,3,5,6}) ({99},{99,99,99,99,99})
2206
+ ({4,3,5},{6}) ({99},{99,99,99,99,99})
2207
+ ({4,3},{5},{6}) ({99},{99,99},{99,99,99})
2208
+ ({4},{3},{5},{6}) ({99},{99},{99},{99},{99,99})
2209
+ """
2210
+ cdef int i
2211
+ for i from 0 <= i < len(col_ents):
2212
+ self.col_ents[i] = col_ents[i]
2213
+ for i from 0 <= i < len(col_lvls):
2214
+ self.col_lvls[i] = col_lvls[i]
2215
+ for i from 0 <= i < len(wd_ents):
2216
+ self.wd_ents[i] = wd_ents[i]
2217
+ for i from 0 <= i < len(wd_lvls):
2218
+ self.wd_lvls[i] = wd_lvls[i]
2219
+
2220
+ def _col_percolate(self, start, end):
2221
+ """
2222
+ Do one round of bubble sort on ents.
2223
+
2224
+ EXAMPLES::
2225
+
2226
+ sage: import sage.coding.binary_code
2227
+ sage: from sage.coding.binary_code import *
2228
+ sage: P = PartitionStack(2, 6)
2229
+ sage: P._dangerous_dont_use_set_ents_lvls(list(range(5,-1,-1)), [1,2,2,3,3,-1], list(range(3,-1,-1)), [1,1,2,-1])
2230
+ sage: P
2231
+ ({3,2,1,0}) ({5,4,3,2,1,0})
2232
+ ({3},{2},{1,0}) ({5},{4,3,2,1,0})
2233
+ ({3},{2},{1},{0}) ({5},{4},{3},{2,1,0})
2234
+ ({3},{2},{1},{0}) ({5},{4},{3},{2},{1},{0})
2235
+ sage: P._wd_percolate(0,3)
2236
+ sage: P._col_percolate(0,5)
2237
+ sage: P
2238
+ ({0,3,2,1}) ({0,5,4,3,2,1})
2239
+ ({0},{3},{2,1}) ({0},{5,4,3,2,1})
2240
+ ({0},{3},{2},{1}) ({0},{5},{4},{3,2,1})
2241
+ ({0},{3},{2},{1}) ({0},{5},{4},{3},{2},{1})
2242
+ """
2243
+ self.col_percolate(start, end)
2244
+
2245
+ cdef void col_percolate(self, int start, int end) noexcept:
2246
+ cdef int i, temp
2247
+ cdef int *self_col_ents = self.col_ents
2248
+ for i from end >= i > start:
2249
+ if self_col_ents[i] < self_col_ents[i-1]:
2250
+ temp = self.col_ents[i]
2251
+ self_col_ents[i] = self_col_ents[i-1]
2252
+ self_col_ents[i-1] = temp
2253
+
2254
+ def _wd_percolate(self, start, end):
2255
+ """
2256
+ Do one round of bubble sort on ents.
2257
+
2258
+ EXAMPLES::
2259
+
2260
+ sage: import sage.coding.binary_code
2261
+ sage: from sage.coding.binary_code import *
2262
+ sage: P = PartitionStack(2, 6)
2263
+ sage: P._dangerous_dont_use_set_ents_lvls(list(range(5,-1,-1)), [1,2,2,3,3,-1], list(range(3,-1,-1)), [1,1,2,-1])
2264
+ sage: P
2265
+ ({3,2,1,0}) ({5,4,3,2,1,0})
2266
+ ({3},{2},{1,0}) ({5},{4,3,2,1,0})
2267
+ ({3},{2},{1},{0}) ({5},{4},{3},{2,1,0})
2268
+ ({3},{2},{1},{0}) ({5},{4},{3},{2},{1},{0})
2269
+ sage: P._wd_percolate(0,3)
2270
+ sage: P._col_percolate(0,5)
2271
+ sage: P
2272
+ ({0,3,2,1}) ({0,5,4,3,2,1})
2273
+ ({0},{3},{2,1}) ({0},{5,4,3,2,1})
2274
+ ({0},{3},{2},{1}) ({0},{5},{4},{3,2,1})
2275
+ ({0},{3},{2},{1}) ({0},{5},{4},{3},{2},{1})
2276
+ """
2277
+ self.wd_percolate(start, end)
2278
+
2279
+ cdef void wd_percolate(self, int start, int end) noexcept:
2280
+ cdef int i, temp
2281
+ cdef int *self_wd_ents = self.wd_ents
2282
+ for i from end >= i > start:
2283
+ if self_wd_ents[i] < self_wd_ents[i-1]:
2284
+ temp = self.wd_ents[i]
2285
+ self_wd_ents[i] = self_wd_ents[i-1]
2286
+ self_wd_ents[i-1] = temp
2287
+
2288
+ # def _split_column(self, int v, int k): #TODO
2289
+ # """
2290
+ # Split column v out, placing it before the rest of the cell it was in.
2291
+ # Returns the location of the split column.
2292
+ #
2293
+ # EXAMPLES::
2294
+ #
2295
+ # sage: import sage.coding.binary_code
2296
+ # sage: from sage.coding.binary_code import *
2297
+ # sage: P = PartitionStack(2, 6)
2298
+ # sage: [P._split_column(i,i+1) for i in range(5)]
2299
+ # [0, 1, 2, 3, 4]
2300
+ # sage: P
2301
+ # ({0,1,2,3})
2302
+ # ({0,1,2,3})
2303
+ # ({0,1,2,3})
2304
+ # ({0,1,2,3})
2305
+ # ({0,1,2,3,4,5})
2306
+ # ({0},{1,2,3,4,5})
2307
+ # ({0},{1},{2,3,4,5})
2308
+ # ({0},{1},{2},{3,4,5})
2309
+ # ({0},{1},{2},{3},{4,5})
2310
+ # ({0},{1},{2},{3},{4},{5})
2311
+ # sage: P = PartitionStack(2, 6)
2312
+ # sage: P._split_column(0,1)
2313
+ # 0
2314
+ # sage: P._split_column(2,2)
2315
+ # 1
2316
+ # sage: P
2317
+ # ({0,1,2,3})
2318
+ # ({0,1,2,3})
2319
+ # ({0,1,2,3})
2320
+ # ({0,1,2,3})
2321
+ # ({0,2,1,3,4,5})
2322
+ # ({0},{2,1,3,4,5})
2323
+ # ({0},{2},{1,3,4,5})
2324
+ # ({0},{2},{1,3,4,5})
2325
+ # ({0},{2},{1,3,4,5})
2326
+ # ({0},{2},{1,3,4,5})
2327
+ #
2328
+ # """
2329
+ # return self.split_column(v, k)
2330
+ #
2331
+ # cdef int split_column(self, int v, int k):
2332
+ # cdef int i = 0, j
2333
+ # cdef int *self_col_ents = self.col_ents
2334
+ # cdef int *self_col_lvls = self.col_lvls
2335
+ # while self_col_ents[i] != v: i += 1
2336
+ # j = i
2337
+ # while self_col_lvls[i] > k: i += 1
2338
+ # if j == 0 or self_col_lvls[j-1] <= k:
2339
+ # self.col_percolate(j+1, i)
2340
+ # else:
2341
+ # while j != 0 and self_col_lvls[j-1] > k:
2342
+ # self_col_ents[j] = self_col_ents[j-1]
2343
+ # j -= 1
2344
+ # self_col_ents[j] = v
2345
+ # self_col_lvls[j] = k
2346
+ # return j
2347
+ #
2348
+
2349
+ def _split_vertex(self, v, k):
2350
+ """
2351
+ Split vertex v out, placing it before the rest of the cell it was in.
2352
+ Returns the location of the split vertex.
2353
+
2354
+ .. NOTE::
2355
+
2356
+ There is a convention regarding whether a vertex is a word or a
2357
+ column. See the 'flag' attribute of the PartitionStack object:
2358
+ If vertex&flag is not zero, it is a word.
2359
+
2360
+ EXAMPLES::
2361
+
2362
+ sage: import sage.coding.binary_code
2363
+ sage: from sage.coding.binary_code import *
2364
+ sage: P = PartitionStack(2, 6)
2365
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
2366
+ [0, 1, 2, 3, 4]
2367
+ sage: P
2368
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2369
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
2370
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
2371
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
2372
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
2373
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
2374
+ """
2375
+ return self.split_vertex(v, k)
2376
+
2377
+ cdef int split_vertex(self, int v, int k) noexcept:
2378
+ cdef int i = 0, j, flag = self.flag
2379
+ cdef int *ents
2380
+ cdef int *lvls
2381
+ if v & flag:
2382
+ ents = self.wd_ents
2383
+ lvls = self.wd_lvls
2384
+ v = v ^ flag
2385
+ while ents[i] != v:
2386
+ i += 1
2387
+ v = v ^ flag
2388
+ else:
2389
+ ents = self.col_ents
2390
+ lvls = self.col_lvls
2391
+ while ents[i] != v:
2392
+ i += 1
2393
+ j = i
2394
+ while lvls[i] > k:
2395
+ i += 1
2396
+ if j == 0 or lvls[j-1] <= k:
2397
+ if v & self.flag:
2398
+ self.wd_percolate(j+1, i)
2399
+ else:
2400
+ self.col_percolate(j+1, i)
2401
+ else:
2402
+ while j != 0 and lvls[j-1] > k:
2403
+ ents[j] = ents[j-1]
2404
+ j -= 1
2405
+ if v & flag:
2406
+ ents[j] = v ^ flag
2407
+ else:
2408
+ ents[j] = v
2409
+ lvls[j] = k
2410
+ if v & flag:
2411
+ return j ^ flag
2412
+ else:
2413
+ return j
2414
+
2415
+ def _col_degree(self, C, col, wd_ptr, k):
2416
+ """
2417
+ Return the number of words in the cell specified by wd_ptr that have a
2418
+ 1 in the col-th column.
2419
+
2420
+ EXAMPLES::
2421
+
2422
+ sage: import sage.coding.binary_code
2423
+ sage: from sage.coding.binary_code import *
2424
+ sage: P = PartitionStack(2, 6)
2425
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0],[0,0,1,1,1,1]])
2426
+ sage: B = BinaryCode(M)
2427
+ sage: B
2428
+ Binary [6,2] linear code, generator matrix
2429
+ [111100]
2430
+ [001111]
2431
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
2432
+ [0, 1, 2, 3, 4]
2433
+ sage: P
2434
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2435
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
2436
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
2437
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
2438
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
2439
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
2440
+ sage: P._col_degree(B, 2, 0, 2)
2441
+ 2
2442
+ """
2443
+ return self.col_degree(C, col, wd_ptr, k)
2444
+
2445
+ cdef int col_degree(self, BinaryCode CG, int col, int wd_ptr, int k) noexcept:
2446
+ cdef int i = 0
2447
+ cdef int *self_wd_lvls = self.wd_lvls
2448
+ cdef int *self_wd_ents = self.wd_ents
2449
+ while True:
2450
+ if CG.is_one(self_wd_ents[wd_ptr], col):
2451
+ i += 1
2452
+ if self_wd_lvls[wd_ptr] > k:
2453
+ wd_ptr += 1
2454
+ else:
2455
+ break
2456
+ return i
2457
+
2458
+ def _wd_degree(self, C, wd, col_ptr, k):
2459
+ """
2460
+ Return the number of columns in the cell specified by col_ptr that are
2461
+ 1 in wd.
2462
+
2463
+ EXAMPLES::
2464
+
2465
+ sage: import sage.coding.binary_code
2466
+ sage: from sage.coding.binary_code import *
2467
+ sage: P = PartitionStack(2, 6)
2468
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0],[0,0,1,1,1,1]])
2469
+ sage: B = BinaryCode(M)
2470
+ sage: B
2471
+ Binary [6,2] linear code, generator matrix
2472
+ [111100]
2473
+ [001111]
2474
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
2475
+ [0, 1, 2, 3, 4]
2476
+ sage: P
2477
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2478
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
2479
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
2480
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
2481
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
2482
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
2483
+ sage: P._wd_degree(B, 1, 1, 1)
2484
+ 3
2485
+ """
2486
+ cdef int *ham_wts = hamming_weights()
2487
+ result = self.wd_degree(C, wd, col_ptr, k, ham_wts)
2488
+ sig_free(ham_wts)
2489
+ return result
2490
+
2491
+ cdef int wd_degree(self, BinaryCode CG, int wd, int col_ptr, int k, int *ham_wts) noexcept:
2492
+
2493
+ cdef int *self_col_lvls = self.col_lvls
2494
+ cdef int *self_col_ents = self.col_ents
2495
+ cdef int mask = (1 << self_col_ents[col_ptr])
2496
+ while self_col_lvls[col_ptr] > k:
2497
+ col_ptr += 1
2498
+ mask += (1 << self_col_ents[col_ptr])
2499
+ mask &= CG.words[wd]
2500
+ return ham_wts[mask & 65535] + ham_wts[(mask >> 16) & 65535]
2501
+
2502
+ def _sort_cols(self, start, degrees, k):
2503
+ """
2504
+ Essentially a counting sort, but on only one cell of the partition.
2505
+
2506
+ INPUT:
2507
+
2508
+ - ``start`` -- location of the beginning of the cell
2509
+ - ``k`` -- at what level of refinement the partition of interest lies
2510
+ - ``degrees`` -- the counts to sort by
2511
+
2512
+ EXAMPLES::
2513
+
2514
+ sage: import sage.coding.binary_code
2515
+ sage: from sage.coding.binary_code import *
2516
+ sage: P = PartitionStack(2, 6)
2517
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
2518
+ [0, 1, 2, 3, 4]
2519
+ sage: P._sort_cols(1, [0,2,2,1,1], 1)
2520
+ 2
2521
+ sage: P
2522
+ ({0,1,2,3}) ({0,1,4,5,2,3})
2523
+ ({0,1,2,3}) ({0},{1},{4,5},{2,3})
2524
+ """
2525
+ cdef int i
2526
+ for i from 0 <= i < len(degrees):
2527
+ self.col_degs[i] = degrees[i]
2528
+ return self.sort_cols(start, k)
2529
+
2530
+ cdef int sort_cols(self, int start, int k) noexcept:
2531
+ cdef int i, j, max, max_location
2532
+ cdef int self_nwords = self.nwords, ii
2533
+ cdef int *self_col_counts = self.col_counts
2534
+ cdef int *self_col_lvls = self.col_lvls
2535
+ cdef int *self_col_degs = self.col_degs
2536
+ cdef int *self_col_ents = self.col_ents
2537
+ cdef int *self_col_output = self.col_output
2538
+ for ii from 0 <= ii < self_nwords:
2539
+ self_col_counts[ii] = 0
2540
+ i = 0
2541
+ while self_col_lvls[i+start] > k:
2542
+ self_col_counts[self_col_degs[i]] += 1
2543
+ i += 1
2544
+ self_col_counts[self_col_degs[i]] += 1
2545
+
2546
+ # i+start is the right endpoint of the cell now
2547
+ max = self_col_counts[0]
2548
+ max_location = 0
2549
+ for ii from 0 < ii < self_nwords:
2550
+ if self_col_counts[ii] > max:
2551
+ max = self_col_counts[ii]
2552
+ max_location = ii
2553
+ self_col_counts[ii] += self_col_counts[ii-1]
2554
+
2555
+ for j from i >= j >= 0:
2556
+ self_col_counts[self_col_degs[j]] -= 1
2557
+ self_col_output[self_col_counts[self_col_degs[j]]] = self_col_ents[start+j]
2558
+
2559
+ max_location = self_col_counts[max_location] + start
2560
+
2561
+ for j from 0 <= j <= i:
2562
+ self_col_ents[start+j] = self_col_output[j]
2563
+
2564
+ ii = 1
2565
+ while ii < self_nwords and self_col_counts[ii] <= i:
2566
+ if self_col_counts[ii] > 0:
2567
+ self_col_lvls[start + self_col_counts[ii] - 1] = k
2568
+ self.col_percolate(start + self_col_counts[ii-1], start + self_col_counts[ii] - 1)
2569
+ ii += 1
2570
+
2571
+ return max_location
2572
+
2573
+ def _sort_wds(self, start, degrees, k):
2574
+ """
2575
+ Essentially a counting sort, but on only one cell of the partition.
2576
+
2577
+ INPUT:
2578
+
2579
+ - ``start`` -- location of the beginning of the cell
2580
+ - ``k`` -- at what level of refinement the partition of interest lies
2581
+ - ``degrees`` -- the counts to sort by
2582
+
2583
+ EXAMPLES::
2584
+
2585
+ sage: import sage.coding.binary_code
2586
+ sage: from sage.coding.binary_code import *
2587
+ sage: P = PartitionStack(3, 6)
2588
+ sage: P._sort_wds(0, [0,0,3,3,3,3,2,2], 1)
2589
+ 4
2590
+ sage: P
2591
+ ({0,1,6,7,2,3,4,5}) ({0,1,2,3,4,5})
2592
+ ({0,1},{6,7},{2,3,4,5}) ({0,1,2,3,4,5})
2593
+ """
2594
+ cdef int i
2595
+ for i from 0 <= i < len(degrees):
2596
+ self.wd_degs[i] = degrees[i]
2597
+ return self.sort_wds(start, k)
2598
+
2599
+ cdef int sort_wds(self, int start, int k) noexcept:
2600
+ cdef int i, j, max, max_location
2601
+ cdef int ii, self_ncols = self.ncols
2602
+ cdef int *self_wd_counts = self.wd_counts
2603
+ cdef int *self_wd_lvls = self.wd_lvls
2604
+ cdef int *self_wd_degs = self.wd_degs
2605
+ cdef int *self_wd_ents = self.wd_ents
2606
+ cdef int *self_wd_output = self.wd_output
2607
+
2608
+ for ii in range(self_ncols + 1):
2609
+ self_wd_counts[ii] = 0
2610
+ i = 0
2611
+ while self_wd_lvls[i+start] > k:
2612
+ self_wd_counts[self_wd_degs[i]] += 1
2613
+ i += 1
2614
+ self_wd_counts[self_wd_degs[i]] += 1
2615
+
2616
+ # i+start is the right endpoint of the cell now
2617
+ max = self_wd_counts[0]
2618
+ max_location = 0
2619
+ for ii from 0 < ii < self_ncols+1:
2620
+ if self_wd_counts[ii] > max:
2621
+ max = self_wd_counts[ii]
2622
+ max_location = ii
2623
+ self_wd_counts[ii] += self_wd_counts[ii-1]
2624
+
2625
+ for j from i >= j >= 0:
2626
+ if j > i:
2627
+ break # cython bug with ints...
2628
+ self_wd_counts[self_wd_degs[j]] -= 1
2629
+ self_wd_output[self_wd_counts[self_wd_degs[j]]] = self_wd_ents[start+j]
2630
+
2631
+ max_location = self_wd_counts[max_location] + start
2632
+
2633
+ for j from 0 <= j <= i:
2634
+ self_wd_ents[start+j] = self_wd_output[j]
2635
+
2636
+ ii = 1
2637
+ while ii < self_ncols+1 and self_wd_counts[ii] <= i:
2638
+ if self_wd_counts[ii] > 0:
2639
+ self_wd_lvls[start + self_wd_counts[ii] - 1] = k
2640
+ self.wd_percolate(start + self_wd_counts[ii-1], start + self_wd_counts[ii] - 1)
2641
+ ii += 1
2642
+
2643
+ return max_location
2644
+
2645
+ def _refine(self, k, alpha, CG):
2646
+ """
2647
+ EXAMPLES::
2648
+
2649
+ sage: import sage.coding.binary_code
2650
+ sage: from sage.coding.binary_code import *
2651
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
2652
+ sage: B = BinaryCode(M)
2653
+ sage: P = PartitionStack(4, 8)
2654
+ sage: P._refine(1, [[0,0],[1,0]], B)
2655
+ 181
2656
+ sage: P._split_vertex(0, 2)
2657
+ 0
2658
+ sage: P._refine(2, [[0,0]], B)
2659
+ 290
2660
+ sage: P._split_vertex(1, 3)
2661
+ 1
2662
+ sage: P._refine(3, [[0,1]], B)
2663
+ 463
2664
+ sage: P._split_vertex(2, 4)
2665
+ 2
2666
+ sage: P._refine(4, [[0,2]], B)
2667
+ 1500
2668
+ sage: P._split_vertex(3, 5)
2669
+ 3
2670
+ sage: P._refine(5, [[0,3]], B)
2671
+ 641
2672
+ sage: P._split_vertex(4, 6)
2673
+ 4
2674
+ sage: P._refine(6, [[0,4]], B)
2675
+ 1224
2676
+ sage: P._is_discrete(5)
2677
+ 0
2678
+ sage: P._is_discrete(6)
2679
+ 1
2680
+ sage: P
2681
+ ({0,4,6,2,13,9,11,15,10,14,12,8,7,3,1,5}) ({0,1,2,3,4,7,6,5})
2682
+ ({0},{4,6,2,13,9,11,15,10,14,12,8,7,3,1},{5}) ({0,1,2,3,4,7,6,5})
2683
+ ({0},{4,6,2,13,9,11,15},{10,14,12,8,7,3,1},{5}) ({0},{1,2,3,4,7,6,5})
2684
+ ({0},{4,6,2},{13,9,11,15},{10,14,12,8},{7,3,1},{5}) ({0},{1},{2,3,4,7,6,5})
2685
+ ({0},{4},{6,2},{13,9},{11,15},{10,14},{12,8},{7,3},{1},{5}) ({0},{1},{2},{3,4,7,6,5})
2686
+ ({0},{4},{6,2},{13,9},{11,15},{10,14},{12,8},{7,3},{1},{5}) ({0},{1},{2},{3},{4,7,6,5})
2687
+ ({0},{4},{6},{2},{13},{9},{11},{15},{10},{14},{12},{8},{7},{3},{1},{5}) ({0},{1},{2},{3},{4},{7},{6},{5})
2688
+ """
2689
+ cdef int i, alpha_length = len(alpha)
2690
+ cdef int *_alpha = <int *> sig_malloc((self.nwords + self.ncols) * sizeof(int))
2691
+ cdef int *ham_wts = hamming_weights()
2692
+ if _alpha is NULL:
2693
+ raise MemoryError("Memory.")
2694
+ for i from 0 <= i < alpha_length:
2695
+ if alpha[i][0]:
2696
+ _alpha[i] = alpha[i][1] ^ self.flag
2697
+ else:
2698
+ _alpha[i] = alpha[i][1]
2699
+ result = self.refine(k, _alpha, alpha_length, CG, ham_wts)
2700
+ sig_free(_alpha)
2701
+ sig_free(ham_wts)
2702
+ return result
2703
+
2704
+ cdef int refine(self, int k, int *alpha, int alpha_length, BinaryCode CG, int *ham_wts) noexcept:
2705
+ cdef int q, r, s, t, flag = self.flag, self_ncols = self.ncols
2706
+ cdef int t_w, invariant = 0, i, j, m = 0
2707
+ cdef int *self_wd_degs = self.wd_degs
2708
+ cdef int *self_wd_lvls = self.wd_lvls
2709
+ cdef int *self_wd_ents = self.wd_ents
2710
+ cdef int *self_col_degs = self.col_degs
2711
+ cdef int *self_col_lvls = self.col_lvls
2712
+ cdef int *self_col_ents = self.col_ents
2713
+ while not self.is_discrete(k) and m < alpha_length:
2714
+ invariant += 1
2715
+ j = 0
2716
+ if alpha[m] & flag:
2717
+ while j < self_ncols:
2718
+ i = j
2719
+ s = 0
2720
+ invariant += 8
2721
+ while True:
2722
+ self_col_degs[i-j] = self.col_degree(CG, self_col_ents[i], alpha[m]^flag, k)
2723
+ if s == 0 and self_col_degs[i-j] != self_col_degs[0]:
2724
+ s = 1
2725
+ i += 1
2726
+ if self_col_lvls[i-1] <= k:
2727
+ break
2728
+ if s:
2729
+ invariant += 8
2730
+ t = self.sort_cols(j, k)
2731
+ invariant += t
2732
+ q = m
2733
+ while q < alpha_length:
2734
+ if alpha[q] == j:
2735
+ alpha[q] = t
2736
+ break
2737
+ q += 1
2738
+ r = j
2739
+ while True:
2740
+ if r == j or self.col_lvls[r-1] == k:
2741
+ if r != t:
2742
+ alpha[alpha_length] = r
2743
+ alpha_length += 1
2744
+ r += 1
2745
+ if r >= i:
2746
+ break
2747
+ invariant += self.col_degree(CG, self_col_ents[i-1], alpha[m]^flag, k)
2748
+ invariant += (i-j)
2749
+ j = i
2750
+ else:
2751
+ while j < self.nwords:
2752
+ i = j
2753
+ s = 0
2754
+ invariant += 64
2755
+ while True:
2756
+ self_wd_degs[i-j] = self.wd_degree(CG, self_wd_ents[i], alpha[m], k, ham_wts)
2757
+ if s == 0 and self_wd_degs[i-j] != self_wd_degs[0]:
2758
+ s = 1
2759
+ i += 1
2760
+ if self_wd_lvls[i-1] <= k:
2761
+ break
2762
+ if s:
2763
+ invariant += 64
2764
+ t_w = self.sort_wds(j, k)
2765
+ invariant += t_w
2766
+ q = m
2767
+ j ^= flag
2768
+ while q < alpha_length:
2769
+ if alpha[q] == j:
2770
+ alpha[q] = t_w ^ flag
2771
+ break
2772
+ q += 1
2773
+ j ^= flag
2774
+ r = j
2775
+ while True:
2776
+ if r == j or self.wd_lvls[r-1] == k:
2777
+ if r != t_w:
2778
+ alpha[alpha_length] = r^flag
2779
+ alpha_length += 1
2780
+ r += 1
2781
+ if r >= i:
2782
+ break
2783
+ invariant += self.wd_degree(CG, self_wd_ents[i-1], alpha[m], k, ham_wts)
2784
+ invariant += (i-j)
2785
+ j = i
2786
+ m += 1
2787
+ return invariant
2788
+
2789
+ def _clear(self, k):
2790
+ """
2791
+ EXAMPLES::
2792
+
2793
+ sage: import sage.coding.binary_code
2794
+ sage: from sage.coding.binary_code import *
2795
+ sage: P = PartitionStack(2, 6)
2796
+ sage: [P._split_vertex(i,i+1) for i in range(5)]
2797
+ [0, 1, 2, 3, 4]
2798
+ sage: P
2799
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2800
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
2801
+ ({0,1,2,3}) ({0},{1},{2,3,4,5})
2802
+ ({0,1,2,3}) ({0},{1},{2},{3,4,5})
2803
+ ({0,1,2,3}) ({0},{1},{2},{3},{4,5})
2804
+ ({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
2805
+ sage: P._clear(2)
2806
+ sage: P
2807
+ ({0,1,2,3}) ({0,1,2,3,4,5})
2808
+ ({0,1,2,3}) ({0},{1,2,3,4,5})
2809
+ """
2810
+ self.clear(k)
2811
+
2812
+ cdef void clear(self, int k) noexcept:
2813
+ cdef int i, j = 0, nwords = self.nwords, ncols = self.ncols
2814
+ cdef int *wd_lvls = self.wd_lvls
2815
+ cdef int *col_lvls = self.col_lvls
2816
+ for i from 0 <= i < nwords:
2817
+ if wd_lvls[i] >= k:
2818
+ wd_lvls[i] += 1
2819
+ if wd_lvls[i] < k:
2820
+ self.wd_percolate(j, i)
2821
+ j = i + 1
2822
+ j = 0
2823
+ for i from 0 <= i < ncols:
2824
+ if col_lvls[i] >= k:
2825
+ col_lvls[i] += 1
2826
+ if col_lvls[i] < k:
2827
+ self.col_percolate(j, i)
2828
+ j = i + 1
2829
+
2830
+ cpdef int cmp(self, PartitionStack other, BinaryCode CG) noexcept:
2831
+ """
2832
+ EXAMPLES::
2833
+
2834
+ sage: import sage.coding.binary_code
2835
+ sage: from sage.coding.binary_code import *
2836
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0], [0,0,1,1,1,1,0,0],
2837
+ ....: [0,0,0,0,1,1,1,1], [1,0,1,0,1,0,1,0]])
2838
+ sage: B = BinaryCode(M)
2839
+ sage: P = PartitionStack(4, 8)
2840
+ sage: P._refine(0, [[0,0],[1,0]], B)
2841
+ 181
2842
+ sage: P._split_vertex(0, 1)
2843
+ 0
2844
+ sage: P._refine(1, [[0,0]], B)
2845
+ 290
2846
+ sage: P._split_vertex(1, 2)
2847
+ 1
2848
+ sage: P._refine(2, [[0,1]], B)
2849
+ 463
2850
+ sage: P._split_vertex(2, 3)
2851
+ 2
2852
+ sage: P._refine(3, [[0,2]], B)
2853
+ 1500
2854
+ sage: P._split_vertex(4, 4)
2855
+ 4
2856
+ sage: P._refine(4, [[0,4]], B)
2857
+ 1224
2858
+ sage: P._is_discrete(4)
2859
+ 1
2860
+ sage: Q = PartitionStack(P)
2861
+ sage: Q._clear(4)
2862
+ sage: Q._split_vertex(5, 4)
2863
+ 4
2864
+ sage: Q._refine(4, [[0,4]], B)
2865
+ 1224
2866
+ sage: Q._is_discrete(4)
2867
+ 1
2868
+ sage: Q.cmp(P, B)
2869
+ 0
2870
+ """
2871
+ cdef int i, j, l, m, ncols = self.ncols, nwords = self.nwords
2872
+ for i in range(1, nwords):
2873
+ for j in range(ncols):
2874
+ l = CG.is_one(self.wd_ents[i], self.col_ents[j])
2875
+ m = CG.is_one(other.wd_ents[i], other.col_ents[j])
2876
+ if l != m:
2877
+ return l - m
2878
+ return 0
2879
+
2880
+ def print_basis(self):
2881
+ """
2882
+ EXAMPLES::
2883
+
2884
+ sage: import sage.coding.binary_code
2885
+ sage: from sage.coding.binary_code import *
2886
+ sage: P = PartitionStack(4, 8)
2887
+ sage: P._dangerous_dont_use_set_ents_lvls(
2888
+ ....: list(range(8)),
2889
+ ....: list(range(7)) + [-1],
2890
+ ....: [4,7,12,11,1,9,3,0,2,5,6,8,10,13,14,15],
2891
+ ....: [0]*16)
2892
+ sage: P
2893
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1,2,3,4,5,6,7})
2894
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2,3,4,5,6,7})
2895
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3,4,5,6,7})
2896
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4,5,6,7})
2897
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5,6,7})
2898
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6,7})
2899
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6},{7})
2900
+ sage: P._find_basis()
2901
+ sage: P.print_basis()
2902
+ basis_locations:
2903
+ 4
2904
+ 8
2905
+ 0
2906
+ 11
2907
+ """
2908
+ cdef int i, j
2909
+ if self.basis_locations:
2910
+ print("basis_locations:")
2911
+ j = 1
2912
+ while (1 << j) < self.nwords:
2913
+ j += 1
2914
+ for i from 0 <= i < j:
2915
+ print(self.basis_locations[i])
2916
+
2917
+ def _find_basis(self):
2918
+ """
2919
+ EXAMPLES::
2920
+
2921
+ sage: import sage.coding.binary_code
2922
+ sage: from sage.coding.binary_code import *
2923
+ sage: P = PartitionStack(4, 8)
2924
+ sage: P._dangerous_dont_use_set_ents_lvls(list(range(8)), list(range(7))+[-1], [4,7,12,11,1,9,3,0,2,5,6,8,10,13,14,15], [0]*16)
2925
+ sage: P
2926
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1,2,3,4,5,6,7})
2927
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2,3,4,5,6,7})
2928
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3,4,5,6,7})
2929
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4,5,6,7})
2930
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5,6,7})
2931
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6,7})
2932
+ ({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6},{7})
2933
+ sage: P._find_basis()
2934
+ sage: P.print_basis()
2935
+ basis_locations:
2936
+ 4
2937
+ 8
2938
+ 0
2939
+ 11
2940
+ """
2941
+ cdef int *ham_wts = hamming_weights()
2942
+ self.find_basis(ham_wts)
2943
+ sig_free(ham_wts)
2944
+
2945
+ cdef int find_basis(self, int *ham_wts) noexcept:
2946
+ cdef int i = 0, j, k, nwords = self.nwords, weight, basis_elts = 0, nrows = self.nrows
2947
+ cdef int *self_wd_ents = self.wd_ents
2948
+ if self.basis_locations is NULL:
2949
+ self.basis_locations = <int *> sig_malloc(2 * nrows * sizeof(int))
2950
+ if self.basis_locations is NULL:
2951
+ raise MemoryError("Memory.")
2952
+ while i < nwords:
2953
+ j = self_wd_ents[i]
2954
+ weight = ham_wts[j & 65535] + ham_wts[(j>>16) & 65535]
2955
+ if weight == 1:
2956
+ basis_elts += 1
2957
+ k = 0
2958
+ while not (1<<k) & j:
2959
+ k += 1
2960
+ self.basis_locations[k] = i
2961
+ if basis_elts == nrows:
2962
+ break
2963
+ i += 1
2964
+ for i from 0 <= i < nrows:
2965
+ self.basis_locations[nrows + i] = self_wd_ents[1 << i]
2966
+
2967
+ def _get_permutation(self, other):
2968
+ """
2969
+ EXAMPLES::
2970
+
2971
+ sage: import sage.coding.binary_code
2972
+ sage: from sage.coding.binary_code import *
2973
+ sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
2974
+ sage: B = BinaryCode(M)
2975
+ sage: P = PartitionStack(4, 8)
2976
+ sage: P._refine(0, [[0,0],[1,0]], B)
2977
+ 181
2978
+ sage: P._split_vertex(0, 1)
2979
+ 0
2980
+ sage: P._refine(1, [[0,0]], B)
2981
+ 290
2982
+ sage: P._split_vertex(1, 2)
2983
+ 1
2984
+ sage: P._refine(2, [[0,1]], B)
2985
+ 463
2986
+ sage: P._split_vertex(2, 3)
2987
+ 2
2988
+ sage: P._refine(3, [[0,2]], B)
2989
+ 1500
2990
+ sage: P._split_vertex(4, 4)
2991
+ 4
2992
+ sage: P._refine(4, [[0,4]], B)
2993
+ 1224
2994
+ sage: P._is_discrete(4)
2995
+ 1
2996
+ sage: Q = PartitionStack(P)
2997
+ sage: Q._clear(4)
2998
+ sage: Q._split_vertex(5, 4)
2999
+ 4
3000
+ sage: Q._refine(4, [[0,4]], B)
3001
+ 1224
3002
+ sage: Q._is_discrete(4)
3003
+ 1
3004
+ sage: P._get_permutation(Q)
3005
+ ([0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 8, 9, 10, 11], [0, 1, 2, 3, 5, 4, 7, 6])
3006
+ """
3007
+ cdef int i
3008
+ cdef MemoryAllocator loc_mem = MemoryAllocator()
3009
+ cdef int *word_g = <int *> loc_mem.malloc(self.nwords * sizeof(int))
3010
+ cdef int *col_g = <int *> loc_mem.malloc(self.ncols * sizeof(int))
3011
+ self.get_permutation(other, word_g, col_g)
3012
+ word_l = [word_g[i] for i from 0 <= i < self.nwords]
3013
+ col_l = [col_g[i] for i from 0 <= i < self.ncols]
3014
+ return word_l, col_l
3015
+
3016
+ cdef void get_permutation(self, PartitionStack other, int *word_gamma, int *col_gamma) noexcept:
3017
+ cdef int i
3018
+ cdef int *self_wd_ents = self.wd_ents
3019
+ cdef int *other_wd_ents = other.wd_ents
3020
+ cdef int *self_col_ents = self.col_ents
3021
+ cdef int *other_col_ents = other.col_ents
3022
+ # word_gamma[i] := image of the ith row as linear comb of rows
3023
+ for i from 0 <= i < self.nwords:
3024
+ word_gamma[other_wd_ents[i]] = self_wd_ents[i]
3025
+ for i from 0 <= i < self.ncols:
3026
+ col_gamma[other_col_ents[i]] = self_col_ents[i]
3027
+
3028
+ cdef class BinaryCodeClassifier:
3029
+
3030
+ def __cinit__(self):
3031
+ """
3032
+ Initialize.
3033
+
3034
+ TESTS::
3035
+
3036
+ sage: import sage.coding.binary_code
3037
+ sage: from sage.coding.binary_code import *
3038
+ sage: BC = BinaryCodeClassifier()
3039
+ sage: TestSuite(BC).run(skip='_test_pickling')
3040
+ """
3041
+ self.radix = sizeof(codeword) << 3
3042
+ self.ham_wts = hamming_weights()
3043
+ self.L = 100 # memory limit for Phi and Omega- multiply by 8KB
3044
+ self.aut_gens_size = self.radix * 100
3045
+
3046
+ self.w_gamma_size = 1 << (self.radix/2)
3047
+ self.alpha_size = self.w_gamma_size + self.radix
3048
+ self.Phi_size = self.w_gamma_size/self.radix + 1
3049
+
3050
+ self.mem = MemoryAllocator()
3051
+ self.w_gamma = <int *> self.mem.malloc(self.w_gamma_size * sizeof(int))
3052
+ self.alpha = <int *> self.mem.malloc(self.alpha_size * sizeof(int))
3053
+ self.Phi = <unsigned int *> self.mem.malloc(self.Phi_size * (self.L+1) * sizeof(unsigned int))
3054
+ self.Omega = <unsigned int *> self.mem.malloc(self.Phi_size * self.L * sizeof(unsigned int))
3055
+ self.W = <unsigned int *> self.mem.malloc(self.Phi_size * self.radix * 2 * sizeof(unsigned int))
3056
+
3057
+ self.base = <int *> self.mem.malloc(self.radix * sizeof(int))
3058
+ self.aut_gp_gens = <int *> self.mem.malloc(self.aut_gens_size * sizeof(int))
3059
+ self.c_gamma = <int *> self.mem.malloc(self.radix * sizeof(int))
3060
+ self.labeling = <int *> self.mem.malloc(self.radix * 3 * sizeof(int))
3061
+ self.Lambda1 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
3062
+ self.Lambda2 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
3063
+ self.Lambda3 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
3064
+ self.v = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
3065
+ self.e = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
3066
+
3067
+ cdef void record_automorphism(self, int *gamma, int ncols) noexcept:
3068
+ cdef int i, j
3069
+ if self.aut_gp_index + ncols > self.aut_gens_size:
3070
+ self.aut_gens_size *= 2
3071
+ self.aut_gp_gens = <int *> self.mem.realloc(self.aut_gp_gens, self.aut_gens_size * sizeof(int))
3072
+ j = self.aut_gp_index
3073
+ for i from 0 <= i < ncols:
3074
+ self.aut_gp_gens[i+j] = gamma[i]
3075
+ self.aut_gp_index += ncols
3076
+
3077
+ def _aut_gp_and_can_label(self, CC, verbosity=0):
3078
+ """
3079
+ Compute the automorphism group and canonical label of the code ``CC``.
3080
+
3081
+ INPUT:
3082
+
3083
+ - ``CC`` -- a BinaryCode object
3084
+ - ``verbosity`` -- nonnegative integer
3085
+
3086
+ OUTPUT:
3087
+
3088
+ a tuple, (gens, labeling, size, base)
3089
+ - gens; list of permutations (in list form) representing generators
3090
+ of the permutation automorphism group of the code CC
3091
+ - labeling; a permutation representing the canonical labeling of the
3092
+ code. mostly for internal use; entries describe the relabeling
3093
+ on the columns.
3094
+ - size; the order of the automorphism group
3095
+ - base; a set of cols whose action determines the action on all cols
3096
+
3097
+ EXAMPLES::
3098
+
3099
+ sage: import sage.coding.binary_code
3100
+ sage: from sage.coding.binary_code import *
3101
+ sage: BC = BinaryCodeClassifier()
3102
+
3103
+ sage: M = Matrix(GF(2),[
3104
+ ....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0],
3105
+ ....: [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
3106
+ ....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
3107
+ ....: [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
3108
+ ....: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]])
3109
+ sage: B = BinaryCode(M)
3110
+ sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
3111
+
3112
+ sage: # needs sage.groups
3113
+ sage: S = SymmetricGroup(M.ncols())
3114
+ sage: L = [S([x+1 for x in g]) for g in gens]
3115
+ sage: PermutationGroup(L).order()
3116
+ 322560
3117
+ sage: size
3118
+ 322560
3119
+
3120
+ sage: M = Matrix(GF(2),[
3121
+ ....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
3122
+ ....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],
3123
+ ....: [0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1],
3124
+ ....: [0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1]])
3125
+ sage: B = BinaryCode(M)
3126
+ sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
3127
+
3128
+ sage: # needs sage.groups
3129
+ sage: S = SymmetricGroup(M.ncols())
3130
+ sage: L = [S([x+1 for x in g]) for g in gens]
3131
+ sage: PermutationGroup(L).order()
3132
+ 2304
3133
+ sage: size
3134
+ 2304
3135
+
3136
+ sage: M = Matrix(GF(2),[
3137
+ ....: [1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
3138
+ ....: [0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0],
3139
+ ....: [0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0],
3140
+ ....: [0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0],
3141
+ ....: [0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0],
3142
+ ....: [0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0],
3143
+ ....: [0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0],
3144
+ ....: [0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1]])
3145
+ sage: B = BinaryCode(M)
3146
+ sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
3147
+
3148
+ sage: # needs sage.groups
3149
+ sage: S = SymmetricGroup(M.ncols())
3150
+ sage: L = [S([x+1 for x in g]) for g in gens]
3151
+ sage: PermutationGroup(L).order()
3152
+ 136
3153
+ sage: size
3154
+ 136
3155
+
3156
+ sage: M = Matrix(GF(2),[
3157
+ ....: [0,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1],
3158
+ ....: [1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0],
3159
+ ....: [0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,1,1,1,0,1,0,0],
3160
+ ....: [1,1,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1],
3161
+ ....: [1,1,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,1,0,0,1,0],
3162
+ ....: [1,0,0,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,0],
3163
+ ....: [0,0,0,1,0,0,1,0,1,1,1,1,1,1,0,1,0,0,1,0,0,0],
3164
+ ....: [0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1],
3165
+ ....: [0,1,0,0,1,0,1,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1],
3166
+ ....: [1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,1,0,0,0,1,1,1],
3167
+ ....: [0,0,1,0,1,1,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,0]])
3168
+ sage: B = BinaryCode(M)
3169
+ sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
3170
+
3171
+ sage: # needs sage.groups
3172
+ sage: S = SymmetricGroup(M.ncols())
3173
+ sage: L = [S([x+1 for x in g]) for g in gens]
3174
+ sage: PermutationGroup(L).order()
3175
+ 887040
3176
+ sage: size
3177
+ 887040
3178
+
3179
+ sage: B = BinaryCode(Matrix(GF(2),[[1,0,1],[0,1,1]]))
3180
+ sage: BC._aut_gp_and_can_label(B)
3181
+ ([[0, 2, 1], [1, 0, 2]], [0, 1, 2], 6, [0, 1])
3182
+
3183
+ sage: B = BinaryCode(Matrix(GF(2),[[1,1,1,1]]))
3184
+ sage: BC._aut_gp_and_can_label(B)
3185
+ ([[0, 1, 3, 2], [0, 2, 1, 3], [1, 0, 2, 3]], [0, 1, 2, 3], 24, [0, 1, 2])
3186
+
3187
+ sage: B = BinaryCode(Matrix(GF(2),[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]]))
3188
+ sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
3189
+ sage: size
3190
+ 87178291200
3191
+
3192
+ sage: M = Matrix(GF(2),[
3193
+ ....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0],
3194
+ ....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
3195
+ ....: [0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1],
3196
+ ....: [0,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,1],
3197
+ ....: [0,0,0,1,0,0,0,1,0,1,0,1,0,1,1,1,0,1],
3198
+ ....: [0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,1,1,0]])
3199
+ sage: B = BinaryCode(M)
3200
+ sage: BC._aut_gp_and_can_label(B)[2]
3201
+ 2160
3202
+
3203
+ sage: M = Matrix(GF(2),[
3204
+ ....: [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
3205
+ ....: [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
3206
+ ....: [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
3207
+ ....: [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],
3208
+ ....: [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
3209
+ ....: [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0],
3210
+ ....: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
3211
+ ....: [1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,1,1,0,0],
3212
+ ....: [1,1,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0],
3213
+ ....: [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0]])
3214
+ sage: B = BinaryCode(M)
3215
+ sage: BC._aut_gp_and_can_label(B)[2]
3216
+ 294912
3217
+
3218
+ sage: M = Matrix(GF(2), [
3219
+ ....: [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
3220
+ ....: [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
3221
+ ....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
3222
+ ....: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],
3223
+ ....: [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0],
3224
+ ....: [0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0],
3225
+ ....: [0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1],
3226
+ ....: [0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1],
3227
+ ....: [0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,1,1,1,0,0,0,1]])
3228
+ sage: B = BinaryCode(M)
3229
+ sage: BC = BinaryCodeClassifier()
3230
+ sage: BC._aut_gp_and_can_label(B)[2]
3231
+ 442368
3232
+ """
3233
+ cdef int i, j
3234
+ cdef BinaryCode C = CC
3235
+ self.aut_gp_and_can_label(C, verbosity)
3236
+ i = 0
3237
+ py_aut_gp_gens = []
3238
+ while i < self.aut_gp_index:
3239
+ gen = [self.aut_gp_gens[i+j] for j from 0 <= j < C.ncols]
3240
+ py_aut_gp_gens.append(gen)
3241
+ i += C.ncols
3242
+ py_labeling = [self.labeling[i] for i from 0 <= i < C.ncols]
3243
+ base = []
3244
+ for i from 0 <= i < self.radix:
3245
+ if self.base[i] == -1:
3246
+ break
3247
+ base.append(self.base[i])
3248
+ aut_gp_size = self.aut_gp_size
3249
+ return py_aut_gp_gens, py_labeling, aut_gp_size, base
3250
+
3251
+ cdef void aut_gp_and_can_label(self, BinaryCode C, int verbosity) noexcept:
3252
+
3253
+ # declare variables:
3254
+ cdef int i, j, ii, jj, iii, jjj, iiii # local variables
3255
+
3256
+ cdef PartitionStack nu, zeta, rho # nu is the current position in the tree,
3257
+ # zeta the first terminal position,
3258
+ # and rho the best-so-far guess at canonical labeling position
3259
+ cdef int k = 0 # the number of partitions in nu
3260
+ cdef int k_rho # the number of partitions in rho
3261
+ cdef int *v = self.v # list of vertices determining nu
3262
+ cdef int h = -1 # longest common ancestor of zeta and nu: zeta[h] == nu[h], zeta[h+1] != nu[h+1]
3263
+ # -1 indicates that zeta is not yet defined
3264
+ cdef int hb # longest common ancestor of rho and nu:
3265
+ # rho[hb] == nu[hb], rho[hb+1] != nu[hb+1]
3266
+ cdef int hh = 1 # the height of the oldest ancestor of nu satisfying Lemma 2.25 in [1]:
3267
+ # if nu does not satisfy it at k, then hh = k
3268
+ cdef int ht # smallest such that all descendants of zeta[ht] are equivalent under
3269
+ # the portion of the automorphism group so far discovered
3270
+ cdef int *alpha # for storing pointers to cells of nu[k]
3271
+ cdef int tvc # tvc keeps track of which vertex is the first where nu and zeta differ-
3272
+ # zeta was defined by splitting one vertex, and nu was defined by splitting tvc
3273
+
3274
+ cdef OrbitPartition Theta # keeps track of which vertices have been discovered to be equivalent
3275
+ cdef unsigned int *Phi # Phi stores the fixed point sets of each automorphism
3276
+ cdef unsigned int *Omega # Omega stores the minimal elements of each cell of the orbit partition
3277
+ cdef int l = -1 # current index for storing values in Phi and Omega- we start at -1 so that when
3278
+ # we increment first, the first place we write to is 0.
3279
+ cdef unsigned int *W # for each k, W[k] is a list (as int mask) of the vertices to be searched down from
3280
+ # the current partition, at k. Phi and Omega are ultimately used to make the size of
3281
+ # W as small as possible
3282
+ cdef int *e # 0 or 1, whether or not we have used Omega and Phi to narrow down W[k] yet: see states 12 and 17
3283
+
3284
+ cdef int index = 0 # Define $\Gamma^{(-1)} := \text{Aut}(C)$, and
3285
+ # $\Gamma^{(i)} := \Gamma^{(-1)}_{v_0,...,v_i}$.
3286
+ # Then index = $|\Gamma^{(k-1)}|/|\Gamma^{(k)}|$ at (POINT A)
3287
+ # and size = $|\Gamma^{(k-1)}|$ at (POINT A) and (POINT B).
3288
+
3289
+ cdef int *Lambda = self.Lambda1 # for tracking indicator values- zf and zb are
3290
+ cdef int *zf__Lambda_zeta = self.Lambda2 # indicator vectors remembering Lambda[k] for
3291
+ cdef int *zb__Lambda_rho = self.Lambda3 # zeta and rho, respectively
3292
+ cdef int qzb # keeps track of Lambda[k] {>,<,=} zb[k]
3293
+ cdef int hzf__h_zeta # the max height for which Lambda and zf agree
3294
+ cdef int hzb__h_rho = -1 # the max height for which Lambda and zb agree
3295
+
3296
+ cdef int *word_gamma
3297
+ cdef int *col_gamma = self.c_gamma # used for storing permutations
3298
+ cdef int nwords = C.nwords, ncols = C.ncols, nrows = C.nrows
3299
+ cdef int *ham_wts = self.ham_wts
3300
+ cdef int state # keeps track of position in algorithm - see sage/graphs/graph_isom.pyx, search for "STATE DIAGRAM"
3301
+
3302
+ self.aut_gp_index = 0
3303
+ self.aut_gp_size = Integer(1)
3304
+
3305
+ if self.w_gamma_size < nwords:
3306
+ while self.w_gamma_size < nwords:
3307
+ self.w_gamma_size *= 2
3308
+ self.alpha_size = self.w_gamma_size + self.radix
3309
+ self.Phi_size = self.w_gamma_size/self.radix + 1
3310
+ self.w_gamma = <int *> self.mem.realloc(self.w_gamma, self.w_gamma_size * sizeof(int))
3311
+ self.alpha = <int *> self.mem.realloc(self.alpha, self.alpha_size * sizeof(int))
3312
+ self.Phi = <unsigned int *> self.mem.realloc(self.Phi, self.Phi_size * self.L * sizeof(int))
3313
+ self.Omega = <unsigned int *> self.mem.realloc(self.Omega, self.Phi_size * self.L * sizeof(int))
3314
+ self.W = <unsigned int *> self.mem.realloc(self.W, self.Phi_size * self.radix * 2 * sizeof(int))
3315
+
3316
+ for i from 0 <= i < self.Phi_size * self.L:
3317
+ self.Omega[i] = 0
3318
+ word_gamma = self.w_gamma
3319
+ alpha = self.alpha # think of alpha as of length exactly nwords + ncols
3320
+ Phi = self.Phi
3321
+ Omega = self.Omega
3322
+ W = self.W
3323
+ e = self.e
3324
+ nu = PartitionStack(nrows, ncols)
3325
+ Theta = OrbitPartition(nrows, ncols)
3326
+
3327
+ # trivial case
3328
+ if ncols == 0 or nrows == 0:
3329
+ raise NotImplementedError("Must supply a nontrivial code.")
3330
+
3331
+ state = 1
3332
+ while state != -1:
3333
+
3334
+ if state == 1: # Entry point: once only
3335
+ alpha[0] = 0
3336
+ alpha[1] = nu.flag
3337
+ nu.refine(k, alpha, 2, C, ham_wts)
3338
+ if nu.sat_225(k):
3339
+ hh = k
3340
+ if nu.is_discrete(k):
3341
+ state = 18
3342
+ continue
3343
+
3344
+ # store the first smallest nontrivial cell in W[k], and set v[k]
3345
+ # equal to its minimum element
3346
+ v[k] = nu.new_first_smallest_nontrivial(k, W, self.Phi_size * k)
3347
+
3348
+ Lambda[k] = 0
3349
+ e[k] = 0
3350
+ state = 2
3351
+
3352
+ elif state == 2: # Move down the search tree one level by refining nu:
3353
+ # split out a vertex, and refine nu against it
3354
+ k += 1
3355
+ nu.clear(k)
3356
+
3357
+ alpha[0] = nu.split_vertex(v[k-1], k)
3358
+ Lambda[k] = nu.refine(k, alpha, 1, C, ham_wts) # store the invariant to Lambda[k]
3359
+ # only if this is the first time moving down the search tree:
3360
+ if h == -1:
3361
+ state = 5
3362
+ continue
3363
+
3364
+ # update hzf__h_zeta
3365
+ if hzf__h_zeta == k-1 and Lambda[k] == zf__Lambda_zeta[k]:
3366
+ hzf__h_zeta = k
3367
+ # update qzb
3368
+ if qzb == 0:
3369
+ if zb__Lambda_rho[k] == -1 or Lambda[k] < zb__Lambda_rho[k]:
3370
+ qzb = -1
3371
+ elif Lambda[k] > zb__Lambda_rho[k]:
3372
+ qzb = 1
3373
+ else:
3374
+ qzb = 0
3375
+ # update hzb
3376
+ if hzb__h_rho == k-1 and qzb == 0:
3377
+ hzb__h_rho = k
3378
+ # if Lambda[k] > zb[k], then zb[k] := Lambda[k]
3379
+ # (zb keeps track of the indicator invariants corresponding to
3380
+ # rho, the closest canonical leaf so far seen- if Lambda is
3381
+ # bigger, then rho must be about to change
3382
+ if qzb > 0:
3383
+ zb__Lambda_rho[k] = Lambda[k]
3384
+ state = 3
3385
+
3386
+ elif state == 3: # attempt to rule out automorphisms while moving down the tree
3387
+ # if k > hzf, then we know that nu currently does not look like zeta, the first
3388
+ # terminal node encountered, thus there is no automorphism to discover. If qzb < 0,
3389
+ # i.e. Lambda[k] < zb[k], then the indicator is not maximal, and we can't reach a
3390
+ # canonical leaf. If neither of these is the case, then proceed to state 4.
3391
+ if hzf__h_zeta <= k or qzb >= 0:
3392
+ state = 4
3393
+ else:
3394
+ state = 6
3395
+
3396
+ elif state == 4: # at this point we have -not- ruled out the presence of automorphisms
3397
+ if nu.is_discrete(k):
3398
+ state = 7
3399
+ continue # we have a terminal node, so process it
3400
+
3401
+ # otherwise, prepare to split out another column:
3402
+ # store the first smallest nontrivial cell in W[k], and set v[k]
3403
+ # equal to its minimum element
3404
+ v[k] = nu.new_first_smallest_nontrivial(k, W, self.Phi_size * k)
3405
+ if not nu.sat_225(k):
3406
+ hh = k + 1
3407
+ e[k] = 0 # see state 12 and 17
3408
+ state = 2 # continue down the tree
3409
+
3410
+ elif state == 5:
3411
+ # same as state 3, but in the case where we haven't yet defined zeta
3412
+ # i.e. this is our first time down the tree. Once we get to the bottom,
3413
+ # we will have zeta = nu = rho, so we do:
3414
+ zf__Lambda_zeta[k] = Lambda[k]
3415
+ zb__Lambda_rho[k] = Lambda[k]
3416
+ state = 4
3417
+
3418
+ elif state == 6: # at this stage, there is no reason to continue downward, so backtrack
3419
+ j = k
3420
+
3421
+ # return to the longest ancestor nu[i] of nu that could have a
3422
+ # descendant equivalent to zeta or could improve on rho.
3423
+ # All terminal nodes descending from nu[hh] are known to be
3424
+ # equivalent, so i < hh. Also, if i > hzb, none of the
3425
+ # descendants of nu[i] can improve rho, since the indicator is
3426
+ # off (Lambda(nu) < Lambda(rho)). If i >= ht, then no descendant
3427
+ # of nu[i] is equivalent to zeta (see [1, p67]).
3428
+ if ht-1 > hzb__h_rho:
3429
+ if ht-1 < hh-1:
3430
+ k = ht-1
3431
+ else:
3432
+ k = hh-1
3433
+ else:
3434
+ if hzb__h_rho < hh-1:
3435
+ k = hzb__h_rho
3436
+ else:
3437
+ k = hh-1
3438
+ # TODO: is the following line necessary?
3439
+ if k == -1:
3440
+ k = 0
3441
+
3442
+ if hb > k: # update hb since we are backtracking
3443
+ hb = k
3444
+ # if j == hh, then all nodes lower than our current position are equivalent, so bail out
3445
+ if j == hh:
3446
+ state = 13
3447
+ continue
3448
+
3449
+ # recall hh: the height of the oldest ancestor of zeta for which Lemma 2.25 is
3450
+ # satisfied, which implies that all terminal nodes descended from there are equivalent.
3451
+ # If we are looking at such a node, then the partition at nu[hh] can be used for later
3452
+ # pruning, so we store its fixed set and a set of representatives of its cells.
3453
+ if l < self.L-1:
3454
+ l += 1
3455
+ nu.new_min_cell_reps(hh, Omega, self.Phi_size*l)
3456
+ nu.fixed_vertices(hh, Phi, Omega, self.Phi_size*l)
3457
+
3458
+ state = 12
3459
+
3460
+ elif state == 7: # we have just arrived at a terminal node of the search tree T(G, Pi)
3461
+ # if this is the first terminal node, go directly to 18, to
3462
+ # process zeta
3463
+ if h == -1:
3464
+ state = 18
3465
+ continue
3466
+
3467
+ # hzf is the extremal height of ancestors of both nu and zeta, so if k < hzf, nu is not
3468
+ # equivalent to zeta, i.e. there is no automorphism to discover.
3469
+ if k < hzf__h_zeta:
3470
+ state = 8
3471
+ continue
3472
+
3473
+ nu.get_permutation(zeta, word_gamma, col_gamma)
3474
+
3475
+ # if C^gamma == C, the permutation is an automorphism, goto 10
3476
+ if C.is_automorphism(col_gamma, word_gamma):
3477
+ state = 10
3478
+ else:
3479
+ state = 8
3480
+
3481
+ elif state == 8: # we have just ruled out the presence of automorphism and have not yet
3482
+ # considered whether nu improves on rho
3483
+ # if qzb < 0, then rho already has larger indicator tuple
3484
+ if qzb < 0:
3485
+ state = 6
3486
+ continue
3487
+
3488
+ # if Lambda[k] > zb[k] or nu is shorter than rho, then we have an improvement for rho
3489
+ if (qzb > 0) or (k < k_rho):
3490
+ state = 9
3491
+ continue
3492
+
3493
+ # now Lambda[k] == zb[k] and k == k_rho, so we appeal to an enumeration:
3494
+ j = nu.cmp(rho, C)
3495
+ # if C(nu) > C(rho), we have a new label, goto 9
3496
+ if j > 0:
3497
+ state = 9
3498
+ continue
3499
+
3500
+ # if C(nu) < C(rho), no new label, goto 6
3501
+ if j < 0:
3502
+ state = 6
3503
+ continue
3504
+
3505
+ # if C(nu) == C(rho), get the automorphism and goto 10
3506
+ rho.get_permutation(nu, word_gamma, col_gamma)
3507
+
3508
+ state = 10
3509
+
3510
+ elif state == 9: # nu is a better guess at the canonical label than rho
3511
+ rho = PartitionStack(nu)
3512
+ k_rho = k
3513
+ qzb = 0
3514
+ hb = k
3515
+ hzb__h_rho = k
3516
+ # set zb[k+1] = Infinity
3517
+ zb__Lambda_rho[k+1] = -1
3518
+ state = 6
3519
+
3520
+ elif state == 10: # we have an automorphism to process
3521
+ # increment l
3522
+ if l < self.L-1: l += 1
3523
+ # store information about the automorphism to Omega and Phi
3524
+ ii = self.Phi_size*l
3525
+ jj = 1 + nwords/self.radix
3526
+ # Omega[ii] = ~(~0 << ncols)
3527
+ for i from 0 <= i < jj:
3528
+ Omega[ii+i] = ~0
3529
+ Phi[ii+i] = 0
3530
+ if nwords % self.radix:
3531
+ jj += 1
3532
+ # Omega[ii+jj-1] = ~((1 << nwords % self.radix) - 1)
3533
+ # Omega stores the minimum cell representatives
3534
+ i = 0
3535
+ while i < ncols:
3536
+ j = col_gamma[i] # i is a minimum
3537
+ while j != i: # cell rep,
3538
+ Omega[ii] ^= (1<<j) # so cancel
3539
+ j = col_gamma[j] # cellmates
3540
+ i += 1
3541
+ while i < ncols and not Omega[ii]&(1<<i): # find minimal element
3542
+ i += 1 # of next cell
3543
+ i = 0
3544
+ jj = self.radix
3545
+ while i < nwords:
3546
+ j = word_gamma[i]
3547
+ while j != i:
3548
+ Omega[ii+1+j/jj] ^= (1<<(j % jj))
3549
+ j = word_gamma[j]
3550
+ i += 1
3551
+ while i < nwords and not Omega[ii+1+i/jj]&(1<<(i % jj)):
3552
+ i += 1
3553
+ # Phi stores the columns fixed by the automorphism
3554
+ for i from 0 <= i < ncols:
3555
+ if col_gamma[i] == i:
3556
+ Phi[ii] ^= (1 << i)
3557
+ for i from 0 <= i < nwords:
3558
+ if word_gamma[i] == i:
3559
+ Phi[ii+1+i/jj] ^= (1<<(i % jj))
3560
+
3561
+ # Now incorporate the automorphism into Theta
3562
+ j = Theta.merge_perm(col_gamma, word_gamma)
3563
+
3564
+ # j stores whether anything happened or not- if not, then the automorphism we have
3565
+ # discovered is already in the subgroup spanned by the generators we have output
3566
+ if not j:
3567
+ state = 11
3568
+ continue
3569
+
3570
+ # otherwise, we have a new generator, so record it:
3571
+ self.record_automorphism(col_gamma, ncols)
3572
+ # The variable tvc was set to be the minimum element of W[k] the last time the
3573
+ # algorithm came up to meet zeta. At this point, we were considering the new
3574
+ # possibilities for descending away from zeta at this level.
3575
+ # if this is still a minimum cell representative of Theta, even in light
3576
+ # of this new automorphism, then the current branch off of zeta hasn't been
3577
+ # found equivalent to one already searched yet, so there may still be a
3578
+ # better canonical label downward.
3579
+ if tvc & nu.flag:
3580
+ i = tvc^nu.flag
3581
+ if Theta.wd_min_cell_rep[Theta.wd_find(i)] == i:
3582
+ state = 11
3583
+ continue
3584
+ elif Theta.col_min_cell_rep[Theta.col_find(tvc)] == tvc:
3585
+ state = 11
3586
+ continue
3587
+
3588
+ # Otherwise, proceed to where zeta meets nu:
3589
+ k = h
3590
+ state = 13
3591
+
3592
+ elif state == 11: # We have just found a new automorphism, and deduced that there may
3593
+ # be a better canonical label below the current branch off of zeta. So go to where
3594
+ # nu meets rho
3595
+ k = hb
3596
+ state = 12
3597
+
3598
+ elif state == 12: # Coming here from either state 6 or 11, the algorithm has discovered
3599
+ # some new information. 11 came from 10, where a new line in Omega and
3600
+ # Phi was just recorded, and 6 stored information about implicit auto-
3601
+ # morphisms in Omega and Phi
3602
+ if e[k] == 1:
3603
+ # this means that the algorithm has come upward to this position (in state 17)
3604
+ # before, so we have already intersected W[k] with the bulk of Omega and Phi, but
3605
+ # we should still catch up with the latest ones
3606
+ ii = self.Phi_size*l
3607
+ jj = self.Phi_size*k
3608
+ j = 1 + nwords/self.radix
3609
+ if nwords % self.radix:
3610
+ j += 1
3611
+ W[jj] &= Omega[ii]
3612
+ for i from 0 < i < j:
3613
+ W[jj+i] &= Omega[ii+i]
3614
+ state = 13
3615
+
3616
+ elif state == 13: # hub state
3617
+ if k == -1:
3618
+ state = -1
3619
+ continue # exit point
3620
+
3621
+ if k > h:
3622
+ state = 17
3623
+ continue # we are still on the same principal branch from zeta
3624
+
3625
+ if k == h:
3626
+ state = 14
3627
+ continue # update the stabilizer index and check for new splits,
3628
+ # since we have returned to a partition of zeta
3629
+ # otherwise k < h, hence we have just backtracked up zeta, and are one level closer to done
3630
+ h = k
3631
+ tvc = 0
3632
+ jj = self.Phi_size*k
3633
+ if W[jj]:
3634
+ while not (1 << tvc) & W[jj]:
3635
+ tvc += 1
3636
+ else:
3637
+ ii = 0
3638
+ while not W[jj+1+ii]:
3639
+ ii += 1
3640
+ while not W[jj+1+ii] & (1 << tvc):
3641
+ tvc += 1
3642
+ tvc = (ii*self.radix + tvc) ^ nu.flag
3643
+ # now tvc points to the minimal cell representative of W[k]
3644
+ state = 14
3645
+
3646
+ elif state == 14: # see if there are any more splits to make from this level of zeta (see state 17)
3647
+ if v[k]&nu.flag == tvc&nu.flag:
3648
+ if tvc&nu.flag:
3649
+ if Theta.wd_find(v[k]^nu.flag) == Theta.wd_find(tvc^nu.flag):
3650
+ index += 1
3651
+ else:
3652
+ if Theta.col_find(v[k]) == Theta.col_find(tvc):
3653
+ index += 1
3654
+
3655
+ # keep tabs on how many elements are in the same cell of Theta as tvc
3656
+ # find the next split
3657
+ jj = self.Phi_size*k
3658
+ if v[k]&nu.flag:
3659
+ ii = self.radix
3660
+ i = (v[k]^nu.flag) + 1
3661
+ while i < nwords and not (1 << i % ii) & W[jj+1+i/ii]:
3662
+ i += 1
3663
+ if i < nwords:
3664
+ v[k] = i^nu.flag
3665
+ else:
3666
+ # there is no new split at this level
3667
+ state = 16
3668
+ continue
3669
+ # new split column better be a minimal representative in Theta, or wasted effort
3670
+ if Theta.wd_min_cell_rep[Theta.wd_find(i)] == i:
3671
+ state = 15
3672
+ else:
3673
+ state = 14
3674
+ else:
3675
+ i = v[k] + 1
3676
+ while i < ncols and not (1 << i) & W[jj]:
3677
+ i += 1
3678
+ if i < ncols:
3679
+ v[k] = i
3680
+ else:
3681
+ # there is no new split at this level
3682
+ state = 16
3683
+ continue
3684
+ # new split column better be a minimal representative in Theta, or wasted effort
3685
+ if Theta.col_min_cell_rep[Theta.col_find(v[k])] == v[k]:
3686
+ state = 15
3687
+ else:
3688
+ state = 14
3689
+
3690
+ elif state == 15: # split out the column v[k]
3691
+ # hh is smallest such that nu[hh] satisfies Lemma 2.25. If it is larger than k+1,
3692
+ # it must be modified, since we are changing that part
3693
+ if k + 1 < hh:
3694
+ hh = k + 1
3695
+ # hzf is maximal such that indicators line up for nu and zeta
3696
+ if k < hzf__h_zeta:
3697
+ hzf__h_zeta = k
3698
+ # hzb is longest such that nu and rho have the same indicators
3699
+ if hzb__h_rho >= k:
3700
+ hzb__h_rho = k
3701
+ qzb = 0
3702
+ state = 2
3703
+
3704
+ elif state == 16: # backtrack up zeta, updating information about stabilizer vector
3705
+ jj = self.Phi_size*k
3706
+ if W[jj]:
3707
+ i = W[jj]
3708
+ j = ham_wts[i & 65535] + ham_wts[(i >> 16) & 65535]
3709
+ else:
3710
+ i = 0
3711
+ j = 0
3712
+ ii = self.radix
3713
+ while i*ii < nwords:
3714
+ iii = W[jj+1+i]
3715
+ j += ham_wts[iii & 65535] + ham_wts[(iii >> 16) & 65535]
3716
+ i += 1
3717
+ if j == index and ht == k + 1:
3718
+ ht = k
3719
+ self.aut_gp_size *= index
3720
+ # (POINT A)
3721
+ index = 0
3722
+ k -= 1
3723
+ if hb > k: # update hb since we are backtracking
3724
+ hb = k
3725
+ state = 13
3726
+
3727
+ elif state == 17: # see if there are any more splits to make from this level of nu (and not zeta)
3728
+
3729
+ jjj = self.Phi_size*k
3730
+ if e[k] == 0: # now is the time to narrow down W[k] by Omega and Phi
3731
+ # intersect W[k] with each Omega[i] such that v[0]...v[k-1] is in Phi[i]
3732
+ jj = self.Phi_size*self.L
3733
+ iii = nwords/self.radix
3734
+ if nwords % self.radix:
3735
+ iii += 1
3736
+ for ii from 0 <= ii < iii:
3737
+ Phi[jj+ii] = 0
3738
+ for ii from 0 <= ii < k:
3739
+ if v[ii]&nu.flag:
3740
+ i = v[ii]^nu.flag
3741
+ Phi[jj+1+i/self.radix] ^= (1 << i % self.radix)
3742
+ else:
3743
+ Phi[jj] ^= (1 << v[ii])
3744
+ for i from 0 <= i <= l:
3745
+ ii = self.Phi_size*i
3746
+ iiii = 1
3747
+ for j from 0 <= j < iii:
3748
+ if Phi[ii + j] & Phi[jj + j] != Phi[jj + j]:
3749
+ iiii = 0
3750
+ break
3751
+ if iiii:
3752
+ for j from 0 <= j < iii:
3753
+ W[jjj + j] &= Omega[ii + j]
3754
+ e[k] = 1
3755
+
3756
+ # see if there is a vertex to split out
3757
+ if nu.flag&v[k]:
3758
+ i = (v[k]^nu.flag)
3759
+ while i < nwords:
3760
+ i += 1
3761
+ if (1 << i % self.radix) & W[jjj+1+i/self.radix]:
3762
+ break
3763
+ if i < nwords:
3764
+ v[k] = i^nu.flag
3765
+ state = 15
3766
+ continue
3767
+ else:
3768
+ i = v[k]
3769
+ while i < ncols:
3770
+ i += 1
3771
+ if (1 << i) & W[jjj]:
3772
+ break
3773
+ if i < ncols:
3774
+ v[k] = i
3775
+ state = 15
3776
+ continue
3777
+
3778
+ k -= 1
3779
+ state = 13
3780
+
3781
+ elif state == 18: # the first time nu becomes a discrete partition: set up zeta, our "identity" leaf
3782
+ # initialize counters for zeta:
3783
+ h = k # zeta[h] == nu[h]
3784
+ ht = k # nodes descended from zeta[ht] are all equivalent
3785
+ hzf__h_zeta = k # max such that indicators for zeta and nu agree
3786
+ zeta = PartitionStack(nu)
3787
+ for i from 0 <= i < k:
3788
+ self.base[i] = v[i]
3789
+ self.base_size = k
3790
+ if k != self.radix:
3791
+ self.base[k] = -1
3792
+ # (POINT B)
3793
+ k -= 1
3794
+ rho = PartitionStack(nu)
3795
+ # initialize counters for rho:
3796
+ k_rho = k+1 # number of partitions in rho
3797
+ hzb__h_rho = k # max such that indicators for rho and nu agree - BDM had k+1
3798
+ hb = k # rho[hb] == nu[hb] - BDM had k+1
3799
+ qzb = 0 # Lambda[k] == zb[k], so...
3800
+ state = 13
3801
+
3802
+ # end big while loop
3803
+ rho.find_basis(ham_wts)
3804
+ for i from 0 <= i < ncols:
3805
+ self.labeling[rho.col_ents[i]] = i
3806
+ for i from 0 <= i < 2*nrows:
3807
+ self.labeling[i+ncols] = rho.basis_locations[i]
3808
+
3809
+ def put_in_canonical_form(self, BinaryCode B):
3810
+ """
3811
+ Put the code into canonical form.
3812
+
3813
+ Canonical form is obtained by performing row reduction, permuting the
3814
+ pivots to the front so that the generator matrix is of the form: the
3815
+ identity matrix augmented to the right by arbitrary data.
3816
+
3817
+ EXAMPLES::
3818
+
3819
+ sage: from sage.coding.binary_code import *
3820
+ sage: BC = BinaryCodeClassifier()
3821
+ sage: B = BinaryCode(codes.GolayCode(GF(2)).generator_matrix())
3822
+ sage: B.apply_permutation(list(range(24,-1,-1)))
3823
+ sage: B
3824
+ Binary [24,12] linear code, generator matrix
3825
+ [011000111010100000000000]
3826
+ [001001001111100000000001]
3827
+ [011010100101100000000010]
3828
+ [001101110001100000000100]
3829
+ [010011011001100000001000]
3830
+ [010110110011000000010000]
3831
+ [011101100110000000100000]
3832
+ [000011110110100001000000]
3833
+ [000111101101000010000000]
3834
+ [001111011010000100000000]
3835
+ [010110001110101000000000]
3836
+ [011100011101010000000000]
3837
+ sage: BC.put_in_canonical_form(B)
3838
+ sage: B
3839
+ Binary [24,12] linear code, generator matrix
3840
+ [100000000000001100111001]
3841
+ [010000000000001010001111]
3842
+ [001000000000001111010010]
3843
+ [000100000000010110101010]
3844
+ [000010000000010110010101]
3845
+ [000001000000010001101101]
3846
+ [000000100000011000110110]
3847
+ [000000010000011111001001]
3848
+ [000000001000010101110011]
3849
+ [000000000100010011011110]
3850
+ [000000000010001011110101]
3851
+ [000000000001001101101110]
3852
+ """
3853
+ aut_gp_gens, labeling, size, base = self._aut_gp_and_can_label(B)
3854
+ B._apply_permutation_to_basis(labeling)
3855
+ B.put_in_std_form()
3856
+
3857
+ def generate_children(self, BinaryCode B, int n, int d=2):
3858
+ """
3859
+ Use canonical augmentation to generate children of the code `B`.
3860
+
3861
+ INPUT:
3862
+
3863
+ - ``B`` -- a :class:`BinaryCode`
3864
+
3865
+ - ``n`` -- limit on the degree of the code
3866
+
3867
+ - ``d`` -- test whether new vector has weight divisible by `d`. If
3868
+ `d=4`, this ensures that all doubly-even canonically augmented
3869
+ children are generated.
3870
+
3871
+ EXAMPLES::
3872
+
3873
+ sage: from sage.coding.binary_code import *
3874
+ sage: BC = BinaryCodeClassifier()
3875
+ sage: B = BinaryCode(Matrix(GF(2), [[1,1,1,1]]))
3876
+ sage: BC.generate_children(B, 6, 4) # needs sage.groups
3877
+ [
3878
+ [1 1 1 1 0 0]
3879
+ [0 1 0 1 1 1]
3880
+ ]
3881
+
3882
+ .. NOTE::
3883
+
3884
+ The function ``codes.databases.self_orthogonal_binary_codes`` makes heavy
3885
+ use of this function.
3886
+
3887
+ MORE EXAMPLES::
3888
+
3889
+ sage: # needs sage.groups
3890
+ sage: soc_iter = codes.databases.self_orthogonal_binary_codes(12, 6, 4)
3891
+ sage: L = list(soc_iter)
3892
+ sage: for n in range(13):
3893
+ ....: s = 'n=%2d : ' % n
3894
+ ....: for k in range(1,7):
3895
+ ....: s += '%3d ' % len([C for C in L
3896
+ ....: if C.length() == n and C.dimension() == k])
3897
+ ....: print(s)
3898
+ n= 0 : 0 0 0 0 0 0
3899
+ n= 1 : 0 0 0 0 0 0
3900
+ n= 2 : 0 0 0 0 0 0
3901
+ n= 3 : 0 0 0 0 0 0
3902
+ n= 4 : 1 0 0 0 0 0
3903
+ n= 5 : 0 0 0 0 0 0
3904
+ n= 6 : 0 1 0 0 0 0
3905
+ n= 7 : 0 0 1 0 0 0
3906
+ n= 8 : 1 1 1 1 0 0
3907
+ n= 9 : 0 0 0 0 0 0
3908
+ n=10 : 0 1 1 1 0 0
3909
+ n=11 : 0 0 1 1 0 0
3910
+ n=12 : 1 2 3 4 2 0
3911
+ """
3912
+ cdef BinaryCode m
3913
+ cdef codeword *ortho_basis
3914
+ cdef codeword *B_can_lab
3915
+ cdef codeword current, swap
3916
+ cdef codeword word, temp, gate, nonzero_gate, orbit, bwd, k_gate
3917
+ cdef codeword *temp_basis
3918
+ cdef codeword *orbit_checks
3919
+ cdef codeword orb_chx_size, orb_chx_shift, radix_gate
3920
+ cdef WordPermutation *gwp
3921
+ cdef WordPermutation *hwp
3922
+ cdef WordPermutation *can_lab
3923
+ cdef WordPermutation *can_lab_inv
3924
+ cdef WordPermutation **parent_generators
3925
+ cdef BinaryCode B_aug
3926
+ cdef int i, ii, j, jj, ij, k = 0, parity, combo, num_gens
3927
+ cdef int base_size, row
3928
+ cdef int *multimod2_index
3929
+ cdef int *ham_wts = self.ham_wts
3930
+ cdef int *num_inner_gens
3931
+ cdef int *num_outer_gens
3932
+ cdef int *v
3933
+ cdef int log_2_radix
3934
+ cdef bint bingo, bingo2, bingo3
3935
+
3936
+ B.put_in_std_form()
3937
+ ortho_basis = expand_to_ortho_basis(B, n) # modifies B!
3938
+
3939
+ aut_gp_gens, labeling, size, base = self._aut_gp_and_can_label(B)
3940
+ B_can_lab = <codeword *> sig_malloc(B.nrows * sizeof(codeword))
3941
+ can_lab = create_word_perm(labeling[:B.ncols])
3942
+ if B_can_lab is NULL or can_lab is NULL:
3943
+ sig_free(ortho_basis)
3944
+ if B_can_lab is not NULL:
3945
+ sig_free(B_can_lab)
3946
+ if can_lab is not NULL:
3947
+ sig_free(can_lab)
3948
+ raise MemoryError()
3949
+ for i from 0 <= i < B.nrows:
3950
+ B_can_lab[i] = permute_word_by_wp(can_lab, B.basis[i])
3951
+ dealloc_word_perm(can_lab)
3952
+ row = 0
3953
+ current = 1
3954
+ while row < B.nrows:
3955
+ i = row
3956
+ while i < B.nrows and not B_can_lab[i] & current:
3957
+ i += 1
3958
+ if i < B.nrows:
3959
+ if i != row:
3960
+ swap = B_can_lab[row]
3961
+ B_can_lab[row] = B_can_lab[i]
3962
+ B_can_lab[i] = swap
3963
+ for j from 0 <= j < row:
3964
+ if B_can_lab[j] & current:
3965
+ B_can_lab[j] ^= B_can_lab[row]
3966
+ for j from row < j < B.nrows:
3967
+ if B_can_lab[j] & current:
3968
+ B_can_lab[j] ^= B_can_lab[row]
3969
+ row += 1
3970
+ current = current << 1
3971
+ num_gens = len(aut_gp_gens)
3972
+ base_size = len(base)
3973
+
3974
+ parent_generators = <WordPermutation **> sig_malloc(len(aut_gp_gens) * sizeof(WordPermutation*))
3975
+ temp_basis = <codeword *> sig_malloc(self.radix * sizeof(codeword))
3976
+
3977
+ output = []
3978
+
3979
+ for i in range(len(aut_gp_gens)):
3980
+ parent_generators[i] = create_word_perm(aut_gp_gens[i] + list(range(B.ncols, n)))
3981
+
3982
+ word = 0
3983
+ while ortho_basis[k] & (((<codeword>1) << B.ncols) - 1):
3984
+ k += 1
3985
+ j = k
3986
+ while ortho_basis[j]:
3987
+ word ^= ortho_basis[j]
3988
+ j += 1
3989
+
3990
+ log_2_radix = 0
3991
+ while ((<codeword>1) << log_2_radix) < <codeword>self.radix:
3992
+ log_2_radix += 1
3993
+ # now we assume (<codeword>1 << log_2_radix) == self.radix
3994
+ if k < log_2_radix:
3995
+ orb_chx_size = 0
3996
+ else:
3997
+ orb_chx_size = k - log_2_radix
3998
+ orbit_checks = <codeword *> sig_malloc(((<codeword>1) << orb_chx_size) * sizeof(codeword))
3999
+ if orbit_checks is NULL:
4000
+ raise MemoryError()
4001
+ for temp from 0 <= temp < ((<codeword>1) << orb_chx_size):
4002
+ orbit_checks[temp] = 0
4003
+
4004
+ combo = 0
4005
+ parity = 0
4006
+ gate = (<codeword>1 << B.nrows) - 1
4007
+ k_gate = (<codeword>1 << k) - 1
4008
+ nonzero_gate = ((<codeword>1 << (n-B.ncols)) - 1) << B.ncols
4009
+ radix_gate = (((<codeword>1) << log_2_radix) - 1)
4010
+
4011
+ while True:
4012
+ if nonzero_gate & word == nonzero_gate and \
4013
+ (ham_wts[word & 65535] + ham_wts[(word >> 16) & 65535]) % d == 0:
4014
+ temp = (word >> B.nrows) & ((<codeword>1 << k) - 1)
4015
+ if not orbit_checks[temp >> log_2_radix] & ((<codeword>1) << (temp & radix_gate)):
4016
+ B_aug = BinaryCode(B, word)
4017
+ aug_aut_gp_gens, aug_labeling, aug_size, aug_base = self._aut_gp_and_can_label(B_aug)
4018
+
4019
+ # check if (B, B_aug) ~ (m(B_aug), B_aug)
4020
+
4021
+ can_lab = create_word_perm(aug_labeling[:n])
4022
+
4023
+ can_lab_inv = create_inv_word_perm(can_lab)
4024
+ for j from 0 <= j < B_aug.nrows:
4025
+ temp_basis[j] = permute_word_by_wp(can_lab, B_aug.basis[j])
4026
+
4027
+ # row reduce to get canonical label
4028
+ i = 0
4029
+ j = 0
4030
+ while j < B_aug.nrows:
4031
+ ii = j
4032
+ while ii < B_aug.nrows and not temp_basis[ii] & (<codeword>1 << i):
4033
+ ii += 1
4034
+ if ii != B_aug.nrows:
4035
+ if ii != j:
4036
+ swap = temp_basis[ii]
4037
+ temp_basis[ii] = temp_basis[j]
4038
+ temp_basis[j] = swap
4039
+ for jj from 0 <= jj < j:
4040
+ if temp_basis[jj] & (<codeword>1 << i):
4041
+ temp_basis[jj] ^= temp_basis[j]
4042
+ for jj from j < jj < B_aug.nrows:
4043
+ if temp_basis[jj] & (<codeword>1 << i):
4044
+ temp_basis[jj] ^= temp_basis[j]
4045
+ j += 1
4046
+ i += 1
4047
+ # done row reduction
4048
+
4049
+ for j from 0 <= j < B.nrows:
4050
+ temp_basis[j] = permute_word_by_wp(can_lab_inv, temp_basis[j])
4051
+ from sage.matrix.constructor import matrix
4052
+ from sage.rings.integer_ring import ZZ
4053
+ from sage.groups.perm_gps.permgroup import PermutationGroup
4054
+ from sage.groups.perm_gps.constructor import PermutationGroupElement
4055
+ from sage.libs.gap.libgap import libgap
4056
+ rs = []
4057
+ for i from 0 <= i < B.nrows:
4058
+ r = []
4059
+ for j from 0 <= j < n:
4060
+ r.append((((<codeword>1)<<j)&temp_basis[i])>>j)
4061
+ rs.append(r)
4062
+ m = BinaryCode(matrix(ZZ, rs))
4063
+
4064
+ m_aut_gp_gens, m_labeling, m_size, m_base = self._aut_gp_and_can_label(m)
4065
+ if True: # size*factorial(n-B.ncols) == m_size:
4066
+
4067
+ if len(m_aut_gp_gens) == 0:
4068
+ aut_m = PermutationGroup([()])
4069
+ else:
4070
+ aut_m = PermutationGroup([PermutationGroupElement([a+1 for a in g]) for g in m_aut_gp_gens])
4071
+
4072
+ if len(aug_aut_gp_gens) == 0:
4073
+ aut_B_aug = libgap(PermutationGroup([()]))
4074
+ else:
4075
+ aut_B_aug = libgap(PermutationGroup([PermutationGroupElement([a+1 for a in g]) for g in aug_aut_gp_gens]))
4076
+ H = libgap(aut_m).Intersection2(aut_B_aug)
4077
+ rt_transversal = [[int(a) - 1 for a in g.ListPerm(n)] for g in aut_B_aug.RightTransversal(H) if not g.IsOne()]
4078
+ rt_transversal.append(list(range(n)))
4079
+
4080
+ bingo2 = 0
4081
+ for coset_rep in rt_transversal:
4082
+ hwp = create_word_perm(coset_rep)
4083
+ # dealloc_word_perm(gwp)
4084
+ bingo2 = 1
4085
+ for j from 0 <= j < B.nrows:
4086
+ temp = permute_word_by_wp(hwp, temp_basis[j])
4087
+ if temp != B.words[temp & gate]:
4088
+ bingo2 = 0
4089
+ dealloc_word_perm(hwp)
4090
+ break
4091
+ if bingo2:
4092
+ dealloc_word_perm(hwp)
4093
+ break
4094
+ if bingo2:
4095
+ from sage.matrix.constructor import matrix
4096
+ from sage.rings.finite_rings.finite_field_constructor import GF
4097
+ M = matrix(GF(2), B_aug.nrows, B_aug.ncols)
4098
+ for i from 0 <= i < B_aug.ncols:
4099
+ for j from 0 <= j < B_aug.nrows:
4100
+ M[j,i] = B_aug.is_one(1 << j, i)
4101
+ output.append(M)
4102
+ dealloc_word_perm(can_lab)
4103
+ dealloc_word_perm(can_lab_inv)
4104
+ # ...
4105
+
4106
+ orbits = [word]
4107
+ j = 0
4108
+ while j < len(orbits):
4109
+ for i from 0 <= i < len(aut_gp_gens):
4110
+ temp = <codeword> orbits[j]
4111
+ temp = permute_word_by_wp(parent_generators[i], temp)
4112
+ temp ^= B.words[temp & gate]
4113
+ if temp not in orbits:
4114
+ orbits.append(temp)
4115
+ j += 1
4116
+ for temp in orbits:
4117
+ temp = (temp >> B.nrows) & k_gate
4118
+ orbit_checks[temp >> log_2_radix] |= ((<codeword>1) << (temp & radix_gate))
4119
+
4120
+ parity ^= 1
4121
+ i = 0
4122
+ if not parity:
4123
+ while not combo & (1 << i):
4124
+ i += 1
4125
+ i += 1
4126
+ if i == k:
4127
+ break
4128
+ else:
4129
+ combo ^= (1 << i)
4130
+ word ^= ortho_basis[i]
4131
+
4132
+ for i from 0 <= i < len(aut_gp_gens):
4133
+ dealloc_word_perm(parent_generators[i])
4134
+ sig_free(B_can_lab)
4135
+ sig_free(parent_generators)
4136
+ sig_free(orbit_checks)
4137
+ sig_free(ortho_basis)
4138
+ sig_free(temp_basis)
4139
+ return output