Recursively split poly using the Berlekamp trace algorithm.
(poly, randv)
| 276 | return [] |
| 277 | |
| 278 | def rec_split(poly, randv): |
| 279 | """Recursively split poly using the Berlekamp trace algorithm.""" |
| 280 | # See https://hal.archives-ouvertes.fr/hal-00626997/document. |
| 281 | assert len(poly) > 1 and poly[-1] == 1 # Require a monic poly. |
| 282 | # If poly is of the form x+a, its root is a. |
| 283 | if len(poly) == 2: |
| 284 | return [poly[0]] |
| 285 | # Try consecutive randomization factors randv, until one is found that factors poly. |
| 286 | while True: |
| 287 | # Compute the trace of (randv*x) mod poly. This is a polynomial that maps half of the |
| 288 | # domain to 0, and the other half to 1. Which half that is is controlled by randv. |
| 289 | # By taking it modulo poly, we only add a multiple of poly. Thus the result has at least |
| 290 | # the shared roots of the trace polynomial and poly still, but may have others. |
| 291 | trace = poly_tracemod(poly, randv, gf) |
| 292 | # Using the set {2^i*a for i=0..fieldsize-1} gives optimally independent randv values |
| 293 | # (no more than fieldsize are ever needed). |
| 294 | randv = gf.mul2(randv) |
| 295 | # Now take the GCD of this trace polynomial with poly. The result is a polynomial |
| 296 | # that only has the shared roots of the trace polynomial and poly as roots. |
| 297 | gcd = poly_gcd(trace, poly, gf) |
| 298 | # If the result has a degree higher than 1, and lower than that of poly, we found a |
| 299 | # useful factorization. |
| 300 | if len(gcd) != len(poly) and len(gcd) > 1: |
| 301 | break |
| 302 | # Otherwise, continue with another randv. |
| 303 | # Find the actual factors: the monic version of the GCD above, and poly divided by it. |
| 304 | factor1 = poly_monic(gcd, gf) |
| 305 | factor2, _ = poly_divmod(poly, gcd, gf) |
| 306 | # Recurse. |
| 307 | return rec_split(factor1, randv) + rec_split(factor2, randv) |
| 308 | |
| 309 | # Invoke the recursive splitting with a random initial factor, and sort the results. |
| 310 | return sorted(rec_split(poly, random.randrange(1, 1 << gf.field_size))) |
no test coverage detected