passagemath-modules 10.6.31__cp314-cp314-macosx_13_0_x86_64.whl

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

Potentially problematic release.


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

Files changed (807) hide show
  1. passagemath_modules-10.6.31.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31.dist-info/RECORD +807 -0
  3. passagemath_modules-10.6.31.dist-info/WHEEL +6 -0
  4. passagemath_modules-10.6.31.dist-info/top_level.txt +2 -0
  5. passagemath_modules.dylibs/libgfortran.5.dylib +0 -0
  6. passagemath_modules.dylibs/libgmp.10.dylib +0 -0
  7. passagemath_modules.dylibs/libgsl.28.dylib +0 -0
  8. passagemath_modules.dylibs/libmpc.3.dylib +0 -0
  9. passagemath_modules.dylibs/libmpfr.6.dylib +0 -0
  10. passagemath_modules.dylibs/libopenblasp-r0.3.29.dylib +0 -0
  11. passagemath_modules.dylibs/libquadmath.0.dylib +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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  74. sage/calculus/integration.pyx +698 -0
  75. sage/calculus/interpolation.cpython-314-darwin.so +0 -0
  76. sage/calculus/interpolation.pxd +13 -0
  77. sage/calculus/interpolation.pyx +387 -0
  78. sage/calculus/interpolators.cpython-314-darwin.so +0 -0
  79. sage/calculus/interpolators.pyx +326 -0
  80. sage/calculus/ode.cpython-314-darwin.so +0 -0
  81. sage/calculus/ode.pxd +5 -0
  82. sage/calculus/ode.pyx +610 -0
  83. sage/calculus/riemann.cpython-314-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  401. sage/matrix/constructor.pyx +750 -0
  402. sage/matrix/docs.py +430 -0
  403. sage/matrix/echelon_matrix.cpython-314-darwin.so +0 -0
  404. sage/matrix/echelon_matrix.pyx +155 -0
  405. sage/matrix/matrix.pxd +2 -0
  406. sage/matrix/matrix0.cpython-314-darwin.so +0 -0
  407. sage/matrix/matrix0.pxd +68 -0
  408. sage/matrix/matrix0.pyx +6324 -0
  409. sage/matrix/matrix1.cpython-314-darwin.so +0 -0
  410. sage/matrix/matrix1.pxd +8 -0
  411. sage/matrix/matrix1.pyx +2851 -0
  412. sage/matrix/matrix2.cpython-314-darwin.so +0 -0
  413. sage/matrix/matrix2.pxd +25 -0
  414. sage/matrix/matrix2.pyx +20181 -0
  415. sage/matrix/matrix_cdv.cpython-314-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  492. sage/matroids/extension.pxd +34 -0
  493. sage/matroids/extension.pyx +519 -0
  494. sage/matroids/flats_matroid.cpython-314-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  701. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  702. sage/rings/function_field/khuri_makdisi.cpython-314-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  771. sage/stats/hmm/chmm.pyx +1595 -0
  772. sage/stats/hmm/distributions.cpython-314-darwin.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-darwin.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-darwin.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-darwin.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-darwin.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
sage/crypto/sbox.pyx ADDED
@@ -0,0 +1,2090 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ # sage.doctest: needs sage.modules sage.rings.finite_rings
3
+ r"""
4
+ S-Boxes and Their Algebraic Representations
5
+ """
6
+ cimport cython
7
+ from cysignals.memory cimport check_allocarray, sig_free
8
+
9
+ from sage.structure.sage_object cimport SageObject
10
+ from sage.structure.element cimport Element
11
+
12
+ from sage.combinat.integer_vector import IntegerVectors
13
+ from sage.crypto.boolean_function import BooleanFunction
14
+ from sage.crypto.boolean_function cimport hamming_weight, walsh_hadamard
15
+ from sage.matrix.constructor import matrix
16
+ from sage.matrix.matrix0 cimport Matrix
17
+ from sage.misc.cachefunc import cached_method
18
+ from sage.misc.functional import is_even
19
+ from sage.misc.misc_c import prod as mul
20
+ from sage.modules.free_module_element import vector
21
+ from sage.rings.finite_rings.finite_field_base import FiniteField
22
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
23
+ from sage.rings.ideal import FieldIdeal, Ideal
24
+ from sage.rings.integer_ring import ZZ
25
+ from sage.rings.integer cimport Integer
26
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
27
+
28
+
29
+ cdef Py_ssize_t _nterms(Py_ssize_t nvars, Py_ssize_t deg) noexcept:
30
+ """
31
+ Return the number of monomials possible up to a given
32
+ degree.
33
+
34
+ INPUT:
35
+
36
+ - ``nvars`` -- number of variables
37
+
38
+ - ``deg`` -- degree
39
+
40
+ TESTS::
41
+
42
+ sage: from sage.crypto.sbox import SBox
43
+ sage: S = SBox(7,6,0,4,2,5,1,3)
44
+ sage: F = S.polynomials(degree=3) # indirect doctest # needs sage.libs.singular
45
+ """
46
+ cdef Py_ssize_t total = 1
47
+ cdef Py_ssize_t divisor = 1
48
+ cdef Py_ssize_t var_choices = 1
49
+
50
+ cdef Py_ssize_t d
51
+ for d in range(1, deg+1):
52
+ var_choices *= (nvars - d + 1)
53
+ divisor *= d
54
+ total += var_choices // divisor
55
+
56
+ return total
57
+
58
+
59
+ @cython.auto_pickle(True)
60
+ cdef class SBox(SageObject):
61
+ r"""
62
+ A substitution box or S-box is one of the basic components of
63
+ symmetric key cryptography. In general, an S-box takes `m` input
64
+ bits and transforms them into `n` output bits. This is called an
65
+ `m \times n` S-box and is often implemented as a lookup table. These
66
+ S-boxes are carefully chosen to resist linear and differential
67
+ cryptanalysis [He2002]_.
68
+
69
+ This module implements an S-box class which allows an algebraic
70
+ treatment and determine various cryptographic properties.
71
+
72
+ EXAMPLES:
73
+
74
+ We consider the S-box of the block cipher PRESENT [BKLPPRSV2007]_::
75
+
76
+ sage: from sage.crypto.sbox import SBox
77
+ sage: S = SBox(12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2); S
78
+ (12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2)
79
+ sage: S(1)
80
+ 5
81
+
82
+ Note that by default bits are interpreted in big endian
83
+ order. This is not consistent with the rest of Sage, which has a
84
+ strong bias towards little endian, but is consistent with most
85
+ cryptographic literature::
86
+
87
+ sage: S([0,0,0,1])
88
+ [0, 1, 0, 1]
89
+
90
+ sage: S = SBox(12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2, big_endian=False)
91
+ sage: S(1)
92
+ 5
93
+ sage: S([0,0,0,1])
94
+ [1, 1, 0, 0]
95
+
96
+
97
+ Now we construct an ``SBox`` object for the 4-bit small scale AES
98
+ S-Box (cf. :mod:`sage.crypto.mq.sr`)::
99
+
100
+ sage: sr = mq.SR(1,1,1,4, allow_zero_inversions=True)
101
+ sage: S = SBox([sr.sub_byte(e) for e in list(sr.k)])
102
+ sage: S
103
+ (6, 5, 2, 9, 4, 7, 3, 12, 14, 15, 10, 0, 8, 1, 13, 11)
104
+
105
+ AUTHORS:
106
+
107
+ - Rusydi H. Makarim (2016-03-31) : added more functions to determine related cryptographic properties
108
+ - Yann Laigle-Chapuy (2009-07-01): improve linear and difference matrix computation
109
+ - Martin R. Albrecht (2008-03-12): initial implementation
110
+
111
+ REFERENCES:
112
+
113
+ - [He2002]_
114
+ - [BKLPPRSV2007]_
115
+ - [CDL2015]_
116
+ """
117
+ cdef list _S_list
118
+ cdef object _ring
119
+ cdef Py_ssize_t m
120
+ cdef Py_ssize_t n
121
+ cdef bint _big_endian
122
+ cdef dict __dict__ # for cached_methods
123
+
124
+ def __init__(self, *args, **kwargs):
125
+ r"""
126
+ Construct a substitution box (S-box) for a given lookup table `S`.
127
+
128
+ INPUT:
129
+
130
+ - ``S`` -- a finite iterable defining the S-box with integer or
131
+ finite field elements
132
+
133
+ - ``big_endian`` -- boolean (default: ``True``); controls whether bits
134
+ shall be ordered in big endian order
135
+
136
+ EXAMPLES:
137
+
138
+ We construct a 3-bit S-box where e.g. the bits (0,0,1) are
139
+ mapped to (1,1,1).::
140
+
141
+ sage: from sage.crypto.sbox import SBox
142
+ sage: S = SBox(7,6,0,4,2,5,1,3); S
143
+ (7, 6, 0, 4, 2, 5, 1, 3)
144
+
145
+ sage: S(0)
146
+ 7
147
+
148
+ Construct S-box from univariate polynomial.::
149
+
150
+ sage: R = PolynomialRing(GF(2**3), 'x')
151
+ sage: inv = R.gen()**(2**3-2)
152
+ sage: inv = SBox(inv); inv
153
+ (0, 1, 5, 6, 7, 2, 3, 4)
154
+ sage: inv.differential_uniformity()
155
+ 2
156
+
157
+ sage: SBox(PolynomialRing(GF(3**3), 'x').gen())
158
+ Traceback (most recent call last):
159
+ ...
160
+ TypeError: only polynomials over rings with characteristic 2 allowed
161
+
162
+ TESTS::
163
+
164
+ sage: from sage.crypto.sbox import SBox
165
+ sage: S = SBox()
166
+ Traceback (most recent call last):
167
+ ...
168
+ TypeError: no lookup table provided
169
+ sage: S = SBox(1, 2, 3)
170
+ Traceback (most recent call last):
171
+ ...
172
+ TypeError: lookup table length is not a power of 2
173
+ sage: S = SBox(5, 6, 0, 3, 4, 2, 1, 2)
174
+ sage: S.output_size()
175
+ 3
176
+ """
177
+ from sage.rings.polynomial.polynomial_element import Polynomial
178
+
179
+ if "S" in kwargs:
180
+ args = kwargs["S"]
181
+
182
+ if len(args) == 1 and isinstance(args[0], Polynomial):
183
+ # SBox defined via Univariate Polynomial, compute lookup table
184
+ # by evaluating the polynomial on every base_ring element
185
+ poly = args[0]
186
+ R = poly.parent().base_ring()
187
+ if R.characteristic() != 2:
188
+ raise TypeError("only polynomials over rings with characteristic 2 allowed")
189
+ S = [poly(v) for v in sorted(R)]
190
+ elif len(args) == 1: # iterables
191
+ S = args[0]
192
+ elif len(args) > 1:
193
+ S = args
194
+ else:
195
+ raise TypeError("no lookup table provided")
196
+
197
+ _S_list = []
198
+ for e in S:
199
+ if isinstance(e, Element) and isinstance(e.parent(), FiniteField):
200
+ e = e.polynomial().change_ring(ZZ).subs(e.parent().characteristic())
201
+ _S_list.append(e)
202
+ S = _S_list
203
+
204
+ if not ZZ(len(S)).is_power_of(2):
205
+ raise TypeError("lookup table length is not a power of 2")
206
+ self._S_list = S
207
+
208
+ self.m = ZZ(len(S)).exact_log(2)
209
+ self.n = ZZ(max(S)).nbits()
210
+ self._big_endian = kwargs.get("big_endian", True)
211
+
212
+ cdef Py_ssize_t i
213
+ self._ring = PolynomialRing(
214
+ GF(2),
215
+ self.m + self.n,
216
+ ["x%d" % i for i in range(self.m)] + ["y%d" % i for i in range(self.n)])
217
+
218
+ def _repr_(self):
219
+ """
220
+ EXAMPLES::
221
+
222
+ sage: from sage.crypto.sbox import SBox
223
+ sage: SBox(7,6,0,4,2,5,1,3) # indirect doctest
224
+ (7, 6, 0, 4, 2, 5, 1, 3)
225
+ """
226
+ return "(" + ", ".join(map(str, self)) + ")"
227
+
228
+ def __len__(self):
229
+ """
230
+ Return the length of input bit strings.
231
+
232
+ EXAMPLES::
233
+
234
+ sage: from sage.crypto.sbox import SBox
235
+ sage: len(SBox(7,6,0,4,2,5,1,3))
236
+ 3
237
+ """
238
+ return self.m
239
+
240
+ def __eq__(self, rhs):
241
+ """
242
+ S-boxes are considered to be equal if all construction
243
+ parameters match.
244
+
245
+ EXAMPLES::
246
+
247
+ sage: from sage.crypto.sbox import SBox
248
+ sage: S = SBox(7,6,0,4,2,5,1,3)
249
+ sage: loads(dumps(S)) == S
250
+ True
251
+ """
252
+ if not isinstance(rhs, SBox):
253
+ raise NotImplemented
254
+
255
+ cdef SBox other = <SBox> rhs
256
+ return (self._S_list == other._S_list) and (self._big_endian == self._big_endian)
257
+
258
+ def __ne__(self, other):
259
+ """
260
+ S-boxes are considered to be equal if all construction
261
+ parameters match.
262
+
263
+ EXAMPLES::
264
+
265
+ sage: from sage.crypto.sbox import SBox
266
+ sage: S = SBox(7,6,0,4,2,5,1,3)
267
+ sage: S != S
268
+ False
269
+ """
270
+ return not self.__eq__(other)
271
+
272
+ cpdef list to_bits(self, x, n=None):
273
+ """
274
+ Return bitstring of length ``n`` for integer ``x``. The
275
+ returned bitstring is guaranteed to have length ``n``.
276
+
277
+ INPUT:
278
+
279
+ - ``x`` -- integer
280
+
281
+ - ``n`` -- bit length (optional)
282
+
283
+ EXAMPLES::
284
+
285
+ sage: from sage.crypto.sbox import SBox
286
+ sage: S = SBox(7,6,0,4,2,5,1,3)
287
+ sage: S.to_bits(6)
288
+ [1, 1, 0]
289
+
290
+ sage: S.to_bits( S(6) )
291
+ [0, 0, 1]
292
+
293
+ sage: S( S.to_bits( 6 ) )
294
+ [0, 0, 1]
295
+ """
296
+ if n is None and self.m == self.n:
297
+ n = self.n
298
+
299
+ F = GF(2)
300
+ cdef list xs = [F(i) for i in ZZ(x).digits(base=2, padto=n)]
301
+
302
+ if self._big_endian:
303
+ xs.reverse()
304
+
305
+ return xs
306
+
307
+ def from_bits(self, x, n=None):
308
+ """
309
+ Return integer for bitstring ``x`` of length ``n``.
310
+
311
+ INPUT:
312
+
313
+ - ``x`` -- a bitstring
314
+
315
+ - ``n`` -- bit length (optional)
316
+
317
+ EXAMPLES::
318
+
319
+ sage: from sage.crypto.sbox import SBox
320
+ sage: S = SBox(7,6,0,4,2,5,1,3)
321
+ sage: S.from_bits( [1,1,0])
322
+ 6
323
+
324
+ sage: S( S.from_bits( [1,1,0] ) )
325
+ 1
326
+ sage: S.from_bits( S( [1,1,0] ) )
327
+ 1
328
+ """
329
+ if n is None and self.m == self.n:
330
+ n = self.n
331
+
332
+ if self._big_endian:
333
+ x = list(reversed(x))
334
+
335
+ return ZZ(self._rpad(x, n), 2)
336
+
337
+ cdef list _rpad(self, list x, Py_ssize_t n=-1):
338
+ """
339
+ Right pads ``x`` such that ``len(x) == n``.
340
+
341
+ EXAMPLES::
342
+
343
+ sage: from sage.crypto.sbox import SBox
344
+ sage: S = SBox(7,6,0,4,2,5,1,3)
345
+ sage: S._rpad([1,1]) # not tested
346
+ [1, 1, 0]
347
+ """
348
+ if n == -1 and self.m == self.n:
349
+ n = self.n
350
+ return x + [GF(2).zero()] * (n-len(x))
351
+
352
+ def __call__(self, X):
353
+ r"""
354
+ Apply substitution to ``X``.
355
+
356
+ If ``X`` is a list, it is interpreted as a sequence of bits
357
+ depending on the bit order of this S-box.
358
+
359
+ INPUT:
360
+
361
+ - ``X`` -- either an integer, a tuple of `\GF{2}` elements of
362
+ length ``len(self)`` or a finite field element in
363
+ `\GF{2^n}`. As a last resort this function tries to convert
364
+ ``X`` to an integer.
365
+
366
+ EXAMPLES:
367
+
368
+ We can call SBoxes with integers as inputs, this will
369
+ return an integer::
370
+
371
+ sage: from sage.crypto.sbox import SBox
372
+ sage: S = SBox(3, 0, 1, 3, 1, 0, 2, 2)
373
+ sage: S(0)
374
+ 3
375
+
376
+ sage: S([0,0,0])
377
+ [1, 1]
378
+
379
+ sage: S = SBox([7,6,0,4,2,5,1,3])
380
+ sage: S(7)
381
+ 3
382
+
383
+ sage: S[0]
384
+ 7
385
+
386
+ sage: S(QQ(3))
387
+ 4
388
+
389
+ Alternatively, we can call in with a list-like object, which
390
+ will return a list::
391
+
392
+ sage: S((0,2,3))
393
+ [0, 1, 1]
394
+
395
+ sage: S((0,0,1))
396
+ [1, 1, 0]
397
+
398
+ Calling it with a vector will return a vector::
399
+
400
+ sage: S(vector(GF(2), [0,0,1]))
401
+ (1, 1, 0)
402
+
403
+ sage: type(vector(GF(2), [0,0,1])) == type(S(vector(GF(2), [0,0,1])))
404
+ True
405
+
406
+ An input from a finite field will be interpreted as given the
407
+ coefficient vector as input::
408
+
409
+ sage: k.<a> = GF(2^3)
410
+ sage: S(a^2) # interpreted as (0,0,1)
411
+ a + 1
412
+ sage: S([0, 0, 1])
413
+ [1, 1, 0]
414
+ sage: vector(a + 1)
415
+ (1, 1, 0)
416
+
417
+ sage: id = SBox(range(8))
418
+ sage: all([x == id(x) for x in k])
419
+ True
420
+
421
+ Some examples for inputs that throw an :exc:`TypeError`::
422
+
423
+ sage: S([1]*10^6)
424
+ Traceback (most recent call last):
425
+ ...
426
+ TypeError: cannot apply SBox to provided element
427
+
428
+ sage: S(1/2)
429
+ Traceback (most recent call last):
430
+ ...
431
+ TypeError: cannot apply SBox to 1/2
432
+ """
433
+ # Handle integer inputs
434
+ if isinstance(X, int):
435
+ return self._S_list[<int> X]
436
+ if isinstance(X, Integer):
437
+ return self._S_list[<Integer> X]
438
+
439
+ # Handle non-integer inputs: vectors, finite field elements to-integer-coercible elements
440
+ # cdef int i
441
+ if isinstance(X, Element):
442
+ K = X.parent()
443
+ if K.base_ring().characteristic() != 2:
444
+ try:
445
+ X = ZZ(X)
446
+ return K(self._S_list[<Integer> X])
447
+ except TypeError:
448
+ raise TypeError("cannot apply SBox to %s" % (X,))
449
+ V = None
450
+ try:
451
+ V = K.vector_space(map=False)
452
+ except AttributeError:
453
+ try:
454
+ return self._S_list[ZZ(X)]
455
+ except TypeError:
456
+ pass
457
+ except TypeError:
458
+ V = K.vector_space()
459
+ # convert finite field element to vector
460
+ if V is not None:
461
+ X = V(X)
462
+ else:
463
+ K = None
464
+
465
+ # At this point, we only handle X being a vector or list-like
466
+ cdef list out
467
+ cdef Py_ssize_t ell
468
+ try:
469
+ ell = len(X)
470
+ X = list(X)
471
+ except TypeError:
472
+ # This will not pass the next test and ultimately raise an error
473
+ ell = -1
474
+
475
+ if ell == self.m:
476
+ if self._big_endian:
477
+ X = list(reversed(X))
478
+ X = ZZ(X, 2)
479
+ out = self.to_bits(self._S_list[X], self.n)
480
+ if K is not None:
481
+ return K(out)
482
+ # NOTE: Parts of the code assume that when a list is passed
483
+ # in that a list is returned
484
+ return out
485
+
486
+ if len(str(X)) > 50:
487
+ raise TypeError("cannot apply SBox to provided element")
488
+ else:
489
+ raise TypeError("cannot apply SBox to %s" % (X,))
490
+
491
+ def __getitem__(self, X):
492
+ """
493
+ See :meth:`SBox.__call__`.
494
+
495
+ EXAMPLES::
496
+
497
+ sage: from sage.crypto.sbox import SBox
498
+ sage: S = SBox([7,6,0,4,2,5,1,3])
499
+ sage: S[7]
500
+ 3
501
+ """
502
+ return self(X)
503
+
504
+ def input_size(self):
505
+ """
506
+ Return the input size of this S-Box.
507
+
508
+ EXAMPLES::
509
+
510
+ sage: from sage.crypto.sbox import SBox
511
+ sage: S = SBox([0, 3, 2, 1, 1, 3, 2, 0])
512
+ sage: S.input_size()
513
+ 3
514
+ """
515
+ return self.m
516
+
517
+ def output_size(self):
518
+ """
519
+ Return the output size of this S-Box.
520
+
521
+ EXAMPLES::
522
+
523
+ sage: from sage.crypto.sbox import SBox
524
+ sage: S = SBox([0, 3, 2, 1, 1, 3, 2, 0])
525
+ sage: S.output_size()
526
+ 2
527
+ """
528
+ return self.n
529
+
530
+ def is_permutation(self):
531
+ r"""
532
+ Return ``True`` if this S-Box is a permutation.
533
+
534
+ EXAMPLES::
535
+
536
+ sage: from sage.crypto.sbox import SBox
537
+ sage: S = SBox(7,6,0,4,2,5,1,3)
538
+ sage: S.is_permutation()
539
+ True
540
+
541
+ sage: S = SBox(3,2,0,0,2,1,1,3)
542
+ sage: S.is_permutation()
543
+ False
544
+ """
545
+ if self.m != self.n:
546
+ return False
547
+ cdef Py_ssize_t m = self.m
548
+ cdef Py_ssize_t i
549
+ return len(set([self._S_list[i] for i in range(1 << m)])) == 1 << m
550
+
551
+ def __iter__(self):
552
+ """
553
+ EXAMPLES::
554
+
555
+ sage: from sage.crypto.sbox import SBox
556
+ sage: S = SBox(7,6,0,4,2,5,1,3)
557
+ sage: [e for e in S]
558
+ [7, 6, 0, 4, 2, 5, 1, 3]
559
+ """
560
+ cdef Py_ssize_t i
561
+ for i in range(1 << self.m):
562
+ yield self._S_list[i]
563
+
564
+ def derivative(self, u):
565
+ r"""
566
+ Return the derivative in direction of ``u``.
567
+
568
+ INPUT:
569
+
570
+ - ``u`` -- either an integer or a tuple/list of `\GF{2}` elements
571
+ of length equal to ``m``
572
+
573
+
574
+ The derivative of `F` in direction of `u` is defined as
575
+ `x \mapsto F(x) + F(x + u)`.
576
+
577
+ EXAMPLES::
578
+
579
+ sage: from sage.crypto.sbox import SBox
580
+ sage: s = SBox(0,1,2,3)
581
+ sage: s.derivative(1)
582
+ (1, 1, 1, 1)
583
+ sage: u = [1,0]
584
+ sage: s.derivative(u)
585
+ (1, 1, 1, 1)
586
+ sage: v = vector(GF(2), [1,0])
587
+ sage: s.derivative(v)
588
+ (1, 1, 1, 1)
589
+ sage: s.derivative(4)
590
+ Traceback (most recent call last):
591
+ ...
592
+ IndexError: list index out of range
593
+ sage: from sage.crypto.sboxes import PRESENT
594
+ sage: PRESENT.derivative(1).max_degree() < PRESENT.max_degree() # needs sage.rings.polynomial.pbori
595
+ True
596
+ """
597
+ from sage.structure.element import Vector
598
+ nvars = self.m
599
+
600
+ if isinstance(u, (tuple, list)):
601
+ v = ZZ(u, base=2)
602
+ elif isinstance(u, Vector):
603
+ if u.base_ring() != GF(2):
604
+ raise TypeError("base ring of input vector must be GF(2)")
605
+ elif u.parent().dimension() != nvars:
606
+ raise TypeError("input vector must be an element of a vector space with dimension %d" % (nvars,))
607
+ v = ZZ(u.list(), base=2)
608
+ else:
609
+ v = u
610
+
611
+ return SBox([self(x) ^ self(x ^ v)
612
+ for x in range(1 << self.input_size())])
613
+
614
+ @cached_method
615
+ def difference_distribution_table(self):
616
+ """
617
+ Return difference distribution table (DDT) ``A`` for this S-box.
618
+
619
+ The rows of ``A`` encode the differences ``Delta I`` of the
620
+ input and the columns encode the difference ``Delta O`` for
621
+ the output. The bits are ordered according to the endianess of
622
+ this S-box. The value at ``A[Delta I,Delta O]`` encodes how
623
+ often ``Delta O`` is the actual output difference given
624
+ ``Delta I`` as input difference.
625
+
626
+ See [He2002]_ for an introduction to differential
627
+ cryptanalysis.
628
+
629
+ EXAMPLES::
630
+
631
+ sage: from sage.crypto.sbox import SBox
632
+ sage: S = SBox(7,6,0,4,2,5,1,3)
633
+ sage: S.difference_distribution_table()
634
+ [8 0 0 0 0 0 0 0]
635
+ [0 2 2 0 2 0 0 2]
636
+ [0 0 2 2 0 0 2 2]
637
+ [0 2 0 2 2 0 2 0]
638
+ [0 2 0 2 0 2 0 2]
639
+ [0 0 2 2 2 2 0 0]
640
+ [0 2 2 0 0 2 2 0]
641
+ [0 0 0 0 2 2 2 2]
642
+ sage: S = SBox(7,4,8,6)
643
+ sage: S.difference_distribution_table()
644
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
645
+ [0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0]
646
+ [0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2]
647
+ [0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 0]
648
+
649
+ TESTS:
650
+
651
+ Testing square SBoxes::
652
+
653
+ sage: from sage.crypto.sbox import SBox
654
+ sage: S = SBox(7,6,0,4,2,5,1,3)
655
+ sage: S.difference_distribution_table()
656
+ [8 0 0 0 0 0 0 0]
657
+ [0 2 2 0 2 0 0 2]
658
+ [0 0 2 2 0 0 2 2]
659
+ [0 2 0 2 2 0 2 0]
660
+ [0 2 0 2 0 2 0 2]
661
+ [0 0 2 2 2 2 0 0]
662
+ [0 2 2 0 0 2 2 0]
663
+ [0 0 0 0 2 2 2 2]
664
+
665
+ Testing non-square SBoxes::
666
+
667
+ sage: from sage.crypto.sbox import SBox
668
+ sage: S = SBox(8,8,8,8)
669
+ sage: S.difference_distribution_table()
670
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
671
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
672
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
673
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
674
+ sage: S = SBox(7,4,8,6)
675
+ sage: S.difference_distribution_table()
676
+ [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
677
+ [0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0]
678
+ [0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2]
679
+ [0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 0]
680
+ sage: S = SBox(0,0,0,1,0,0,1,3)
681
+ sage: S.difference_distribution_table()
682
+ [8 0 0 0]
683
+ [4 2 2 0]
684
+ [2 4 0 2]
685
+ [2 4 0 2]
686
+ [4 2 2 0]
687
+ [6 0 0 2]
688
+ [2 4 0 2]
689
+ [2 4 0 2]
690
+ """
691
+ cdef Py_ssize_t nrows = 1 << self.m
692
+ cdef Py_ssize_t ncols = 1 << self.n
693
+ cdef Py_ssize_t i, di
694
+
695
+ cdef list L = [0]*(nrows*ncols)
696
+
697
+ for i in range(nrows):
698
+ si = self._S_list[i]
699
+ for di in range(nrows):
700
+ L[di*ncols + si ^ self._S_list[i ^ di]] += 1
701
+
702
+ A = matrix(ZZ, nrows, ncols, L)
703
+ A.set_immutable()
704
+
705
+ return A
706
+
707
+ def maximal_difference_probability_absolute(self):
708
+ """
709
+ Return the difference probability of the difference with the
710
+ highest probability in absolute terms, i.e. how often it
711
+ occurs in total.
712
+
713
+ Equivalently, this is equal to the differential uniformity
714
+ of this S-Box.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: from sage.crypto.sbox import SBox
719
+ sage: S = SBox(7,6,0,4,2,5,1,3)
720
+ sage: S.maximal_difference_probability_absolute()
721
+ 2
722
+
723
+ .. NOTE::
724
+
725
+ This code is mainly called internally.
726
+ """
727
+ A = self.difference_distribution_table().__copy__()
728
+ A[0, 0] = 0
729
+ return max(map(abs, A.list()))
730
+
731
+ differential_uniformity = maximal_difference_probability_absolute
732
+
733
+ def maximal_difference_probability(self):
734
+ r"""
735
+ Return the difference probability of the difference with the
736
+ highest probability in the range between 0.0 and 1.0
737
+ indicating 0\% or 100\% respectively.
738
+
739
+ EXAMPLES::
740
+
741
+ sage: from sage.crypto.sbox import SBox
742
+ sage: S = SBox(7,6,0,4,2,5,1,3)
743
+ sage: S.maximal_difference_probability()
744
+ 0.25
745
+ """
746
+ return self.maximal_difference_probability_absolute() / (2.0**self.output_size())
747
+
748
+ @cached_method
749
+ def linear_approximation_table(self, scale='absolute_bias'):
750
+ r"""
751
+ Return linear approximation table (LAT) `A` for this S-box.
752
+
753
+ The entry `A[\alpha,\beta]` corresponds to the probability
754
+ `Pr[\alpha\cdot x = \beta\cdot S(x)]`, where `S` is this S-box
755
+ mapping `n`-bit inputs to `m`-bit outputs.
756
+ There are three typical notations for this probability used in
757
+ the literature:
758
+
759
+ - `Pr[\alpha\cdot x = \beta\cdot S(x)] = 1/2 + e(\alpha, \beta)`,
760
+ where `e(\alpha, \beta)` is called the bias,
761
+ - `2\cdot Pr[\alpha\cdot x = \beta\cdot S(x)] = 1 + c(\alpha, \beta)`,
762
+ where `c(\alpha, \beta) = 2\cdot e(\alpha, \beta)` is the
763
+ correlation, and
764
+ - `2^{(m+1)}\cdot Pr[\alpha\cdot x = \beta\cdot S(x)] = 2^m +
765
+ \hat{S}(\alpha, \beta)`, where `\hat{S}(\alpha, \beta)` is
766
+ the Fourier coefficient of S.
767
+
768
+ See [He2002]_ for an introduction to linear cryptanalysis.
769
+
770
+ INPUT:
771
+
772
+ - ``scale`` -- string to choose the scaling for the LAT, one of
773
+
774
+ * "bias": elements are `e(\alpha, \beta)`
775
+ * "correlation": elements are `c(\alpha, \beta)`
776
+ * "absolute_bias": elements are `2^m\cdot e(\alpha, \beta)` (default)
777
+ * "fourier_coefficient": elements are `\hat{S}(\alpha, \beta)`
778
+
779
+ EXAMPLES::
780
+
781
+ sage: from sage.crypto.sbox import SBox
782
+ sage: S = SBox(7,6,0,4,2,5,1,3)
783
+ sage: lat_abs_bias = S.linear_approximation_table()
784
+ sage: lat_abs_bias
785
+ [ 4 0 0 0 0 0 0 0]
786
+ [ 0 0 0 0 2 2 2 -2]
787
+ [ 0 0 -2 -2 -2 2 0 0]
788
+ [ 0 0 -2 2 0 0 -2 -2]
789
+ [ 0 2 0 2 -2 0 2 0]
790
+ [ 0 -2 0 2 0 2 0 2]
791
+ [ 0 -2 -2 0 0 -2 2 0]
792
+ [ 0 -2 2 0 -2 0 0 -2]
793
+
794
+ sage: lat_abs_bias/(1 << S.input_size()) == S.linear_approximation_table(scale='bias')
795
+ True
796
+
797
+ sage: lat_abs_bias/(1 << (S.input_size()-1)) == S.linear_approximation_table(scale='correlation')
798
+ True
799
+
800
+ sage: lat_abs_bias*2 == S.linear_approximation_table(scale='fourier_coefficient')
801
+ True
802
+
803
+ According to this table the first bit of the input is equal
804
+ to the third bit of the output 6 out of 8 times::
805
+
806
+ sage: for i in srange(8): print(S.to_bits(i)[0] == S.to_bits(S(i))[2])
807
+ False
808
+ True
809
+ True
810
+ True
811
+ False
812
+ True
813
+ True
814
+ True
815
+ """
816
+ cdef Py_ssize_t m = self.m
817
+ cdef Py_ssize_t n = self.n
818
+
819
+ cdef Py_ssize_t nrows = 1 << m
820
+ cdef Py_ssize_t ncols = 1 << n
821
+
822
+ # directly compute the walsh_hadamard transform here, without
823
+ # creating the BooleanFunction object
824
+ cdef long* temp = <long*> check_allocarray(nrows*ncols, sizeof(long))
825
+ cdef Py_ssize_t i, j
826
+
827
+ for i in range(ncols):
828
+ for j in range(nrows):
829
+ temp[i*nrows + j] = 1 - (<int>(hamming_weight(i & self._S_list[j]) & 1) << 1)
830
+ walsh_hadamard(&temp[i*nrows], m)
831
+
832
+ cdef list L = [temp[i*nrows + j] for j in range(nrows) for i in range(ncols)]
833
+ sig_free(temp)
834
+
835
+ A = matrix(ZZ, nrows, ncols, L)
836
+
837
+ if (scale is None) or (scale == "absolute_bias"):
838
+ A /= 2
839
+ elif scale == "bias":
840
+ A /= 1 << (m+1)
841
+ elif scale == "correlation":
842
+ A /= 1 << m
843
+ elif scale == "fourier_coefficient":
844
+ pass
845
+ else:
846
+ raise ValueError("no such scaling for the LAT: %s" % scale)
847
+
848
+ A.set_immutable()
849
+ return A
850
+
851
+ def maximal_linear_bias_absolute(self):
852
+ r"""
853
+ Return maximal linear bias, i.e. how often the linear
854
+ approximation with the highest bias is true or false minus
855
+ `2^{n-1}`.
856
+
857
+ EXAMPLES::
858
+
859
+ sage: from sage.crypto.sbox import SBox
860
+ sage: S = SBox(7,6,0,4,2,5,1,3)
861
+ sage: S.maximal_linear_bias_absolute()
862
+ 2
863
+ """
864
+ cdef list L = self.linear_approximation_table().list()
865
+ L[0] = 0 # Set the upper left corner to be 0
866
+ return max(map(abs, L))
867
+
868
+ def maximal_linear_bias_relative(self):
869
+ """
870
+ Return maximal bias of all linear approximations of this
871
+ S-box.
872
+
873
+ EXAMPLES::
874
+
875
+ sage: from sage.crypto.sbox import SBox
876
+ sage: S = SBox(7,6,0,4,2,5,1,3)
877
+ sage: S.maximal_linear_bias_relative()
878
+ 0.25
879
+ """
880
+ return self.maximal_linear_bias_absolute() / (2.0**self.m)
881
+
882
+ def ring(self):
883
+ """
884
+ Create, return, and cache a polynomial ring for S-box polynomials.
885
+
886
+ EXAMPLES::
887
+
888
+ sage: from sage.crypto.sbox import SBox
889
+ sage: S = SBox(7,6,0,4,2,5,1,3)
890
+ sage: S.ring()
891
+ Multivariate Polynomial Ring in x0, x1, x2, y0, y1, y2 over
892
+ Finite Field of size 2
893
+ """
894
+ return self._ring
895
+
896
+ def solutions(self, X=None, Y=None):
897
+ """
898
+ Return a dictionary of solutions to this S-box.
899
+
900
+ INPUT:
901
+
902
+ - ``X`` -- (optional) input variables
903
+
904
+ - ``Y`` -- (optional) output variables
905
+
906
+ EXAMPLES::
907
+
908
+ sage: from sage.crypto.sbox import SBox
909
+ sage: S = SBox([7,6,0,4,2,5,1,3])
910
+ sage: F = S.polynomials() # needs sage.libs.singular
911
+ sage: s = S.solutions()
912
+ sage: any(f.subs(_s) for f in F for _s in s) # needs sage.libs.singular
913
+ False
914
+ """
915
+ if X is None and Y is None:
916
+ P = self.ring()
917
+ gens = P.gens()
918
+ else:
919
+ P = X[0].parent()
920
+ gens = X + Y
921
+
922
+ cdef Py_ssize_t m = self.m
923
+
924
+ cdef list solution, solutions = []
925
+ cdef Py_ssize_t i
926
+ for i in range(1 << m):
927
+ solution = self.to_bits(i, m) + <list> self(self.to_bits(i, m))
928
+ solutions.append(dict(zip(gens, solution)))
929
+
930
+ return solutions
931
+
932
+ def polynomials(self, X=None, Y=None, degree=2, groebner=False):
933
+ """
934
+ Return a list of polynomials satisfying this S-box.
935
+
936
+ First, a simple linear fitting is performed for the given
937
+ ``degree`` (cf. for example [BC2003]_). If ``groebner=True`` a
938
+ Groebner basis is also computed for the result of that
939
+ process.
940
+
941
+ INPUT:
942
+
943
+ - ``X`` -- (optional) input variables
944
+
945
+ - ``Y`` -- (optional) output variables
946
+
947
+ - ``degree`` -- (default: ``2``) integer > 0
948
+
949
+ - ``groebner`` -- boolean (default: ``False``); calculate a reduced
950
+ Groebner basis of the spanning polynomials to obtain more polynomials
951
+
952
+ EXAMPLES::
953
+
954
+ sage: from sage.crypto.sbox import SBox
955
+ sage: S = SBox(7,6,0,4,2,5,1,3)
956
+ sage: P = S.ring()
957
+
958
+ By default, this method returns an indirect representation::
959
+
960
+ sage: S.polynomials() # needs sage.libs.singular
961
+ [x0*x2 + x1 + y1 + 1,
962
+ x0*x1 + x1 + x2 + y0 + y1 + y2 + 1,
963
+ x0*y1 + x0 + x2 + y0 + y2,
964
+ x0*y0 + x0*y2 + x1 + x2 + y0 + y1 + y2 + 1,
965
+ x1*x2 + x0 + x1 + x2 + y2 + 1,
966
+ x0*y0 + x1*y0 + x0 + x2 + y1 + y2,
967
+ x0*y0 + x1*y1 + x1 + y1 + 1,
968
+ x1*y2 + x1 + x2 + y0 + y1 + y2 + 1,
969
+ x0*y0 + x2*y0 + x1 + x2 + y1 + 1,
970
+ x2*y1 + x0 + y1 + y2,
971
+ x2*y2 + x1 + y1 + 1,
972
+ y0*y1 + x0 + x2 + y0 + y1 + y2,
973
+ y0*y2 + x1 + x2 + y0 + y1 + 1,
974
+ y1*y2 + x2 + y0]
975
+
976
+ We can get a direct representation by computing a
977
+ lexicographical Groebner basis with respect to the right
978
+ variable ordering, i.e. a variable ordering where the output
979
+ bits are greater than the input bits::
980
+
981
+ sage: P.<y0,y1,y2,x0,x1,x2> = PolynomialRing(GF(2),6,order='lex')
982
+ sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True) # needs sage.libs.singular
983
+ [y0 + x0*x1 + x0*x2 + x0 + x1*x2 + x1 + 1,
984
+ y1 + x0*x2 + x1 + 1,
985
+ y2 + x0 + x1*x2 + x1 + x2 + 1]
986
+
987
+ TESTS:
988
+
989
+ Check that :issue:`22453` is fixed::
990
+
991
+ sage: from sage.crypto.sboxes import AES
992
+ sage: aes_polys = AES.polynomials() # long time
993
+ sage: aes_polys[3] # long time
994
+ x3*y0 + x5*y0 + x7*y0 + x6*y1 + x2*y2 + x3*y2 + x4*y2
995
+ + x2*y3 + x3*y3 + x5*y4 + x6*y4 + x3*y5 + x4*y5
996
+ + x4*y7 + x2 + x3 + y2 + y3 + y4 + 1
997
+ """
998
+ cdef Py_ssize_t m = self.m
999
+ cdef Py_ssize_t n = self.n
1000
+
1001
+ if X is None and Y is None:
1002
+ P = self.ring()
1003
+ X = P.gens()[:m]
1004
+ Y = P.gens()[m:]
1005
+ else:
1006
+ P = X[0].parent()
1007
+
1008
+ gens = X + Y
1009
+
1010
+ cdef Py_ssize_t i
1011
+ cdef list bits = []
1012
+ for i in range(1 << m):
1013
+ bits.append(self.to_bits(i, m) + <list> self(self.to_bits(i, m)))
1014
+
1015
+ cdef Py_ssize_t ncols = (1 << m) + 1
1016
+
1017
+ A = matrix(P, _nterms(m + n, degree), ncols)
1018
+
1019
+ cdef list exponents = []
1020
+ cdef Py_ssize_t d
1021
+ for d in range(degree+1):
1022
+ exponents += IntegerVectors(d, max_length=m+n, min_length=m+n,
1023
+ min_part=0, max_part=1).list()
1024
+
1025
+ row = 0
1026
+ for exponent in exponents:
1027
+ A[row, ncols-1] = mul([gens[i]**exponent[i] for i in range(len(exponent))])
1028
+ for col in range(1 << m):
1029
+ A[row, col] = mul([bits[col][i] for i in range(len(exponent)) if exponent[i]])
1030
+ row += 1
1031
+
1032
+ rankSize = A.rank() - 1
1033
+
1034
+ cdef Py_ssize_t c
1035
+ for c in range(ncols):
1036
+ A[0, c] = 1
1037
+
1038
+ RR = A.echelon_form(algorithm='row_reduction')
1039
+
1040
+ # extract spanning stet
1041
+ gens = (RR.column(ncols-1)[rankSize:]).list()
1042
+
1043
+ if not groebner:
1044
+ return gens
1045
+
1046
+ FI = set(FieldIdeal(P).gens())
1047
+ I = Ideal(gens + list(FI))
1048
+ gb = I.groebner_basis()
1049
+
1050
+ gens = []
1051
+ for f in gb:
1052
+ # filter out field equations
1053
+ if f not in FI:
1054
+ gens.append(f)
1055
+ return gens
1056
+
1057
+ def interpolation_polynomial(self, k=None):
1058
+ r"""
1059
+ Return a univariate polynomial over an extension field
1060
+ representing this S-box.
1061
+
1062
+ If ``m`` is the input length of this S-box then the extension
1063
+ field is of degree ``m``.
1064
+
1065
+ If the output length does not match the input length then a
1066
+ :exc:`TypeError` is raised.
1067
+
1068
+ INPUT:
1069
+
1070
+ - ``k`` -- (optional) an instance of `\GF{2^m}`
1071
+
1072
+ EXAMPLES::
1073
+
1074
+ sage: from sage.crypto.sbox import SBox
1075
+ sage: S = SBox(7,6,0,4,2,5,1,3)
1076
+ sage: f = S.interpolation_polynomial()
1077
+ sage: f
1078
+ (a^2 + a + 1)*x^6 + a^2*x^5 + (a + 1)*x^4 + (a^2 + a)*x^3
1079
+ + x^2 + a*x + a^2 + a + 1
1080
+
1081
+ sage: a = f.base_ring().gen()
1082
+
1083
+ sage: f(0), S(0)
1084
+ (a^2 + a + 1, 7)
1085
+
1086
+ sage: f(a^2 + 1), S(5)
1087
+ (a^2 + 1, 5)
1088
+
1089
+ .. NOTE::
1090
+
1091
+ The method-internal call to the S-box initially used a different
1092
+ endianess for handling finite field elements. This changed in
1093
+ :issue:`25633`, by calling the S-box directly.
1094
+ """
1095
+ if self.m != self.n:
1096
+ raise TypeError("Lagrange interpolation only supported if"
1097
+ "self.input_size() == self.output_size()")
1098
+
1099
+ cdef Py_ssize_t m = self.m
1100
+ if k is None:
1101
+ k = GF(2**m, 'a')
1102
+
1103
+ cdef list l = []
1104
+ cdef int i
1105
+ for i in range(2**m):
1106
+ x = k(vector(self.to_bits(i, m)))
1107
+ l.append((x, self(x)))
1108
+
1109
+ P = PolynomialRing(k, 'x')
1110
+ return P.lagrange_polynomial(l)
1111
+
1112
+ def cnf(self, xi=None, yi=None, format=None):
1113
+ r"""
1114
+ Return a representation of this S-Box in conjunctive normal
1115
+ form.
1116
+
1117
+ This function examines the truth tables for each output bit of
1118
+ the S-Box and thus has complexity `n * 2^m` for an `m \times n`
1119
+ S-Box.
1120
+
1121
+ INPUT:
1122
+
1123
+ - ``xi`` -- (default: ``1...m``) indices for the input variables
1124
+
1125
+ - ``yi`` -- (default: ``m+1 ... m+n``) indices for the output variables
1126
+
1127
+ - ``format`` -- (default: ``None``) output format, see below
1128
+
1129
+ FORMATS:
1130
+
1131
+ - ``None`` -- return a list of tuples of integers where each
1132
+ tuple represents a clause, the absolute value of an integer
1133
+ represents a variable and the sign of an integer indicates
1134
+ inversion
1135
+
1136
+ - ``symbolic`` -- string that can be parsed by the
1137
+ ``SymbolicLogic`` package
1138
+
1139
+ - ``dimacs`` -- string in DIMACS format which is the gold
1140
+ standard for SAT-solver input (cf. http://www.satlib.org/)
1141
+
1142
+ - ``dimacs_headless`` -- string in DIMACS format, but without
1143
+ the header; this is useful for concatenation of outputs
1144
+
1145
+ EXAMPLES:
1146
+
1147
+ We give a very small example to explain the output format::
1148
+
1149
+ sage: from sage.crypto.sbox import SBox
1150
+ sage: S = SBox(1,2,0,3); S
1151
+ (1, 2, 0, 3)
1152
+ sage: cnf = S.cnf(); cnf
1153
+ [(1, 2, -3), (1, 2, 4),
1154
+ (1, -2, 3), (1, -2, -4),
1155
+ (-1, 2, -3), (-1, 2, -4),
1156
+ (-1, -2, 3), (-1, -2, 4)]
1157
+
1158
+ This output completely describes the S-Box. For instance, we
1159
+ can check that ``S([0,1]) -> [1,0]`` satisfies every clause if
1160
+ the first input bit corresponds to the index ``1`` and the
1161
+ last output bit corresponds to the index ``3`` in the output.
1162
+
1163
+ We can convert this representation to the DIMACS format::
1164
+
1165
+ sage: print(S.cnf(format='dimacs'))
1166
+ p cnf 4 8
1167
+ 1 2 -3 0
1168
+ 1 2 4 0
1169
+ 1 -2 3 0
1170
+ 1 -2 -4 0
1171
+ -1 2 -3 0
1172
+ -1 2 -4 0
1173
+ -1 -2 3 0
1174
+ -1 -2 4 0
1175
+
1176
+ For concatenation we can strip the header::
1177
+
1178
+ sage: print(S.cnf(format='dimacs_headless'))
1179
+ 1 2 -3 0
1180
+ 1 2 4 0
1181
+ 1 -2 3 0
1182
+ 1 -2 -4 0
1183
+ -1 2 -3 0
1184
+ -1 2 -4 0
1185
+ -1 -2 3 0
1186
+ -1 -2 4 0
1187
+
1188
+ This might be helpful in combination with the ``xi`` and
1189
+ ``yi`` parameter to assign indices manually::
1190
+
1191
+ sage: print(S.cnf(xi=[10,20],yi=[30,40], format='dimacs_headless'))
1192
+ 10 20 -30 0
1193
+ 10 20 40 0
1194
+ 10 -20 30 0
1195
+ 10 -20 -40 0
1196
+ -10 20 -30 0
1197
+ -10 20 -40 0
1198
+ -10 -20 30 0
1199
+ -10 -20 40 0
1200
+
1201
+ We can also return a string which is parse-able by the
1202
+ ``SymbolicLogic`` package::
1203
+
1204
+ sage: log = SymbolicLogic()
1205
+ sage: s = log.statement(S.cnf(format='symbolic'))
1206
+ sage: log.truthtable(s)[1:]
1207
+ [['False', 'False', 'False', 'False', 'False'],
1208
+ ['False', 'False', 'False', 'True', 'False'],
1209
+ ['False', 'False', 'True', 'False', 'False'],
1210
+ ['False', 'False', 'True', 'True', 'True'],
1211
+ ['False', 'True', 'False', 'False', 'True'],
1212
+ ['False', 'True', 'False', 'True', 'True'],
1213
+ ['False', 'True', 'True', 'False', 'True'],
1214
+ ['False', 'True', 'True', 'True', 'True'],
1215
+ ['True', 'False', 'False', 'False', 'True'],
1216
+ ['True', 'False', 'False', 'True', 'True'],
1217
+ ['True', 'False', 'True', 'False', 'True'],
1218
+ ['True', 'False', 'True', 'True', 'True'],
1219
+ ['True', 'True', 'False', 'False', 'True'],
1220
+ ['True', 'True', 'False', 'True', 'True'],
1221
+ ['True', 'True', 'True', 'False', 'True'],
1222
+ ['True', 'True', 'True', 'True', 'True']]
1223
+
1224
+ This function respects endianness of the S-Box::
1225
+
1226
+ sage: S = SBox(1,2,0,3, big_endian=False); S
1227
+ (1, 2, 0, 3)
1228
+ sage: cnf = S.cnf(); cnf
1229
+ [(1, 2, -4), (1, 2, 3),
1230
+ (-1, 2, 4), (-1, 2, -3),
1231
+ (1, -2, -4), (1, -2, -3),
1232
+ (-1, -2, 4), (-1, -2, 3)]
1233
+
1234
+ S-Boxes with m!=n also work:
1235
+
1236
+ sage: o = list(range(8)) + list(range(8))
1237
+ sage: shuffle(o)
1238
+ sage: S = SBox(o)
1239
+ sage: S.is_permutation()
1240
+ False
1241
+
1242
+ sage: len(S.cnf()) == 3*2^4
1243
+ True
1244
+
1245
+ TESTS:
1246
+
1247
+ sage: from sage.crypto.sbox import SBox
1248
+ sage: S = SBox(1,2,0,3, big_endian=False)
1249
+ sage: S.cnf([1000,1001,1002], [2000,2001,2002])
1250
+ Traceback (most recent call last):
1251
+ ...
1252
+ TypeError: first arg required to have length 2, got 3 instead
1253
+ """
1254
+ cdef Py_ssize_t m = self.m
1255
+ cdef Py_ssize_t n = self.n
1256
+
1257
+ cdef Py_ssize_t i
1258
+ if xi is None:
1259
+ xi = [i+1 for i in range(m)]
1260
+
1261
+ if yi is None:
1262
+ yi = [m+i+1 for i in range(n)]
1263
+
1264
+ if len(xi) != m:
1265
+ raise TypeError("first arg required to have length %d, got %d instead" % (m, len(xi)))
1266
+
1267
+ if len(yi) != n:
1268
+ raise TypeError("second arg required to have length %d, got %d instead" % (n, len(yi)))
1269
+
1270
+ cdef list output_bits = list(range(n))
1271
+ if not self._big_endian:
1272
+ output_bits = list(reversed(output_bits))
1273
+
1274
+ C = [] # the set of clauses
1275
+ cdef Py_ssize_t e, output_bit, v
1276
+ cdef list x, y
1277
+ for e in range(1 << m):
1278
+ x = self.to_bits(e, m)
1279
+ y = <list> self(x) # evaluate at x
1280
+ for output_bit in output_bits: # consider each bit
1281
+ clause = [(-1)**(int(v)) * i for v, i in zip(x, xi)]
1282
+ clause.append((-1)**(1-int(y[output_bit])) * yi[output_bit])
1283
+ C.append(tuple(clause))
1284
+
1285
+ if format is None:
1286
+ return C
1287
+ elif format == 'symbolic':
1288
+ gd = self.ring().gens()
1289
+ formula = []
1290
+ for clause in C:
1291
+ clause = "|".join([str(gd[abs(v)-1]).replace("-", "~") for v in clause])
1292
+ formula.append("("+clause+")")
1293
+ return " & ".join(formula)
1294
+
1295
+ elif format.startswith('dimacs'):
1296
+ if format == "dimacs_headless":
1297
+ header = ""
1298
+ else:
1299
+ header = "p cnf %d %d\n" % (m + n, len(C))
1300
+ values = " 0\n".join([" ".join(map(str, line)) for line in C])
1301
+ return header + values + " 0\n"
1302
+ else:
1303
+ raise ValueError("Format '%s' not supported" % (format,))
1304
+
1305
+ def component_function(self, b):
1306
+ r"""
1307
+ Return a Boolean function corresponding to the component function
1308
+ `b \cdot S(x)`.
1309
+
1310
+ If `S` is an `m \times n` S-Box, then `b \in \GF{2}^n` and
1311
+ `\cdot` denotes dot product of two vectors.
1312
+
1313
+ INPUT:
1314
+
1315
+ - ``b`` -- either an integer or a list/tuple/vector of `\GF{2}`
1316
+ elements of length ``self.output_size()``
1317
+
1318
+ EXAMPLES::
1319
+
1320
+ sage: from sage.crypto.sbox import SBox
1321
+ sage: S = SBox([7,6,0,4,2,5,1,3])
1322
+ sage: f3 = S.component_function(3)
1323
+ sage: f3.algebraic_normal_form() # needs sage.rings.polynomial.pbori
1324
+ x0*x1 + x0*x2 + x0 + x2
1325
+
1326
+ sage: f5 = S.component_function([1, 0, 1])
1327
+ sage: f5.algebraic_normal_form() # needs sage.rings.polynomial.pbori
1328
+ x0*x2 + x0 + x1*x2
1329
+
1330
+ TESTS::
1331
+
1332
+ sage: from sage.crypto.sboxes import SBox
1333
+ sage: sb = SBox([0, 1, 2, 3, 0, 1, 2, 3])
1334
+ sage: sb.component_function([1, 0])
1335
+ Boolean function with 3 variables
1336
+ """
1337
+ cdef Py_ssize_t m = self.m
1338
+ cdef Py_ssize_t n = self.n
1339
+
1340
+ try:
1341
+ b = list(b)
1342
+ if len(b) > n:
1343
+ raise ValueError("input (%s) is too long and would be truncated" % (b,))
1344
+ b = self.from_bits(b, n)
1345
+ except TypeError:
1346
+ try:
1347
+ b = ZZ(b)
1348
+ except TypeError:
1349
+ raise TypeError("cannot handle input argument %s" % (b,))
1350
+
1351
+ cdef Py_ssize_t x
1352
+ ret = BooleanFunction([ZZ(b & self._S_list[x]).popcount() & 1 for x in range(1 << m)])
1353
+
1354
+ return ret
1355
+
1356
+ def nonlinearity(self):
1357
+ """
1358
+ Return the nonlinearity of this S-Box.
1359
+
1360
+ The nonlinearity of an S-Box is defined as the minimum nonlinearity
1361
+ of all its component functions.
1362
+
1363
+ EXAMPLES::
1364
+
1365
+ sage: from sage.crypto.sbox import SBox
1366
+ sage: S = mq.SR(1,4,4,8).sbox()
1367
+ sage: S.nonlinearity()
1368
+ 112
1369
+ """
1370
+ return (1 << (self.m-1)) - self.maximal_linear_bias_absolute()
1371
+
1372
+ def linearity(self):
1373
+ """
1374
+ Return the linearity of this S-Box.
1375
+
1376
+ EXAMPLES::
1377
+
1378
+ sage: from sage.crypto.sbox import SBox
1379
+ sage: S = mq.SR(1, 4, 4, 8).sbox()
1380
+ sage: S.linearity()
1381
+ 32
1382
+ """
1383
+ return self.maximal_linear_bias_absolute() << 1
1384
+
1385
+ def is_apn(self):
1386
+ r"""
1387
+ Return ``True`` if this S-Box is an almost perfect nonlinear (APN)
1388
+ function.
1389
+
1390
+ An `m \times m` S-Box `S` is called almost perfect nonlinear if for
1391
+ every nonzero `\alpha \in \GF{2}^m` and every
1392
+ `\beta \in \GF{2}^m`, the equation
1393
+ `S(x) \oplus S(x \oplus \alpha) = \beta` has 0 or 2 solutions.
1394
+ Equivalently, the differential uniformity of `S` is equal to 2.
1395
+
1396
+ EXAMPLES::
1397
+
1398
+ sage: from sage.crypto.sbox import SBox
1399
+ sage: S = SBox([0,1,3,6,7,4,5,2])
1400
+ sage: S.is_apn()
1401
+ True
1402
+ sage: S.differential_uniformity()
1403
+ 2
1404
+ """
1405
+ if self.input_size() != self.output_size():
1406
+ raise TypeError("APN function is only defined for"
1407
+ "self.input_size() == self.output_size()")
1408
+ return self.differential_uniformity() == 2
1409
+
1410
+ def differential_branch_number(self):
1411
+ r"""
1412
+ Return differential branch number of this S-Box.
1413
+
1414
+ The differential branch number of an S-Box `S` is defined as
1415
+
1416
+ .. MATH::
1417
+
1418
+ \min_{v, w \neq v} \{ \mathrm{wt}(v \oplus w)
1419
+ + \mathrm{wt}(S(v) \oplus S(w)) \},
1420
+
1421
+ where `\mathrm{wt}(x)` denotes the Hamming weight of vector `x`.
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: from sage.crypto.sbox import SBox
1426
+ sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2])
1427
+ sage: S.differential_branch_number()
1428
+ 3
1429
+ """
1430
+ cdef Py_ssize_t m = self.m
1431
+ cdef Py_ssize_t n = self.n
1432
+ cdef Py_ssize_t ret = (1 << m) + (1 << n)
1433
+
1434
+ cdef Py_ssize_t a, b
1435
+ cdef Py_ssize_t x, y, w
1436
+ for a in range(1 << m):
1437
+ for b in range(1 << n):
1438
+ if a != b:
1439
+ x = a ^ b
1440
+ y = self._S_list[a] ^ self._S_list[b]
1441
+ w = hamming_weight(x) + hamming_weight(y)
1442
+ if w < ret:
1443
+ ret = w
1444
+ return ret
1445
+
1446
+ def linear_branch_number(self):
1447
+ r"""
1448
+ Return linear branch number of this S-Box.
1449
+
1450
+ The linear branch number of an S-Box `S` is defined as
1451
+
1452
+ .. MATH::
1453
+
1454
+ \min_{\substack{\alpha \neq 0, \beta \\ \mathrm{LAM}(\alpha, \beta) \neq 0}}
1455
+ \{ \mathrm{wt}(\alpha) + \mathrm{wt}(\beta) \},
1456
+
1457
+ where `\mathrm{LAM}(\alpha, \beta)` is the entry at row `\alpha` and
1458
+ column `\beta` of linear approximation matrix correspond to this
1459
+ S-Box. The `\mathrm{wt}(x)` denotes the Hamming weight of `x`.
1460
+
1461
+ EXAMPLES::
1462
+
1463
+ sage: from sage.crypto.sbox import SBox
1464
+ sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2])
1465
+ sage: S.linear_branch_number()
1466
+ 2
1467
+
1468
+ TESTS::
1469
+
1470
+ sage: f = SBox([0, 2, 0, 6, 2, 2, 3, 7])
1471
+ sage: f.linear_branch_number()
1472
+ 1
1473
+ """
1474
+ cdef Py_ssize_t m = self.m
1475
+ cdef Py_ssize_t n = self.n
1476
+ cdef Matrix lat = <Matrix> self.linear_approximation_table()
1477
+ cdef Py_ssize_t ret = (1 << m) + (1 << n)
1478
+
1479
+ cdef Py_ssize_t a, b, w
1480
+ for a in range(1 << m):
1481
+ for b in range(1, 1 << n):
1482
+ if lat.get_unsafe(a, b) != 0:
1483
+ w = hamming_weight(a) + hamming_weight(b)
1484
+ if w < ret:
1485
+ ret = w
1486
+ return ret
1487
+
1488
+ @cached_method
1489
+ def autocorrelation_table(self):
1490
+ r"""
1491
+ Return the autocorrelation table corresponding to this S-Box.
1492
+
1493
+ for an `m \times n` S-Box `S`, its autocorrelation table entry at
1494
+ row `a \in \GF{2}^m` and column `b \in \GF{2}^n`
1495
+ (considering their integer representation) is defined as:
1496
+
1497
+ .. MATH::
1498
+
1499
+ \sum_{x \in \GF{2}^m} (-1)^{b \cdot S(x) \oplus
1500
+ b \cdot S(x \oplus a)}.
1501
+
1502
+ Equivalently, the columns `b` of autocorrelation table correspond to
1503
+ the autocorrelation spectrum of component function `b \cdot S(x)`.
1504
+
1505
+ EXAMPLES::
1506
+
1507
+ sage: from sage.crypto.sbox import SBox
1508
+ sage: S = SBox(7,6,0,4,2,5,1,3)
1509
+ sage: S.autocorrelation_table() # needs sage.combinat
1510
+ [ 8 8 8 8 8 8 8 8]
1511
+ [ 8 0 0 0 0 0 0 -8]
1512
+ [ 8 0 -8 0 0 0 0 0]
1513
+ [ 8 0 0 0 0 -8 0 0]
1514
+ [ 8 -8 0 0 0 0 0 0]
1515
+ [ 8 0 0 0 0 0 -8 0]
1516
+ [ 8 0 0 -8 0 0 0 0]
1517
+ [ 8 0 0 0 -8 0 0 0]
1518
+ """
1519
+ from sage.combinat.matrices.hadamard_matrix import hadamard_matrix
1520
+ A = self.difference_distribution_table() * hadamard_matrix(1 << self.n)
1521
+ A.set_immutable()
1522
+
1523
+ return A
1524
+
1525
+ @cached_method
1526
+ def boomerang_connectivity_table(self):
1527
+ r"""
1528
+ Return the boomerang connectivity table (BCT) for this S-Box.
1529
+
1530
+ Boomerang connectivity matrix of an invertible `m \times m`
1531
+ S-Box `S` is an `2^m \times 2^m` matrix with entry at row
1532
+ `\Delta_i \in \GF{2}^m` and column `\Delta_o \in \GF{2}^m`
1533
+ equal to
1534
+
1535
+ .. MATH::
1536
+
1537
+ |\{ x \in \GF{2}^m | S^{-1}( S(x) \oplus \Delta_o) \oplus
1538
+ S^{-1}( S(x \oplus \Delta_i) \oplus \Delta_o) = \Delta_i\}|.
1539
+
1540
+ For more results concerning boomerang connectivity matrix,
1541
+ see [CHPSS18]_. The algorithm used here is the one from
1542
+ Dunkelman [Du2018]_.
1543
+
1544
+ EXAMPLES::
1545
+
1546
+ sage: from sage.crypto.sboxes import PRESENT
1547
+ sage: PRESENT.boomerang_connectivity_table()
1548
+ [16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16]
1549
+ [16 0 4 4 0 16 4 4 4 4 0 0 4 4 0 0]
1550
+ [16 0 0 6 0 4 6 0 0 0 2 0 2 2 2 0]
1551
+ [16 2 0 6 2 4 4 2 0 0 2 2 0 0 0 0]
1552
+ [16 0 0 0 0 4 2 2 0 6 2 0 6 0 2 0]
1553
+ [16 2 0 0 2 4 0 0 0 6 2 2 4 2 0 0]
1554
+ [16 4 2 0 4 0 2 0 2 0 0 4 2 0 4 8]
1555
+ [16 4 2 0 4 0 2 0 2 0 0 4 2 0 4 8]
1556
+ [16 4 0 2 4 0 0 2 0 2 0 4 0 2 4 8]
1557
+ [16 4 2 0 4 0 2 0 2 0 0 4 2 0 4 8]
1558
+ [16 0 2 2 0 4 0 0 6 0 2 0 0 6 2 0]
1559
+ [16 2 0 0 2 4 0 0 4 2 2 2 0 6 0 0]
1560
+ [16 0 6 0 0 4 0 6 2 2 2 0 0 0 2 0]
1561
+ [16 2 4 2 2 4 0 6 0 0 2 2 0 0 0 0]
1562
+ [16 0 2 2 0 0 2 2 2 2 0 0 2 2 0 0]
1563
+ [16 8 0 0 8 0 0 0 0 0 0 8 0 0 8 16]
1564
+ """
1565
+ from itertools import product
1566
+
1567
+ cdef SBox Si = self.inverse()
1568
+
1569
+ cdef Py_ssize_t nrows = 1 << self.m
1570
+ cdef Py_ssize_t ncols = 1 << self.n
1571
+
1572
+ cdef list L = []
1573
+
1574
+ cdef Py_ssize_t delta_in, x, i, j
1575
+ cdef list l, table, row
1576
+ for delta_in in range(ncols):
1577
+ table = [[] for _ in range(ncols)]
1578
+ for x in range(nrows):
1579
+ table[x ^ self._S_list[Si._S_list[x] ^ delta_in]].append(x)
1580
+
1581
+ row = [0]*ncols
1582
+ for l in table:
1583
+ for i, j in product(l, l):
1584
+ row[i ^ j] += 1
1585
+ L.extend(row)
1586
+
1587
+ A = matrix(ZZ, nrows, ncols, L)
1588
+ A.set_immutable()
1589
+ return A
1590
+
1591
+ def boomerang_uniformity(self):
1592
+ """
1593
+ Return the boomerang uniformity.
1594
+
1595
+ The boomerang uniformity is defined as the highest entry in the
1596
+ boomerang connectivity table, ignoring the first row and column.
1597
+
1598
+ EXAMPLES::
1599
+
1600
+ sage: from sage.crypto.sboxes import AES
1601
+ sage: AES.boomerang_uniformity()
1602
+ 6
1603
+ """
1604
+ bct = self.boomerang_connectivity_table()
1605
+ return max(bct.delete_rows([0]).delete_columns([0]).list())
1606
+
1607
+ def linear_structures(self):
1608
+ r"""
1609
+ Return a list of 3-valued tuple `(b, \alpha, c)` such that `\alpha` is
1610
+ a `c`-linear structure of the component function `b \cdot S(x)`.
1611
+
1612
+ A Boolean function `f : \GF{2}^m \mapsto \GF{2}` is said
1613
+ to have a `c`-linear structure if there exists a nonzero `\alpha` such
1614
+ that `f(x) \oplus f(x \oplus \alpha)` is a constant function `c`.
1615
+
1616
+ An `m \times n` S-Box `S` has a linear structure if there exists a
1617
+ component function `b \cdot S(x)` that has a linear structure.
1618
+
1619
+ The three valued tuple `(b, \alpha, c)` shows that `\alpha` is a
1620
+ `c`-linear structure of the component function `b \cdot S(x)`. This
1621
+ implies that for all output differences `\beta` of the S-Box
1622
+ correspond to input difference `\alpha`, we have `b \cdot \beta = c`.
1623
+
1624
+ .. SEEALSO::
1625
+
1626
+ :meth:`is_linear_structure`,
1627
+ :meth:`has_linear_structure`
1628
+
1629
+ EXAMPLES::
1630
+
1631
+ sage: from sage.crypto.sbox import SBox
1632
+ sage: S = SBox([0,1,3,6,7,4,5,2])
1633
+ sage: S.linear_structures() # needs sage.combinat
1634
+ [(1, 1, 1), (2, 2, 1), (3, 3, 1), (4, 4, 1),
1635
+ (5, 5, 1), (6, 6, 1), (7, 7, 1)]
1636
+ """
1637
+ cdef Py_ssize_t n = self.n
1638
+ cdef Py_ssize_t m = self.m
1639
+ cdef Matrix act = <Matrix> self.autocorrelation_table()
1640
+ cdef list ret = []
1641
+
1642
+ cdef Py_ssize_t j, i, c
1643
+ for j in range(1, 1 << n):
1644
+ for i in range(1, 1 << m):
1645
+ if abs(act.get_unsafe(i, j)) == (1 << m):
1646
+ c = ((1 - (act.get_unsafe(i, j) >> m)) >> 1)
1647
+ ret.append((j, i, c))
1648
+ return ret
1649
+
1650
+ def has_linear_structure(self) -> bool:
1651
+ """
1652
+ Return ``True`` if there exists a nonzero component function of this
1653
+ S-Box that has a linear structure.
1654
+
1655
+ .. SEEALSO::
1656
+
1657
+ :meth:`is_linear_structure`,
1658
+ :meth:`linear_structures`.
1659
+
1660
+ EXAMPLES::
1661
+
1662
+ sage: from sage.crypto.sbox import SBox
1663
+ sage: S = SBox(12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2)
1664
+ sage: S.has_linear_structure()
1665
+ True
1666
+ """
1667
+ cdef Py_ssize_t i
1668
+ return any(self.component_function(i).has_linear_structure()
1669
+ for i in range(1, 1 << self.n))
1670
+
1671
+ def is_linear_structure(self, a, b):
1672
+ r"""
1673
+ Return ``True`` if `a` is a linear structure of the component function
1674
+ `b \cdot S(x)` where S is this `m \times n` S-Box.
1675
+
1676
+ INPUT:
1677
+
1678
+ - ``a`` -- either an integer or a tuple of `\GF{2}` elements of
1679
+ length equal to the input size of SBox
1680
+ - ``b`` -- either an integer or a tuple of `\GF{2}` elements of
1681
+ length equal to the output size of SBox
1682
+
1683
+ .. SEEALSO::
1684
+
1685
+ :meth:`linear_structures`,
1686
+ :meth:`has_linear_structure`
1687
+
1688
+ EXAMPLES::
1689
+
1690
+ sage: from sage.crypto.sbox import SBox
1691
+ sage: S = SBox(12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2)
1692
+ sage: S.component_function(1).autocorrelation()
1693
+ (16, -16, 0, 0, 0, 0, 0, 0, -16, 16, 0, 0, 0, 0, 0, 0)
1694
+ sage: S.is_linear_structure(1, 1)
1695
+ True
1696
+ sage: S.is_linear_structure([1, 0, 0, 1], [0, 0, 0, 1])
1697
+ True
1698
+ sage: S.is_linear_structure([0, 1, 1, 1], 1)
1699
+ False
1700
+ """
1701
+ return self.component_function(b).is_linear_structure(a)
1702
+
1703
+ def max_degree(self):
1704
+ """
1705
+ Return the maximal algebraic degree of all its component functions.
1706
+
1707
+ EXAMPLES::
1708
+
1709
+ sage: from sage.crypto.sbox import SBox
1710
+ sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2])
1711
+ sage: S.max_degree() # needs sage.rings.polynomial.pbori
1712
+ 3
1713
+ """
1714
+ ret = ZZ.zero()
1715
+
1716
+ cdef Py_ssize_t i
1717
+ for i in range(self.n):
1718
+ deg_Si = self.component_function(1 << i).algebraic_degree()
1719
+ if deg_Si > ret:
1720
+ ret = deg_Si
1721
+ return ret
1722
+
1723
+ def min_degree(self):
1724
+ """
1725
+ Return the minimal algebraic degree of all its component functions.
1726
+
1727
+ EXAMPLES::
1728
+
1729
+ sage: from sage.crypto.sbox import SBox
1730
+ sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2])
1731
+ sage: S.min_degree() # needs sage.rings.polynomial.pbori
1732
+ 2
1733
+ """
1734
+ ret = ZZ(self.m)
1735
+
1736
+ cdef Py_ssize_t b
1737
+ for b in range(1, 1 << self.n):
1738
+ deg_bS = self.component_function(b).algebraic_degree()
1739
+ if deg_bS < ret:
1740
+ ret = deg_bS
1741
+ return ret
1742
+
1743
+ def is_balanced(self):
1744
+ r"""
1745
+ Return ``True`` if this S-Box is balanced.
1746
+
1747
+ An S-Box is balanced if all its component functions are balanced.
1748
+
1749
+ EXAMPLES::
1750
+
1751
+ sage: from sage.crypto.sbox import SBox
1752
+ sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2])
1753
+ sage: S.is_balanced()
1754
+ True
1755
+ """
1756
+ cdef Py_ssize_t b
1757
+ for b in range(1, 1 << self.n):
1758
+ bS = self.component_function(b)
1759
+ if not bS.is_balanced():
1760
+ return False
1761
+ return True
1762
+
1763
+ def is_almost_bent(self):
1764
+ r"""
1765
+ Return ``True`` if this S-Box is an almost bent (AB) function.
1766
+
1767
+ An `m \times m` S-Box `S`, for `m` odd, is called almost bent if its
1768
+ nonlinearity is equal to `2^{m-1} - 2^{(m-1)/2}`.
1769
+
1770
+ EXAMPLES::
1771
+
1772
+ sage: from sage.crypto.sbox import SBox
1773
+ sage: S = SBox([0,1,3,6,7,4,5,2])
1774
+ sage: S.is_almost_bent()
1775
+ True
1776
+ """
1777
+ if self.m != self.n:
1778
+ raise TypeError("almost bent function only exists for"
1779
+ " self.input_size() == self.output_size()")
1780
+
1781
+ cdef Py_ssize_t m = self.m
1782
+
1783
+ if is_even(m):
1784
+ return False
1785
+
1786
+ return self.nonlinearity() == 2**(m-1) - 2**((m-1)//2)
1787
+
1788
+ def fixed_points(self):
1789
+ """
1790
+ Return a list of all fixed points of this S-Box.
1791
+
1792
+ EXAMPLES::
1793
+
1794
+ sage: from sage.crypto.sbox import SBox
1795
+ sage: S = SBox([0,1,3,6,7,4,5,2])
1796
+ sage: S.fixed_points()
1797
+ [0, 1]
1798
+ """
1799
+ cdef Py_ssize_t i
1800
+ return [i for i in range(1 << self.m) if i == self._S_list[i]]
1801
+
1802
+ def inverse(self):
1803
+ """
1804
+ Return the inverse of this S-Box.
1805
+
1806
+ Note that the S-Box must be invertible, otherwise it will raise
1807
+ a :exc:`TypeError`.
1808
+
1809
+ EXAMPLES::
1810
+
1811
+ sage: from sage.crypto.sbox import SBox
1812
+ sage: S = SBox([0, 1, 3, 6, 7, 4, 5, 2])
1813
+ sage: Sinv = S.inverse()
1814
+ sage: [Sinv(S(i)) for i in range(8)]
1815
+ [0, 1, 2, 3, 4, 5, 6, 7]
1816
+ """
1817
+ if not self.is_permutation():
1818
+ raise TypeError("S-Box must be a permutation")
1819
+
1820
+ cdef Py_ssize_t i
1821
+ cdef list L = [self._S_list[i] for i in range(1 << self.m)]
1822
+
1823
+ return SBox([L.index(i) for i in range(1 << self.m)],
1824
+ big_endian=self._big_endian)
1825
+
1826
+ def is_monomial_function(self):
1827
+ r"""
1828
+ Return ``True`` if this S-Box is a monomial/power function.
1829
+
1830
+ EXAMPLES::
1831
+
1832
+ sage: from sage.crypto.sbox import SBox
1833
+ sage: S = SBox([0,1,3,6,7,4,5,2])
1834
+ sage: S.is_monomial_function()
1835
+ False
1836
+ sage: S_poly = S.interpolation_polynomial(); S_poly
1837
+ (a + 1)*x^6 + (a^2 + a + 1)*x^5 + (a^2 + a)*x^4
1838
+ + (a^2 + 1)*x^3 + a*x^2 + a*x
1839
+
1840
+ sage: all([S(x) == S_poly(x) for x in S_poly.base_ring()])
1841
+ True
1842
+
1843
+ sage: S = SBox(0,3,2,1)
1844
+ sage: S.interpolation_polynomial()
1845
+ x^2
1846
+ sage: S.is_monomial_function()
1847
+ True
1848
+ """
1849
+ return self.interpolation_polynomial().is_monomial()
1850
+
1851
+ def is_plateaued(self):
1852
+ r"""
1853
+ Return ``True`` if this S-Box is plateaued, i.e. for all nonzero
1854
+ `b \in \GF{2}^n` the Boolean function `b \cdot S(x)`
1855
+ is plateaued.
1856
+
1857
+ EXAMPLES::
1858
+
1859
+ sage: from sage.crypto.sbox import SBox
1860
+ sage: S = SBox(0, 3, 1, 2, 4, 6, 7, 5)
1861
+ sage: S.is_plateaued()
1862
+ True
1863
+ """
1864
+ cdef Py_ssize_t b
1865
+ for b in range(1, 1 << self.n):
1866
+ bS = self.component_function(b)
1867
+ if not bS.is_plateaued():
1868
+ return False
1869
+ return True
1870
+
1871
+ def is_bent(self):
1872
+ r"""
1873
+ Return ``True`` if this S-Box is bent, i.e. its nonlinearity
1874
+ is equal to `2^{m-1} - 2^{m/2 - 1}` where `m` is the input size
1875
+ of the S-Box.
1876
+
1877
+ EXAMPLES::
1878
+
1879
+ sage: from sage.crypto.sbox import SBox
1880
+ sage: R.<x> = GF(2**2, 'a')[]
1881
+ sage: base = R.base_ring()
1882
+ sage: a = base.gen()
1883
+ sage: G = a * x^2 + 1
1884
+ sage: S = SBox([G(x * y**(14)) for x in sorted(base) for y in sorted(base)])
1885
+ sage: S.is_bent()
1886
+ True
1887
+ sage: S.nonlinearity()
1888
+ 6
1889
+ sage: S.linear_approximation_table()
1890
+ [ 8 -2 2 -2]
1891
+ [ 0 -2 2 -2]
1892
+ [ 0 -2 2 -2]
1893
+ [ 0 -2 2 -2]
1894
+ [ 0 -2 2 -2]
1895
+ [ 0 -2 -2 2]
1896
+ [ 0 2 2 2]
1897
+ [ 0 2 -2 -2]
1898
+ [ 0 -2 2 -2]
1899
+ [ 0 2 -2 -2]
1900
+ [ 0 -2 -2 2]
1901
+ [ 0 2 2 2]
1902
+ [ 0 -2 2 -2]
1903
+ [ 0 2 2 2]
1904
+ [ 0 2 -2 -2]
1905
+ [ 0 -2 -2 2]
1906
+ """
1907
+ cdef Py_ssize_t m = self.m
1908
+ cdef Py_ssize_t n = self.n
1909
+
1910
+ if not is_even(m) or n > m // 2:
1911
+ return False
1912
+
1913
+ return self.nonlinearity() == 2**(m-1) - 2**(m//2 - 1)
1914
+
1915
+ def is_involution(self):
1916
+ r"""
1917
+ Return ``True`` if this S-Box is an involution, i.e. the inverse S-Box
1918
+ is equal itself.
1919
+
1920
+ EXAMPLES::
1921
+
1922
+ sage: from sage.crypto.sbox import SBox
1923
+ sage: S = SBox([x**254 for x in sorted(GF(2**8))])
1924
+ sage: S.is_involution()
1925
+ True
1926
+ """
1927
+ return self == self.inverse()
1928
+
1929
+
1930
+ cdef Py_ssize_t feistel_substitute(Py_ssize_t x, Py_ssize_t input_size, list sboxes) noexcept:
1931
+ """
1932
+ Compute a Feistel output using the given sboxes.
1933
+
1934
+ INPUT:
1935
+
1936
+ - ``x`` -- integer; the input to the Feistel construction
1937
+ - ``input_size`` -- integer; the bitsize of the Feistel construction
1938
+ - ``sboxes`` -- list of SBox; the sboxes applied in the Feistel construction
1939
+
1940
+ EXAMPLES::
1941
+
1942
+ sage: from sage.crypto.sbox import feistel_construction
1943
+ sage: from sage.crypto.sboxes import PRESENT as s
1944
+ sage: S = feistel_construction(s, s, s) # indirect doctest
1945
+ """
1946
+ cdef Py_ssize_t mask = (1 << input_size) - 1
1947
+ cdef Py_ssize_t xl = (x >> input_size) & mask
1948
+ cdef Py_ssize_t xr = x & mask
1949
+
1950
+ cdef SBox sb
1951
+ for sb in sboxes:
1952
+ xl, xr = sb(xl) ^ xr, xl
1953
+
1954
+ return (xl << input_size) | xr
1955
+
1956
+
1957
+ cdef Py_ssize_t misty_substitute(Py_ssize_t x, Py_ssize_t input_size, list sboxes) noexcept:
1958
+ """
1959
+ Compute a Misty output using the given sboxes.
1960
+
1961
+ INPUT:
1962
+
1963
+ - ``x`` -- integer; the input to the Misty construction
1964
+ - ``input_size`` -- integer; the bitsize of the Misty construction
1965
+ - ``sboxes`` -- list of SBox; the sboxes applied in the Misty construction
1966
+
1967
+ EXAMPLES::
1968
+
1969
+ sage: from sage.crypto.sbox import misty_construction
1970
+ sage: from sage.crypto.sboxes import PRESENT as s
1971
+ sage: S = misty_construction(s, s, s) # indirect doctest
1972
+ """
1973
+ cdef Py_ssize_t mask = (1 << input_size) - 1
1974
+ cdef Py_ssize_t xl = (x >> input_size) & mask
1975
+ cdef Py_ssize_t xr = x & mask
1976
+
1977
+ cdef SBox sb
1978
+ for sb in sboxes:
1979
+ xl, xr = sb(xr) ^ xl, xl
1980
+
1981
+ return (xl << input_size) | xr
1982
+
1983
+
1984
+ ctypedef Py_ssize_t (*_SBOX_CONSTR) (Py_ssize_t, Py_ssize_t, list) noexcept
1985
+
1986
+
1987
+ cdef sbox_construction(_SBOX_CONSTR construction, list args):
1988
+ """
1989
+ Construct an Sbox from the given input sboxes that has a twice
1990
+ as big input size.
1991
+
1992
+ INPUT:
1993
+
1994
+ - ``args`` -- a finite iterable SBox objects
1995
+
1996
+ EXAMPLES::
1997
+
1998
+ sage: from sage.crypto.sbox import feistel_construction
1999
+ sage: from sage.crypto.sboxes import PRESENT as s
2000
+ sage: S = feistel_construction(s, s, s) # indirect doctest
2001
+ """
2002
+ if len(args) == 1:
2003
+ if isinstance(args[0], SBox):
2004
+ sboxes = [args[0]]
2005
+ else:
2006
+ sboxes = args[0]
2007
+ elif len(args) > 1:
2008
+ sboxes = args
2009
+ else:
2010
+ raise TypeError("no input provided")
2011
+
2012
+ for sb in sboxes:
2013
+ if not isinstance(sb, SBox):
2014
+ raise TypeError("all inputs must be an instance of SBox object")
2015
+
2016
+ cdef Py_ssize_t input_size = sboxes[0].input_size()
2017
+ cdef Py_ssize_t m = 2 * input_size
2018
+
2019
+ cdef Py_ssize_t i
2020
+ return SBox([construction(i, input_size, sboxes) for i in range(1 << m)])
2021
+
2022
+
2023
+ def feistel_construction(*args):
2024
+ r"""
2025
+ Return an S-Box constructed by Feistel structure using smaller S-Boxes in
2026
+ ``args``. The number of round in the construction is equal to the number of
2027
+ S-Boxes provided as input. For more results concerning the differential
2028
+ uniformity and the nonlinearity of S-Boxes constructed by Feistel structures
2029
+ see [CDL2015]_.
2030
+
2031
+ INPUT:
2032
+
2033
+ - ``args`` -- a finite iterable SBox objects
2034
+
2035
+ EXAMPLES:
2036
+
2037
+ Suppose we construct an `8 \times 8` S-Box with 3-round Feistel
2038
+ construction from the S-Box of PRESENT::
2039
+
2040
+ sage: from sage.crypto.sbox import SBox
2041
+ sage: s = SBox(12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2)
2042
+ sage: from sage.crypto.sbox import feistel_construction
2043
+ sage: S = feistel_construction(s, s, s)
2044
+
2045
+ The properties of the constructed S-Box can be easily examined::
2046
+
2047
+ sage: S.nonlinearity()
2048
+ 96
2049
+ sage: S.differential_branch_number()
2050
+ 2
2051
+ sage: S.linear_branch_number()
2052
+ 2
2053
+ """
2054
+ return sbox_construction(feistel_substitute, list(args))
2055
+
2056
+
2057
+ def misty_construction(*args):
2058
+ r"""
2059
+ Return an S-Box constructed by MISTY structure using smaller
2060
+ S-Boxes in ``args``.
2061
+
2062
+ The number of round in the construction is equal to the number
2063
+ of S-Boxes provided as input. For further result related to the
2064
+ nonlinearity and differential uniformity of the constructed S-Box
2065
+ one may consult [CDL2015]_.
2066
+
2067
+ INPUT:
2068
+
2069
+ - ``args`` -- a finite iterable SBox objects
2070
+
2071
+ EXAMPLES:
2072
+
2073
+ We construct an `8 \times 8` S-Box using 3-round MISTY structure with the
2074
+ following `4 \times 4` S-Boxes `S1, S2, S3` (see Example 2 in [CDL2015]_)::
2075
+
2076
+ sage: from sage.crypto.sbox import SBox
2077
+ sage: S1 = SBox([0x4,0x0,0x1,0xF,0x2,0xB,0x6,0x7,0x3,0x9,0xA,0x5,0xC,0xD,0xE,0x8])
2078
+ sage: S2 = SBox([0x0,0x0,0x0,0x1,0x0,0xA,0x8,0x3,0x0,0x8,0x2,0xB,0x4,0x6,0xE,0xD])
2079
+ sage: S3 = SBox([0x0,0x7,0xB,0xD,0x4,0x1,0xB,0xF,0x1,0x2,0xC,0xE,0xD,0xC,0x5,0x5])
2080
+ sage: from sage.crypto.sbox import misty_construction
2081
+ sage: S = misty_construction(S1, S2, S3)
2082
+
2083
+ The properties of the constructed S-Box can be easily examined::
2084
+
2085
+ sage: S.differential_uniformity()
2086
+ 8
2087
+ sage: S.linearity()
2088
+ 64
2089
+ """
2090
+ return sbox_construction(misty_substitute, list(args))