From 08d525cff58a5c93f1f7496f6a3bf8893053fa3e Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Wed, 6 Dec 2017 18:03:11 +0300 Subject: [PATCH] Api enhancements (#24) - generify `FactorDecomposition` - rename old `FactorDecomposition` to `PolynomialFactorDecomposition` - implement `FactorDecomposition` for generic rings - add default `gcd` method in Ring interface - add default `extendedGCD` method to `Ring` interface - add `factor` and `factorSquareFree` methods to `Ring` interface - rename PolynomialRing in scaladsl to IPolynomialRing (consistent with Java API) - synthetic sugar methods for Rationals in scaladsl - Diophantine solver for univariate polynomials - Util multivariate conversions - minor fixes --- doc/guide.rst | 14 +- ..._vs_FLINT_vs_Mathematica_UnivariateZp.java | 6 +- ...ngs_vs_Singular_vs_Mathematica_Factor.java | 4 +- .../cc/redberry/rings/scaladsl/Ops.scala | 4 +- .../cc/redberry/rings/scaladsl/Predef.scala | 42 +- .../cc/redberry/rings/scaladsl/Rings.scala | 91 +++- .../cc/redberry/rings/scaladsl/Syntax.scala | 4 +- .../cc/redberry/rings/scaladsl/package.scala | 6 +- .../cc/redberry/rings/scaladsl/Examples.scala | 197 +++++++- .../redberry/rings/scaladsl/SyntaxTest.scala | 30 +- .../java/cc/redberry/rings/AIntegers.java | 7 +- .../rings/{bigint => }/ChineseRemainders.java | 45 +- .../redberry/rings/FactorDecomposition.java | 339 ++++++++++++++ .../main/java/cc/redberry/rings/Integers.java | 16 + .../java/cc/redberry/rings/IntegersZp.java | 10 + .../main/java/cc/redberry/rings/Rational.java | 20 + .../java/cc/redberry/rings/Rationals.java | 13 +- .../src/main/java/cc/redberry/rings/Ring.java | 112 ++++- .../main/java/cc/redberry/rings/Rings.java | 8 +- .../redberry/rings/poly/APolynomialRing.java | 2 +- .../rings/poly/FactorDecomposition.java | 435 ------------------ .../cc/redberry/rings/poly/FiniteField.java | 11 +- .../cc/redberry/rings/poly/IPolynomial.java | 9 + ...lynomialRing.java => IPolynomialRing.java} | 2 +- .../redberry/rings/poly/MultivariateRing.java | 11 + .../poly/PolynomialFactorDecomposition.java | 237 ++++++++++ .../rings/poly/PolynomialMethods.java | 24 +- .../redberry/rings/poly/UnivariateRing.java | 20 +- .../rings/poly/multivar/HenselLifting.java | 4 +- .../multivar/MultivariateConversions.java | 98 ++++ .../multivar/MultivariateFactorization.java | 274 +++++------ .../rings/poly/multivar/MultivariateGCD.java | 2 +- .../multivar/MultivariateInterpolation.java | 6 +- .../MultivariateSquareFreeFactorization.java | 52 +-- .../poly/univar/AUnivariatePolynomial64.java | 5 - .../poly/univar/DiophantineEquations.java | 62 +++ .../univar/DistinctDegreeFactorization.java | 52 +-- .../poly/univar/EqualDegreeFactorization.java | 8 +- .../rings/poly/univar/HenselLifting.java | 2 + .../poly/univar/IrreduciblePolynomials.java | 16 +- .../poly/univar/UnivariateFactorization.java | 120 +++-- .../rings/poly/univar/UnivariateGCD.java | 4 +- .../poly/univar/UnivariatePolynomialZ64.java | 5 + .../poly/univar/UnivariatePolynomialZp64.java | 19 +- .../UnivariateSquareFreeFactorization.java | 60 +-- .../{bigint => }/ChineseRemaindersTest.java | 6 +- .../test/java/cc/redberry/rings/Examples.java | 4 +- .../java/cc/redberry/rings/IntegersTest.java | 19 + .../rings/poly/FactorDecompositionTest.java | 4 +- .../redberry/rings/poly/FiniteFieldTest.java | 4 +- .../poly/multivar/HenselLiftingTest.java | 2 +- .../multivar/MultivariateConversionsTest.java | 53 +++ .../MultivariateFactorizationTest.java | 245 +++++----- .../MultivariateInterpolationTest.java | 7 +- ...ltivariateSquareFreeFactorizationTest.java | 14 +- .../rings/poly/test/FactorizationInput.java | 14 +- .../poly/univar/DiophantineEquationsTest.java | 48 ++ .../DistinctDegreeFactorizationTest.java | 49 +- .../poly/univar/FactorizationTestUtil.java | 6 +- .../rings/poly/univar/HenselLiftingTest.java | 17 +- .../univar/IrreduciblePolynomialsTest.java | 4 +- .../univar/UnivariateFactorizationTest.java | 46 +- ...UnivariateSquareFreeFactorizationTest.java | 24 +- 63 files changed, 1998 insertions(+), 1076 deletions(-) rename rings/src/main/java/cc/redberry/rings/{bigint => }/ChineseRemainders.java (86%) create mode 100644 rings/src/main/java/cc/redberry/rings/FactorDecomposition.java delete mode 100644 rings/src/main/java/cc/redberry/rings/poly/FactorDecomposition.java rename rings/src/main/java/cc/redberry/rings/poly/{PolynomialRing.java => IPolynomialRing.java} (88%) create mode 100644 rings/src/main/java/cc/redberry/rings/poly/PolynomialFactorDecomposition.java create mode 100644 rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateConversions.java create mode 100644 rings/src/main/java/cc/redberry/rings/poly/univar/DiophantineEquations.java rename rings/src/test/java/cc/redberry/rings/{bigint => }/ChineseRemaindersTest.java (98%) create mode 100644 rings/src/test/java/cc/redberry/rings/IntegersTest.java create mode 100644 rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateConversionsTest.java create mode 100644 rings/src/test/java/cc/redberry/rings/poly/univar/DiophantineEquationsTest.java diff --git a/doc/guide.rst b/doc/guide.rst index 759a9c5..ed3e7c2 100644 --- a/doc/guide.rst +++ b/doc/guide.rst @@ -792,7 +792,7 @@ Methods added to `Ring[E]`_ interface: Polynomial ring methods """"""""""""""""""""""" -Methods added to `PolynomialRing[Poly, E]`_ class (``Poly`` is polynomial type, ``E`` is a type of coefficients): +Methods added to `IPolynomialRing[Poly, E]`_ interface (``Poly`` is polynomial type, ``E`` is a type of coefficients): +------------------------------+--------------------------------------------------------------------------------------------------+ | Scala DSL | Description | @@ -808,14 +808,14 @@ Methods added to `PolynomialRing[Poly, E]`_ class (``Poly`` is polynomial type, +------------------------------+--------------------------------------------------------------------------------------------------+ -For more details see `PolynomialRing[Poly, E]`_. +For more details see `IPolynomialRing[Poly, E]`_. .. _Ring: https://github.com/PoslavskySV/rings/blob/develop/rings/src/main/java/cc/redberry/rings/Ring.java .. _Ring[E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala -.. _PolynomialRing[Poly, E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala +.. _IPolynomialRing[Poly, E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala .. _Z: https://github.com/PoslavskySV/rings/blob/develop/rings/src/main/java/cc/redberry/rings/Rings.java#L30 @@ -1031,7 +1031,7 @@ Note that there is no any specific polynomial ring used in the ``genericFunc`` a * @tparam E type of polynomial coefficients */ def genericFuncWithRing[Poly <: IPolynomial[Poly], E](poly: Poly) - (implicit ring: PolynomialRing[Poly, E]): Poly = { + (implicit ring: IPolynomialRing[Poly, E]): Poly = { poly.pow(2) * 3 + poly * 2 + 1 } @@ -1049,7 +1049,7 @@ Note that there is no any specific polynomial ring used in the ``genericFunc`` a /** * @param polynomial type */ - static > Poly genericFuncWithRing(Poly poly, PolynomialRing ring) { + static > Poly genericFuncWithRing(Poly poly, IPolynomialRing ring) { return ring.add( ring.getOne(), ring.multiply(poly, ring.valueOf(2)), @@ -1165,7 +1165,7 @@ Internally both implementations use dense data structure (array of coefficients) * @param univariate polynomial type */ static > - Poly genericFuncWithRing(Poly poly, PolynomialRing ring) { return null; } + Poly genericFuncWithRing(Poly poly, IPolynomialRing ring) { return null; } .. _ref-univariate-divison: @@ -1628,7 +1628,7 @@ The generic parent class for multivariate polynomials is `AMultivariatePolynomia */ static , Poly extends AMultivariatePolynomial> - Poly genericFuncWithRing(Poly poly, PolynomialRing ring) { return null; } + Poly genericFuncWithRing(Poly poly, IPolynomialRing ring) { return null; } // call generic funcs genericFunc(MultivariatePolynomial.parse("a + b")); diff --git a/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp.java b/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp.java index 7ee2682..f09f28e 100644 --- a/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp.java +++ b/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp.java @@ -1,7 +1,7 @@ package cc.redberry.rings.benchmark; import cc.redberry.rings.benchmark.Bench.ExternalResult; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.PolynomialMethods; import cc.redberry.rings.poly.univar.UnivariatePolynomialZp64; import cc.redberry.rings.util.TimeUnits; @@ -10,10 +10,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import static cc.redberry.rings.benchmark.Bench.mathematicaFactor; -import static cc.redberry.rings.benchmark.Bench.writeTimingsTSV; public class Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp { //NTL and FLINT data are generated from C++ binaries! @@ -47,7 +45,7 @@ public static long[][] run(int maxL, boolean silent) throws IOException { long start = System.nanoTime(); for (int i = 0; i < nIterations; i++) { - FactorDecomposition rFactors = PolynomialMethods.Factor(poly); + PolynomialFactorDecomposition rFactors = PolynomialMethods.Factor(poly); dummy += rFactors.signum(); } long ringsTime = (System.nanoTime() - start); diff --git a/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_Singular_vs_Mathematica_Factor.java b/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_Singular_vs_Mathematica_Factor.java index 1227a98..3bc4047 100644 --- a/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_Singular_vs_Mathematica_Factor.java +++ b/rings.benchmarks/src/main/java/cc/redberry/rings/benchmark/Rings_vs_Singular_vs_Mathematica_Factor.java @@ -3,7 +3,7 @@ import cc.redberry.rings.Ring; import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.MultivariateRing; import cc.redberry.rings.poly.PolynomialMethods; import cc.redberry.rings.poly.multivar.MultivariatePolynomial; @@ -133,7 +133,7 @@ static long[][] run(int nVariables, System.out.println("Sparsity: " + poly.sparsity()); long start = System.nanoTime(); - FactorDecomposition> ringsResult + PolynomialFactorDecomposition> ringsResult = timeConstrained(RINGS_TIMEOUT, () -> PolynomialMethods.Factor(poly)); long ringsTime = System.nanoTime() - start; if (!silent) diff --git a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Ops.scala b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Ops.scala index 52d6bc4..078f391 100644 --- a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Ops.scala +++ b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Ops.scala @@ -123,7 +123,7 @@ trait PolynomialSetSyntax { implicit def polynomialSetOps[Poly <: IPolynomial[Poly]](poly: Poly): PolynomialSetOps[Poly] = new PolynomialSetOps[Poly](poly) } -class PolynomialCfOps[Poly <: IPolynomial[Poly], E](self: Poly)(pRing: PolynomialRing[Poly, E]) { +class PolynomialCfOps[Poly <: IPolynomial[Poly], E](self: Poly)(pRing: IPolynomialRing[Poly, E]) { def lc: E = pRing.lc(self) def cc: E = pRing.cc(self) @@ -246,7 +246,7 @@ class MultivariateCfOps[Term <: DegreeVector[Term], Poly <: AMultivariatePolynom def swapVariables(i: String, j: String): Poly = rings.poly.multivar.AMultivariatePolynomial.swapVariables[Term, Poly](self, pRing.index(i), pRing.index(j)) } -class CfOps[E, Poly <: IPolynomial[Poly]](self: E)(ring: PolynomialRing[Poly, E]) { +class CfOps[E, Poly <: IPolynomial[Poly]](self: E)(ring: IPolynomialRing[Poly, E]) { def +(poly: Poly): Poly = ring.addConstant(poly, self) def -(poly: Poly): Poly = ring.negate(ring.subtractConstant(poly, self)) diff --git a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Predef.scala b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Predef.scala index 77ad514..033ba2b 100644 --- a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Predef.scala +++ b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Predef.scala @@ -3,9 +3,10 @@ package cc.redberry.rings.scaladsl import cc.redberry.rings import cc.redberry.rings.bigint.BigInteger import cc.redberry.rings.poly.FiniteField -import cc.redberry.rings.{IntegersZp64, Rational, poly} +import cc.redberry.rings.{FactorDecomposition, IntegersZp64, poly} import org.apache.commons.math3.random.{AbstractRandomGenerator, RandomGenerator} +import scala.collection.JavaConverters.collectionAsScalaIterableConverter import scala.language.implicitConversions import scala.util.Random @@ -35,30 +36,30 @@ private[scaladsl] trait Predef { override def setSeed(seed: Long): Unit = random.setSeed(seed) } /** - * Delegate [[PolynomialRing]] methods for [[PolynomialRing]] + * Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]] */ - implicit def ringMethods[Poly <: IPolynomial[Poly], E](ring: PolynomialRing[Poly, E]): poly.PolynomialRing[Poly] = ring.theRing + implicit def ringMethods[Poly <: IPolynomial[Poly], E](ring: IPolynomialRing[Poly, E]): rings.poly.IPolynomialRing[Poly] = ring.theRing /** - * Delegate [[PolynomialRing]] methods for [[PolynomialRing]] + * Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]] */ implicit def ringMethods[E](ring: UnivariateRing[E]): poly.UnivariateRing[UnivariatePolynomial[E]] = ring.theRing.asInstanceOf[poly.UnivariateRing[UnivariatePolynomial[E]]] /** - * Delegate [[PolynomialRing]] methods for [[PolynomialRing]] + * Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]] */ implicit def ringMethods(ring: UnivariateRingZp64): poly.UnivariateRing[UnivariatePolynomialZp64] = ring.theRing.asInstanceOf[poly.UnivariateRing[UnivariatePolynomialZp64]] /** - * Delegate [[PolynomialRing]] methods for [[PolynomialRing]] + * Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]] */ implicit def ringMethods[E](ring: MultivariateRing[E]): poly.MultivariateRing[MultivariatePolynomial[E]] = ring.theRing.asInstanceOf[poly.MultivariateRing[MultivariatePolynomial[E]]] /** - * Delegate [[PolynomialRing]] methods for [[PolynomialRing]] + * Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]] */ implicit def ringMethods(ring: MultivariateRingZp64): poly.MultivariateRing[MultivariatePolynomialZp64] = ring.theRing.asInstanceOf[poly.MultivariateRing[MultivariatePolynomialZp64]] @@ -96,7 +97,7 @@ private[scaladsl] trait Predef { /** * Field of rationals (Q) */ - val Q: Ring[Rational[BigInteger]] = rings.Rings.Q + val Q: Ring[rings.Rational[BigInteger]] = rings.Rings.Q /** * Field of integers modulo `modulus` @@ -151,7 +152,7 @@ private[scaladsl] trait Predef { def apply(cf: Int, exponents: Int*) = new MonomialZp64(exponents.toArray, cf.toLong) def apply(cf: Int, exponents: (String, Int)*) - (implicit ring: PolynomialRing[MultivariatePolynomialZp64, Long]) = { + (implicit ring: IPolynomialRing[MultivariatePolynomialZp64, Long]) = { val exps: Array[Int] = new Array[Int](exponents.length) exponents.foreach(e => exps(ring.index(e._1)) = e._2) new MonomialZp64(exps, ring.cfValue(cf)) @@ -162,13 +163,31 @@ private[scaladsl] trait Predef { def apply[E](cf: E, exponents: Int*) = new Monomial[E](exponents.toArray, cf) def apply[E](cf: E, exponents: (String, Int)*) - (implicit ring: PolynomialRing[MultivariatePolynomial[E], E]) = { + (implicit ring: IPolynomialRing[MultivariatePolynomial[E], E]) = { val exps: Array[Int] = new Array[Int](exponents.length) exponents.foreach(e => exps(ring.index(e._1)) = e._2) new Monomial[E](exps, cf) } } + object Rational { + def apply[E](num: E, den: E)(implicit ring: Ring[E]): rings.Rational[E] = new rings.Rational[E](ring, num, den) + + def apply[E](num: E)(implicit ring: Ring[E]): rings.Rational[E] = new rings.Rational[E](ring, num) + + @inline + def apply[E](num: Int, den: E)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num), den)(ring) + + @inline + def apply[E](num: E, den: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(num, ring(den))(ring) + + @inline + def apply[E](num: Int, den: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num), ring(den))(ring) + + @inline + def apply[E](num: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num))(ring) + } + final class RichArrayTuple[Poly](arr: Array[Poly]) { def tuple2: (Poly, Poly) = (arr(0), arr(1)) @@ -178,4 +197,7 @@ private[scaladsl] trait Predef { } implicit def arrayToTuple[Poly](arr: Array[Poly]): RichArrayTuple[Poly] = new RichArrayTuple(arr) + + implicit def factors2Seq[E](factors: FactorDecomposition[E]): Seq[(E, Int)] = + (factors.factors.asScala zip factors.exponents.toArray().toSeq).toSeq } diff --git a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala index 0797140..7a1a8cd 100644 --- a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala +++ b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala @@ -3,13 +3,13 @@ package cc.redberry.rings.scaladsl import java.util.Objects import cc.redberry.rings +import cc.redberry.rings._ import cc.redberry.rings.poly.multivar.MonomialOrder -import cc.redberry.rings.{poly, _} import scala.language.{existentials, implicitConversions, postfixOps} /** - * Simple wrapper around [[Ring]] used to unify PolynomialRing and Ring + * Simple wrapper around [[Ring]] used to unify IPolynomialRing and Ring * * @param theRing the [[Ring]] **/ @@ -41,6 +41,8 @@ sealed class Ring[E](val theRing: rings.Ring[E]) extends ToStringSupport[E] with final def apply(int: IntZ): E = theRing.valueOfBigInteger(int) + final def apply(e: ElementType): E = theRing.valueOf(e) + final def apply(a: String, b: String): (E, E) = (parse(a), parse(b)) final def apply(a: String, b: String, c: String): (E, E, E) @@ -106,17 +108,27 @@ final case class Frac[E](ring: Ring[E]) extends Ring[Rational[E]](rings.Rings.Fr rat.toString(ring) case element => ring.show(element) } + + def apply(a: E): Rational[E] = new Rational[E](rationalsDomain.ring, a) + + def apply(a: E, b: E): (Rational[E], Rational[E]) = (apply(a), apply(b)) + + def apply(a: E, b: E, c: E): (Rational[E], Rational[E], Rational[E]) = (apply(a), apply(b), apply(c)) + + def apply(a: E, b: E, c: E, d: E): (Rational[E], Rational[E], Rational[E], Rational[E]) = (apply(a), apply(b), apply(c), apply(d)) + + def apply(a: E, b: E, c: E, d: E, e: E): (Rational[E], Rational[E], Rational[E], Rational[E], Rational[E]) = (apply(a), apply(b), apply(c), apply(d), apply(e)) } /** * Base class for polynomial rings * - * @param theRing the [[PolynomialRing]] + * @param theRing the [[IPolynomialRing]] * @param variables polynomial variables * @tparam E coefficient type */ -abstract class PolynomialRing[Poly <: IPolynomial[Poly], E] -(override val theRing: poly.PolynomialRing[Poly], +abstract class IPolynomialRing[Poly <: IPolynomial[Poly], E] +(override val theRing: rings.poly.IPolynomialRing[Poly], val variables: Array[String]) extends Ring[Poly](theRing) { /** @@ -220,6 +232,14 @@ abstract class PolynomialRing[Poly <: IPolynomial[Poly], E] final def apply(value: E): Poly = getConstant(value) + final def apply(a: E, b: E): (Poly, Poly) = (apply(a), apply(b)) + + final def apply(a: E, b: E, c: E): (Poly, Poly, Poly) = (apply(a), apply(b), apply(c)) + + final def apply(a: E, b: E, c: E, d: E): (Poly, Poly, Poly, Poly) = (apply(a), apply(b), apply(c), apply(d)) + + final def apply(a: E, b: E, c: E, d: E, e: E): (Poly, Poly, Poly, Poly, Poly) = (apply(a), apply(b), apply(c), apply(d), apply(e)) + /** * Constant polynomial with specified value */ @@ -266,12 +286,12 @@ abstract class PolynomialRing[Poly <: IPolynomial[Poly], E] def lc(poly: Poly): E } -object PolynomialRing { - def apply[Poly <: IPolynomial[Poly], E](factory: Poly): PolynomialRing[Poly, E] = factory match { - case p: UnivariatePolynomialZp64 => UnivariateRingZp64(p.ring, WithVariables.defaultVars(1)(0)).asInstanceOf[PolynomialRing[Poly, E]] - case p: UnivariatePolynomial[E forSome {type E}] => UnivariateRing(p.ring, WithVariables.defaultVars(1)(0)).asInstanceOf[PolynomialRing[Poly, E]] - case p: MultivariatePolynomialZp64 => MultivariateRingZp64(p.ring, WithVariables.defaultVars(p.nVariables), p.ordering).asInstanceOf[PolynomialRing[Poly, E]] - case p: MultivariatePolynomial[E forSome {type E}] => MultivariateRing(p.ring, WithVariables.defaultVars(p.nVariables), p.ordering).asInstanceOf[PolynomialRing[Poly, E]] +object IPolynomialRing { + def apply[Poly <: IPolynomial[Poly], E](factory: Poly): IPolynomialRing[Poly, E] = factory match { + case p: UnivariatePolynomialZp64 => UnivariateRingZp64(p.ring, WithVariables.defaultVars(1)(0)).asInstanceOf[IPolynomialRing[Poly, E]] + case p: UnivariatePolynomial[E forSome {type E}] => UnivariateRing(p.ring, WithVariables.defaultVars(1)(0)).asInstanceOf[IPolynomialRing[Poly, E]] + case p: MultivariatePolynomialZp64 => MultivariateRingZp64(p.ring, WithVariables.defaultVars(p.nVariables), p.ordering).asInstanceOf[IPolynomialRing[Poly, E]] + case p: MultivariatePolynomial[E forSome {type E}] => MultivariateRing(p.ring, WithVariables.defaultVars(p.nVariables), p.ordering).asInstanceOf[IPolynomialRing[Poly, E]] case _ => ??? } } @@ -279,12 +299,12 @@ object PolynomialRing { /** * Ring of univariate polynomials * - * @param theRing the [[PolynomialRing]] + * @param theRing the [[IPolynomialRing]] * @param variable the variable */ sealed abstract class IUnivariateRing[Poly <: IUnivariatePolynomial[Poly], E] -(override val theRing: poly.PolynomialRing[Poly], - val variable: String) extends PolynomialRing[Poly, E](theRing, Array(variable)) { +(override val theRing: rings.poly.IPolynomialRing[Poly], + val variable: String) extends IPolynomialRing[Poly, E](theRing, Array(variable)) { /** * Evaluate poly at a given point */ @@ -294,6 +314,11 @@ sealed abstract class IUnivariateRing[Poly <: IUnivariatePolynomial[Poly], E] * i-th coefficient */ def at(poly: Poly, index: Int): E = cc(poly.getAsPoly(index)) + + /** + * Create univariate polynomial from the array of coefficients + */ + def create(coefficients: E*): Poly } /** @@ -365,6 +390,11 @@ final case class GaloisField64 * Leading coefficient */ override def lc(poly: UnivariatePolynomialZp64): Long = poly.lc() + + /** + * Create univariate polynomial from the array of coefficients + */ + override def create(coefficients: Long*) = theRing.valueOf(theRing.factory().createFromArray(coefficients.toArray)) } /** @@ -466,6 +496,11 @@ final case class GaloisField[E] * Leading coefficient */ override def lc(poly: UnivariatePolynomial[E]): E = poly.lc() + + /** + * Create univariate polynomial from the array of coefficients + */ + override def create(coefficients: E*) = theRing.valueOf(UnivariatePolynomial.apply[E, E](coefficients: _*)(cfRing)) } object GF { @@ -508,17 +543,17 @@ object GF { /** * Ring of Zp[x] polynomials * - * @param coefficientDomain coefficient ring - * @param variable variable + * @param coefficientRing coefficient ring + * @param variable variable */ -final case class UnivariateRingZp64 private(override val variable: String, coefficientDomain: IntegersZp64) - extends IUnivariateRing[UnivariatePolynomialZp64, Long](rings.Rings.UnivariateRingZp64(coefficientDomain), variable) { - val modulus: Long = coefficientDomain.modulus +final case class UnivariateRingZp64 private(override val variable: String, coefficientRing: IntegersZp64) + extends IUnivariateRing[UnivariatePolynomialZp64, Long](rings.Rings.UnivariateRingZp64(coefficientRing), variable) { + val modulus: Long = coefficientRing.modulus /** * The coefficient ring */ - override val cfRing: Ring[Long] = coefficientDomain + override val cfRing: Ring[Long] = coefficientRing /** * Constant polynomial with specified value @@ -574,6 +609,11 @@ final case class UnivariateRingZp64 private(override val variable: String, coeff * Leading coefficient */ override def lc(poly: UnivariatePolynomialZp64): Long = poly.lc() + + /** + * Create univariate polynomial from the array of coefficients + */ + override def create(coefficients: Long*) = UnivariatePolynomialZp64.apply(coefficients: _*)(coefficientRing) } object UnivariateRingZp64 { @@ -675,18 +715,23 @@ final case class UnivariateRing[E](coefficientDomain: Ring[E], override val vari * Leading coefficient */ override def lc(poly: UnivariatePolynomial[E]): E = poly.lc() + + /** + * Create univariate polynomial from the array of coefficients + */ + override def create(coefficients: E*) = UnivariatePolynomial.apply[E, E](coefficients: _*)(cfRing) } /** * Ring of multivariate polynomials * - * @param theRing the [[PolynomialRing]] + * @param theRing the [[IPolynomialRing]] * @param variables the variables */ sealed abstract class IMultivariateRing[Term <: DegreeVector[Term], Poly <: AMultivariatePolynomial[Term, Poly], E] -(override val theRing: poly.PolynomialRing[Poly], +(override val theRing: rings.poly.IPolynomialRing[Poly], variables: Array[String], - ordering: Ordering) extends PolynomialRing[Poly, E](theRing, variables) { + ordering: Ordering) extends IPolynomialRing[Poly, E](theRing, variables) { /** * The type of monomials */ diff --git a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Syntax.scala b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Syntax.scala index dd2d526..c336c88 100644 --- a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Syntax.scala +++ b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Syntax.scala @@ -7,7 +7,7 @@ trait RingSyntax { } trait PolynomialCfSyntax { - implicit def polynomialOps[Poly <: IPolynomial[Poly], E](lhs: Poly)(implicit pRing: PolynomialRing[Poly, E]): PolynomialCfOps[Poly, E] = new PolynomialCfOps[Poly, E](lhs)(pRing) + implicit def polynomialOps[Poly <: IPolynomial[Poly], E](lhs: Poly)(implicit pRing: IPolynomialRing[Poly, E]): PolynomialCfOps[Poly, E] = new PolynomialCfOps[Poly, E](lhs)(pRing) } trait UnivariateSyntax { @@ -56,7 +56,7 @@ trait MultivariateCfSyntax { } trait CfSyntax { - implicit def cfOps[E, Poly <: IPolynomial[Poly]](self: E)(implicit pRing: PolynomialRing[Poly, E]) + implicit def cfOps[E, Poly <: IPolynomial[Poly]](self: E)(implicit pRing: IPolynomialRing[Poly, E]) = new CfOps[E, Poly](self)(pRing) } diff --git a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/package.scala b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/package.scala index 1fa45e4..1fdd680 100644 --- a/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/package.scala +++ b/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/package.scala @@ -1,5 +1,7 @@ package cc.redberry.rings +import cc.redberry.rings.poly.PolynomialFactorDecomposition + /** * @since 1.0 @@ -29,7 +31,7 @@ package object scaladsl extends Predef { type MultivariatePolynomial[E] = poly.multivar.MultivariatePolynomial[E] type MultivariatePolynomialZp64 = poly.multivar.MultivariatePolynomialZp64 - type FactorDecomposition[P <: IPolynomial[P]] = poly.FactorDecomposition[P] + type PolynomialFactorDecomposition[P <: IPolynomial[P]] = poly.PolynomialFactorDecomposition[P] private[scaladsl] trait LowPrioritySyntax extends PolynomialSetSyntax @@ -41,7 +43,7 @@ package object scaladsl extends Predef { with IntegerSyntax object syntax extends LowPrioritySyntax { - implicit def cfOps[E, Poly <: IPolynomial[Poly]](self: E)(implicit pRing: PolynomialRing[Poly, E]) + implicit def cfOps[E, Poly <: IPolynomial[Poly]](self: E)(implicit pRing: IPolynomialRing[Poly, E]) = new CfOps[E, Poly](self)(pRing) implicit def ringOps[E](lhs: E)(implicit ringSupport: RingSupport[E]): RingOps[E] = new RingOps[E](lhs)(ringSupport.ringEv(lhs)) diff --git a/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/Examples.scala b/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/Examples.scala index 575a6a4..ce4bad0 100644 --- a/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/Examples.scala +++ b/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/Examples.scala @@ -2,9 +2,11 @@ package cc.redberry.rings.scaladsl import cc.redberry.rings import cc.redberry.rings.Rational +import cc.redberry.rings.linear.LinearSolver import cc.redberry.rings.poly.PolynomialMethods -import cc.redberry.rings.poly.multivar.{MonomialOrder, MultivariatePolynomial} -import cc.redberry.rings.poly.univar.UnivariatePolynomialArithmetic +import cc.redberry.rings.poly.multivar.MonomialOrder.LEX +import cc.redberry.rings.poly.multivar.{MonomialOrder, MultivariateInterpolation, MultivariatePolynomial} +import cc.redberry.rings.poly.univar.{IrreduciblePolynomials, UnivariatePolynomialArithmetic} import cc.redberry.rings.primes.SmallPrimes import org.apache.commons.math3.random.Well1024a import org.junit.{Ignore, Test} @@ -355,7 +357,7 @@ class Examples { * @tparam E type of polynomial coefficients */ def genericFuncWithRing[Poly <: IPolynomial[Poly], E](poly: Poly) - (implicit ring: PolynomialRing[Poly, E]): Poly = { + (implicit ring: IPolynomialRing[Poly, E]): Poly = { import syntax._ poly.pow(2) * 3 + poly * 2 + 1 } @@ -386,7 +388,7 @@ class Examples { * @tparam E type of polynomial coefficients */ def genericFuncWithRing[Poly <: IPolynomial[Poly], E](poly: Poly) - (implicit ring: PolynomialRing[Poly, E]): Poly = { + (implicit ring: IPolynomialRing[Poly, E]): Poly = { import syntax._ poly.pow(2) * 3 + poly * 2 + 1 } @@ -463,7 +465,7 @@ class Examples { func(poly) funcWithRing(poly) - MonomialOrder.LEX + LEX } @@ -477,8 +479,8 @@ class Examples { assert(poly.ordering == MonomialOrder.GREVLEX) // poly in LEX - val poly2 = poly.setOrdering(MonomialOrder.LEX) - assert(poly2.ordering == MonomialOrder.LEX) + val poly2 = poly.setOrdering(LEX) + assert(poly2.ordering == LEX) // poly in GREVLEX (ordering of lhs is used) val add = poly + poly2 @@ -486,13 +488,13 @@ class Examples { // poly in LEX (ordering of lhs is used) val add2 = poly2 + poly - assert(add2.ordering == MonomialOrder.LEX) + assert(add2.ordering == LEX) } @Test def test20: Unit = { import syntax._ - val ring = MultivariateRing(Z, Array("x", "y", "z"), MonomialOrder.LEX) + val ring = MultivariateRing(Z, Array("x", "y", "z"), LEX) val dividend = ring("x - x^2*y^2 + 2*x*y + 1 - z*y^2*x^2 + z").pow(3) @@ -807,7 +809,7 @@ class Examples { * @tparam Coef type of polynomial coefficients */ def genericFunc[Poly <: IPolynomial[Poly], Coef] - (poly: Poly)(implicit ring: PolynomialRing[Poly, Coef]): Poly = { + (poly: Poly)(implicit ring: IPolynomialRing[Poly, Coef]): Poly = { // implicit coefficient ring (setups algebraic operators on type Coef) implicit val cfRing: Ring[Coef] = ring.cfRing @@ -895,10 +897,183 @@ class Examples { } @Test - def test32 : Unit = { + def test32: Unit = { import syntax._ implicit val ring = MultivariateRing(Zp(2), Array("x", "y", "z")) val poly = ring("x^2*y - z^2*x^3 - y^2*z - 1").pow(20) - 1 println(PolynomialMethods.Factor(poly)) } + + @Test + def test33: Unit = { + import syntax._ + + implicit val ring = Frac(MultivariateRing(Zp(2), Array("x", "y", "z"))) + val (x, y, z) = ring("x", "y", "z") + val lhs = + Array( + Array(x + z, y * z, z - x * y), + Array(x - y, x / y, z + x / y), + Array(x * y, x + y, z / x + y) + ) + val rhs = Array(x, y, z) + + val solution = LinearSolver.solve[ring.ElementType](ring, lhs, rhs) + + println(solution.mkString("\n")) + } + + @Test + def test34: Unit = { + import syntax._ + + implicit val ring = UnivariateRing(Frac(MultivariateRing(Zp(47), Array("x", "y", "z"))), "t") + val (x, y, z, t) = ring("(x + y)", "(y)", "(z)", "t") + println(ring show IrreduciblePolynomials.randomIrreduciblePolynomial[ring.cfRing.ElementType](ring.cfRing, 4, new Random())) + val s = rings.ChineseRemainders.ChineseRemainders[ring.ElementType](ring, x + y + t.pow(2), y + t, x + t, z + t.pow(2)) + println(s) + } + + @Test + def test35: Unit = { + import syntax._ + + val cfRing = Zp(17) + implicit val ring = UnivariateRing(cfRing, "x") + + + val random = new Random + val nextPrime = (degree: Int) => { + import IrreduciblePolynomials._ + randomIrreduciblePolynomial[cfRing.ElementType](cfRing, degree, random) + } + + val primes = Array(nextPrime(5), nextPrime(6), nextPrime(7)) + val remainders = primes.map(_.degree()).map(i => ring.randomElement(random.nextInt(i), random)) + + import rings.ChineseRemainders._ + + val crt = ChineseRemainders[ring.ElementType](ring, primes, remainders) + //assert(crt.degree() == primes.map(_.degree()).sum - 1) + assert((primes zip remainders).forall { case (prime, rem) => crt % prime == rem }) + } + + @Test + def test36: Unit = { + import PolynomialMethods._ + import syntax._ + + // Galois field %$\color{commcolor}\GF(17, 3)$% + implicit val gf = GF(17, 3, "t") + // parse ring element from its string representation + val t = gf("t") + // or create element programmatically + val t1 = 1 + t.pow(2) + // do some basic math (+-*/) with elements of gf + val t2 = 3 + t1 - t.pow(22) / (1 + t + t1.pow(999)) + + // from string + val elem = gf("1 + t^2") + // from Int + val unit = gf(1L) + // from elements of other GF fields + val elementFromOtherField: UnivariatePolynomialZp64 = GF(19, 5).randomElement() + val cast = gf(elementFromOtherField) + // synthetic sugar for multiple assignment + // val el1 = gf("t + 1"); val el2 = gf("t + 2") + val (el1, el2) = gf("t + 1", "t + 2") + + // multivariate ring %$\color{commcolor}\GF(17, 3)[x, y, z]$% + implicit val ring = MultivariateRing(gf, Array("x", "y", "z"), LEX) + val (x, y, z) = ring("x", "y", "z") + // construct multivariate polynomials + val p1 = (t.pow(2) + 1) * x * y.pow(2)*z + (t + 1) * x.pow(5) *z * y.pow(6) + 1 + val p2 = p1.pow(2) + (t + 1) * x.pow(2) * y.pow(2) + (t.pow(9) + 1) * z.pow(7) + + // standard division with remainder + val (div, rem) = p2 /% p1 + // define a simple ideal (just a tuple of polynomials) + val (i1, i2, i3) = (x + y + z, x - y - z, y.pow(2) - z.pow(2)) + // do complete multivariate division with remainder (polynomial reduction) + val (div1, div2, div3, rem1) = p2 /%/% (i1, i2, i3) + assert ( p2 == div1 * i1 + div2 * i2 + div3 * i3 + rem1 ) + // or just reduce poly modulo ideal + val p3 = p2 %% (i1, i2, i3) + assert ( p3 == rem1 ) + + ring.isEuclideanRing // whether ring is Euclidean ring + ring.isField // whether ring is a field + ring.isFinite // whether ring is finite + ring.cardinality // ring cardinality (BigInteger) + ring.characteristic // ring characteristic (BigInteger) + + // GCD of polynomials from %$\color{commcolor}\GF(17, 3)[x, y, z]$% + val gcd1 = PolynomialGCD(p1 * p3, p2 * p3) + assert ( gcd1 % p3 === 0 ) + val gcd2 = PolynomialGCD(p1 * p3, p2 * p3 + 1) + assert ( gcd2.isConstant ) + + // a really huge polynomial from %$\color{commcolor}\GF(17, 3)[x, y, z]$% + // with more than %$\color{commcolor}4 \times 10^3$% terms and total degree of 145 + val hugePoly = p1 * p2.pow(2) * p3.pow(3) + // factorize it + val factors = Factor(hugePoly) + + // field of rational functions %$\color{commcolor}Frac(\GF(17, 3)[x, y, z])$% + implicit val ratRing = Frac(ring) + // convert x, y, z and t to elements of %$\color{commcolor}Frac(\GF(17, 3)[x, y, z])$% + // that is rationals with unit denominators + val (rx, ry, rz, rt) = ratRing(x, y, z, ring(t)) + // lhs matrix + val lhs = + Array( + Array(rt + rx + rz, ry * rz, rz - rx * ry), + Array(rx - ry - rt, rx / ry, rz + rx / ry), + Array(rx * ry / rt, rx + ry, rz / rx + ry) + ) + // rhs column + val rhs = Array(rx, ry, rz) + // solve the system with Gaussian elimination + val solution = LinearSolver.solve[ratRing.ElementType](ratRing, lhs, rhs) + + val rxxx = Rational(x, 1) // x is numerator and 1 is denominator + + + /** + * Solves equation %$\color{commcolor} \sum f_i s_i = gcd(f_1, \dots, f_N)$% for given %\color{commcolor}$f_i$% and unknown %\color{commcolor}$s_i$% + * @return a tuple (gcd, solution) + */ + def solveDiophantine[E](fi: Seq[E])(implicit ring: Ring[E]) = + fi.foldLeft((ring(0), Seq.empty[E])) { case ((gcd, seq), f) => + val xgcd = ring.extendedGCD(gcd, f) + (xgcd(0), seq.map(_ * xgcd(1)) :+ xgcd(2)) + } + + /** Computes partial fraction decomposition of given rational */ + def apart[E](frac: Rational[E]) = { + implicit val ring: Ring[E] = frac.ring + val factors = ring.factor(frac.denominator).map {case (f, exp) => f.pow(exp)} + val (gcd, nums) = solveDiophantine(factors.map(frac.denominator / _)) + val (ints, rats) = (nums zip factors) + .map { case (num, den) => Rational(frac.numerator * num, den * gcd) } + .flatMap(_.normal) // extract integral parts from fractions + .partition(_.isIntegral) // separate integrals and fractions + rats :+ ints.foldLeft(Rational(ring(0)))(_ + _) + } + + // partial fraction decomposition for rationals + // gives List(184/479, (-10)/13, 1/8, (-10)/47, 1) + val qFracs = apart( Q("1234213 / 2341352")) + + // partial fraction decomposition for rational functions + val ufRing = Frac(UnivariateRingZp64(17, "x")) + // gives List(4/(16+x), 1/(10+x), 15/(1+x), (14*x)/(15+7*x+x^2)) + val pFracs = apart( ufRing("1 / (3 - 3*x^2 - x^3 + x^5)") ) + + // partial fraction decomposition of rational functions + // in the ring %$\color{commcolor} Frac(\GF(17, 3)[x, y, z])[W]$% + implicit val uRing = UnivariateRing(ratRing, "W") + val W = uRing("W") + val fracs = apart( Rational(W + 1, (rx/ry + W.pow(2)) * (rz/rx + W.pow(3))) ) + } } \ No newline at end of file diff --git a/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/SyntaxTest.scala b/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/SyntaxTest.scala index 53396e8..7a22c60 100644 --- a/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/SyntaxTest.scala +++ b/rings.scaladsl/src/test/scala/cc/redberry/rings/scaladsl/SyntaxTest.scala @@ -142,7 +142,7 @@ class SyntaxTest { @Test def testPolynomialRingOps2: Unit = { - def genericAssertions[Poly <: IPolynomial[Poly], E](implicit ring: PolynomialRing[Poly, E]) = { + def genericAssertions[Poly <: IPolynomial[Poly], E](implicit ring: IPolynomialRing[Poly, E]) = { import syntax._ val x = ring("x") @@ -263,7 +263,7 @@ class SyntaxTest { @Test def testPolynomialRingOps4: Unit = { - def genericAssertions[E <: IPolynomial[E]](implicit ring: PolynomialRing[UnivariatePolynomial[E], E]) = { + def genericAssertions[E <: IPolynomial[E]](implicit ring: IPolynomialRing[UnivariatePolynomial[E], E]) = { import syntax._ val x: UnivariatePolynomial[E] = ring("x") @@ -368,7 +368,7 @@ class SyntaxTest { @Test def testGenericFunction: Unit = { - def interpolate[Poly <: IPolynomial[Poly], E](points: Seq[E], values: Seq[E])(implicit ring: PolynomialRing[Poly, E]) = { + def interpolate[Poly <: IPolynomial[Poly], E](points: Seq[E], values: Seq[E])(implicit ring: IPolynomialRing[Poly, E]) = { import syntax._ points.indices .foldLeft(ring getZero) { case (sum, i) => @@ -410,7 +410,7 @@ class SyntaxTest { assertEquals( interpolate(points.toSeq, values.toSeq), - UnivariateInterpolation.interpolateNewton(ring.coefficientDomain, points, values) + UnivariateInterpolation.interpolateNewton(ring.coefficientRing, points, values) ) } } @@ -523,7 +523,6 @@ class SyntaxTest { assertEquals(12, evaled.degree("z")) - val mod1 = p mod ideal assertEquals(0, mod1.degree("x")) assertEquals(14, mod1.degree("y")) @@ -611,11 +610,11 @@ class SyntaxTest { // calculate GCD val gcd = PolynomialGCD(poly1 * poly3, poly2 * poly4) - println(s"gcd : ${ring show gcd}") + println(s"gcd : ${ring show gcd }") // factor some complicated poly val factors = Factor(poly1 * poly2 ** 2 * poly3 ** 3 * poly4 ** 4) - println(s"factors : ${ring show factors}") + println(s"factors : ${ring show factors }") } @Test @@ -634,10 +633,10 @@ class SyntaxTest { implicit val ring = gf2 println(s"ring: $ring") - println(s"ring cardinality: ${ring.cardinality()}") - println(s"ring characteristic: ${ring.characteristic()}") - println(s"ring pp base: ${ring.perfectPowerBase()}") - println(s"ring pp exponent: ${ring.perfectPowerExponent()}") + println(s"ring cardinality: ${ring.cardinality() }") + println(s"ring characteristic: ${ring.characteristic() }") + println(s"ring pp base: ${ring.perfectPowerBase() }") + println(s"ring pp exponent: ${ring.perfectPowerExponent() }") val rndPoly = ring.randomElement(new Well1024a()) println(ring show rndPoly) @@ -720,4 +719,13 @@ class SyntaxTest { println(poly /%/% (p1, p2, p2)) println(poly /%/% (p1, p2, p2, p1)) } + + @Ignore //issue #23 + @Test + def testParse1: Unit = { + + implicit val gf = GF(17, 3, "t") + implicit val ring = MultivariateRing(gf, Array("x", "y", "z")) + val t = ring("t") + } } diff --git a/rings/src/main/java/cc/redberry/rings/AIntegers.java b/rings/src/main/java/cc/redberry/rings/AIntegers.java index 823abb4..0086b13 100644 --- a/rings/src/main/java/cc/redberry/rings/AIntegers.java +++ b/rings/src/main/java/cc/redberry/rings/AIntegers.java @@ -30,12 +30,7 @@ public final boolean isOne(BigInteger element) { @Override public final BigInteger parse(String string) { - return valueOf(new BigInteger(string)); - } - - @Override - public final BigInteger gcd(BigInteger a, BigInteger b) { - return a.gcd(b); + return valueOf(new BigInteger(string.trim())); } @Override diff --git a/rings/src/main/java/cc/redberry/rings/bigint/ChineseRemainders.java b/rings/src/main/java/cc/redberry/rings/ChineseRemainders.java similarity index 86% rename from rings/src/main/java/cc/redberry/rings/bigint/ChineseRemainders.java rename to rings/src/main/java/cc/redberry/rings/ChineseRemainders.java index 5bcc311..7397f83 100644 --- a/rings/src/main/java/cc/redberry/rings/bigint/ChineseRemainders.java +++ b/rings/src/main/java/cc/redberry/rings/ChineseRemainders.java @@ -1,7 +1,8 @@ -package cc.redberry.rings.bigint; +package cc.redberry.rings; import cc.redberry.libdivide4j.FastDivision; import cc.redberry.rings.Ring; +import cc.redberry.rings.bigint.BigInteger; import static java.lang.Math.*; @@ -9,6 +10,7 @@ * @since 1.0 */ public final class ChineseRemainders { + private ChineseRemainders() {} /** * Runs Chinese Remainders algorithm @@ -70,7 +72,8 @@ public static BigInteger ChineseRemainders(BigInteger prime1, BigInteger prime2, * @param remainder2 #2 remainder * @return the result */ - public static E ChineseRemainders(Ring ring, E prime1, E prime2, + public static E ChineseRemainders(Ring ring, + E prime1, E prime2, E remainder1, E remainder2) { E modulus = ring.multiply(prime1, prime2); @@ -197,18 +200,46 @@ public static long ChineseRemainders(final long[] primes, public static BigInteger ChineseRemainders(final BigInteger[] primes, final BigInteger[] remainders) { if (primes.length != remainders.length) throw new IllegalArgumentException(); - BigInteger m = primes[0]; + BigInteger modulus = primes[0]; for (int i = 1; i < primes.length; i++) { if (primes[i].signum() <= 0) throw new RuntimeException("Negative CRT input: " + primes[i]); - m = primes[i].multiply(m); + modulus = primes[i].multiply(modulus); } BigInteger result = BigInteger.ZERO; for (int i = 0; i < primes.length; i++) { - BigInteger mi = m.divide(primes[i]); - BigInteger eea = bezout0(mi, primes[i]); - result = result.add(mi.multiply(eea.multiply(remainders[i]).mod(primes[i]))).mod(m); + BigInteger iModulus = modulus.divide(primes[i]); + BigInteger bezout = bezout0(iModulus, primes[i]); + result = result.add(iModulus.multiply(bezout.multiply(remainders[i]).mod(primes[i]))).mod(modulus); + } + return result; + } + + /** + * Runs Chinese Remainders algorithm + * + * @param ring the ring + * @param primes primes + * @param remainders remainders + * @return the result + */ + public static E ChineseRemainders(Ring ring, + E[] primes, + E[] remainders) { + + if (primes.length != remainders.length) + throw new IllegalArgumentException(); + E modulus = primes[0]; + for (int i = 1; i < primes.length; i++) + modulus = ring.multiply(primes[i], modulus); + + E result = ring.getZero(); + for (int i = 0; i < primes.length; i++) { + E iModulus = ring.divideExact(modulus, primes[i]); + E bezout = bezout0(ring, iModulus, primes[i]); + result = ring.remainder(ring.add(result, + ring.remainder(ring.multiply(iModulus, ring.remainder(ring.multiply(bezout, remainders[i]), primes[i])), modulus)), modulus); } return result; } diff --git a/rings/src/main/java/cc/redberry/rings/FactorDecomposition.java b/rings/src/main/java/cc/redberry/rings/FactorDecomposition.java new file mode 100644 index 0000000..a7109f1 --- /dev/null +++ b/rings/src/main/java/cc/redberry/rings/FactorDecomposition.java @@ -0,0 +1,339 @@ +package cc.redberry.rings; + +import cc.redberry.rings.poly.MachineArithmetic; +import cc.redberry.rings.util.ArraysUtil; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TObjectIntHashMap; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Factor decomposition of element. Unit coefficient of decomposition is stored in {@link #unit}, factors returned by + * {@link #get(int)} are non-units. This class is mutable. + * + *

Iterable specification provides iterator over non-unit factors only; to iterate over all factors including + * the constant factor use {@link #iterableWithUnit()} + * + * @author Stanislav Poslavsky + * @since 2.2 + */ +public class FactorDecomposition implements Iterable { + /** The ring */ + public final Ring ring; + /** unit coefficient */ + public E unit; + /** factors */ + public final List factors; + /** exponents */ + public final TIntArrayList exponents; + + protected FactorDecomposition(Ring ring, E unit, List factors, TIntArrayList exponents) { + this.ring = ring; + this.unit = unit; + this.factors = factors; + this.exponents = exponents; + if (!isUnit(unit)) + throw new IllegalArgumentException(); + } + + @Override + public Iterator iterator() { + return factors.iterator(); + } + + /** + * Iterator over all factors including a unit one + * + * @return iterator over all factors including a unit one + */ + public Iterable iterableWithUnit() { + ArrayList it = new ArrayList<>(); + if (!ring.isOne(unit)) + it.add(unit); + it.addAll(factors); + return it; + } + + public boolean isUnit(E element) { return ring.isUnit(element);} + + /** Returns i-th factor */ + public E get(int i) { return factors.get(i); } + + /** Exponent of i-th factor */ + public int getExponent(int i) { return exponents.get(i); } + + /** Number of non-constant factors */ + public int size() { return factors.size(); } + + /** Whether this is a trivial factorization (contains only one factor) */ + public boolean isTrivial() { return size() == 1;} + + /** Sum all exponents */ + public int sumExponents() { + return exponents.sum(); + } + + /** Multiply each exponent by a given factor */ + public void raiseExponents(long val) { + for (int i = exponents.size() - 1; i >= 0; --i) + exponents.set(i, MachineArithmetic.safeToInt(exponents.get(i) * val)); + } + + /** Sets the unit factor */ + public FactorDecomposition setUnit(E unit) { + if (!isUnit(unit)) + throw new IllegalArgumentException("not a unit: " + unit); + this.unit = unit; + return this; + } + + /** add another unit factor */ + public FactorDecomposition addUnit(E unit) { + if (!isUnit(unit)) + throw new IllegalArgumentException("not a unit: " + unit); + this.unit = ring.multiply(this.unit, unit); + return this; + } + + /** add another unit factor */ + public FactorDecomposition addUnit(E unit, int exponent) { + if (!isUnit(unit)) + throw new IllegalArgumentException("not a unit: " + unit); + this.unit = ring.multiply(this.unit, ring.pow(unit, exponent)); + return this; + } + + /** add another factor */ + public FactorDecomposition addFactor(E factor, int exponent) { + if (isUnit(factor)) + return addUnit(factor, exponent); + factors.add(factor); + exponents.add(exponent); + return this; + } + + /** add all factors from other */ + public FactorDecomposition addAll(FactorDecomposition other) { + addUnit(other.unit); + factors.addAll(other.factors); + exponents.addAll(other.exponents); + return this; + } + + /** + * Raise all factors to its corresponding exponents + */ + public FactorDecomposition applyExponents(Ring ring) { + List newFactors = new ArrayList<>(); + for (int i = 0; i < size(); i++) + newFactors.add(ring.pow(factors.get(i), exponents.get(i))); + return new FactorDecomposition<>(ring, unit, newFactors, new TIntArrayList(ArraysUtil.arrayOf(1, size()))); + } + + /** + * Drops constant factor from this (new instance returned) + */ + public FactorDecomposition dropUnit() { + this.unit = ring.getOne(); + return this; + } + + /** Stream of all factors */ + public Stream stream() { + return Stream.concat(Stream.of(unit), factors.stream()); + } + + /** Stream of all factors except {@link #unit} */ + public Stream streamWithoutUnit() { + return factors.stream(); + } + + /** Array of factors without constant factor */ + public E[] toArrayWithoutUnit() { + return factors.toArray(ring.createArray(size())); + } + + /** Array of factors without constant factor */ + public E[] toArrayWithUnit() { + E[] array = factors.toArray(ring.createArray(1 + size())); + System.arraycopy(array, 0, array, 1, size()); + array[0] = unit; + return array; + } + + /** Multiply factors */ + public E multiply() { + return multiply0(false); + } + + /** Multiply with no account for exponents */ + public E multiplyIgnoreExponents() { + return multiply0(true); + } + + /** Square-free part */ + public E squareFreePart() { + return multiplyIgnoreExponents(); + } + + private E multiply0(boolean ignoreExponents) { + E r = ring.copy(unit); + for (int i = 0; i < factors.size(); i++) { + E tmp = ignoreExponents ? factors.get(i) : ring.pow(factors.get(i), exponents.get(i)); + r = ring.multiplyMutable(r, tmp); + } + return r; + } + + /** + * Sort factors. + */ + public FactorDecomposition canonical() { + @SuppressWarnings("unchecked") + wrapper[] wr = factors.stream().map(e -> new wrapper<>(ring, e)).toArray(wrapper[]::new); + int[] ex = exponents.toArray(); + ArraysUtil.quickSort(wr, ex); + factors.clear(); + exponents.clear(); + factors.addAll(Arrays.stream(wr).map(w -> w.el).collect(Collectors.toList())); + exponents.addAll(ex); + return this; + } + + private static final class wrapper implements Comparable> { + final Ring ring; + final E el; + + wrapper(Ring ring, E el) { this.ring = ring; this.el = el; } + + @Override + public int compareTo(wrapper o) { return ring.compare(el, o.el); } + } + + @Override + public String toString() { + return toString(ToStringSupport.plain()); + } + + /** + * @param stringifier custom stringifier + */ + public String toString(ToStringSupport stringifier) { + return toString(stringifier, true); + } + + /** + * @param stringifier custom stringifier + * @param withExponents do stringify exponents + */ + public String toString(ToStringSupport stringifier, boolean withExponents) { + if (factors.isEmpty()) + return stringifier.toString(unit); + + StringBuilder sb = new StringBuilder(); + if (!ring.isOne(unit)) { + sb.append(stringifier.toString(unit)); + if (factors.size() > 0) + sb.append("*"); + } + for (int i = 0; ; i++) { + sb.append("(").append(stringifier.toString(factors.get(i))).append(")"); + if (withExponents && exponents.get(i) != 1) + sb.append("^").append(exponents.get(i)); + if (i == factors.size() - 1) + return sb.toString(); + sb.append("*"); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FactorDecomposition factors1 = (FactorDecomposition) o; + + if (!unit.equals(factors1.unit)) return false; + if (!factors.equals(factors1.factors)) return false; + return exponents.equals(factors1.exponents); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + unit.hashCode(); + result = 31 * result + factors.hashCode(); + result = 31 * result + exponents.hashCode(); + return result; + } + + @Override + public FactorDecomposition clone() { + return new FactorDecomposition<>( + ring, + ring.copy(unit), + factors.stream().map(ring::copy).collect(Collectors.toList()), + new TIntArrayList(exponents)); + } + + /** Unit factorization */ + public static FactorDecomposition unit(Ring ring, E unit) { + if (!ring.isUnitOrZero(unit)) + throw new IllegalArgumentException("not a unit"); + return new FactorDecomposition<>(ring, unit, new ArrayList<>(), new TIntArrayList()); + } + + /** Empty factorization */ + public static FactorDecomposition empty(Ring ring) { + return unit(ring, ring.getOne()); + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param ring the ring + * @param unit the unit coefficient + * @param factors the factors + * @param exponents the exponents + */ + public static FactorDecomposition of(Ring ring, E unit, List factors, TIntArrayList exponents) { + if (factors.size() != exponents.size()) + throw new IllegalArgumentException(); + FactorDecomposition r = empty(ring).addUnit(unit); + for (int i = 0; i < factors.size(); i++) + r.addFactor(factors.get(i), exponents.get(i)); + return r; + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param ring the ring + * @param factors factors + */ + public static FactorDecomposition of(Ring ring, E... factors) { + return of(ring, Arrays.asList(factors)); + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param ring the ring + * @param factors factors + */ + public static FactorDecomposition of(Ring ring, Collection factors) { + TObjectIntHashMap map = new TObjectIntHashMap<>(); + for (E e : factors) + map.adjustOrPutValue(e, 1, 1); + List l = new ArrayList<>(); + TIntArrayList e = new TIntArrayList(); + map.forEachEntry((a, b) -> { + l.add(a); + e.add(b); + return true; + }); + return of(ring, ring.getOne(), l, e); + } +} diff --git a/rings/src/main/java/cc/redberry/rings/Integers.java b/rings/src/main/java/cc/redberry/rings/Integers.java index 9ae7c11..27cd00d 100644 --- a/rings/src/main/java/cc/redberry/rings/Integers.java +++ b/rings/src/main/java/cc/redberry/rings/Integers.java @@ -1,6 +1,7 @@ package cc.redberry.rings; import cc.redberry.rings.bigint.BigInteger; +import cc.redberry.rings.primes.BigPrimes; import java.util.Iterator; @@ -57,6 +58,21 @@ public BigInteger reciprocal(BigInteger element) { throw new UnsupportedOperationException(); } + @Override + public final BigInteger gcd(BigInteger a, BigInteger b) { + return a.gcd(b); + } + + @Override + public FactorDecomposition factorSquareFree(BigInteger element) { + return factor(element); + } + + @Override + public FactorDecomposition factor(BigInteger element) { + return FactorDecomposition.of(this, BigPrimes.primeFactors(element)); + } + @Override public BigInteger valueOf(BigInteger val) {return val;} diff --git a/rings/src/main/java/cc/redberry/rings/IntegersZp.java b/rings/src/main/java/cc/redberry/rings/IntegersZp.java index b8ae0f3..7a60a83 100644 --- a/rings/src/main/java/cc/redberry/rings/IntegersZp.java +++ b/rings/src/main/java/cc/redberry/rings/IntegersZp.java @@ -119,6 +119,16 @@ public BigInteger reciprocal(BigInteger element) { return element.modInverse(modulus); } + @Override + public FactorDecomposition factorSquareFree(BigInteger element) { + return factor(element); + } + + @Override + public FactorDecomposition factor(BigInteger element) { + return FactorDecomposition.of(this, element); + } + @Override public BigInteger valueOf(BigInteger val) {return modulus(val);} diff --git a/rings/src/main/java/cc/redberry/rings/Rational.java b/rings/src/main/java/cc/redberry/rings/Rational.java index 191be5c..20862ed 100644 --- a/rings/src/main/java/cc/redberry/rings/Rational.java +++ b/rings/src/main/java/cc/redberry/rings/Rational.java @@ -70,6 +70,26 @@ public Rational(Ring ring, E numerator) { this.denominator = ring.getOne(); } + /** + * Reduces this rational to normal form by doing division with remainder, that is if {@code numerator = div * + * denominator + rem} then the array {@code (div, rem/denominator)} will be returned. If either div or rem is zero + * an singleton array with this instance will be returned. + */ + @SuppressWarnings("unchecked") + public Rational[] normal() { + if (isIntegral()) + return new Rational[]{this}; + + E[] qd = ring.divideAndRemainder(numerator, denominator); + if (qd[0] == null) + throw new RuntimeException("division with remainder is not supported."); + + if (ring.isZero(qd[0]) || ring.isZero(qd[1])) + return new Rational[]{this}; + + return new Rational[]{new Rational(ring, qd[0]), new Rational(ring, qd[1], denominator)}; + } + /** * Constructs zero */ diff --git a/rings/src/main/java/cc/redberry/rings/Rationals.java b/rings/src/main/java/cc/redberry/rings/Rationals.java index a0361d2..bb68764 100644 --- a/rings/src/main/java/cc/redberry/rings/Rationals.java +++ b/rings/src/main/java/cc/redberry/rings/Rationals.java @@ -142,7 +142,7 @@ public Rational copy(Rational element) { public Rational valueOf(Rational val) { if (val.ring.equals(ring)) return val; - else return new Rational(ring, ring.valueOf(val.numerator), ring.valueOf(val.denominator)); + else return new Rational<>(ring, ring.valueOf(val.numerator), ring.valueOf(val.denominator)); } @Override @@ -181,6 +181,12 @@ public Rational randomElement(RandomGenerator rnd) { return new Rational<>(ring, ring.valueOf(rnd.nextInt()), eden); } + public Rational randomNonTrivialElement(RandomGenerator rnd) { + E den; + do {den = ring.randomElement(rnd);} while (ring.isZero(den)); + return new Rational<>(ring, ring.randomElement(rnd), den); + } + public Rational parse(ElementParser parser, String string) { int level = 0; int indexOfDiv = -1; @@ -198,8 +204,8 @@ else if (c == ')') if (indexOfDiv == -1) return new Rational<>(ring, parser.parse(removeParenthesis(string))); return new Rational<>(ring, - parser.parse(removeParenthesis(string.substring(0, indexOfDiv))), - parser.parse(removeParenthesis(string.substring(indexOfDiv + 1)))); + parser.parse(removeParenthesis(string.substring(0, indexOfDiv)).trim()), + parser.parse(removeParenthesis(string.substring(indexOfDiv + 1)).trim())); } @Override @@ -208,6 +214,7 @@ public Rational parse(String string) { } private static String removeParenthesis(String string) { + string = string.trim(); if (!string.startsWith("(") || !string.endsWith(")")) return string; diff --git a/rings/src/main/java/cc/redberry/rings/Ring.java b/rings/src/main/java/cc/redberry/rings/Ring.java index ed80524..5aab708 100644 --- a/rings/src/main/java/cc/redberry/rings/Ring.java +++ b/rings/src/main/java/cc/redberry/rings/Ring.java @@ -2,7 +2,6 @@ import cc.redberry.rings.bigint.BigInteger; import org.apache.commons.math3.random.RandomGenerator; -import org.apache.commons.math3.random.Well44497b; import java.lang.reflect.Array; import java.util.Arrays; @@ -307,7 +306,80 @@ default E divideExact(E dividend, E divider) { * @param b the second element * @return gcd */ - E gcd(E a, E b); + default E gcd(E a, E b) { + if (isField()) + return a; + if (!isEuclideanRing()) + throw new UnsupportedOperationException("GCD is not supported in this ring"); + if (isZero(a)) return b; + if (isZero(b)) return a; + + // run Euclidean algorithm by default + E x = a, y = b, r; + while (true) { + r = remainder(x, y); + if (r == null) + throw new ArithmeticException("Not divisible with remainder: (" + x + ") / (" + y + ")"); + + if (isZero(r)) + break; + x = y; + y = r; + } + return y; + } + + /** + * Returns array of {@code [gcd(a,b), s, t]} such that {@code s * a + t * b = gcd(a, b)} + * + * @throws UnsupportedOperationException if this is not the Euclidean ring and there is no special implementation + * provided by particular subtype + */ + default E[] extendedGCD(E a, E b) { + if (!isEuclideanRing()) + throw new UnsupportedOperationException("Extended GCD is not supported in this ring"); + + if (isZero(a)) return createArray(b, getOne(), getOne()); + if (isZero(b)) return createArray(a, getOne(), getOne()); + + if (isField()) { + E[] r = createArray(3); + r[0] = getOne(); + r[1] = divideExact(reciprocal(a), valueOf(2)); + r[2] = divideExact(reciprocal(b), valueOf(2)); + return r; + } + + E s = getZero(), old_s = getOne(); + E t = getOne(), old_t = getZero(); + E r = b, old_r = a; + + E q; + E tmp; + while (!isZero(r)) { + q = quotient(old_r, r); + if (q == null) + throw new ArithmeticException("Not divisible with remainder: (" + old_r + ") / (" + r + ")"); + + tmp = old_r; + old_r = r; + r = subtract(tmp, multiply(q, r)); + + tmp = old_s; + old_s = s; + s = subtract(tmp, multiply(q, s)); + + tmp = old_t; + old_t = t; + t = subtract(tmp, multiply(q, t)); + } + + E[] result = createArray(3); + result[0] = old_r; + result[1] = old_s; + result[2] = old_t; + return result; + } /** * Returns the least common multiple of two elements @@ -350,6 +422,20 @@ default E gcd(Iterable elements) { return gcd; } + /** + * Square-free factorization of specified element + */ + default FactorDecomposition factorSquareFree(E element) { + throw new UnsupportedOperationException(); + } + + /** + * Factor specified element + */ + default FactorDecomposition factor(E element) { + throw new UnsupportedOperationException(); + } + /** * Returns zero element of this ring * @@ -399,6 +485,16 @@ default E getNegativeOne() { */ boolean isUnit(E element); + /** + * Tests whether specified element is a ring unit or zero + * + * @param element the ring element + * @return whether specified element is a ring unit or zero + */ + default boolean isUnitOrZero(E element) { + return isUnit(element) || isZero(element); + } + /** * Tests whether specified element is minus one * @@ -531,6 +627,18 @@ default E[] createArray(E a, E b) { return array; } + /** + * Creates generic array of {@code {a, b, c}} + */ + @SuppressWarnings("unchecked") + default E[] createArray(E a, E b, E c) { + E[] array = createArray(3); + array[0] = a; + array[1] = b; + array[2] = c; + return array; + } + /** * Creates generic array with single element * diff --git a/rings/src/main/java/cc/redberry/rings/Rings.java b/rings/src/main/java/cc/redberry/rings/Rings.java index 8a11a0f..6065b76 100644 --- a/rings/src/main/java/cc/redberry/rings/Rings.java +++ b/rings/src/main/java/cc/redberry/rings/Rings.java @@ -113,7 +113,7 @@ public static UnivariateRing> UnivariateRing(Ring * * @param factory factory */ - public static > PolynomialRing UnivariateRing(Poly factory) { + public static > IPolynomialRing UnivariateRing(Poly factory) { return new UnivariateRing<>(factory); } @@ -289,10 +289,10 @@ MultivariateRing MultivariateRing(Poly factory) { * Generic factory for polynomial ring */ @SuppressWarnings("unchecked") - public static > PolynomialRing PolynomialRing(Poly factory) { + public static > IPolynomialRing PolynomialRing(Poly factory) { if (factory instanceof IUnivariatePolynomial) - return (PolynomialRing) UnivariateRing((IUnivariatePolynomial) factory); + return (IPolynomialRing) UnivariateRing((IUnivariatePolynomial) factory); else - return (PolynomialRing) MultivariateRing((AMultivariatePolynomial) factory); + return (IPolynomialRing) MultivariateRing((AMultivariatePolynomial) factory); } } diff --git a/rings/src/main/java/cc/redberry/rings/poly/APolynomialRing.java b/rings/src/main/java/cc/redberry/rings/poly/APolynomialRing.java index e38dc05..df2eb3c 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/APolynomialRing.java +++ b/rings/src/main/java/cc/redberry/rings/poly/APolynomialRing.java @@ -10,7 +10,7 @@ /** * @since 1.0 */ -abstract class APolynomialRing> extends ARing implements PolynomialRing { +abstract class APolynomialRing> extends ARing implements IPolynomialRing { private static final long serialVersionUID = 1L; /** the factory polynomial */ diff --git a/rings/src/main/java/cc/redberry/rings/poly/FactorDecomposition.java b/rings/src/main/java/cc/redberry/rings/poly/FactorDecomposition.java deleted file mode 100644 index dffe25d..0000000 --- a/rings/src/main/java/cc/redberry/rings/poly/FactorDecomposition.java +++ /dev/null @@ -1,435 +0,0 @@ -package cc.redberry.rings.poly; - -import cc.redberry.rings.ToStringSupport; -import cc.redberry.rings.WithVariables; -import cc.redberry.rings.util.ArraysUtil; -import gnu.trove.list.array.TIntArrayList; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static cc.redberry.rings.poly.PolynomialMethods.polyPow; - -/** - * Factor decomposition of polynomial. Constant factor of decomposition is stored in {@link #constantFactor}, factors - * returned by {@link #get(int)} are non-constant. This class is mutable. - * - *

Iterable specification provides iterator over non-constant factors only; to iterate over all factors - * including the constant factor use {@link #iterableWithConstant()} - * - * @since 1.0 - */ -public final class FactorDecomposition> - implements Iterable, WithVariables, java.io.Serializable { - private static final long serialVersionUID = 1L; - /** Holds a numerical factor */ - public final Poly constantFactor; - /** Factors */ - public final List factors; - /** Either exponents or distinct-degree powers */ - public final TIntArrayList exponents; - - private FactorDecomposition(Poly constantFactor) { - this(constantFactor, new ArrayList<>(), new TIntArrayList()); - } - - private FactorDecomposition(Poly constantFactor, List factors, TIntArrayList exponents) { - if (!constantFactor.isConstant()) - throw new IllegalArgumentException("Factor " + constantFactor + " is not a constant."); - assert factors.size() == exponents.size(); - this.constantFactor = constantFactor; - this.factors = factors; - this.exponents = exponents; - } - - /** - * Iterator over all non-constant factors - * - * @return iterator over all non-constant factors - */ - @Override - public Iterator iterator() { - return factors.iterator(); - } - - /** - * Iterator over all factors including constant one - * - * @return iterator over all factors including constant one - */ - public Iterable iterableWithConstant() { - ArrayList it = new ArrayList<>(); - if (!constantFactor.isOne()) - it.add(constantFactor); - it.addAll(factors); - return it; - } - - /** Returns i-th factor */ - public Poly get(int i) { return factors.get(i); } - - /** Exponent of i-th factor */ - public int getExponent(int i) { return exponents.get(i); } - - /** Number of non-constant factors */ - public int size() { return factors.size(); } - - /** Sets the constant factor */ - public FactorDecomposition setConstantFactor(Poly constantFactor) { - this.constantFactor.set(constantFactor); - return this; - } - - /** Whether this is a trivial factorization (contains only one factor) */ - public boolean isTrivial() { return size() == 1;} - - /** Sum all exponents */ - public int sumExponents() { - return exponents.sum(); - } - - /** Multiply each exponent by a given factor */ - public void raiseExponents(long val) { - for (int i = exponents.size() - 1; i >= 0; --i) - exponents.set(i, MachineArithmetic.safeToInt(exponents.get(i) * val)); - } - - /** add another factor */ - public FactorDecomposition addConstantFactor(Poly poly) { - if (!poly.isConstant()) - throw new RuntimeException("not a constant"); - constantFactor.multiply(poly); - return this; - } - - /** add another factor */ - public FactorDecomposition addConstantFactor(Poly poly, int exponent) { - if (!poly.isConstant()) - throw new RuntimeException("not a constant"); - constantFactor.multiply(PolynomialMethods.polyPow(poly, exponent, true)); - return this; - } - - /** add another factor */ - public FactorDecomposition addFactor(Poly factor, int exponent) { - if (factor.isConstant()) { - if (exponent != 1) - throw new IllegalArgumentException("exponent != 1"); - return addConstantFactor(factor); - } - - factors.add(factor); - exponents.add(exponent); - return this; - } - - /** add all factors from other */ - public FactorDecomposition addAll(FactorDecomposition other) { - factors.addAll(other.factors); - exponents.addAll(other.exponents); - constantFactor.multiply(other.constantFactor); - return this; - } - - /** - * Puts this factor decomposition into the canonical form (shifts constant content to constant factor and sorts - * factors in natural order) - */ - @SuppressWarnings("unchecked") - public FactorDecomposition canonicalForm() { - if (factors.size() == 0) - return this; - reduceConstantContent(); - Poly[] fTmp = factors.toArray(factors.get(0).createArray(factors.size())); - int[] eTmp = exponents.toArray(); - for (int i = fTmp.length - 1; i >= 0; --i) { - Poly poly = fTmp[i]; - if (poly.isMonomial() && eTmp[i] != 1) { - poly = PolynomialMethods.polyPow(poly, eTmp[i], false); - assert poly.isMonomial(); - } - if (poly.signumOfLC() < 0) { - poly.negate(); - if (eTmp[i] % 2 == 1) - constantFactor.negate(); - } - } - - ArraysUtil.quickSort(fTmp, eTmp); - for (int i = 0; i < fTmp.length; i++) { - factors.set(i, fTmp[i]); - exponents.set(i, eTmp[i]); - } - return this; - } - - /** - * Calculates the signum of the polynomial constituted by this decomposition - * - * @return the signum of the polynomial constituted by this decomposition - */ - public int signum() { - int signum = constantFactor.signumOfLC(); - for (int i = 0; i < factors.size(); i++) - signum *= exponents.get(i) % 2 == 0 ? 1 : factors.get(i).signumOfLC(); - return signum; - } - - /** - * Drops constant factor from this (new instance returned) - */ - public FactorDecomposition withoutConstantFactor() { - return new FactorDecomposition<>(constantFactor.createOne(), factors, exponents); - } - - /** - * Makes each factor monic (moving leading coefficients to the {@link #constantFactor}) - */ - public FactorDecomposition monic() { - for (int i = 0; i < factors.size(); i++) { - Poly factor = factors.get(i); - addConstantFactor(polyPow(factor.lcAsPoly(), exponents.get(i), false)); - factor = factor.monic(); - assert factor != null; - } - return this; - } - - /** - * Makes each factor primitive (moving contents to the {@link #constantFactor}) - */ - public FactorDecomposition primitive() { - for (int i = 0; i < factors.size(); i++) { - Poly factor = factors.get(i); - Poly content = factor.contentAsPoly(); - addConstantFactor(polyPow(content, exponents.get(i), false)); - factor = factor.divideByLC(content); - assert factor != null; - if (factor.signumOfLC() < 0) { - factor.negate(); - if (exponents.get(i) % 2 == 1) - constantFactor.negate(); - } - } - return this; - } - - /** - * Calls {@link #monic()} if the coefficient ring is field and {@link #primitive()} otherwise - */ - public FactorDecomposition reduceConstantContent() { - return constantFactor.isOverField() ? monic() : primitive(); - } - - /** Maps all factors using specified mapping function */ - public > - FactorDecomposition map(Function mapper) { - return FactorDecomposition.of(mapper.apply(constantFactor), - factors.stream().map(mapper).collect(Collectors.toList()), - exponents); - } - - /** Stream of all factors */ - public Stream stream() { - return Stream.concat(Stream.of(constantFactor), factors.stream()); - } - - /** Stream of all factors except {@link #constantFactor} */ - public Stream streamWithoutConstant() { - return factors.stream(); - } - - /** Array of factors without constant factor */ - public Poly[] toArrayWithoutConstant() { - Poly[] array = constantFactor.createArray(size()); - return factors.toArray(array); - } - - /** - * Array of exponents (constant factor is not taken into account) - */ - public int[] toArrayExponentsArrayWithoutConstant() { - return exponents.toArray(); - } - - /** Array of factors (constant factor is the last in the array) */ - public Poly[] toArray() { - if (constantFactor.isOne()) - return toArrayWithoutConstant(); - Poly[] array = constantFactor.createArray(size() + 1); - array = factors.toArray(array); - array[array.length - 1] = constantFactor; - return array; - } - - /** - * Array of exponents - */ - public int[] toArrayExponents() { - if (constantFactor.isOne()) - return toArrayExponentsArrayWithoutConstant(); - int[] r = new int[size() + 1]; - r = exponents.toArray(r); - r[r.length - 1] = 1; - return r; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FactorDecomposition that = (FactorDecomposition) o; - - if (!constantFactor.equals(that.constantFactor)) return false; - if (factors != null ? !factors.equals(that.factors) : that.factors != null) return false; - return exponents != null ? exponents.equals(that.exponents) : that.exponents == null; - } - - @Override - public int hashCode() { - int result = factors != null ? factors.hashCode() : 0; - result = 31 * result + (exponents != null ? exponents.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return toString(true, null); - } - - @Override - public String toString(String[] vars) { - return toString(true, vars); - } - - public String toString(ToStringSupport polyToString) { - return toStringFactorization(factors, exponents, constantFactor, true, polyToString); - } - - protected String toString(boolean infoAsExponents, String[] vars) { - return toStringFactorization(factors, exponents, constantFactor, infoAsExponents, vars); - } - - private static

> String toStringFactorization(List

factors, TIntArrayList exponents, - P factor, boolean infoAsExponents, - ToStringSupport

polyToString) { - - if (factors.isEmpty()) - return polyToString.toString(factor); - - StringBuilder sb = new StringBuilder(); - if (!factor.isOne()) { - sb.append(polyToString.toString(factor)); - if (factors.size() > 0) - sb.append("*"); - } - for (int i = 0; ; i++) { - sb.append("(").append(polyToString.toString(factors.get(i))).append(")"); - if (infoAsExponents && exponents.get(i) != 1) - sb.append("^").append(exponents.get(i)); - if (i == factors.size() - 1) - return sb.toString(); - sb.append("*"); - } - } - - /** pretty print for factorization */ - private static

> String toStringFactorization(List

factors, TIntArrayList exponents, - P factor, boolean infoAsExponents, String[] vars) { - return toStringFactorization(factors, exponents, factor, infoAsExponents, vars == null ? ToStringSupport.plain() : ToStringSupport.withVariables(vars)); - } - - /** Multiply factors */ - public Poly toPolynomial() { - return toPolynomial(false); - } - - /** Multiply DDF factors (same as squareFreePart) */ - public Poly toPolynomialIgnoringExponents() { - return toPolynomial(true); - } - - /** Square-free part */ - public Poly squareFreePart() { - return toPolynomialIgnoringExponents(); - } - - private Poly toPolynomial(boolean ignoreExps) { - Poly r = constantFactor.clone(); - for (int i = 0; i < factors.size(); i++) { - Poly tmp = ignoreExps ? factors.get(i) : PolynomialMethods.polyPow(factors.get(i), exponents.get(i), true); - r = r.multiply(tmp); - } - return r; - } - - @Override - public FactorDecomposition clone() { - return new FactorDecomposition<>( - constantFactor.clone(), - factors.stream().map(Poly::clone).collect(Collectors.toList()), - new TIntArrayList(exponents)); - } - - /** decomposition of unit */ - public static > FactorDecomposition empty(Poly factory) { - return new FactorDecomposition<>(factory.createOne()); - } - - /** decomposition with single constant factor */ - public static > FactorDecomposition constantFactor(Poly factor) { - return new FactorDecomposition<>(factor); - } - - /** decomposition with single factor */ - public static > FactorDecomposition singleFactor(Poly constantFactor, Poly poly) { - FactorDecomposition ts = new FactorDecomposition<>(constantFactor); - ts.addFactor(poly, 1); - return ts; - } - - /** decomposition with single factor */ - public static > FactorDecomposition singleFactor(Poly poly) { - if (poly.isConstant()) - return constantFactor(poly); - return singleFactor(poly.createOne(), poly); - } - - /** decomposition with specified factors */ - public static > FactorDecomposition of(List factors) { - return of(factors.get(0).createOne(), new ArrayList<>(factors)); - } - - /** decomposition with specified factors */ - public static > FactorDecomposition of(Poly... factors) { - return of(Arrays.asList(factors)); - } - - /** decomposition with specified factors */ - public static > FactorDecomposition of(Poly constantFactor, List factors) { - return of(constantFactor, factors, new TIntArrayList(ArraysUtil.arrayOf(1, factors.size()))); - } - - /** decomposition with specified factors and exponents */ - public static > FactorDecomposition of(Poly constantFactor, List factors, TIntArrayList exponents) { - if (factors.size() != exponents.size()) - throw new IllegalArgumentException(); - - factors = new ArrayList<>(factors); - exponents = new TIntArrayList(exponents); - - for (int i = factors.size() - 1; i >= 0; --i) - if (factors.get(i).isConstant()) { - constantFactor.multiply(PolynomialMethods.polyPow(factors.get(i), exponents.get(i))); - factors.remove(i); - exponents.removeAt(i); - } - return new FactorDecomposition<>(constantFactor, factors, exponents); - } -} diff --git a/rings/src/main/java/cc/redberry/rings/poly/FiniteField.java b/rings/src/main/java/cc/redberry/rings/poly/FiniteField.java index 5edde2f..04a3a78 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/FiniteField.java +++ b/rings/src/main/java/cc/redberry/rings/poly/FiniteField.java @@ -18,7 +18,7 @@ * @since 1.0 */ public final class FiniteField> - extends ARing implements PolynomialRing { + extends ARing implements IPolynomialRing { private static final long serialVersionUID = 1L; /** GF(3^3) */ @@ -160,7 +160,12 @@ public Poly reciprocal(Poly element) { @Override public Poly gcd(Poly a, Poly b) { - return UnivariateGCD.PolynomialGCD(a, b); + return a; + } + + @Override + public FactorDecomposition factor(Poly element) { + return FactorDecomposition.unit(this, element); } @Override @@ -200,7 +205,7 @@ public Poly valueOfBigInteger(BigInteger val) { @Override public Poly valueOf(Poly val) { - return UnivariatePolynomialArithmetic.polyMod(val, irreducible, inverseMod, true); + return UnivariatePolynomialArithmetic.polyMod(val.setCoefficientRingFrom(factory), irreducible, inverseMod, false); } @Override diff --git a/rings/src/main/java/cc/redberry/rings/poly/IPolynomial.java b/rings/src/main/java/cc/redberry/rings/poly/IPolynomial.java index 509fae2..9524932 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/IPolynomial.java +++ b/rings/src/main/java/cc/redberry/rings/poly/IPolynomial.java @@ -436,6 +436,15 @@ default Poly[] createArray(Poly a, Poly b) { return r; } + /** overcome Java generics... */ + default Poly[] createArray(Poly a, Poly b, Poly c) { + Poly[] r = createArray(3); + r[0] = a; + r[1] = b; + r[2] = c; + return r; + } + /** * Parse string representation of polynomial * diff --git a/rings/src/main/java/cc/redberry/rings/poly/PolynomialRing.java b/rings/src/main/java/cc/redberry/rings/poly/IPolynomialRing.java similarity index 88% rename from rings/src/main/java/cc/redberry/rings/poly/PolynomialRing.java rename to rings/src/main/java/cc/redberry/rings/poly/IPolynomialRing.java index 9822154..ce23a49 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/PolynomialRing.java +++ b/rings/src/main/java/cc/redberry/rings/poly/IPolynomialRing.java @@ -8,7 +8,7 @@ * * @since 1.0 */ -public interface PolynomialRing> extends Ring, WithVariables { +public interface IPolynomialRing> extends Ring, WithVariables { /** * Number of polynomial variables */ diff --git a/rings/src/main/java/cc/redberry/rings/poly/MultivariateRing.java b/rings/src/main/java/cc/redberry/rings/poly/MultivariateRing.java index ad6b7eb..ffa99cf 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/MultivariateRing.java +++ b/rings/src/main/java/cc/redberry/rings/poly/MultivariateRing.java @@ -48,6 +48,17 @@ public Poly gcd(Iterable elements) { return MultivariateGCD.PolynomialGCD(elements); } + @Override + @SuppressWarnings("unchecked") + public PolynomialFactorDecomposition factorSquareFree(Poly element) { + return (PolynomialFactorDecomposition) MultivariateSquareFreeFactorization.SquareFreeFactorization((AMultivariatePolynomial) element); + } + + @Override + public PolynomialFactorDecomposition factor(Poly element) { + return MultivariateFactorization.Factor(element); + } + @Override @SuppressWarnings("unchecked") public Poly variable(int variable) { diff --git a/rings/src/main/java/cc/redberry/rings/poly/PolynomialFactorDecomposition.java b/rings/src/main/java/cc/redberry/rings/poly/PolynomialFactorDecomposition.java new file mode 100644 index 0000000..7718660 --- /dev/null +++ b/rings/src/main/java/cc/redberry/rings/poly/PolynomialFactorDecomposition.java @@ -0,0 +1,237 @@ +package cc.redberry.rings.poly; + +import cc.redberry.rings.FactorDecomposition; +import cc.redberry.rings.ToStringSupport; +import cc.redberry.rings.WithVariables; +import cc.redberry.rings.util.ArraysUtil; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TObjectIntHashMap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static cc.redberry.rings.Rings.PolynomialRing; +import static cc.redberry.rings.poly.PolynomialMethods.polyPow; + +/** + * {@inheritDoc} + * + * @since 1.0 + * @since 2.2 FactorDecomposition renamed to PolynomialFactorDecomposition + */ +public final class PolynomialFactorDecomposition> + extends FactorDecomposition + implements WithVariables, java.io.Serializable { + private static final long serialVersionUID = 1L; + + private PolynomialFactorDecomposition(Poly unit, List factors, TIntArrayList exponents) { + super(PolynomialRing(unit), unit, factors, exponents); + } + + private PolynomialFactorDecomposition(FactorDecomposition factors) { + super(factors.ring, factors.unit, factors.factors, factors.exponents); + } + + @Override + public boolean isUnit(Poly element) { + return element.isConstant(); + } + + @Override + public PolynomialFactorDecomposition setUnit(Poly unit) { + super.setUnit(unit); + return this; + } + + @Override + public PolynomialFactorDecomposition addUnit(Poly unit) { + super.addUnit(unit); + return this; + } + + @Override + public PolynomialFactorDecomposition addFactor(Poly factor, int exponent) { + super.addFactor(factor, exponent); + return this; + } + + @Override + public PolynomialFactorDecomposition addAll(FactorDecomposition other) { + super.addAll(other); + return this; + } + + @Override + public PolynomialFactorDecomposition canonical() { + if (factors.size() == 0) + return this; + reduceUnitContent(); + Poly[] fTmp = factors.toArray(factors.get(0).createArray(factors.size())); + int[] eTmp = exponents.toArray(); + for (int i = fTmp.length - 1; i >= 0; --i) { + Poly poly = fTmp[i]; + if (poly.isMonomial() && eTmp[i] != 1) { + poly = PolynomialMethods.polyPow(poly, eTmp[i], false); + assert poly.isMonomial(); + } + if (poly.signumOfLC() < 0) { + poly.negate(); + if (eTmp[i] % 2 == 1) + unit.negate(); + } + } + + ArraysUtil.quickSort(fTmp, eTmp); + for (int i = 0; i < fTmp.length; i++) { + factors.set(i, fTmp[i]); + exponents.set(i, eTmp[i]); + } + return this; + } + + /** + * Calculates the signum of the polynomial constituted by this decomposition + * + * @return the signum of the polynomial constituted by this decomposition + */ + public int signum() { + int signum = unit.signumOfLC(); + for (int i = 0; i < factors.size(); i++) + signum *= exponents.get(i) % 2 == 0 ? 1 : factors.get(i).signumOfLC(); + return signum; + } + + /** + * Makes each factor monic (moving leading coefficients to the {@link #unit}) + */ + public PolynomialFactorDecomposition monic() { + for (int i = 0; i < factors.size(); i++) { + Poly factor = factors.get(i); + addUnit(polyPow(factor.lcAsPoly(), exponents.get(i), false)); + factor = factor.monic(); + assert factor != null; + } + return this; + } + + /** + * Makes each factor primitive (moving contents to the {@link #unit}) + */ + public PolynomialFactorDecomposition primitive() { + for (int i = 0; i < factors.size(); i++) { + Poly factor = factors.get(i); + Poly content = factor.contentAsPoly(); + addUnit(polyPow(content, exponents.get(i), false)); + factor = factor.divideByLC(content); + assert factor != null; + if (factor.signumOfLC() < 0) { + factor.negate(); + if (exponents.get(i) % 2 == 1) + unit.negate(); + } + } + return this; + } + + public > PolynomialFactorDecomposition map(Function mapper) { + return of(mapper.apply(unit), factors.stream().map(mapper).collect(Collectors.toList()), exponents); + } + + /** + * Calls {@link #monic()} if the coefficient ring is field and {@link #primitive()} otherwise + */ + public PolynomialFactorDecomposition reduceUnitContent() { + return unit.isOverField() ? monic() : primitive(); + } + + @Override + public String toString(String[] variables) { + return toString(ToStringSupport.withVariables(variables)); + } + + @Override + public PolynomialFactorDecomposition clone() { + return new PolynomialFactorDecomposition<>(unit.clone(), factors.stream().map(Poly::clone).collect(Collectors.toList()), new TIntArrayList(exponents)); + } + + /** Unit factorization */ + public static > PolynomialFactorDecomposition unit(Poly unit) { + if (!unit.isConstant()) + throw new IllegalArgumentException(); + return empty(unit).addUnit(unit); + } + + /** Empty factorization */ + public static > PolynomialFactorDecomposition empty(Poly factory) { + return new PolynomialFactorDecomposition<>(factory.createOne(), new ArrayList<>(), new TIntArrayList()); + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param unit the unit coefficient + * @param factors the factors + * @param exponents the exponents + */ + public static > PolynomialFactorDecomposition + of(Poly unit, List factors, TIntArrayList exponents) { + if (factors.size() != exponents.size()) + throw new IllegalArgumentException(); + PolynomialFactorDecomposition r = empty(unit).addUnit(unit); + for (int i = 0; i < factors.size(); i++) + r.addFactor(factors.get(i), exponents.get(i)); + return r; + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param factors factors + */ + public static > PolynomialFactorDecomposition + of(Poly... factors) { + if (factors.length == 0) + throw new IllegalArgumentException(); + return of(Arrays.asList(factors)); + } + + public static > PolynomialFactorDecomposition + of(Poly a) { + Poly[] array = a.createArray(1); + array[0] = a; + return of(array); + } + + public static > PolynomialFactorDecomposition + of(Poly a, Poly b) { + return of(a.createArray(a, b)); + } + + public static > PolynomialFactorDecomposition + of(Poly a, Poly b, Poly c) { + return of(a.createArray(a, b, c)); + } + + /** + * Factor decomposition with specified factors and exponents + * + * @param factors factors + */ + public static > PolynomialFactorDecomposition of(Collection factors) { + TObjectIntHashMap map = new TObjectIntHashMap<>(); + for (Poly e : factors) + map.adjustOrPutValue(e, 1, 1); + List l = new ArrayList<>(); + TIntArrayList e = new TIntArrayList(); + map.forEachEntry((a, b) -> { + l.add(a); + e.add(b); + return true; + }); + return of(factors.iterator().next().createOne(), l, e); + } +} diff --git a/rings/src/main/java/cc/redberry/rings/poly/PolynomialMethods.java b/rings/src/main/java/cc/redberry/rings/poly/PolynomialMethods.java index 257472f..541cb69 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/PolynomialMethods.java +++ b/rings/src/main/java/cc/redberry/rings/poly/PolynomialMethods.java @@ -23,11 +23,11 @@ private PolynomialMethods() {} */ @SuppressWarnings("unchecked") public static > - FactorDecomposition Factor(Poly poly) { + PolynomialFactorDecomposition Factor(Poly poly) { if (poly instanceof IUnivariatePolynomial) - return (FactorDecomposition) UnivariateFactorization.Factor((IUnivariatePolynomial) poly); + return (PolynomialFactorDecomposition) UnivariateFactorization.Factor((IUnivariatePolynomial) poly); else if (poly instanceof AMultivariatePolynomial) - return (FactorDecomposition) MultivariateFactorization.Factor((AMultivariatePolynomial) poly); + return (PolynomialFactorDecomposition) MultivariateFactorization.Factor((AMultivariatePolynomial) poly); else throw new RuntimeException(); } @@ -40,11 +40,11 @@ else if (poly instanceof AMultivariatePolynomial) */ @SuppressWarnings("unchecked") public static > - FactorDecomposition FactorSquareFree(Poly poly) { + PolynomialFactorDecomposition FactorSquareFree(Poly poly) { if (poly instanceof IUnivariatePolynomial) - return (FactorDecomposition) UnivariateSquareFreeFactorization.SquareFreeFactorization((IUnivariatePolynomial) poly); + return (PolynomialFactorDecomposition) UnivariateSquareFreeFactorization.SquareFreeFactorization((IUnivariatePolynomial) poly); else if (poly instanceof AMultivariatePolynomial) - return (FactorDecomposition) MultivariateSquareFreeFactorization.SquareFreeFactorization((AMultivariatePolynomial) poly); + return (PolynomialFactorDecomposition) MultivariateSquareFreeFactorization.SquareFreeFactorization((AMultivariatePolynomial) poly); else throw new RuntimeException(); } @@ -223,6 +223,18 @@ boolean coprimeQ(Iterable polynomials) { return coprimeQ(StreamSupport.stream(polynomials.spliterator(), false).toArray(factory::createArray)); } + /** + * Returns whether specified polynomial is irreducible + */ + @SuppressWarnings("unchecked") + public static > + boolean irreducibleQ(Poly poly) { + if (poly instanceof IUnivariatePolynomial) + return IrreduciblePolynomials.irreducibleQ((IUnivariatePolynomial) poly); + else + return MultivariateFactorization.Factor((AMultivariatePolynomial) poly).isTrivial(); + } + /** * Returns {@code base} in a power of non-negative {@code exponent}. * diff --git a/rings/src/main/java/cc/redberry/rings/poly/UnivariateRing.java b/rings/src/main/java/cc/redberry/rings/poly/UnivariateRing.java index cb8db58..95cdcdc 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/UnivariateRing.java +++ b/rings/src/main/java/cc/redberry/rings/poly/UnivariateRing.java @@ -1,9 +1,6 @@ package cc.redberry.rings.poly; -import cc.redberry.rings.poly.univar.IUnivariatePolynomial; -import cc.redberry.rings.poly.univar.RandomUnivariatePolynomials; -import cc.redberry.rings.poly.univar.UnivariateDivision; -import cc.redberry.rings.poly.univar.UnivariateGCD; +import cc.redberry.rings.poly.univar.*; import org.apache.commons.math3.random.RandomGenerator; /** @@ -35,6 +32,21 @@ public final class UnivariateRing> exte @Override public Poly gcd(Poly a, Poly b) {return UnivariateGCD.PolynomialGCD(a, b);} + @Override + public Poly[] extendedGCD(Poly a, Poly b) { + return UnivariateGCD.PolynomialExtendedGCD(a, b); + } + + @Override + public PolynomialFactorDecomposition factorSquareFree(Poly element) { + return UnivariateSquareFreeFactorization.SquareFreeFactorization(element); + } + + @Override + public PolynomialFactorDecomposition factor(Poly element) { + return UnivariateFactorization.Factor(element); + } + @Override public Poly variable(int variable) { if (variable != 0) diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/HenselLifting.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/HenselLifting.java index 508c725..4fc4e97 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/multivar/HenselLifting.java +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/HenselLifting.java @@ -1262,7 +1262,7 @@ BlockSolution solveBlock(List> block) { Poly factory = baseEq.rhs; // polynomial ring - PolynomialRing polyRing = PolynomialRing(factory); + IPolynomialRing polyRing = PolynomialRing(factory); // field of rational functions Ring> fracRing = Frac(polyRing); @@ -1328,7 +1328,7 @@ BlockSolution solveBlock(List> block) { @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - void addRow(PolynomialRing polyRing, Equation eq, + void addRow(IPolynomialRing polyRing, Equation eq, List[]> lhs, List> rhs, int[] unknowns) { Rational[] row = new Rational[unknowns.length]; for (int j = 0; j < row.length; j++) { diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateConversions.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateConversions.java new file mode 100644 index 0000000..1594e4f --- /dev/null +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateConversions.java @@ -0,0 +1,98 @@ +package cc.redberry.rings.poly.multivar; + + +import cc.redberry.rings.Rings; +import cc.redberry.rings.poly.IPolynomialRing; +import cc.redberry.rings.poly.univar.UnivariatePolynomial; +import cc.redberry.rings.util.ArraysUtil; + +import java.util.Arrays; + +/** + * @author Stanislav Poslavsky + * @since 2.2 + */ +public final class MultivariateConversions { + private MultivariateConversions() {} + + /** + * Given poly in R[x1,x2,...,xN] converts to poly in R[variables][other_variables] + */ + @SuppressWarnings("unchecked") + public static > + MultivariatePolynomial split(Poly poly, int... variables) { + return poly.asOverMultivariateEliminate(variables); + } + + /** + * Given poly in R[variables][other_variables] converts it to poly in R[x1,x2,...,xN] + */ + @SuppressWarnings("unchecked") + public static > + Poly mergeSplit(MultivariatePolynomial poly, int... variables) { + variables = variables.clone(); + Arrays.sort(variables); + int[] mainVariables = ArraysUtil.intSetDifference( + ArraysUtil.sequence(0, poly.nVariables + variables.length), + variables); + if (poly.cc() instanceof MultivariatePolynomial) + return (Poly) MultivariatePolynomial.asNormalMultivariate((MultivariatePolynomial) poly, variables, mainVariables); + else + return (Poly) MultivariatePolynomialZp64.asNormalMultivariate((MultivariatePolynomial) poly, variables, mainVariables); + } + + /** + * Given poly in R[x1,x2,...,xN] converts to poly in R[variables][other_variables] + */ + public static > + IPolynomialRing> split(IPolynomialRing ring, int... variables) { + return Rings.MultivariateRing(split(ring.factory(), variables)); + } + + /** + * Given poly in R[x1,x2,...,xN] converts to poly in R[variables][other_variables] + */ + @SuppressWarnings("unchecked") + public static > + IPolynomialRing mergeSplit(IPolynomialRing> ring, int... variables) { + return (IPolynomialRing) Rings.MultivariateRing((AMultivariatePolynomial) mergeSplit(ring.factory(), variables)); + } + + /** + * Given poly in R[x1,x2,...,xN] converts to poly in R[other_variables][variable] + */ + @SuppressWarnings("unchecked") + public static > + UnivariatePolynomial splitUnivariate(Poly poly, int variable) { + return poly.asUnivariateEliminate(variable); + } + + /** + * Given poly in R[variables][other_variables] converts it to poly in R[x1,x2,...,xN] + */ + @SuppressWarnings("unchecked") + public static > + Poly mergeUnivariateSplit(UnivariatePolynomial poly, int variable) { + if (poly.cc() instanceof MultivariatePolynomial) + return (Poly) MultivariatePolynomial.asMultivariate((UnivariatePolynomial) poly, variable, true); + else + return (Poly) MultivariatePolynomialZp64.asMultivariate((UnivariatePolynomial) poly, variable, true); + } + + /** + * Given poly in R[x1,x2,...,xN] converts to poly in R[other_variables][variable] + */ + public static > + IPolynomialRing> splitUnivariate(IPolynomialRing ring, int variable) { + return Rings.UnivariateRing(splitUnivariate(ring.factory(), variable)); + } + + /** + * Given poly in R[variables][other_variables] converts it to poly in R[x1,x2,...,xN] + */ + @SuppressWarnings("unchecked") + public static > + IPolynomialRing mergeUnivariateSplit(IPolynomialRing> ring, int variable) { + return (IPolynomialRing) Rings.MultivariateRing((AMultivariatePolynomial) mergeUnivariateSplit(ring.factory(), variable)); + } +} diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateFactorization.java index 4217562..85ea6cc 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateFactorization.java @@ -38,15 +38,15 @@ private MultivariateFactorization() {} */ @SuppressWarnings("unchecked") public static > - FactorDecomposition Factor(final Poly poly) { + PolynomialFactorDecomposition Factor(final Poly poly) { if (poly.isOverFiniteField()) - return (FactorDecomposition) FactorInGF((AMultivariatePolynomial) poly); + return (PolynomialFactorDecomposition) FactorInGF((AMultivariatePolynomial) poly); else if (poly.isOverZ()) return FactorInZ((MultivariatePolynomial) poly); else if (Util.isOverRationals(poly)) - return (FactorDecomposition) FactorInQ((MultivariatePolynomial) poly); + return (PolynomialFactorDecomposition) FactorInQ((MultivariatePolynomial) poly); else { - FactorDecomposition factors = tryNested(poly, MultivariateFactorization::Factor); + PolynomialFactorDecomposition factors = tryNested(poly, MultivariateFactorization::Factor); if (factors != null) return factors; throw new RuntimeException("Unsupported ring: " + poly.coefficientRingToString()); @@ -55,7 +55,7 @@ else if (Util.isOverRationals(poly)) @SuppressWarnings("unchecked") static > - FactorDecomposition tryNested(Poly poly, Function> factorFunction) { + PolynomialFactorDecomposition tryNested(Poly poly, Function> factorFunction) { if (MultivariateGCD.isOverUnivariate(poly)) return FactorOverUnivariate((MultivariatePolynomial) poly, (Function) factorFunction); else if (MultivariateGCD.isOverUnivariateZp64(poly)) @@ -67,25 +67,25 @@ else if (MultivariateGCD.isOverMultivariateZp64(poly)) return null; } - private static FactorDecomposition>> + private static PolynomialFactorDecomposition>> FactorOverUnivariate(MultivariatePolynomial> poly, - Function, FactorDecomposition>> factorFunction) { + Function, PolynomialFactorDecomposition>> factorFunction) { return factorFunction.apply( MultivariatePolynomial.asNormalMultivariate(poly, 0)). map(p -> p.asOverUnivariateEliminate(0)); } - private static FactorDecomposition> + private static PolynomialFactorDecomposition> FactorOverUnivariateZp64(MultivariatePolynomial poly, - Function> factorFunction) { + Function> factorFunction) { return factorFunction.apply( MultivariatePolynomialZp64.asNormalMultivariate(poly, 0)). map(p -> p.asOverUnivariateEliminate(0)); } - private static FactorDecomposition>> + private static PolynomialFactorDecomposition>> FactorOverMultivariate(MultivariatePolynomial> poly, - Function, FactorDecomposition>> factorFunction) { + Function, PolynomialFactorDecomposition>> factorFunction) { int[] cfVars = ArraysUtil.sequence(poly.lc().nVariables); int[] mainVars = ArraysUtil.sequence(poly.lc().nVariables, poly.lc().nVariables + poly.nVariables); return factorFunction.apply( @@ -93,9 +93,9 @@ else if (MultivariateGCD.isOverMultivariateZp64(poly)) .map(p -> p.asOverMultivariateEliminate(cfVars)); } - private static FactorDecomposition> + private static PolynomialFactorDecomposition> FactorOverMultivariateZp64(MultivariatePolynomial poly, - Function> factorFunction) { + Function> factorFunction) { int[] cfVars = ArraysUtil.sequence(poly.lc().nVariables); int[] mainVars = ArraysUtil.sequence(poly.lc().nVariables, poly.lc().nVariables + poly.nVariables); return factorFunction.apply( @@ -109,13 +109,13 @@ else if (MultivariateGCD.isOverMultivariateZp64(poly)) * @param polynomial the polynomial * @return factor decomposition */ - public static FactorDecomposition>> FactorInQ(MultivariatePolynomial> polynomial) { + public static PolynomialFactorDecomposition>> FactorInQ(MultivariatePolynomial> polynomial) { Tuple2, E> cmd = Util.toCommonDenominator(polynomial); MultivariatePolynomial integral = cmd._1; E denominator = cmd._2; return Factor(integral) .map(p -> Util.asOverRationals(polynomial.ring, p)) - .addConstantFactor(polynomial.createConstant(new Rational<>(integral.ring, integral.ring.getOne(), denominator))); + .addUnit(polynomial.createConstant(new Rational<>(integral.ring, integral.ring.getOne(), denominator))); } /** @@ -125,7 +125,7 @@ public static FactorDecomposition>> Facto * @return factor decomposition */ @SuppressWarnings("unchecked") - public static FactorDecomposition> FactorInZ(final MultivariatePolynomial polynomial) { + public static PolynomialFactorDecomposition> FactorInZ(final MultivariatePolynomial polynomial) { return Factor(polynomial, MultivariateFactorization::factorPrimitiveInZ); } @@ -138,7 +138,7 @@ public static FactorDecomposition> FactorInZ( @SuppressWarnings("unchecked") public static , Poly extends AMultivariatePolynomial> - FactorDecomposition FactorInGF(final Poly polynomial) { + PolynomialFactorDecomposition FactorInGF(final Poly polynomial) { if (canConvertToZp64(polynomial)) return FactorInGF(asOverZp64(polynomial)).map(Conversions64bit::convert); @@ -154,24 +154,24 @@ FactorDecomposition FactorInGF(final Poly polynomial) { @SuppressWarnings("unchecked") private static , Poly extends AMultivariatePolynomial> - FactorDecomposition Factor(final Poly polynomial, Function> algorithm) { + PolynomialFactorDecomposition Factor(final Poly polynomial, Function> algorithm) { if (polynomial.isEffectiveUnivariate()) return factorUnivariate(polynomial); - FactorDecomposition + PolynomialFactorDecomposition // square-free decomposition sqf = MultivariateSquareFreeFactorization.SquareFreeFactorization(polynomial), // the result - res = FactorDecomposition.constantFactor(sqf.constantFactor); + res = PolynomialFactorDecomposition.unit(sqf.unit); for (int i = 0; i < sqf.size(); i++) { Poly factor = sqf.get(i); // factor into primitive polynomials - FactorDecomposition primitiveFactors = factorToPrimitive(factor); - res.addConstantFactor(primitiveFactors.constantFactor, sqf.getExponent(i)); + PolynomialFactorDecomposition primitiveFactors = factorToPrimitive(factor); + res.addUnit(primitiveFactors.unit, sqf.getExponent(i)); for (Poly primitiveFactor : primitiveFactors) { // factor each primitive polynomial - FactorDecomposition pFactors = algorithm.apply(primitiveFactor); - res.addConstantFactor(pFactors.constantFactor, sqf.getExponent(i)); + PolynomialFactorDecomposition pFactors = algorithm.apply(primitiveFactor); + res.addUnit(pFactors.unit, sqf.getExponent(i)); for (Poly pFactor : pFactors) res.addFactor(pFactor, sqf.getExponent(i)); } @@ -183,19 +183,19 @@ FactorDecomposition Factor(final Poly polynomial, Function, Poly extends AMultivariatePolynomial> - FactorDecomposition factorUnivariate(Poly poly) { + PolynomialFactorDecomposition factorUnivariate(Poly poly) { int uVar = poly.univariateVariable(); - FactorDecomposition + PolynomialFactorDecomposition uFactors = UnivariateFactorization.Factor(poly.asUnivariate()); return uFactors.map(u -> (Poly) AMultivariatePolynomial.asMultivariate(u, poly.nVariables, uVar, poly.ordering)); } @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorToPrimitive(Poly poly) { + PolynomialFactorDecomposition factorToPrimitive(Poly poly) { if (poly.isEffectiveUnivariate()) - return FactorDecomposition.singleFactor(poly); - FactorDecomposition result = FactorDecomposition.empty(poly); + return PolynomialFactorDecomposition.of(poly); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.empty(poly); for (int i = 0; i < poly.nVariables; i++) { Poly factor = poly.asUnivariate(i).content(); result.addFactor(factor, 1); @@ -215,7 +215,7 @@ private static int[] add(int[] array, int value) { private interface FactorizationAlgorithm< Term extends DegreeVector, Poly extends AMultivariatePolynomial> { - FactorDecomposition factor(Poly poly, boolean switchToExtensionField); + PolynomialFactorDecomposition factor(Poly poly, boolean switchToExtensionField); } @@ -234,7 +234,7 @@ private interface FactorizationAlgorithm< * @param poly primitive, square-free bivariate polynomial over Zp * @return factor decomposition */ - private static FactorDecomposition factorInExtensionField( + private static PolynomialFactorDecomposition factorInExtensionField( MultivariatePolynomialZp64 poly, FactorizationAlgorithm, MultivariatePolynomial> algorithm) { @@ -245,7 +245,7 @@ private static FactorDecomposition factorInExtension IrreduciblePolynomials.randomIrreduciblePolynomial( ring.modulus, startingDegree++, cc.redberry.rings.poly.multivar.PrivateRandom.getRandom())); - FactorDecomposition result = + PolynomialFactorDecomposition result = factorInExtensionField(poly, extensionField, algorithm); if (result != null) @@ -259,20 +259,20 @@ private static FactorDecomposition factorInExtension * @param poly primitive, square-free bivariate polynomial over Zp * @return factor decomposition */ - private static FactorDecomposition factorInExtensionField( + private static PolynomialFactorDecomposition factorInExtensionField( MultivariatePolynomialZp64 poly, FiniteField extensionField, FactorizationAlgorithm, MultivariatePolynomial> algorithm) { - FactorDecomposition> factorization + PolynomialFactorDecomposition> factorization = algorithm.factor(poly.mapCoefficients(extensionField, extensionField::valueOf), false); if (factorization == null) // too small extension return null; - if (!factorization.constantFactor.cc().isConstant()) + if (!factorization.unit.cc().isConstant()) return null; - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createConstant(factorization.constantFactor.cc().cc())); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(poly.createConstant(factorization.unit.cc().cc())); for (int i = 0; i < factorization.size(); i++) { if (!factorization.get(i).stream().allMatch(p -> p.isConstant())) return null; @@ -288,7 +288,7 @@ private static FactorDecomposition factorInExtension * @return factor decomposition */ private static - FactorDecomposition> factorInExtensionField( + PolynomialFactorDecomposition> factorInExtensionField( MultivariatePolynomial poly, FactorizationAlgorithm>, MultivariatePolynomial>> algorithm) { Ring ring = poly.ring; @@ -299,7 +299,7 @@ FactorDecomposition> factorInExtensionField( IrreduciblePolynomials.randomIrreduciblePolynomial( ring, startingDegree++, cc.redberry.rings.poly.multivar.PrivateRandom.getRandom())); - FactorDecomposition> result = + PolynomialFactorDecomposition> result = factorInExtensionField(poly, extensionField, algorithm); if (result != null) @@ -314,19 +314,19 @@ FactorDecomposition> factorInExtensionField( * @return factor decomposition */ private static - FactorDecomposition> factorInExtensionField( + PolynomialFactorDecomposition> factorInExtensionField( MultivariatePolynomial poly, FiniteField> extensionField, FactorizationAlgorithm>, MultivariatePolynomial>> algorithm) { - FactorDecomposition>> factorization + PolynomialFactorDecomposition>> factorization = algorithm.factor(poly.mapCoefficients(extensionField, c -> UnivariatePolynomial.constant(poly.ring, c)), false); if (factorization == null) // too small extension return null; - if (!factorization.constantFactor.cc().isConstant()) + if (!factorization.unit.cc().isConstant()) return null; - FactorDecomposition> result = FactorDecomposition.constantFactor(poly.createConstant(factorization.constantFactor.cc().cc())); + PolynomialFactorDecomposition> result = PolynomialFactorDecomposition.unit(poly.createConstant(factorization.unit.cc().cc())); for (int i = 0; i < factorization.size(); i++) { if (!factorization.get(i).stream().allMatch(UnivariatePolynomial::isConstant)) return null; @@ -471,7 +471,7 @@ static boolean isBivariateCertainlyIrreducible(AMultivariatePolynomial + static PolynomialFactorDecomposition bivariateDenseFactorSquareFreeInGF(MultivariatePolynomialZp64 poly) { return bivariateDenseFactorSquareFreeInGF(poly, true); } @@ -483,7 +483,7 @@ static boolean isBivariateCertainlyIrreducible(AMultivariatePolynomial + static PolynomialFactorDecomposition bivariateDenseFactorSquareFreeInGF(MultivariatePolynomialZp64 poly, boolean switchToExtensionField, boolean doGCDTest) { assert poly.nUsedVariables() <= 2 && IntStream.range(2, poly.nVariables).allMatch(i -> poly.degree(i) == 0) : poly; @@ -491,7 +491,7 @@ static boolean isBivariateCertainlyIrreducible(AMultivariatePolynomial + PolynomialFactorDecomposition gcdFactorization = bivariateDenseFactorSquareFreeInGF(dGCD, switchToExtensionField, doGCDTest), restFactorization = bivariateDenseFactorSquareFreeInGF(MultivariateDivision.divideExact(reducedPoly, dGCD), switchToExtensionField, doGCDTest); @@ -543,7 +543,7 @@ static boolean isBivariateCertainlyIrreducible(AMultivariatePolynomial uFactorization = null; + PolynomialFactorDecomposition uFactorization = null; // number of univariate factorizations tried int univariateFactorizations = 0; @@ -588,10 +588,10 @@ else if (switchToExtensionField) // ensure that univariate image is also square free continue; - FactorDecomposition factorization = UnivariateFactorization.FactorSquareFreeInGF(uImage); + PolynomialFactorDecomposition factorization = UnivariateFactorization.FactorSquareFreeInGF(uImage); if (factorization.size() == 1) // irreducible polynomial - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); if (uFactorization == null || factorization.size() < uFactorization.size()) { @@ -650,7 +650,7 @@ else if (switchToExtensionField) lifted = Arrays.copyOfRange(lifted, 1, lifted.length); // factors are lifted => do recombination - FactorDecomposition result = denseBivariateRecombination(reducedPoly, baseSeries, lifted, evaluation, liftDegree); + PolynomialFactorDecomposition result = denseBivariateRecombination(reducedPoly, baseSeries, lifted, evaluation, liftDegree); if (swapVariables) // reconstruct original variables order @@ -660,7 +660,7 @@ else if (switchToExtensionField) } private static , Poly extends AMultivariatePolynomial> - void swap(FactorDecomposition factorDecomposition) { + void swap(PolynomialFactorDecomposition factorDecomposition) { for (int i = 0; i < factorDecomposition.factors.size(); i++) factorDecomposition.factors.set(i, AMultivariatePolynomial.swapVariables(factorDecomposition.get(i), 0, 1)); } @@ -671,7 +671,7 @@ void swap(FactorDecomposition factorDecomposition) { * @param poly primitive, square-free bivariate polynomial over Zp * @return factor decomposition */ - static FactorDecomposition> + static PolynomialFactorDecomposition> bivariateDenseFactorSquareFreeInGF(MultivariatePolynomial poly) { return bivariateDenseFactorSquareFreeInGF(poly, true); } @@ -683,7 +683,7 @@ void swap(FactorDecomposition factorDecomposition) { * @param switchToExtensionField whether to switch to extension field if ring cardinality is too small * @return factor decomposition */ - static FactorDecomposition> + static PolynomialFactorDecomposition> bivariateDenseFactorSquareFreeInGF(MultivariatePolynomial poly, boolean switchToExtensionField, boolean doGCDTest) { assert poly.nUsedVariables() <= 2 && IntStream.range(2, poly.nVariables).allMatch(i -> poly.degree(i) == 0); @@ -691,7 +691,7 @@ void swap(FactorDecomposition factorDecomposition) { return factorUnivariate(poly); if (isBivariateCertainlyIrreducible(poly)) - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); MultivariatePolynomial reducedPoly = poly; int[] degreeBounds = reducedPoly.degrees(); @@ -719,7 +719,7 @@ void swap(FactorDecomposition factorDecomposition) { continue; MultivariatePolynomial dGCD = MultivariateGCD.PolynomialGCD(xDerivative, reducedPoly); if (!dGCD.isConstant()) { - FactorDecomposition> + PolynomialFactorDecomposition> gcdFactorization = bivariateDenseFactorSquareFreeInGF(dGCD, switchToExtensionField), restFactorization = bivariateDenseFactorSquareFreeInGF(MultivariateDivision.divideExact(reducedPoly, dGCD), switchToExtensionField); @@ -743,7 +743,7 @@ void swap(FactorDecomposition factorDecomposition) { // substitution value for second variable E ySubstitution = null; // univariate factorization - FactorDecomposition> uFactorization = null; + PolynomialFactorDecomposition> uFactorization = null; // number of univariate factorizations tried int univariateFactorizations = 0; @@ -786,10 +786,10 @@ else if (switchToExtensionField) // ensure that univariate image is also square free continue; - FactorDecomposition> factorization = UnivariateFactorization.FactorSquareFreeInGF(uImage); + PolynomialFactorDecomposition> factorization = UnivariateFactorization.FactorSquareFreeInGF(uImage); if (factorization.size() == 1) // irreducible polynomial - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); if (uFactorization == null || factorization.size() < uFactorization.size()) { @@ -848,7 +848,7 @@ else if (switchToExtensionField) lifted = Arrays.copyOfRange(lifted, 1, factors.length); // factors are lifted => do recombination - FactorDecomposition> result = denseBivariateRecombination(reducedPoly, baseSeries, lifted, evaluation, liftDegree); + PolynomialFactorDecomposition> result = denseBivariateRecombination(reducedPoly, baseSeries, lifted, evaluation, liftDegree); if (swapVariables) // reconstruct original variables order @@ -899,7 +899,7 @@ private static int[] select(int[] data, int[] positions) { static , Poly extends AMultivariatePolynomial, uPoly extends IUnivariatePolynomial> - FactorDecomposition denseBivariateRecombination( + PolynomialFactorDecomposition denseBivariateRecombination( Poly factory, UnivariatePolynomial poly, UnivariatePolynomial[] modularFactors, @@ -907,7 +907,7 @@ FactorDecomposition denseBivariateRecombination( int liftDegree) { int[] modIndexes = naturalSequenceRef(modularFactors.length); - FactorDecomposition trueFactors = FactorDecomposition.empty(factory); + PolynomialFactorDecomposition trueFactors = PolynomialFactorDecomposition.empty(factory); UnivariatePolynomial fRest = poly; int s = 1; @@ -954,7 +954,7 @@ FactorDecomposition denseBivariateRecombination( * @param poly primitive, square-free bivariate polynomial over Z * @return factor decomposition */ - static FactorDecomposition> + static PolynomialFactorDecomposition> bivariateDenseFactorSquareFreeInZ(MultivariatePolynomial poly) { assert poly.nUsedVariables() <= 2 && IntStream.range(2, poly.nVariables).allMatch(i -> poly.degree(i) == 0); @@ -962,7 +962,7 @@ FactorDecomposition denseBivariateRecombination( return factorUnivariate(poly); if (isBivariateCertainlyIrreducible(poly)) - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); MultivariatePolynomial content = poly.contentAsPoly(); MultivariatePolynomial reducedPoly = content.isOne() ? poly : poly.clone().divideByLC(content); @@ -980,7 +980,7 @@ FactorDecomposition denseBivariateRecombination( assert !xDerivative.isZero(); MultivariatePolynomial dGCD = MultivariateGCD.PolynomialGCD(xDerivative, reducedPoly); if (!dGCD.isConstant()) { - FactorDecomposition> + PolynomialFactorDecomposition> gcdFactorization = bivariateDenseFactorSquareFreeInZ(dGCD), restFactorization = bivariateDenseFactorSquareFreeInZ(MultivariateDivision.divideExact(reducedPoly, dGCD)); @@ -988,7 +988,7 @@ FactorDecomposition denseBivariateRecombination( if (swapVariables) swap(gcdFactorization); - return gcdFactorization.addConstantFactor(content); + return gcdFactorization.addUnit(content); } // degree in main variable @@ -996,7 +996,7 @@ FactorDecomposition denseBivariateRecombination( // substitution value for second variable BigInteger ySubstitution = null; // univariate factorization - FactorDecomposition> uFactorization = null; + PolynomialFactorDecomposition> uFactorization = null; // number of univariate factorizations tried int univariateFactorizations = 0; @@ -1032,10 +1032,10 @@ FactorDecomposition denseBivariateRecombination( // ensure that univariate image is also square free continue; - FactorDecomposition> factorization = UnivariateFactorization.FactorSquareFreeInZ(uImage); + PolynomialFactorDecomposition> factorization = UnivariateFactorization.FactorSquareFreeInZ(uImage); if (factorization.size() == 1) // irreducible polynomial - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); if (uFactorization == null || factorization.size() < uFactorization.size()) { // better univariate factorization found @@ -1120,7 +1120,7 @@ FactorDecomposition denseBivariateRecombination( // factors are lifted => do recombination UnivariatePolynomial> baseSeriesZ = seriesExpansionDenseZ(reducedPoly, ySubstitution); - FactorDecomposition> result = denseBivariateRecombinationZ( + PolynomialFactorDecomposition> result = denseBivariateRecombinationZ( reducedPoly, baseZp, baseSeriesZ, liftedZp, evaluation, ySubstitution, zpDomain, liftDegree); if (swapVariables) @@ -1128,7 +1128,7 @@ FactorDecomposition denseBivariateRecombination( for (int i = 0; i < result.factors.size(); i++) result.factors.set(i, AMultivariatePolynomial.swapVariables(result.get(i), 0, 1)); - return result.addConstantFactor(content); + return result.addUnit(content); } private static boolean isGoodPrime(BigInteger prime, BigInteger ulc, BigInteger ucc) { @@ -1168,7 +1168,7 @@ static BigInteger coefficientsBound(MultivariatePolynomial poly) { } /** naive recombination for lifting to factorization in Z */ - static FactorDecomposition> denseBivariateRecombinationZ( + static PolynomialFactorDecomposition> denseBivariateRecombinationZ( MultivariatePolynomial baseZ, MultivariatePolynomial factoryZp, UnivariatePolynomial> baseSeriesZ, @@ -1179,7 +1179,7 @@ static FactorDecomposition> denseBivariateRec int liftDegree) { int[] modIndexes = naturalSequenceRef(modularFactorsZp.length); - FactorDecomposition> trueFactors = FactorDecomposition.empty(baseZ); + PolynomialFactorDecomposition> trueFactors = PolynomialFactorDecomposition.empty(baseZ); UnivariatePolynomial> fRest = baseSeriesZ; int s = 1; @@ -1297,23 +1297,23 @@ UnivariatePolynomial lcInSeries(UnivariatePolynomial poly) { @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition + PolynomialFactorDecomposition bivariateDenseFactorSquareFreeInGF(Poly poly, boolean switchToExtensionField) { if (poly instanceof MultivariatePolynomialZp64) - return (FactorDecomposition) bivariateDenseFactorSquareFreeInGF((MultivariatePolynomialZp64) poly, switchToExtensionField, true); + return (PolynomialFactorDecomposition) bivariateDenseFactorSquareFreeInGF((MultivariatePolynomialZp64) poly, switchToExtensionField, true); else - return (FactorDecomposition) bivariateDenseFactorSquareFreeInGF((MultivariatePolynomial) poly, switchToExtensionField, true); + return (PolynomialFactorDecomposition) bivariateDenseFactorSquareFreeInGF((MultivariatePolynomial) poly, switchToExtensionField, true); } /* ================================ Multivariate factorization over finite fields ================================ */ @SuppressWarnings("unchecked") private static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorInExtensionFieldGeneric(Poly poly, FactorizationAlgorithm algorithm) { + PolynomialFactorDecomposition factorInExtensionFieldGeneric(Poly poly, FactorizationAlgorithm algorithm) { if (poly instanceof MultivariatePolynomialZp64) - return (FactorDecomposition) factorInExtensionField((MultivariatePolynomialZp64) poly, (FactorizationAlgorithm, MultivariatePolynomial>) algorithm); + return (PolynomialFactorDecomposition) factorInExtensionField((MultivariatePolynomialZp64) poly, (FactorizationAlgorithm, MultivariatePolynomial>) algorithm); else if (poly instanceof MultivariatePolynomial) - return (FactorDecomposition) factorInExtensionField((MultivariatePolynomial) poly, (FactorizationAlgorithm) algorithm); + return (PolynomialFactorDecomposition) factorInExtensionField((MultivariatePolynomial) poly, (FactorizationAlgorithm) algorithm); else throw new RuntimeException(); } @@ -1414,7 +1414,7 @@ OrderByDegrees orderByDegrees(Poly poly, boolean reduceNVariables, i @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorPrimitiveInGF(final Poly polynomial) { + PolynomialFactorDecomposition factorPrimitiveInGF(final Poly polynomial) { return factorPrimitiveInGF(polynomial, true); } @@ -1428,7 +1428,7 @@ FactorDecomposition factorPrimitiveInGF(final Poly polynomial) { @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorPrimitiveInGF( + PolynomialFactorDecomposition factorPrimitiveInGF( final Poly polynomial, boolean switchToExtensionField) { @@ -1437,7 +1437,7 @@ FactorDecomposition factorPrimitiveInGF( // order the polynomial by degrees OrderByDegrees input = orderByDegrees(polynomial, true, -1); - FactorDecomposition decomposition = factorPrimitiveInGF0(input.ordered, switchToExtensionField); + PolynomialFactorDecomposition decomposition = factorPrimitiveInGF0(input.ordered, switchToExtensionField); if (decomposition == null) return null; return decomposition.map(input::restoreOrder); @@ -1452,7 +1452,7 @@ static final class LeadingCoefficientData< /** the original leading coefficient */ final Poly lc; /** its square-free decomposition */ - final FactorDecomposition lcSqFreeDecomposition; + final PolynomialFactorDecomposition lcSqFreeDecomposition; /** square-free part of l.c. */ final Poly lcSqFreePart; /** @@ -1586,7 +1586,7 @@ static final class SplitContent< @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorPrimitiveInGF0( + PolynomialFactorDecomposition factorPrimitiveInGF0( final Poly poly, boolean switchToExtensionField) { return factorPrimitiveInGF0(poly, -1, switchToExtensionField); @@ -1598,7 +1598,7 @@ FactorDecomposition factorPrimitiveInGF0( @SuppressWarnings("unchecked") static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorPrimitiveInGF0( + PolynomialFactorDecomposition factorPrimitiveInGF0( final Poly initialPoly, final int fixSecondVar, boolean switchToExtensionField) { @@ -1619,7 +1619,7 @@ FactorDecomposition factorPrimitiveInGF0( Poly dGCD = MultivariateGCD.PolynomialGCD(xDerivative, poly); if (!dGCD.isConstant()) { - FactorDecomposition + PolynomialFactorDecomposition gcdFactorization = factorPrimitiveInGF(dGCD, switchToExtensionField), restFactorization = factorPrimitiveInGF(MultivariateDivision.divideExact(poly, dGCD), switchToExtensionField); @@ -1690,7 +1690,7 @@ FactorDecomposition factorPrimitiveInGF0( continue; // factor bivariate image - FactorDecomposition biFactorsMain = + PolynomialFactorDecomposition biFactorsMain = bivariateDenseFactorSquareFreeInGF(bivariateImage, false); if (biFactorsMain == null) if (switchToExtensionField) @@ -1699,7 +1699,7 @@ FactorDecomposition factorPrimitiveInGF0( return null; if (biFactorsMain.size() == 1) - return FactorDecomposition.singleFactor(initialPoly); + return PolynomialFactorDecomposition.of(initialPoly); if (biFactorsMain.size() > nBivariateFactors) { ++nFailedWithSuperfluousFactors; @@ -1749,7 +1749,7 @@ FactorDecomposition factorPrimitiveInGF0( || biImage.lc(0).degree(freeVariable) != lc.degree(freeVariable)) continue; - FactorDecomposition fct = bivariateDenseFactorSquareFreeInGF( + PolynomialFactorDecomposition fct = bivariateDenseFactorSquareFreeInGF( orderByDegrees(biImage, true, -1).ordered, false); if (fct != null && fct.size() < nBivariateFactors) { nBivariateFactors = fct.size(); @@ -1793,7 +1793,7 @@ FactorDecomposition factorPrimitiveInGF0( } // bivariate factors in F[x1, x_i] - FactorDecomposition biFactors; + PolynomialFactorDecomposition biFactors; if (freeVariable == 1) biFactors = biFactorsMain; else { @@ -1866,20 +1866,20 @@ FactorDecomposition factorPrimitiveInGF0( // .equals(biFactorsMain.map(p -> evaluation.evaluateFrom(p, 1).asUnivariate()).monic()); // square-free decomposition of the leading coefficients of bivariate factors - FactorDecomposition[] ulcFactors = (FactorDecomposition[]) + PolynomialFactorDecomposition[] ulcFactors = (PolynomialFactorDecomposition[]) biFactors.factors.stream() .map(f -> UnivariateSquareFreeFactorization.SquareFreeFactorization(f.lc(0).asUnivariate())) - .toArray(FactorDecomposition[]::new); + .toArray(PolynomialFactorDecomposition[]::new); // move to GCD-free basis of sq.-f. decomposition (univariate, because fast) GCDFreeBasis(ulcFactors); // map to multivariate factors for further Hensel lifting - FactorDecomposition[] + PolynomialFactorDecomposition[] ilcFactors = Arrays.stream(ulcFactors) .map(decomposition -> decomposition.map(p -> (Poly) AMultivariatePolynomial.asMultivariate((IUnivariatePolynomial) p, poly.nVariables - 1, 0, poly.ordering))) - .toArray(FactorDecomposition[]::new); + .toArray(PolynomialFactorDecomposition[]::new); // <- set same polys in ulcFactors with the same single reference! @@ -1902,7 +1902,7 @@ FactorDecomposition factorPrimitiveInGF0( // pick unique factors from lc decompositions (complete square-free ) Set ilcFactorsSet = Arrays.stream(ilcFactors) - .flatMap(FactorDecomposition::streamWithoutConstant) + .flatMap(PolynomialFactorDecomposition::streamWithoutUnit) .collect(Collectors.toSet()); Poly[] ilcFactorsSqFree = ilcFactorsSet .toArray(poly.createArray(ilcFactorsSet.size())); @@ -1952,7 +1952,7 @@ FactorDecomposition factorPrimitiveInGF0( // l.c. has content in x2 for (int jFactor = 0; jFactor < lcFactors.length; jFactor++) { Poly obtainedLcFactor = AMultivariatePolynomial.renameVariables( - ilcFactors[jFactor].toPolynomial(), lcSplit.ppOrdered.variablesMapping) + ilcFactors[jFactor].multiply(), lcSplit.ppOrdered.variablesMapping) .insertVariable(0); Poly commonPart = MultivariateGCD.PolynomialGCD(obtainedLcFactor, lcFactors[jFactor]); Poly addon = MultivariateDivision.divideExact(obtainedLcFactor, commonPart); @@ -1974,7 +1974,7 @@ FactorDecomposition factorPrimitiveInGF0( Poly base; if (lcRest.isOne()) - base = poly.clone().divideByLC(biFactorsMain.constantFactor); + base = poly.clone().divideByLC(biFactorsMain.unit); else { base = poly.clone(); base.divideByLC(lcRest); @@ -2005,26 +2005,26 @@ FactorDecomposition factorPrimitiveInGF0( } else { Poly base; - if (biFactorsMain.constantFactor.isOne()) + if (biFactorsMain.unit.isOne()) base = poly; else { base = poly.clone(); - base.divideByLC(biFactorsMain.constantFactor); + base.divideByLC(biFactorsMain.unit); } biFactorsArrayMain = biFactorsMain.factors.toArray(poly.createArray(biFactorsMain.size())); HenselLifting.multivariateLift0(base, biFactorsArrayMain, null, evaluation, poly.degrees(), 2); } - FactorDecomposition factorization - = FactorDecomposition.of(Arrays.asList(biFactorsArrayMain)) + PolynomialFactorDecomposition factorization + = PolynomialFactorDecomposition.of(Arrays.asList(biFactorsArrayMain)) .monic() - .setConstantFactor(poly.lcAsPoly()); + .setUnit(poly.lcAsPoly()); Poly - lcNumeric = factorization.factors.stream().reduce(factorization.constantFactor.clone(), (a, b) -> a.lcAsPoly().multiply(b.lcAsPoly())), - ccNumeric = factorization.factors.stream().reduce(factorization.constantFactor.clone(), (a, b) -> a.ccAsPoly().multiply(b.ccAsPoly())); - if (!lcNumeric.equals(poly.lcAsPoly()) || !ccNumeric.equals(poly.ccAsPoly()) || !factorization.toPolynomial().equals(poly)) { + lcNumeric = factorization.factors.stream().reduce(factorization.unit.clone(), (a, b) -> a.lcAsPoly().multiply(b.lcAsPoly())), + ccNumeric = factorization.factors.stream().reduce(factorization.unit.clone(), (a, b) -> a.ccAsPoly().multiply(b.ccAsPoly())); + if (!lcNumeric.equals(poly.lcAsPoly()) || !ccNumeric.equals(poly.ccAsPoly()) || !factorization.multiply().equals(poly)) { // bad bivariate factorization => recombination required // instead of recombination we try again with another evaluation // searching for good enough bivariate factorization @@ -2044,7 +2044,7 @@ Poly swapSecondVar(final Poly initialPoly, final int fixSecondVar) { } private static , Poly extends AMultivariatePolynomial> - FactorDecomposition swapSecondVar(final FactorDecomposition factors, final int fixSecondVar) { + PolynomialFactorDecomposition swapSecondVar(final PolynomialFactorDecomposition factors, final int fixSecondVar) { if (fixSecondVar == -1) return factors; else @@ -2065,14 +2065,14 @@ private static boolean isSmallCharacteristics(IPolynomial poly) { private static , Poly extends AMultivariatePolynomial, uPoly extends IUnivariatePolynomial> - void toCanonicalSort(FactorDecomposition biFactors, + void toCanonicalSort(PolynomialFactorDecomposition biFactors, HenselLifting.IEvaluation evaluation) { // assertion removed since monomials may occur in factorization e.g/ (b)^2 * (a+b) * ... //assert biFactors.exponents.sum() == biFactors.size(); uPoly[] uFactorsArray = biFactors.map(p -> (uPoly) evaluation.evaluateFrom(p, 1).asUnivariate()) - .reduceConstantContent().toArrayWithoutConstant(); - Poly[] biFactorsArray = biFactors.toArrayWithoutConstant(); + .reduceUnitContent().toArrayWithoutUnit(); + Poly[] biFactorsArray = biFactors.toArrayWithoutUnit(); ArraysUtil.quickSort(uFactorsArray, biFactorsArray); biFactors.factors.clear(); @@ -2170,9 +2170,9 @@ public int hashCode() { } static > - void GCDFreeBasis(FactorDecomposition[] decompositions) { + void GCDFreeBasis(PolynomialFactorDecomposition[] decompositions) { ArrayList> allFactors = new ArrayList<>(); - for (FactorDecomposition decomposition : decompositions) + for (PolynomialFactorDecomposition decomposition : decompositions) for (int j = 0; j < decomposition.size(); j++) allFactors.add(new FactorRef<>(decomposition, j)); @@ -2212,12 +2212,12 @@ void GCDFreeBasis(FactorDecomposition[] decompositions) { } private static > - void normalizeGCDFreeDecomposition(FactorDecomposition decomposition) { + void normalizeGCDFreeDecomposition(PolynomialFactorDecomposition decomposition) { main: for (int i = decomposition.factors.size() - 1; i >= 0; --i) { Poly factor = decomposition.get(i).clone(); Poly content = factor.isOverField() ? factor.lcAsPoly() : factor.contentAsPoly(); - decomposition.addConstantFactor(polyPow(content, decomposition.getExponent(i), false)); + decomposition.addUnit(polyPow(content, decomposition.getExponent(i), false)); factor = factor.divideByLC(content); assert factor != null; @@ -2242,7 +2242,7 @@ void normalizeGCDFreeDecomposition(FactorDecomposition decomposition) { } private static final class FactorRef> { - final List> decompositions; + final List> decompositions; final TIntArrayList indexes; FactorRef() { @@ -2250,7 +2250,7 @@ private static final class FactorRef> { this.indexes = new TIntArrayList(); } - FactorRef(FactorDecomposition decomposition, int index) { + FactorRef(PolynomialFactorDecomposition decomposition, int index) { this.decompositions = new ArrayList<>(); this.indexes = new TIntArrayList(); decompositions.add(decomposition); @@ -2263,7 +2263,7 @@ TIntArrayList update(Poly reduced, Poly gcd) { TIntArrayList gcdIndexes = new TIntArrayList(indexes.size()); // add gcd to all required decompositions for (int i = 0; i < decompositions.size(); i++) { - FactorDecomposition decomposition = decompositions.get(i); + PolynomialFactorDecomposition decomposition = decompositions.get(i); decomposition.factors.set(indexes.get(i), reduced); // <- just in case gcdIndexes.add(decomposition.size()); decomposition.addFactor(gcd, decomposition.getExponent(indexes.get(i))); @@ -2314,7 +2314,7 @@ public HenselLifting.Evaluation next() { * @return factor decomposition */ @SuppressWarnings("unchecked") - static FactorDecomposition> factorPrimitiveInZ( + static PolynomialFactorDecomposition> factorPrimitiveInZ( MultivariatePolynomial polynomial) { if (polynomial.isEffectiveUnivariate()) @@ -2322,7 +2322,7 @@ static FactorDecomposition> factorPrimitiveIn // order the polynomial by degrees OrderByDegrees, MultivariatePolynomial> input = orderByDegrees(polynomial, true, -1); - FactorDecomposition> decomposition = factorPrimitiveInZ0(input.ordered); + PolynomialFactorDecomposition> decomposition = factorPrimitiveInZ0(input.ordered); if (decomposition == null) return null; return decomposition.map(input::restoreOrder); @@ -2332,7 +2332,7 @@ static FactorDecomposition> factorPrimitiveIn * The main factorization algorithm in Z */ @SuppressWarnings("unchecked") - static FactorDecomposition> factorPrimitiveInZ0( + static PolynomialFactorDecomposition> factorPrimitiveInZ0( final MultivariatePolynomial poly) { // assert that poly is at least bivariate @@ -2401,11 +2401,11 @@ static FactorDecomposition> factorPrimitiveIn continue; // factor bivariate image - FactorDecomposition> biFactorsMain = + PolynomialFactorDecomposition> biFactorsMain = bivariateDenseFactorSquareFreeInZ(bivariateImage); if (biFactorsMain.size() == 1) - return FactorDecomposition.singleFactor(poly); + return PolynomialFactorDecomposition.of(poly); if (biFactorsMain.size() > nBivariateFactors) // bad evaluation @@ -2479,7 +2479,7 @@ static FactorDecomposition> factorPrimitiveIn } // bivariate factors in F[x1, x_i] - FactorDecomposition> biFactors; + PolynomialFactorDecomposition> biFactors; if (freeVariable == 1) biFactors = biFactorsMain; else { @@ -2508,24 +2508,24 @@ static FactorDecomposition> factorPrimitiveIn } assert biFactors - .map(p -> iEvaluation.evaluateFrom(p, 1).asUnivariate()).primitive().canonicalForm() - .equals(biFactorsMain.map(p -> evaluation.evaluateFrom(p, 1).asUnivariate()).primitive().canonicalForm()); + .map(p -> iEvaluation.evaluateFrom(p, 1).asUnivariate()).primitive().canonical() + .equals(biFactorsMain.map(p -> evaluation.evaluateFrom(p, 1).asUnivariate()).primitive().canonical()); // square-free decomposition of the leading coefficients of bivariate factors - FactorDecomposition[] ulcFactors = (FactorDecomposition[]) + PolynomialFactorDecomposition[] ulcFactors = (PolynomialFactorDecomposition[]) biFactors.factors.stream() .map(f -> UnivariateSquareFreeFactorization.SquareFreeFactorization(f.lc(0).asUnivariate())) - .toArray(FactorDecomposition[]::new); + .toArray(PolynomialFactorDecomposition[]::new); // move to GCD-free basis of sq.-f. decomposition (univariate, because fast) GCDFreeBasis(ulcFactors); // map to multivariate factors for further Hensel lifting - FactorDecomposition>[] + PolynomialFactorDecomposition>[] ilcFactors = Arrays.stream(ulcFactors) .map(decomposition -> decomposition.map(p -> AMultivariatePolynomial.asMultivariate((IUnivariatePolynomial) p, poly.nVariables - 1, 0, poly.ordering))) - .toArray(FactorDecomposition[]::new); + .toArray(PolynomialFactorDecomposition[]::new); // <- set same polys in ulcFactors with the same single reference! @@ -2547,7 +2547,7 @@ static FactorDecomposition> factorPrimitiveIn // pick unique factors from lc decompositions (complete square-free) Set> ilcFactorsSet = Arrays.stream(ilcFactors) - .flatMap(FactorDecomposition::streamWithoutConstant) + .flatMap(PolynomialFactorDecomposition::streamWithoutUnit) .collect(Collectors.toSet()); MultivariatePolynomial[] ilcFactorsSqFree = ilcFactorsSet .toArray(poly.createArray(ilcFactorsSet.size())); @@ -2602,7 +2602,7 @@ static FactorDecomposition> factorPrimitiveIn // l.c. has content in x2 for (int jFactor = 0; jFactor < lcFactors.length; jFactor++) { MultivariatePolynomial obtainedLcFactor = AMultivariatePolynomial.renameVariables( - ilcFactors[jFactor].toPolynomial(), lcSplit.ppOrdered.variablesMapping) + ilcFactors[jFactor].multiply(), lcSplit.ppOrdered.variablesMapping) .insertVariable(0); MultivariatePolynomial commonPart = MultivariateGCD.PolynomialGCD(obtainedLcFactor, lcFactors[jFactor]); MultivariatePolynomial addon = MultivariateDivision.divideExact(obtainedLcFactor, commonPart); @@ -2650,8 +2650,8 @@ static FactorDecomposition> factorPrimitiveIn } else { // switch to Z/p and lift MultivariatePolynomial base = poly.setRing(zpDomain); - if (!biFactorsMain.constantFactor.isOne()) { - BigInteger correction = biFactorsMain.constantFactor.lc(); + if (!biFactorsMain.unit.isOne()) { + BigInteger correction = biFactorsMain.unit.lc(); base.multiply(zpDomain.pow(correction, biFactorsMain.size() - 1)); for (MultivariatePolynomial f : biFactorsMain.factors) f.multiply(correction); @@ -2661,17 +2661,17 @@ static FactorDecomposition> factorPrimitiveIn biFactorsMain.factors.toArray(base.createArray(biFactorsMain.size())), null); } - FactorDecomposition> factorization - = FactorDecomposition.of(Arrays.asList(biFactorsArrayMainZ)) + PolynomialFactorDecomposition> factorization + = PolynomialFactorDecomposition.of(Arrays.asList(biFactorsArrayMainZ)) .primitive(); if (factorization.signum() != poly.signumOfLC()) - factorization = factorization.addConstantFactor(poly.createOne().negate()); + factorization = factorization.addUnit(poly.createOne().negate()); MultivariatePolynomial - lcNumeric = factorization.factors.stream().reduce(factorization.constantFactor.clone(), (a, b) -> a.lcAsPoly().multiply(b.lcAsPoly())), - ccNumeric = factorization.factors.stream().reduce(factorization.constantFactor.clone(), (a, b) -> a.ccAsPoly().multiply(b.ccAsPoly())); - if (!lcNumeric.equals(poly.lcAsPoly()) || !ccNumeric.equals(poly.ccAsPoly()) || !factorization.toPolynomial().equals(poly)) { + lcNumeric = factorization.factors.stream().reduce(factorization.unit.clone(), (a, b) -> a.lcAsPoly().multiply(b.lcAsPoly())), + ccNumeric = factorization.factors.stream().reduce(factorization.unit.clone(), (a, b) -> a.ccAsPoly().multiply(b.ccAsPoly())); + if (!lcNumeric.equals(poly.lcAsPoly()) || !ccNumeric.equals(poly.ccAsPoly()) || !factorization.multiply().equals(poly)) { // bad bivariate factorization => recombination required // instead of recombination we try again with another evaluation // searching for good enough bivariate factorization diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateGCD.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateGCD.java index 12f59a4..ff13d2c 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateGCD.java +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateGCD.java @@ -7,7 +7,7 @@ import cc.redberry.rings.Ring; import cc.redberry.rings.bigint.BigInteger; import cc.redberry.rings.bigint.BigIntegerUtil; -import cc.redberry.rings.bigint.ChineseRemainders; +import cc.redberry.rings.ChineseRemainders; import cc.redberry.rings.linear.LinearSolver; import cc.redberry.rings.poly.*; import cc.redberry.rings.poly.Util.Tuple2; diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateInterpolation.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateInterpolation.java index 451b793..12aece3 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateInterpolation.java +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateInterpolation.java @@ -3,7 +3,7 @@ import cc.redberry.rings.IntegersZp64; import cc.redberry.rings.Ring; -import cc.redberry.rings.poly.PolynomialRing; +import cc.redberry.rings.poly.IPolynomialRing; import gnu.trove.list.array.TLongArrayList; import java.util.ArrayList; @@ -116,7 +116,7 @@ public Interpolation(int variable, MultivariatePolynomial factory) { * @param variable interpolating variable * @param factory factory polynomial */ - public Interpolation(int variable, PolynomialRing> factory) { + public Interpolation(int variable, IPolynomialRing> factory) { this(variable, factory.factory()); } @@ -257,7 +257,7 @@ public InterpolationZp64(int variable, MultivariatePolynomialZp64 factory) { * @param variable interpolating variable * @param factory factory polynomial */ - public InterpolationZp64(int variable, PolynomialRing factory) { + public InterpolationZp64(int variable, IPolynomialRing factory) { this(variable, factory.factory()); } diff --git a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorization.java index 61dc6bd..623ec47 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorization.java @@ -2,7 +2,7 @@ import cc.redberry.rings.Ring; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.IPolynomial; import cc.redberry.rings.poly.MachineArithmetic; import cc.redberry.rings.poly.univar.IUnivariatePolynomial; @@ -27,10 +27,10 @@ private MultivariateSquareFreeFactorization() {} * @return square-free decomposition */ public static , Poly extends AMultivariatePolynomial> - FactorDecomposition SquareFreeFactorization(Poly poly) { + PolynomialFactorDecomposition SquareFreeFactorization(Poly poly) { if (poly instanceof MultivariatePolynomial && ((MultivariatePolynomial) poly).ring.getZero() instanceof IPolynomial) { - FactorDecomposition factors = MultivariateFactorization.tryNested(poly, + PolynomialFactorDecomposition factors = MultivariateFactorization.tryNested(poly, MultivariateSquareFreeFactorization::SquareFreeFactorization); if (factors != null) return factors; @@ -64,9 +64,9 @@ Poly SquareFreePart(Poly poly) { } private static , Poly extends AMultivariatePolynomial> - void addMonomial(FactorDecomposition decomposition, Poly poly) { + void addMonomial(PolynomialFactorDecomposition decomposition, Poly poly) { assert poly.isMonomial(); - decomposition.addConstantFactor(poly.lcAsPoly()); + decomposition.addUnit(poly.lcAsPoly()); poly = poly.monic(); Term term = poly.lt(); @@ -79,7 +79,7 @@ void addMonomial(FactorDecomposition decomposition, Poly poly) { @SuppressWarnings("unchecked") private static , Poly extends AMultivariatePolynomial> - FactorDecomposition factorUnivariate(Poly poly) { + PolynomialFactorDecomposition factorUnivariate(Poly poly) { int var = poly.univariateVariable(); return UnivariateSquareFreeFactorization .SquareFreeFactorization(poly.asUnivariate()) @@ -107,7 +107,7 @@ Poly[] reduceContent(Poly poly) { * @return square-free decomposition */ public static , Poly extends AMultivariatePolynomial> - FactorDecomposition SquareFreeFactorizationYunZeroCharacteristics(Poly poly) { + PolynomialFactorDecomposition SquareFreeFactorizationYunZeroCharacteristics(Poly poly) { if (!poly.coefficientRingCharacteristic().isZero()) throw new IllegalArgumentException("Characteristics 0 expected"); @@ -116,16 +116,14 @@ FactorDecomposition SquareFreeFactorizationYunZeroCharacteristics(Poly pol poly = poly.clone(); Poly[] content = reduceContent(poly); - FactorDecomposition decomposition - = FactorDecomposition - .constantFactor(content[0]); + PolynomialFactorDecomposition decomposition = PolynomialFactorDecomposition.unit(content[0]); addMonomial(decomposition, content[1]); SquareFreeFactorizationYun0(poly, decomposition); return decomposition; } private static , Poly extends AMultivariatePolynomial> - void SquareFreeFactorizationYun0(Poly poly, FactorDecomposition factorization) { + void SquareFreeFactorizationYun0(Poly poly, PolynomialFactorDecomposition factorization) { Poly[] derivative = poly.derivative(); Poly gcd = MultivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) { @@ -162,7 +160,7 @@ void SquareFreeFactorizationYun0(Poly poly, FactorDecomposition factorizat * @return square-free decomposition */ public static , Poly extends AMultivariatePolynomial> - FactorDecomposition SquareFreeFactorizationMusserZeroCharacteristics(Poly poly) { + PolynomialFactorDecomposition SquareFreeFactorizationMusserZeroCharacteristics(Poly poly) { if (!poly.coefficientRingCharacteristic().isZero()) throw new IllegalArgumentException("Characteristics 0 expected"); @@ -171,16 +169,14 @@ FactorDecomposition SquareFreeFactorizationMusserZeroCharacteristics(Poly poly = poly.clone(); Poly[] content = reduceContent(poly); - FactorDecomposition decomposition - = FactorDecomposition - .constantFactor(content[0]); + PolynomialFactorDecomposition decomposition = PolynomialFactorDecomposition.unit(content[0]); addMonomial(decomposition, content[1]); SquareFreeFactorizationMusserZeroCharacteristics0(poly, decomposition); return decomposition; } private static , Poly extends AMultivariatePolynomial> - void SquareFreeFactorizationMusserZeroCharacteristics0(Poly poly, FactorDecomposition factorization) { + void SquareFreeFactorizationMusserZeroCharacteristics0(Poly poly, PolynomialFactorDecomposition factorization) { Poly[] derivative = poly.derivative(); Poly gcd = MultivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) { @@ -212,7 +208,7 @@ void SquareFreeFactorizationMusserZeroCharacteristics0(Poly poly, FactorDecompos * @return square-free decomposition */ public static , Poly extends AMultivariatePolynomial> - FactorDecomposition SquareFreeFactorizationMusser(Poly poly) { + PolynomialFactorDecomposition SquareFreeFactorizationMusser(Poly poly) { if (poly.coefficientRingCharacteristic().isZero()) throw new IllegalArgumentException("Positive characteristic expected"); @@ -225,32 +221,30 @@ FactorDecomposition SquareFreeFactorizationMusser(Poly poly) { poly = poly.clone(); Poly[] content = reduceContent(poly); Poly lc = poly.lcAsPoly(); - FactorDecomposition fct = SquareFreeFactorizationMusser0(poly); + PolynomialFactorDecomposition fct = SquareFreeFactorizationMusser0(poly); addMonomial(fct, content[1]); - return fct - .addFactor(content[0], 1) - .addFactor(lc, 1); + return fct.addFactor(content[0], 1).addFactor(lc, 1); } /** {@code poly} will be destroyed */ @SuppressWarnings("ConstantConditions") private static , Poly extends AMultivariatePolynomial> - FactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { + PolynomialFactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { poly.monic(); if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.unit(poly); if (poly.degree() <= 1) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); Poly[] derivative = poly.derivative(); if (!Arrays.stream(derivative).allMatch(IPolynomial::isZero)) { Poly gcd = MultivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); Poly quot = divideExact(poly, gcd); // can safely destroy poly (not used further) - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createOne()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(poly.createOne()); int i = 0; //if (!quot.isConstant()) while (true) { @@ -267,7 +261,7 @@ FactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { } if (!gcd.isConstant()) { gcd = pRoot(gcd); - FactorDecomposition gcdFactorization = SquareFreeFactorizationMusser0(gcd); + PolynomialFactorDecomposition gcdFactorization = SquareFreeFactorizationMusser0(gcd); gcdFactorization.raiseExponents(poly.coefficientRingCharacteristic().intValueExact()); result.addAll(gcdFactorization); return result; @@ -275,9 +269,9 @@ FactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { return result; } else { Poly pRoot = pRoot(poly); - FactorDecomposition fd = SquareFreeFactorizationMusser0(pRoot); + PolynomialFactorDecomposition fd = SquareFreeFactorizationMusser0(pRoot); fd.raiseExponents(poly.coefficientRingCharacteristic().intValueExact()); - return fd.setConstantFactor(poly.createOne()); + return fd.setUnit(poly.createOne()); } } diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/AUnivariatePolynomial64.java b/rings/src/main/java/cc/redberry/rings/poly/univar/AUnivariatePolynomial64.java index a2848ac..fdc463e 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/AUnivariatePolynomial64.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/AUnivariatePolynomial64.java @@ -296,11 +296,6 @@ public final lPoly setAndDestroy(lPoly oth) { return self; } - @Override - public final lPoly setCoefficientRingFrom(lPoly poly) { - return clone(); - } - @Override public final lPoly shiftLeft(int offset) { if (offset == 0) diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/DiophantineEquations.java b/rings/src/main/java/cc/redberry/rings/poly/univar/DiophantineEquations.java new file mode 100644 index 0000000..7cb262b --- /dev/null +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/DiophantineEquations.java @@ -0,0 +1,62 @@ +package cc.redberry.rings.poly.univar; + +/** + * @author Stanislav Poslavsky + * @since 2.1 + */ +public final class DiophantineEquations { + private DiophantineEquations() {} + + /** runs xgcd for coprime polynomials ensuring that gcd is 1 (not another constant) */ + public static > + Poly[] monicExtendedEuclid(Poly a, Poly b) { + Poly[] xgcd = UnivariateGCD.PolynomialExtendedGCD(a, b); + if (xgcd[0].isOne()) + return xgcd; + + //normalize: x * a + y * b = 1 + xgcd[2].divideByLC(xgcd[0]); + xgcd[1].divideByLC(xgcd[0]); + xgcd[0].monic(); + + return xgcd; + } + + /** + * Solves a1 * x1 + a2 * x2 + ... = rhs for given univariate and rhs and unknown x_i + */ + public static final class DiophantineSolver> { + /** the given factors */ + final Poly[] factors; + final Poly[] solution; + final Poly gcd; + + @SuppressWarnings("unchecked") + public DiophantineSolver(Poly[] factors) { + this.factors = factors; + this.solution = factors[0].createArray(factors.length); + + Poly prev = factors[0]; + solution[0] = factors[0].createOne(); + + for (int i = 1; i < factors.length; i++) { + Poly[] xgcd = monicExtendedEuclid(prev, factors[i]); + for (int j = 0; j < i; j++) + solution[j].multiply(xgcd[1]); + solution[i] = xgcd[2]; + prev = xgcd[0]; + } + gcd = prev; + } + + public Poly[] solve(Poly rhs) { + rhs = UnivariateDivision.divideOrNull(rhs, gcd, true); + if (rhs == null) + throw new IllegalArgumentException("Not solvable."); + Poly[] solution = rhs.createArray(this.solution.length); + for (int i = 0; i < solution.length; i++) + solution[i] = this.solution[i].clone().multiply(rhs); + return solution; + } + } +} diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorization.java index 7448530..2148730 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorization.java @@ -1,6 +1,6 @@ package cc.redberry.rings.poly.univar; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.Util; import java.util.ArrayList; @@ -27,23 +27,23 @@ private DistinctDegreeFactorization() {} * @param poly the polynomial * @return distinct-degree decomposition of {@code poly} */ - public static FactorDecomposition DistinctDegreeFactorizationPlain(UnivariatePolynomialZp64 poly) { + public static PolynomialFactorDecomposition DistinctDegreeFactorizationPlain(UnivariatePolynomialZp64 poly) { if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.unit(poly); long factor = poly.lc(); UnivariatePolynomialZp64 base = poly.clone().monic(); UnivariatePolynomialZp64 polyModulus = base.clone(); if (base.degree <= 1) - return FactorDecomposition.singleFactor(base.createConstant(factor), base); + return PolynomialFactorDecomposition.of(base.createConstant(factor), base); if (base.isMonomial()) - return FactorDecomposition.singleFactor(base.createConstant(factor), base); + return PolynomialFactorDecomposition.of(base.createConstant(factor), base); UnivariateDivision.InverseModMonomial invMod = UnivariateDivision.fastDivisionPreConditioning(polyModulus); UnivariatePolynomialZp64 exponent = poly.createMonomial(1); - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createOne()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(poly.createOne()); int i = 0; while (!base.isConstant()) { ++i; @@ -64,7 +64,7 @@ public static FactorDecomposition DistinctDegreeFactor break; } } - return result.setConstantFactor(poly.createConstant(factor)); + return result.setUnit(poly.createConstant(factor)); } /** @@ -76,23 +76,23 @@ public static FactorDecomposition DistinctDegreeFactor * @param poly the polynomial * @return distinct-degree decomposition of {@code poly} */ - public static FactorDecomposition DistinctDegreeFactorizationPrecomputedExponents(UnivariatePolynomialZp64 poly) { + public static PolynomialFactorDecomposition DistinctDegreeFactorizationPrecomputedExponents(UnivariatePolynomialZp64 poly) { if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.unit(poly); long factor = poly.lc(); UnivariatePolynomialZp64 base = poly.clone().monic(); UnivariatePolynomialZp64 polyModulus = base.clone(); if (base.degree <= 1) - return FactorDecomposition.singleFactor(base.createConstant(factor), base); + return PolynomialFactorDecomposition.of(base.createConstant(factor), base); if (base.isMonomial()) - return FactorDecomposition.singleFactor(base.createConstant(factor), base); + return PolynomialFactorDecomposition.of(base.createConstant(factor), base); UnivariateDivision.InverseModMonomial invMod = UnivariateDivision.fastDivisionPreConditioning(polyModulus); UnivariatePolynomialZp64 exponent = poly.createMonomial(1); - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createOne()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(poly.createOne()); ArrayList xPowers = xPowers(polyModulus, invMod); int i = 0; @@ -114,7 +114,7 @@ public static FactorDecomposition DistinctDegreeFactor break; } } - return result.setConstantFactor(poly.createConstant(factor)); + return result.setUnit(poly.createConstant(factor)); } /** Shoup's parameter */ @@ -123,7 +123,7 @@ public static FactorDecomposition DistinctDegreeFactor /** Shoup's main gcd loop */ private static > void DistinctDegreeFactorizationShoup(T poly, BabyGiantSteps steps, - FactorDecomposition result) { + PolynomialFactorDecomposition result) { //generate each I_j T current = poly.clone(); for (int j = 1; j <= steps.m; ++j) { @@ -160,11 +160,11 @@ private static > void DistinctDegreeFactoriza * @param poly the polynomial * @return distinct-degree decomposition of {@code poly} */ - public static > FactorDecomposition DistinctDegreeFactorizationShoup(Poly poly) { + public static > PolynomialFactorDecomposition DistinctDegreeFactorizationShoup(Poly poly) { Util.ensureOverFiniteField(poly); Poly factor = poly.lcAsPoly(); poly = poly.clone().monic(); - FactorDecomposition result = FactorDecomposition.constantFactor(factor); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(factor); DistinctDegreeFactorizationShoup(poly, new BabyGiantSteps<>(poly), result); return result; } @@ -233,7 +233,7 @@ Poly giantStep(int j) { * @param poly the polynomial * @return distinct-degree decomposition of {@code poly} */ - public static FactorDecomposition DistinctDegreeFactorization(UnivariatePolynomialZp64 poly) { + public static PolynomialFactorDecomposition DistinctDegreeFactorization(UnivariatePolynomialZp64 poly) { if (poly.degree < DEGREE_SWITCH_TO_SHOUP) return DistinctDegreeFactorizationPrecomputedExponents(poly); else @@ -249,10 +249,10 @@ public static FactorDecomposition DistinctDegreeFactor * @return distinct-degree decomposition of {@code poly} */ @SuppressWarnings("unchecked") - public static > FactorDecomposition DistinctDegreeFactorization(Poly poly) { + public static > PolynomialFactorDecomposition DistinctDegreeFactorization(Poly poly) { Util.ensureOverFiniteField(poly); if (poly instanceof UnivariatePolynomialZp64) - return (FactorDecomposition) DistinctDegreeFactorization((UnivariatePolynomialZp64) poly); + return (PolynomialFactorDecomposition) DistinctDegreeFactorization((UnivariatePolynomialZp64) poly); else return DistinctDegreeFactorizationShoup(poly); } @@ -264,19 +264,19 @@ public static > FactorDecomposition DistinctDegreeFactorizationComplete(UnivariatePolynomialZp64 poly) { - FactorDecomposition squareFree = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); - long overallFactor = squareFree.constantFactor.lc(); + static PolynomialFactorDecomposition DistinctDegreeFactorizationComplete(UnivariatePolynomialZp64 poly) { + PolynomialFactorDecomposition squareFree = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); + long overallFactor = squareFree.unit.lc(); - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createOne()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(poly.createOne()); for (int i = squareFree.size() - 1; i >= 0; --i) { - FactorDecomposition dd = DistinctDegreeFactorization(squareFree.get(i)); + PolynomialFactorDecomposition dd = DistinctDegreeFactorization(squareFree.get(i)); int nFactors = dd.size(); for (int j = nFactors - 1; j >= 0; --j) result.addFactor(dd.get(j), squareFree.getExponent(i)); - overallFactor = poly.multiply(overallFactor, dd.constantFactor.lc()); + overallFactor = poly.multiply(overallFactor, dd.unit.lc()); } - return result.setConstantFactor(poly.createConstant(overallFactor)); + return result.setUnit(poly.createConstant(overallFactor)); } } diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/EqualDegreeFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/univar/EqualDegreeFactorization.java index 0641f5d..8c6652d 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/EqualDegreeFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/EqualDegreeFactorization.java @@ -1,7 +1,7 @@ package cc.redberry.rings.poly.univar; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.MachineArithmetic; import cc.redberry.rings.poly.Util; import org.apache.commons.math3.random.RandomGenerator; @@ -35,9 +35,9 @@ static > T randomMonicPoly(T factory) { * @param d distinct degree * @return irreducible factor of {@code poly} */ - public static > FactorDecomposition CantorZassenhaus(Poly input, int d) { + public static > PolynomialFactorDecomposition CantorZassenhaus(Poly input, int d) { Util.ensureOverFiniteField(input); - FactorDecomposition result = FactorDecomposition.constantFactor(input.lcAsPoly()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.unit(input.lcAsPoly()); if (!input.coefficientRingCardinality().testBit(0)) //even characteristic => GF2p CantorZassenhaus(input, d, result, input.coefficientRingPerfectPowerExponent().intValueExact()); @@ -53,7 +53,7 @@ public static > FactorDecomposition> void CantorZassenhaus(T input, int d, FactorDecomposition result, int pPower) { + private static > void CantorZassenhaus(T input, int d, PolynomialFactorDecomposition result, int pPower) { assert input.degree() % d == 0; int nFactors = input.degree() / d; if (input.degree() == 1 || nFactors == 1) { diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/HenselLifting.java b/rings/src/main/java/cc/redberry/rings/poly/univar/HenselLifting.java index e6d26c5..ca305d1 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/HenselLifting.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/HenselLifting.java @@ -22,6 +22,8 @@ * very cheap, but the convergence is worse. The actual lifting used in factorization switches between linear and * quadratic lift in order to obtain the best trade-off. * + * NOTE: Quadratic lifts may fail in Z/2 + * * @since 1.0 */ public final class HenselLifting { diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/IrreduciblePolynomials.java b/rings/src/main/java/cc/redberry/rings/poly/univar/IrreduciblePolynomials.java index f93439b..808cf17 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/IrreduciblePolynomials.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/IrreduciblePolynomials.java @@ -100,19 +100,19 @@ public static UnivariatePolynomialZp64 randomIrreduciblePolynomial(long modulus, } /** - * Generated random irreducible polynomial over finite field of degree {@code degree} + * Generated random irreducible polynomial over specified ring of degree {@code degree} * - * @param ring finite field ring + * @param ring coefficient ring * @param degree the degree * @param rnd random source * @return irreducible polynomial */ public static UnivariatePolynomial randomIrreduciblePolynomial(Ring ring, int degree, RandomGenerator rnd) { - if (!ring.isFiniteField()) - throw new IllegalArgumentException("Not a finite ring."); UnivariatePolynomial poly; do { - poly = RandomUnivariatePolynomials.randomMonicPoly(degree, ring, rnd); + poly = RandomUnivariatePolynomials.randomPoly(degree, ring, rnd); + if (ring.isField()) + poly.monic(); } while (!irreducibleQ(poly)); assert poly.degree == degree; return poly; @@ -132,16 +132,14 @@ public static UnivariatePolynomial randomIrreduciblePolynomialOverZ( } /** - * Generated random irreducible Zp polynomial of degree {@code degree} + * Generated random irreducible polynomial of degree {@code degree} * - * @param factory tyep marker + * @param factory type marker * @param degree the degree * @param rnd random source * @return irreducible polynomial */ public static > Poly randomIrreduciblePolynomial(Poly factory, int degree, RandomGenerator rnd) { - if (!factory.isOverFiniteField()) - throw new IllegalArgumentException("Not a finite ring."); Poly poly; do { poly = RandomUnivariatePolynomials.randomPoly(factory, degree, rnd); diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateFactorization.java index c41944a..27850a2 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateFactorization.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; import static cc.redberry.rings.poly.univar.Conversions64bit.asOverZp64; import static cc.redberry.rings.poly.univar.Conversions64bit.canConvertToZp64; @@ -38,7 +37,7 @@ private UnivariateFactorization() {} * @return factor decomposition */ @SuppressWarnings("unchecked") - public static > FactorDecomposition Factor(Poly poly) { + public static > PolynomialFactorDecomposition Factor(Poly poly) { if (poly.isOverFiniteField()) return FactorInGF(poly); else if (poly.isOverZ()) @@ -46,9 +45,9 @@ else if (poly.isOverZ()) else if (Util.isOverRationals(poly)) return FactorInQ((UnivariatePolynomial) poly); else if (isOverMultivariate(poly)) - return (FactorDecomposition) FactorOverMultivariate((UnivariatePolynomial) poly, MultivariateFactorization::Factor); + return (PolynomialFactorDecomposition) FactorOverMultivariate((UnivariatePolynomial) poly, MultivariateFactorization::Factor); else if (isOverUnivariate(poly)) - return (FactorDecomposition) FactorOverUnivariate((UnivariatePolynomial) poly, MultivariateFactorization::Factor); + return (PolynomialFactorDecomposition) FactorOverUnivariate((UnivariatePolynomial) poly, MultivariateFactorization::Factor); else throw new RuntimeException("ring is not supported: " + poly.coefficientRingToString()); } @@ -65,17 +64,17 @@ static > boolean isOverUnivariate(T poly) { static , Poly extends AMultivariatePolynomial> - FactorDecomposition> + PolynomialFactorDecomposition> FactorOverMultivariate(UnivariatePolynomial poly, - Function> factorFunction) { + Function> factorFunction) { return factorFunction.apply(AMultivariatePolynomial.asMultivariate(poly, 0, true)) .map(p -> p.asUnivariateEliminate(0)); } static > - FactorDecomposition> + PolynomialFactorDecomposition> FactorOverUnivariate(UnivariatePolynomial poly, - Function, FactorDecomposition>> factorFunction) { + Function, PolynomialFactorDecomposition>> factorFunction) { return factorFunction.apply(AMultivariatePolynomial.asMultivariate(poly, 1, 0, MonomialOrder.LEX)) .map(MultivariatePolynomial::asUnivariate); } @@ -86,13 +85,13 @@ static > boolean isOverUnivariate(T poly) { * @param poly the polynomial over finite field * @return irreducible factor decomposition */ - public static FactorDecomposition>> FactorInQ(UnivariatePolynomial> poly) { + public static PolynomialFactorDecomposition>> FactorInQ(UnivariatePolynomial> poly) { Tuple2, E> cmd = Util.toCommonDenominator(poly); UnivariatePolynomial integral = cmd._1; E denominator = cmd._2; return Factor(integral) .map(p -> Util.asOverRationals(poly.ring, p)) - .addConstantFactor(poly.createConstant(new Rational<>(integral.ring, integral.ring.getOne(), denominator))); + .addUnit(poly.createConstant(new Rational<>(integral.ring, integral.ring.getOne(), denominator))); } /** x^n * poly */ @@ -115,9 +114,9 @@ private static > FactorMonomial f } /** early check for trivial cases */ - private static > FactorDecomposition earlyFactorizationChecks(Poly poly) { + private static > PolynomialFactorDecomposition earlyFactorizationChecks(Poly poly) { if (poly.degree() <= 1 || poly.isMonomial()) - return FactorDecomposition.singleFactor(poly.lcAsPoly(), poly.isMonic() ? poly : poly.clone().monic()); + return PolynomialFactorDecomposition.of(poly.lcAsPoly(), poly.isMonic() ? poly : poly.clone().monic()); return null; } @@ -133,17 +132,17 @@ private static > FactorDecomposition> FactorDecomposition FactorInGF(Poly poly) { + public static > PolynomialFactorDecomposition FactorInGF(Poly poly) { Util.ensureOverFiniteField(poly); if (canConvertToZp64(poly)) return FactorInGF(asOverZp64(poly)).map(Conversions64bit::convert); - FactorDecomposition result = earlyFactorizationChecks(poly); + PolynomialFactorDecomposition result = earlyFactorizationChecks(poly); if (result != null) return result; - result = FactorDecomposition.empty(poly); + result = PolynomialFactorDecomposition.empty(poly); FactorInGF(poly, result); - return result.setConstantFactor(poly.lcAsPoly()); + return result.setUnit(poly.lcAsPoly()); } /** @@ -154,20 +153,20 @@ public static > FactorDecomposition> FactorDecomposition FactorSquareFreeInGF(T poly) { + public static > PolynomialFactorDecomposition FactorSquareFreeInGF(T poly) { Util.ensureOverFiniteField(poly); if (canConvertToZp64(poly)) return FactorInGF(asOverZp64(poly)).map(Conversions64bit::convert); - FactorDecomposition result = FactorDecomposition.empty(poly); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.empty(poly); FactorSquareFreeInGF(poly, 1, result); return result; } private static > - void FactorSquareFreeInGF(T poly, int exponent, FactorDecomposition result) { + void FactorSquareFreeInGF(T poly, int exponent, PolynomialFactorDecomposition result) { //do distinct-degree factorization - FactorDecomposition ddf = DistinctDegreeFactorization(poly); + PolynomialFactorDecomposition ddf = DistinctDegreeFactorization(poly); //assertDistinctDegreeFactorization(sqfFactor, ddf); for (int j = 0; j < ddf.size(); ++j) { //for each distinct-degree factor @@ -175,20 +174,20 @@ void FactorSquareFreeInGF(T poly, int exponent, FactorDecomposition result) { int ddfExponent = ddf.getExponent(j); //do equal-degree factorization - FactorDecomposition edf = CantorZassenhaus(ddfFactor, ddfExponent); + PolynomialFactorDecomposition edf = CantorZassenhaus(ddfFactor, ddfExponent); for (T irreducibleFactor : edf.factors) //put final irreducible factor into the result result.addFactor(irreducibleFactor.monic(), exponent); } } - private static > void FactorInGF(T poly, FactorDecomposition result) { + private static > void FactorInGF(T poly, PolynomialFactorDecomposition result) { FactorMonomial base = factorOutMonomial(poly); if (!base.monomial.isConstant()) result.addFactor(poly.createMonomial(1), base.monomial.degree()); //do square-free factorization - FactorDecomposition sqf = SquareFreeFactorization(base.theRest); + PolynomialFactorDecomposition sqf = SquareFreeFactorization(base.theRest); //assert sqf.toPolynomial().equals(base.theRest) : base.toString(); for (int i = 0; i < sqf.size(); ++i) { //for each square-free factor @@ -199,10 +198,10 @@ private static > void FactorInGF(T poly, Fact } private static > - void assertDistinctDegreeFactorization(T poly, FactorDecomposition factorization) { + void assertDistinctDegreeFactorization(T poly, PolynomialFactorDecomposition factorization) { for (int i = 0; i < factorization.factors.size(); i++) assert 0 == factorization.factors.get(i).degree() % factorization.exponents.get(i) : "Factor's degree is not divisible by d.d.f. exponent"; - assert poly.equals(factorization.toPolynomialIgnoringExponents()); + assert poly.equals(factorization.multiplyIgnoreExponents()); } /* =========================================== Factorization in Z[x] =========================================== */ @@ -244,17 +243,17 @@ private static int[] select(int[] data, int[] positions) { } /** reconstruct true factors by enumerating all combinations */ - static FactorDecomposition reconstructFactorsZ( + static PolynomialFactorDecomposition reconstructFactorsZ( UnivariatePolynomialZ64 poly, - FactorDecomposition modularFactors) { + PolynomialFactorDecomposition modularFactors) { if (modularFactors.isTrivial()) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); UnivariatePolynomialZp64 factory = modularFactors.get(0); int[] modIndexes = naturalSequenceRef(modularFactors.size()); - FactorDecomposition trueFactors = FactorDecomposition.empty(poly); + PolynomialFactorDecomposition trueFactors = PolynomialFactorDecomposition.empty(poly); UnivariatePolynomialZ64 fRest = poly; int s = 1; @@ -298,17 +297,17 @@ static FactorDecomposition reconstructFactorsZ( /** reconstruct true factors by enumerating all combinations */ - static FactorDecomposition> reconstructFactorsZ( + static PolynomialFactorDecomposition> reconstructFactorsZ( UnivariatePolynomial poly, - FactorDecomposition> modularFactors) { + PolynomialFactorDecomposition> modularFactors) { if (modularFactors.isTrivial()) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); UnivariatePolynomial factory = modularFactors.get(0); int[] modIndexes = naturalSequenceRef(modularFactors.size()); - FactorDecomposition> trueFactors = FactorDecomposition.empty(poly); + PolynomialFactorDecomposition> trueFactors = PolynomialFactorDecomposition.empty(poly); UnivariatePolynomial fRest = poly; int s = 1; @@ -379,13 +378,13 @@ private static int next32BitPrime(int val) { * * @param poly Z[x] primitive square-free polynomial */ - static FactorDecomposition> FactorSquareFreeInZ0(UnivariatePolynomial poly) { + static PolynomialFactorDecomposition> FactorSquareFreeInZ0(UnivariatePolynomial poly) { assert poly.content().isOne(); assert poly.lc().signum() > 0; BigInteger bound2 = BigInteger.TWO.multiply(UnivariatePolynomial.mignotteBound(poly)).multiply(poly.lc().abs()); if (bound2.compareTo(MachineArithmetic.b_MAX_SUPPORTED_MODULUS) < 0) { - FactorDecomposition tryLong = FactorSquareFreeInZ0(UnivariatePolynomial.asOverZ64(poly)); + PolynomialFactorDecomposition tryLong = FactorSquareFreeInZ0(UnivariatePolynomial.asOverZ64(poly)); if (tryLong != null) return convertFactorizationToBigIntegers(tryLong); } @@ -393,7 +392,7 @@ static FactorDecomposition> FactorSquareFreeInZ // choose prime at random long modulus = -1; UnivariatePolynomialZp64 moduloImage; - FactorDecomposition lModularFactors = null; + PolynomialFactorDecomposition lModularFactors = null; for (int attempt = 0; attempt < N_MODULAR_FACTORIZATION_TRIALS; attempt++) { long tmpModulus; @@ -404,9 +403,9 @@ static FactorDecomposition> FactorSquareFreeInZ while (moduloImage.cc() == 0 || moduloImage.degree() != poly.degree() || !UnivariateSquareFreeFactorization.isSquareFree(moduloImage)); // do modular factorization - FactorDecomposition tmpFactors = FactorInGF(moduloImage.monic()); + PolynomialFactorDecomposition tmpFactors = FactorInGF(moduloImage.monic()); if (tmpFactors.size() == 1) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); if (lModularFactors == null || lModularFactors.size() > tmpFactors.size()) { lModularFactors = tmpFactors; @@ -419,16 +418,13 @@ static FactorDecomposition> FactorSquareFreeInZ List> modularFactors = HenselLifting.liftFactorization(BigInteger.valueOf(modulus), bound2, poly, lModularFactors.factors); assert modularFactors.get(0).ring.cardinality().compareTo(bound2) >= 0; - return reconstructFactorsZ(poly, FactorDecomposition.of(modularFactors)); + return reconstructFactorsZ(poly, PolynomialFactorDecomposition.of(modularFactors)); } /** machine integers -> BigIntegers */ - static > FactorDecomposition> - convertFactorizationToBigIntegers(FactorDecomposition decomposition) { - return FactorDecomposition.of( - decomposition.constantFactor.toBigPoly(), - decomposition.factors.stream().map(AUnivariatePolynomial64::toBigPoly).collect(Collectors.toList()), - decomposition.exponents); + static > PolynomialFactorDecomposition> + convertFactorizationToBigIntegers(PolynomialFactorDecomposition decomposition) { + return decomposition.map(AUnivariatePolynomial64::toBigPoly); } /** determines the lower bound for the possible modulus for Zp trials */ @@ -462,7 +458,7 @@ private static int chooseModulusLowerBound(double bound2) { * * @param poly Z[x] square-free polynomial */ - static FactorDecomposition FactorSquareFreeInZ0(UnivariatePolynomialZ64 poly) { + static PolynomialFactorDecomposition FactorSquareFreeInZ0(UnivariatePolynomialZ64 poly) { assert poly.content() == 1; assert poly.lc() > 0; @@ -490,35 +486,37 @@ static FactorDecomposition FactorSquareFreeInZ0(Univari } // do modular factorization - FactorDecomposition modularFactors = FactorInGF(moduloImage.monic()); + PolynomialFactorDecomposition modularFactors = FactorInGF(moduloImage.monic()); // actual lift if (henselIterations > 0) - modularFactors = FactorDecomposition.of(modularFactors.constantFactor, HenselLifting.liftFactorization(modulus, liftedModulus, henselIterations, poly, modularFactors.factors, true)); + modularFactors = PolynomialFactorDecomposition.of(HenselLifting.liftFactorization( + modulus, liftedModulus, henselIterations, poly, modularFactors.factors, true)) + .addUnit(modularFactors.unit.setModulus(liftedModulus)); //reconstruct true factors return reconstructFactorsZ(poly, modularFactors); } - public static > FactorDecomposition FactorSquareFreeInZ(PolyZ poly) { + public static > PolynomialFactorDecomposition FactorSquareFreeInZ(PolyZ poly) { ensureIntegersDomain(poly); if (poly.degree() <= 1 || poly.isMonomial()) - return FactorDecomposition.singleFactor( + return PolynomialFactorDecomposition.of( poly.isMonic() ? poly.createOne() : poly.contentAsPoly(), poly.isMonic() ? poly : poly.clone().primitivePart()); PolyZ content = poly.contentAsPoly(); if (poly.signumOfLC() < 0) content = content.negate(); - return FactorSquareFreeInZ0(poly.clone().divideByLC(content)).setConstantFactor(content); + return FactorSquareFreeInZ0(poly.clone().divideByLC(content)).setUnit(content); } @SuppressWarnings("unchecked") - private static > FactorDecomposition FactorSquareFreeInZ0(PolyZ poly) { + private static > PolynomialFactorDecomposition FactorSquareFreeInZ0(PolyZ poly) { if (poly instanceof UnivariatePolynomialZ64) - return (FactorDecomposition) FactorSquareFreeInZ0((UnivariatePolynomialZ64) poly); + return (PolynomialFactorDecomposition) FactorSquareFreeInZ0((UnivariatePolynomialZ64) poly); else - return (FactorDecomposition) FactorSquareFreeInZ0((UnivariatePolynomial) poly); + return (PolynomialFactorDecomposition) FactorSquareFreeInZ0((UnivariatePolynomial) poly); } private static void ensureIntegersDomain(IUnivariatePolynomial poly) { @@ -536,35 +534,35 @@ private static void ensureIntegersDomain(IUnivariatePolynomial poly) { * @see #FactorInGF(IUnivariatePolynomial) * @see HenselLifting */ - public static > FactorDecomposition FactorInZ(Poly poly) { + public static > PolynomialFactorDecomposition FactorInZ(Poly poly) { ensureIntegersDomain(poly); if (poly.degree() <= 1 || poly.isMonomial()) - return FactorDecomposition.singleFactor( + return PolynomialFactorDecomposition.of( poly.isMonic() ? poly.createOne() : poly.contentAsPoly(), poly.isMonic() ? poly : poly.clone().primitivePart()); - FactorDecomposition result = FactorDecomposition.empty(poly); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.empty(poly); Poly content = poly.contentAsPoly(); if (poly.signumOfLC() < 0) content = content.negate(); FactorInZ(poly.clone().divideByLC(content), result); - return result.setConstantFactor(content); + return result.setUnit(content); } - private static > void FactorInZ(T poly, FactorDecomposition result) { + private static > void FactorInZ(T poly, PolynomialFactorDecomposition result) { FactorMonomial base = factorOutMonomial(poly); if (!base.monomial.isConstant()) result.addFactor(poly.createMonomial(1), base.monomial.degree()); //do square-free factorization - FactorDecomposition sqf = SquareFreeFactorization(base.theRest); + PolynomialFactorDecomposition sqf = SquareFreeFactorization(base.theRest); for (int i = 0; i < sqf.size(); ++i) { //for each square-free factor T sqfFactor = sqf.get(i); int sqfExponent = sqf.getExponent(i); //do distinct-degree factorization - FactorDecomposition cz = FactorSquareFreeInZ0(sqfFactor); + PolynomialFactorDecomposition cz = FactorSquareFreeInZ0(sqfFactor); //do equal-degree factorization for (T irreducibleFactor : cz.factors) //put final irreducible factor into the result diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateGCD.java b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateGCD.java index dbf59c5..4883663 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateGCD.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateGCD.java @@ -7,7 +7,7 @@ import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; import cc.redberry.rings.bigint.BigIntegerUtil; -import cc.redberry.rings.bigint.ChineseRemainders; +import cc.redberry.rings.ChineseRemainders; import cc.redberry.rings.poly.MachineArithmetic; import cc.redberry.rings.poly.MultivariateRing; import cc.redberry.rings.poly.Util; @@ -24,7 +24,7 @@ import java.util.Arrays; import java.util.stream.Collectors; -import static cc.redberry.rings.bigint.ChineseRemainders.ChineseRemainders; +import static cc.redberry.rings.ChineseRemainders.ChineseRemainders; import static cc.redberry.rings.poly.univar.Conversions64bit.asOverZp64; import static cc.redberry.rings.poly.univar.Conversions64bit.canConvertToZp64; diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZ64.java b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZ64.java index 361e08d..3678b60 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZ64.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZ64.java @@ -95,6 +95,11 @@ public static UnivariatePolynomialZ64 constant(long value) { return new UnivariatePolynomialZ64(new long[]{value}, 0); } + @Override + public UnivariatePolynomialZ64 setCoefficientRingFrom(UnivariatePolynomialZ64 univariatePolynomialZ64) { + return univariatePolynomialZ64.clone(); + } + /** * Reduces this polynomial modulo {@code modulus} and returns the result. * diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZp64.java b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZp64.java index 5169a3b..40b375b 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZp64.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariatePolynomialZp64.java @@ -65,7 +65,7 @@ public static UnivariatePolynomialZp64 create(long modulus, long[] data) { * Creates poly with specified coefficients represented as signed integers reducing them modulo {@code modulus} * * @param ring the ring - * @param data coefficients + * @param data coefficients * @return the polynomial */ public static UnivariatePolynomialZp64 create(IntegersZp64 ring, long[] data) { @@ -173,6 +173,11 @@ public static UnivariatePolynomialZp64 one(IntegersZp64 ring) { return new UnivariatePolynomialZp64(ring, new long[]{1L}, 0); } + @Override + public UnivariatePolynomialZp64 setCoefficientRingFrom(UnivariatePolynomialZp64 univariatePolynomialZp64) { + return setModulus(univariatePolynomialZp64.ring); + } + /** Returns the modulus */ public long modulus() {return ring.modulus;} @@ -194,6 +199,18 @@ public UnivariatePolynomialZp64 setModulus(long newModulus) { return new UnivariatePolynomialZp64(newDomain, newData); } + /** + * Creates new Zp[x] polynomial by coping the coefficients of this and reducing them modulo new modulus. + * + * @param newDomain the new domain + * @return the copy of this reduced modulo new modulus + */ + public UnivariatePolynomialZp64 setModulus(IntegersZp64 newDomain) { + long[] newData = data.clone(); + newDomain.modulus(newData); + return new UnivariatePolynomialZp64(newDomain, newData); + } + /** * Returns Z[x] polynomial formed from the coefficients of this represented in symmetric modular form ({@code * -modulus/2 <= cfx <= modulus/2}). diff --git a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorization.java b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorization.java index 063eef4..61094a9 100644 --- a/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorization.java +++ b/rings/src/main/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorization.java @@ -2,7 +2,7 @@ import cc.redberry.rings.Ring; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.MachineArithmetic; import cc.redberry.rings.poly.multivar.MultivariateSquareFreeFactorization; @@ -37,11 +37,11 @@ public static > boolean isSquareFree(T poly) * @return square-free decomposition */ @SuppressWarnings("unchecked") - public static > FactorDecomposition SquareFreeFactorization(T poly) { + public static > PolynomialFactorDecomposition SquareFreeFactorization(T poly) { if (UnivariateFactorization.isOverMultivariate(poly)) - return (FactorDecomposition) UnivariateFactorization.FactorOverMultivariate((UnivariatePolynomial) poly, MultivariateSquareFreeFactorization::SquareFreeFactorization); + return (PolynomialFactorDecomposition) UnivariateFactorization.FactorOverMultivariate((UnivariatePolynomial) poly, MultivariateSquareFreeFactorization::SquareFreeFactorization); else if (UnivariateFactorization.isOverUnivariate(poly)) - return (FactorDecomposition) UnivariateFactorization.FactorOverUnivariate((UnivariatePolynomial) poly, MultivariateSquareFreeFactorization::SquareFreeFactorization); + return (PolynomialFactorDecomposition) UnivariateFactorization.FactorOverUnivariate((UnivariatePolynomial) poly, MultivariateSquareFreeFactorization::SquareFreeFactorization); else if (poly.coefficientRingCharacteristic().isZero()) return SquareFreeFactorizationYunZeroCharacteristics(poly); else @@ -65,13 +65,13 @@ public static > T SquareFreePart(T poly) { * @param poly the polynomial * @return square-free decomposition */ - public static > FactorDecomposition + public static > PolynomialFactorDecomposition SquareFreeFactorizationYunZeroCharacteristics(Poly poly) { if (!poly.coefficientRingCharacteristic().isZero()) throw new IllegalArgumentException("Characteristics 0 expected"); if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.of(poly); // x^2 + x^3 -> x^2 (1 + x) int exponent = 0; @@ -80,7 +80,7 @@ public static > T SquareFreePart(T poly) { return SquareFreeFactorizationYun0(poly); Poly expFree = poly.getRange(exponent, poly.degree() + 1); - FactorDecomposition fd = SquareFreeFactorizationYun0(expFree); + PolynomialFactorDecomposition fd = SquareFreeFactorizationYun0(expFree); fd.addFactor(poly.createMonomial(1), exponent); return fd; } @@ -92,9 +92,9 @@ public static > T SquareFreePart(T poly) { * @return square-free decomposition */ @SuppressWarnings("ConstantConditions") - static > FactorDecomposition SquareFreeFactorizationYun0(Poly poly) { + static > PolynomialFactorDecomposition SquareFreeFactorizationYun0(Poly poly) { if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.of(poly); Poly content = poly.contentAsPoly(); if (poly.signumOfLC() < 0) @@ -102,14 +102,14 @@ static > FactorDecomposition Squa poly = poly.clone().divideByLC(content); if (poly.degree() <= 1) - return FactorDecomposition.singleFactor(content, poly); + return PolynomialFactorDecomposition.of(content, poly); - FactorDecomposition factorization = FactorDecomposition.constantFactor(content); + PolynomialFactorDecomposition factorization = PolynomialFactorDecomposition.of(content); SquareFreeFactorizationYun0(poly, factorization); return factorization; } - private static > void SquareFreeFactorizationYun0(Poly poly, FactorDecomposition factorization) { + private static > void SquareFreeFactorizationYun0(Poly poly, PolynomialFactorDecomposition factorization) { Poly derivative = poly.derivative(), gcd = UnivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) { factorization.addFactor(poly, 1); @@ -139,13 +139,13 @@ private static > void SquareFreeFactori * @return square-free decomposition */ @SuppressWarnings("ConstantConditions") - public static > FactorDecomposition + public static > PolynomialFactorDecomposition SquareFreeFactorizationMusserZeroCharacteristics(Poly poly) { if (!poly.coefficientRingCharacteristic().isZero()) throw new IllegalArgumentException("Characteristics 0 expected"); if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.of(poly); Poly content = poly.contentAsPoly(); if (poly.signumOfLC() < 0) @@ -153,15 +153,15 @@ private static > void SquareFreeFactori poly = poly.clone().divideByLC(content); if (poly.degree() <= 1) - return FactorDecomposition.singleFactor(content, poly); + return PolynomialFactorDecomposition.of(content, poly); - FactorDecomposition factorization = FactorDecomposition.constantFactor(content); + PolynomialFactorDecomposition factorization = PolynomialFactorDecomposition.of(content); SquareFreeFactorizationMusserZeroCharacteristics0(poly, factorization); return factorization; } private static > void - SquareFreeFactorizationMusserZeroCharacteristics0(Poly poly, FactorDecomposition factorization) { + SquareFreeFactorizationMusserZeroCharacteristics0(Poly poly, PolynomialFactorDecomposition factorization) { Poly derivative = poly.derivative(), gcd = UnivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) { factorization.addFactor(poly, 1); @@ -190,7 +190,7 @@ private static > void SquareFreeFactori * @param poly the polynomial * @return square-free decomposition */ - public static > FactorDecomposition SquareFreeFactorizationMusser(Poly poly) { + public static > PolynomialFactorDecomposition SquareFreeFactorizationMusser(Poly poly) { if (canConvertToZp64(poly)) return SquareFreeFactorizationMusser(asOverZp64(poly)).map(Conversions64bit::convert); @@ -200,12 +200,12 @@ public static > FactorDecomposition factorization; + PolynomialFactorDecomposition factorization; // x^2 + x^3 -> x^2 (1 + x) int exponent = 0; while (exponent <= poly.degree() && poly.isZeroAt(exponent)) { ++exponent; } @@ -217,27 +217,27 @@ public static > FactorDecomposition> FactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { + private static > PolynomialFactorDecomposition SquareFreeFactorizationMusser0(Poly poly) { poly.monic(); if (poly.isConstant()) - return FactorDecomposition.constantFactor(poly); + return PolynomialFactorDecomposition.of(poly); if (poly.degree() <= 1) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); Poly derivative = poly.derivative(); if (!derivative.isZero()) { Poly gcd = UnivariateGCD.PolynomialGCD(poly, derivative); if (gcd.isConstant()) - return FactorDecomposition.singleFactor(poly.createOne(), poly); + return PolynomialFactorDecomposition.of(poly); Poly quot = UnivariateDivision.divideAndRemainder(poly, gcd, false)[0]; // can safely destroy poly (not used further) - FactorDecomposition result = FactorDecomposition.constantFactor(poly.createOne()); + PolynomialFactorDecomposition result = PolynomialFactorDecomposition.of(poly.createOne()); int i = 0; //if (!quot.isConstant()) while (true) { @@ -254,7 +254,7 @@ private static > FactorDecomposition gcdFactorization = SquareFreeFactorizationMusser0(gcd); + PolynomialFactorDecomposition gcdFactorization = SquareFreeFactorizationMusser0(gcd); gcdFactorization.raiseExponents(poly.coefficientRingCharacteristic().intValueExact()); result.addAll(gcdFactorization); return result; @@ -262,9 +262,9 @@ private static > FactorDecomposition fd = SquareFreeFactorizationMusser0(pRoot); + PolynomialFactorDecomposition fd = SquareFreeFactorizationMusser0(pRoot); fd.raiseExponents(poly.coefficientRingCharacteristic().intValueExact()); - return fd.setConstantFactor(poly.createOne()); + return fd.setUnit(poly.createOne()); } } diff --git a/rings/src/test/java/cc/redberry/rings/bigint/ChineseRemaindersTest.java b/rings/src/test/java/cc/redberry/rings/ChineseRemaindersTest.java similarity index 98% rename from rings/src/test/java/cc/redberry/rings/bigint/ChineseRemaindersTest.java rename to rings/src/test/java/cc/redberry/rings/ChineseRemaindersTest.java index d7205e8..da82f60 100644 --- a/rings/src/test/java/cc/redberry/rings/bigint/ChineseRemaindersTest.java +++ b/rings/src/test/java/cc/redberry/rings/ChineseRemaindersTest.java @@ -1,6 +1,6 @@ -package cc.redberry.rings.bigint; +package cc.redberry.rings; -import cc.redberry.rings.Ring; +import cc.redberry.rings.bigint.BigInteger; import cc.redberry.rings.poly.MachineArithmetic; import cc.redberry.rings.poly.UnivariateRing; import cc.redberry.rings.poly.univar.UnivariatePolynomialZ64; @@ -18,7 +18,7 @@ import java.util.BitSet; import static cc.redberry.rings.bigint.BigInteger.*; -import static cc.redberry.rings.bigint.ChineseRemainders.ChineseRemainders; +import static cc.redberry.rings.ChineseRemainders.ChineseRemainders; import static java.lang.Math.floorMod; /** diff --git a/rings/src/test/java/cc/redberry/rings/Examples.java b/rings/src/test/java/cc/redberry/rings/Examples.java index c3a73dc..34ee078 100644 --- a/rings/src/test/java/cc/redberry/rings/Examples.java +++ b/rings/src/test/java/cc/redberry/rings/Examples.java @@ -3,7 +3,7 @@ import cc.redberry.rings.bigint.BigInteger; import cc.redberry.rings.poly.*; import cc.redberry.rings.poly.MultivariateRing; -import cc.redberry.rings.poly.PolynomialRing; +import cc.redberry.rings.poly.IPolynomialRing; import cc.redberry.rings.poly.UnivariateRing; import cc.redberry.rings.poly.multivar.*; import cc.redberry.rings.poly.univar.UnivariateDivision; @@ -280,7 +280,7 @@ public void test11() throws Exception { */ static , Poly extends AMultivariatePolynomial> - Poly genericFuncWithRing(Poly poly, PolynomialRing ring) { return null; } + Poly genericFuncWithRing(Poly poly, IPolynomialRing ring) { return null; } @Test public void test12() throws Exception { diff --git a/rings/src/test/java/cc/redberry/rings/IntegersTest.java b/rings/src/test/java/cc/redberry/rings/IntegersTest.java new file mode 100644 index 0000000..ce5dccc --- /dev/null +++ b/rings/src/test/java/cc/redberry/rings/IntegersTest.java @@ -0,0 +1,19 @@ +package cc.redberry.rings; + +import cc.redberry.rings.bigint.BigInteger; +import org.junit.Test; + +import static cc.redberry.rings.Rings.Z; +import static org.junit.Assert.*; + +/** + * @author Stanislav Poslavsky + * @since 2.2 + */ +public class IntegersTest { + @Test + public void test1() throws Exception { + BigInteger p = Z.valueOf(2 * 3 * 4 * 5); + System.out.println(Z.factor(p)); + } +} \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/FactorDecompositionTest.java b/rings/src/test/java/cc/redberry/rings/poly/FactorDecompositionTest.java index fc06b09..03d58fb 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/FactorDecompositionTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/FactorDecompositionTest.java @@ -7,7 +7,7 @@ */ public class FactorDecompositionTest { - public static > void assertFactorization(T poly, FactorDecomposition factorization) { - assertEquals(poly, factorization.toPolynomial()); + public static > void assertFactorization(T poly, PolynomialFactorDecomposition factorization) { + assertEquals(poly, factorization.multiply()); } } \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/FiniteFieldTest.java b/rings/src/test/java/cc/redberry/rings/poly/FiniteFieldTest.java index e56ef51..7fdb6f9 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/FiniteFieldTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/FiniteFieldTest.java @@ -42,10 +42,10 @@ public void test2() throws Exception { poly = poly1.clone().multiply(poly2).multiply(poly1.clone().add(poly2)); // System.out.println(poly1.monic()); - FactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); System.out.println(factors); System.out.println(poly); - System.out.println(factors.toPolynomial()); + System.out.println(factors.multiply()); } @Test diff --git a/rings/src/test/java/cc/redberry/rings/poly/multivar/HenselLiftingTest.java b/rings/src/test/java/cc/redberry/rings/poly/multivar/HenselLiftingTest.java index cb0acc9..b95bdf2 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/multivar/HenselLiftingTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/multivar/HenselLiftingTest.java @@ -446,7 +446,7 @@ public void test6() throws Exception { // assert MultivariateSquareFreeFactorization.isSquareFree(base); // for (int i = 0; i < its(20, 20); i++) { // long start = System.nanoTime(); -// FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); +// PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); // Assert.assertEquals(3, decomposition.size()); // System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); // } diff --git a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateConversionsTest.java b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateConversionsTest.java new file mode 100644 index 0000000..9947234 --- /dev/null +++ b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateConversionsTest.java @@ -0,0 +1,53 @@ +package cc.redberry.rings.poly.multivar; + +import cc.redberry.combinatorics.Combinatorics; +import cc.redberry.rings.Rational; +import cc.redberry.rings.Rationals; +import cc.redberry.rings.Rings; +import cc.redberry.rings.bigint.BigInteger; +import cc.redberry.rings.poly.MultivariateRing; +import cc.redberry.rings.poly.PolynomialMethods; +import cc.redberry.rings.poly.IPolynomialRing; +import cc.redberry.rings.poly.univar.UnivariatePolynomial; +import org.junit.Test; + +import java.util.Arrays; + +import static cc.redberry.rings.poly.multivar.MultivariateConversions.*; +import static org.junit.Assert.assertEquals; + +/** + * @author Stanislav Poslavsky + * @since 1.0 + */ +public class MultivariateConversionsTest { + @Test + public void test1() throws Exception { + MultivariatePolynomial + poly = MultivariatePolynomial.parse("x1*x2 + 2*x2*x3 + 3*x3*x4 + 4*x4*x5 + 5*x5*x6"); + for (int i = 1; i < poly.nVariables; i++) + for (int[] c : Combinatorics.combinationsWithPermutations(poly.nVariables, i)) { + MultivariatePolynomial> split = split(poly, c); + assertEquals(poly, mergeSplit(split, c)); + } + } + + @Test + public void test2() throws Exception { + MultivariatePolynomial + a = MultivariatePolynomial.parse("x1*x2 + 12*x2*x3 + 3*x3*x4^5 + 4*x4*x5 + 5*x5*x6"), + b = MultivariatePolynomial.parse("x1*x2 + 2*x2^2*x3 + 3*x3^6*x4^7 + 41*x4*x5 + 1*x5*x6"); + + MultivariateRing> ring = Rings.MultivariateRing(a); + + int var = 3; + IPolynomialRing>> uRing = splitUnivariate(ring, var); + + Rationals> frac = Rings.Frac(uRing.factory().ring); + UnivariatePolynomial>> + ra = splitUnivariate(a, var).mapCoefficients(frac, p -> new Rational<>(frac.ring, p)), + rb = splitUnivariate(b, var).mapCoefficients(frac, p -> new Rational<>(frac.ring, p)); + + System.out.println(Arrays.toString(PolynomialMethods.divideAndRemainder(rb, ra))); + } +} \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateFactorizationTest.java b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateFactorizationTest.java index f8cffb2..5e86a57 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateFactorizationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateFactorizationTest.java @@ -63,7 +63,7 @@ public void testBivariate2() throws Exception { MultivariatePolynomialZp64.parse("43370+32368*a^2*b^2+45712*a^2*b^4+52302*a^4+23776*a^4*b^2", domain, vars) }; MultivariatePolynomialZp64 poly = factors[0].createOne().multiply(factors); - FactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); + PolynomialFactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); FactorDecompositionTest.assertFactorization(poly, factorization); Assert.assertTrue(factorization.size() >= factors.length); } @@ -102,7 +102,7 @@ public void testBivariate5() throws Exception { MultivariatePolynomialZp64.parse("616781+1057293*b^2+158725*a+730076*a*b^2", domain, vars) }; MultivariatePolynomialZp64 poly = factors[0].createOne().multiply(factors); - FactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); + PolynomialFactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); FactorDecompositionTest.assertFactorization(poly, factorization); Assert.assertTrue(factorization.size() >= factors.length); } @@ -116,7 +116,7 @@ public void testBivariate6() throws Exception { MultivariatePolynomialZp64.parse("39330400+51579304*a^2", domain, vars) }; MultivariatePolynomialZp64 poly = factors[0].createOne().multiply(factors); - FactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); + PolynomialFactorDecomposition factorization = bivariateDenseFactorSquareFreeInGF(poly); FactorDecompositionTest.assertFactorization(poly, factorization); Assert.assertTrue(factorization.size() >= factors.length); } @@ -135,7 +135,7 @@ public void testBivaraiteSmallDomain7() throws Exception { //System.out.println(base); for (int i = 0; i < its(2, 2); i++) { long start = System.nanoTime(); - FactorDecomposition decomposition = bivariateDenseFactorSquareFreeInGF(base); + PolynomialFactorDecomposition decomposition = bivariateDenseFactorSquareFreeInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(5, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -184,7 +184,7 @@ public void testBivariateZ10() throws Exception { //System.out.println(base); for (int i = 0; i < its(10, 10); i++) { long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(4, factors.size()); @@ -203,7 +203,7 @@ public void testBivariateZ11() throws Exception { //System.out.println(base); for (int i = 0; i < its(10, 10); i++) { long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(4, factors.size()); @@ -235,7 +235,7 @@ public void testBivariateZ12() throws Exception { for (int i = 0; i < its(2, 2); i++) { long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(5, factors.size()); @@ -253,7 +253,7 @@ public void testBivariateZ13() throws Exception { for (int i = 0; i < its(2, 12); i++) { long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(3, factors.size()); @@ -273,7 +273,7 @@ public void testBivariateZ14() throws Exception { for (int i = 0; i < its(2, 2); i++) { long start = System.nanoTime(); PrivateRandom.getRandom().setSeed(i); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(3, factors.size()); @@ -293,7 +293,7 @@ public void testBivariateZ15() throws Exception { for (int i = 0; i < its(2, 2); i++) { long start = System.nanoTime(); PrivateRandom.getRandom().setSeed(i); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(3, factors.size()); @@ -324,7 +324,7 @@ public void testBivariateZ17() throws Exception { for (int i = 0; i < its(2, 2); i++) { long start = System.nanoTime(); PrivateRandom.getRandom().setSeed(i); - FactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.bivariateDenseFactorSquareFreeInZ(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(base, factors); Assert.assertEquals(3, factors.size()); @@ -369,25 +369,25 @@ public void testGCDFreeBasis1() throws Exception { c = UnivariatePolynomialZ64.create(1, 0, 0, 2, 3).modulus(modulus), d = UnivariatePolynomialZ64.create(1, 11, 0, 12, 4).modulus(modulus); - FactorDecomposition - d1 = FactorDecomposition.of(Arrays.asList(multiply(a, b, b, b), multiply(a, c, c), multiply(a, a, d))), - d2 = FactorDecomposition.of(Arrays.asList(multiply(a, c, b), multiply(b, d, c), multiply(d, c, d))), - d3 = FactorDecomposition.of(Arrays.asList(multiply(c, c, d), multiply(b, b, c), multiply(a, b, c, d))); + PolynomialFactorDecomposition + d1 = PolynomialFactorDecomposition.of(Arrays.asList(multiply(a, b, b, b), multiply(a, c, c), multiply(a, a, d))), + d2 = PolynomialFactorDecomposition.of(Arrays.asList(multiply(a, c, b), multiply(b, d, c), multiply(d, c, d))), + d3 = PolynomialFactorDecomposition.of(Arrays.asList(multiply(c, c, d), multiply(b, b, c), multiply(a, b, c, d))); @SuppressWarnings("unchecked") - FactorDecomposition[] decomps = new FactorDecomposition[]{ + PolynomialFactorDecomposition[] decomps = new PolynomialFactorDecomposition[]{ d1.clone(), d2.clone(), d3.clone() }; MultivariateFactorization.GCDFreeBasis(decomps); - Assert.assertEquals(d1.toPolynomial(), decomps[0].toPolynomial()); - Assert.assertEquals(d2.toPolynomial(), decomps[1].toPolynomial()); - Assert.assertEquals(d3.toPolynomial(), decomps[2].toPolynomial()); + Assert.assertEquals(d1.multiply(), decomps[0].multiply()); + Assert.assertEquals(d2.multiply(), decomps[1].multiply()); + Assert.assertEquals(d3.multiply(), decomps[2].multiply()); - System.out.println(d1.toPolynomial().equals(decomps[0].toPolynomial())); - System.out.println(Arrays.toString(UnivariateDivision.divideAndRemainder(d1.toPolynomial(), decomps[0].toPolynomial(), true))); - for (FactorDecomposition decomp : decomps) + System.out.println(d1.multiply().equals(decomps[0].multiply())); + System.out.println(Arrays.toString(UnivariateDivision.divideAndRemainder(d1.multiply(), decomps[0].multiply(), true))); + for (PolynomialFactorDecomposition decomp : decomps) System.out.println(decomp.size() + " => " + decomp); } @@ -398,13 +398,13 @@ public void testGCDFreeBasis2() throws Exception { b = UnivariatePolynomial.create(4, 8), c = UnivariatePolynomial.create(2); - FactorDecomposition> - d1 = FactorDecomposition.of(Arrays.asList(a)), - d2 = FactorDecomposition.of(b.contentAsPoly(), Arrays.asList(b.primitivePart())), - d3 = FactorDecomposition.of(Arrays.asList(c)); + PolynomialFactorDecomposition> + d1 = PolynomialFactorDecomposition.of(Arrays.asList(a)), + d2 = PolynomialFactorDecomposition.of(Arrays.asList(b.primitivePart())).addFactor(b.contentAsPoly(), 1), + d3 = PolynomialFactorDecomposition.of(Arrays.asList(c)); @SuppressWarnings("unchecked") - FactorDecomposition[] decomps = new FactorDecomposition[]{ + PolynomialFactorDecomposition[] decomps = new PolynomialFactorDecomposition[]{ d1.clone(), d2.clone(), d3.clone() }; @@ -423,14 +423,14 @@ public void testGCDFreeBasis3() throws Exception { c = UnivariatePolynomialZ64.create(3, 1).modulus(17), d = UnivariatePolynomialZ64.create(13, 14, 8, 1).modulus(17); - FactorDecomposition - d1 = FactorDecomposition.of(a), - d2 = FactorDecomposition.of(b), - d3 = FactorDecomposition.of(c), - d4 = FactorDecomposition.of(d); + PolynomialFactorDecomposition + d1 = PolynomialFactorDecomposition.of(a), + d2 = PolynomialFactorDecomposition.of(b), + d3 = PolynomialFactorDecomposition.of(c), + d4 = PolynomialFactorDecomposition.of(d); @SuppressWarnings("unchecked") - FactorDecomposition[] decomps = new FactorDecomposition[]{ + PolynomialFactorDecomposition[] decomps = new PolynomialFactorDecomposition[]{ d1.clone(), d2.clone(), d3.clone(), d4.clone(), }; // System.out.println(Arrays.toString(Stream.of(a, b, c, d).map(p -> Factor(p).toString()).toArray())); @@ -438,10 +438,10 @@ public void testGCDFreeBasis3() throws Exception { MultivariateFactorization.GCDFreeBasis(decomps); System.out.println(Arrays.asList(decomps)); - Assert.assertEquals(d1.toPolynomial(), decomps[0].toPolynomial()); - Assert.assertEquals(d2.toPolynomial(), decomps[1].toPolynomial()); - Assert.assertEquals(d3.toPolynomial(), decomps[2].toPolynomial()); - Assert.assertEquals(d4.toPolynomial(), decomps[3].toPolynomial()); + Assert.assertEquals(d1.multiply(), decomps[0].multiply()); + Assert.assertEquals(d2.multiply(), decomps[1].multiply()); + Assert.assertEquals(d3.multiply(), decomps[2].multiply()); + Assert.assertEquals(d4.multiply(), decomps[3].multiply()); } @Test @@ -455,7 +455,7 @@ public void testMultivariateFactorization1() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -471,7 +471,7 @@ public void testMultivariateFactorization1a() throws Exception { base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(42); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -485,7 +485,7 @@ public void testMultivariateFactorization1b() throws Exception { base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(328); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -501,7 +501,7 @@ public void testMultivariateFactorization2() throws Exception { for (int i = 0; i < its(100, 100); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -519,7 +519,7 @@ public void testMultivariateFactorization3() throws Exception { for (int i = 0; i < its(100, 100); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -538,7 +538,7 @@ public void testMultivariateFactorization4() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -554,7 +554,7 @@ public void testMultivariateFactorization4a() throws Exception { base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(31); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -568,7 +568,7 @@ public void testMultivariateFactorization4b() throws Exception { base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(88); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -582,7 +582,7 @@ public void testMultivariateFactorization4c() throws Exception { base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(531); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -598,7 +598,7 @@ public void testMultivariateFactorization5() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -616,7 +616,7 @@ public void testMultivariateFactorization6() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -634,7 +634,7 @@ public void testMultivariateFactorization7() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -653,7 +653,7 @@ public void testMultivariateFactorization8() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -671,7 +671,7 @@ public void testMultivariateFactorization9() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); //long start = System.nanoTime(); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -693,13 +693,13 @@ public void testMultivariateFactorization10() throws Exception { MultivariatePolynomialZp64.parse("433*d^2*e+165*d*e+265*b^4*c^3*d+107*c*d^3*a+1338*a^15*e +a^15*e + c^2 + a^15*b + a^15 + a^15*d + a^15*e", domain, vars), }, base = factors[0].createOne().multiply(factors); -// System.out.println(FactorDecomposition.create(Arrays.asList(factors))); +// System.out.println(PolynomialFactorDecomposition.create(Arrays.asList(factors))); assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(100, 10); i++) { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(5, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -733,7 +733,7 @@ public void testMultivariateFactorization10a() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(0); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(5, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -749,7 +749,7 @@ public void testMultivariateFactorization11() throws Exception { d = MultivariatePolynomialZp64.parse("2*d + 2*e + 2*a + 2*b", domain, vars), e = MultivariatePolynomialZp64.parse("e + a + b + 2*c", domain, vars), base = a.clone().multiply(b, c, d, e); - FactorDecomposition decomposition = MultivariateFactorization.factorToPrimitive(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorToPrimitive(base); Assert.assertEquals(5, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -766,7 +766,8 @@ public void testMultivariateFactorization12() throws Exception { MultivariatePolynomialZp64 base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + System.out.println(factors); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -779,7 +780,7 @@ public void testMultivariateFactorization13() throws Exception { b = MultivariatePolynomialZp64.parse("1+105163*a^2+81015*a^2*c+166076*a^3*c^3+106464*a^3*b^2*c^2+43621*a^3*b^3", domain); MultivariatePolynomialZp64 base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -795,7 +796,7 @@ public void testMultivariateFactorization14() throws Exception { b = AMultivariatePolynomial.renameVariables(b, new int[]{0, 2, 1}); MultivariatePolynomialZp64 base = a.clone().multiply(b); assert MultivariateSquareFreeFactorization.isSquareFree(base); - FactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition factors = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -820,7 +821,7 @@ public void testMultivariateFactorization15() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(0); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -841,7 +842,7 @@ public void testMultivariateFactorization16() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(0); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -866,7 +867,7 @@ public void testMultivariateFactorization17() throws Exception { PrivateRandom.getRandom().setSeed(0); for (int i = 0; i < its(10, 10); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base, false); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -931,7 +932,7 @@ public void testMultivariateFactorizationRandom3a() throws Exception { PrivateRandom.getRandom().setSeed(0); for (int i = 0; i < its(10, 10); i++) { long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(2, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -964,7 +965,7 @@ public void testMultivariateFactorization18_SmallDomain() throws Exception { PrivateRandom.getRandom().setSeed(0); for (int i = 0; i < its(10, 30); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -991,7 +992,7 @@ public void testMultivariateFactorization19_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1012,7 +1013,7 @@ public void testMultivariateFactorization20_SmallDomain() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1034,7 +1035,7 @@ public void testMultivariateFactorization21_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1057,7 +1058,7 @@ public void testMultivariateFactorization22_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1080,7 +1081,7 @@ public void testMultivariateFactorization23_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1104,7 +1105,7 @@ public void testMultivariateFactorization24_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1125,7 +1126,7 @@ public void testMultivariateFactorization25_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1148,7 +1149,7 @@ public void testMultivariateFactorization26_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1167,7 +1168,7 @@ public void testMultivariateFactorization27_SmallDomain() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(2, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1202,7 +1203,7 @@ public void testMultivariateFactorizationRandom4_SmallDomain_a() throws Exceptio //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base.toBigPoly()); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base.toBigPoly()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(2, decomposition.size()); FactorDecompositionTest.assertFactorization(base.toBigPoly(), decomposition); @@ -1225,7 +1226,7 @@ public void testMultivariateFactorizationRandom4_SmallDomain_b() throws Exceptio //System.out.println(i); PrivateRandom.getRandom().setSeed(i + 1); timestamp(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); timeElapsed(); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1249,7 +1250,7 @@ public void testMultivariateFactorizationRandom4_SmallDomain_c() throws Exceptio //System.out.println(i); PrivateRandom.getRandom().setSeed(i + 1); timestamp(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); timeElapsed(); Assert.assertEquals(2, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1269,7 +1270,7 @@ public void testMultivariateFactorization18() throws Exception { MultivariatePolynomialZp64.parse("1+4*a*b^2*c^2*d^3*e^3+4*a^2*b*c*d^2+3*a^3*b*c^3*e^3+3*a^3*b^2*c^2*d^3*e^2", domain, vars), }; - //System.out.println(FactorDecomposition.create(Arrays.asList(factors))); + //System.out.println(PolynomialFactorDecomposition.create(Arrays.asList(factors))); MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); @@ -1277,7 +1278,7 @@ public void testMultivariateFactorization18() throws Exception { //System.out.println(i); //PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1315,13 +1316,13 @@ public void testMultivariateFactorization18a() throws Exception { MultivariatePolynomialZp64.parse("1+4*a*b^2*c^2*d^3*e^3+4*a^2*b*c*d^2+3*a^3*b*c^3*e^3+3*a^3*b^2*c^2*d^3*e^2", domain, vars), }; - //System.out.println(FactorDecomposition.create(Arrays.asList(factors))); + //System.out.println(PolynomialFactorDecomposition.create(Arrays.asList(factors))); MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(9); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(4, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -1339,7 +1340,7 @@ public void testMultivariateFactorization19() throws Exception { MultivariatePolynomialZp64.parse("1+c*d^3+b*c^2*d^2*e^2+a^3*b^2*c*d^3*e^2", domain, vars), }; - //System.out.println(FactorDecomposition.create(Arrays.asList(factors))); + //System.out.println(PolynomialFactorDecomposition.create(Arrays.asList(factors))); MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); @@ -1349,7 +1350,7 @@ public void testMultivariateFactorization19() throws Exception { //cc.r2.core.poly.univar.PrivateRandom.getRandom().setSeed(i); //PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); @@ -1383,7 +1384,7 @@ public void testMultivariateFactorization19a() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(5); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -1403,7 +1404,7 @@ public void testMultivariateFactorization19b() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(2); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(3, decomposition.size()); FactorDecompositionTest.assertFactorization(base, decomposition); } @@ -1423,7 +1424,7 @@ public void testMultivariateFactorization19c() throws Exception { MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(7); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(3, decomposition.size()); } @@ -1443,7 +1444,7 @@ public void testMultivariateFactorization19d() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); //cc.r2.core.poly.univar.PrivateRandom.getRandom().setSeed(10); PrivateRandom.getRandom().setSeed(10); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(3, decomposition.size()); } @@ -1463,7 +1464,7 @@ public void testMultivariateFactorization20() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(2, 2); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(4, decomposition.size()); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1483,7 +1484,7 @@ public void testMultivariateFactorization21() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(20, 20); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(2, decomposition.size()); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1504,7 +1505,7 @@ public void testMultivariateFactorization22() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(20, 20); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.factorPrimitiveInGF(base); Assert.assertEquals(2, decomposition.size()); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1526,7 +1527,7 @@ public void testMultivariateFactorization23() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(20, 20); i++) { //long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); Assert.assertEquals(4, decomposition.size()); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1547,7 +1548,7 @@ public void testMultivariateFactorization24() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); for (int i = 0; i < its(20, 20); i++) { long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); Assert.assertEquals(3, decomposition.size()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1582,7 +1583,7 @@ public void testMultivariateFactorization26() throws Exception { System.out.println(i + 20); PrivateRandom.getRandom().setSeed(i + 20); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); Assert.assertEquals(4, decomposition.size()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1604,7 +1605,7 @@ public void testMultivariateFactorization26a() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(27); long start = System.nanoTime(); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); Assert.assertEquals(4, decomposition.size()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -1624,7 +1625,7 @@ public void testMultivariateFactorization25() throws Exception { }; MultivariatePolynomialZp64 base = factors[0].createOne().multiply(factors); - FactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); + PolynomialFactorDecomposition decomposition = MultivariateFactorization.FactorInGF(base); Assert.assertEquals(3, decomposition.size()); } @@ -1638,7 +1639,7 @@ public void testMultivariateFactorization27() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1655,7 +1656,7 @@ public void testMultivariateFactorization28() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1673,7 +1674,7 @@ public void testMultivariateFactorization29() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(3, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1694,7 +1695,7 @@ public void testMultivariateFactorization30() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1716,7 +1717,7 @@ public void testMultivariateFactorization30a() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(1); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -1736,7 +1737,7 @@ public void testMultivariateFactorization30b() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(3); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -1756,7 +1757,7 @@ public void testMultivariateFactorization30c() throws Exception { assert MultivariateSquareFreeFactorization.isSquareFree(base); PrivateRandom.getRandom().setSeed(9); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); } @@ -1782,7 +1783,7 @@ public void testMultivariateFactorization31() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1805,7 +1806,7 @@ public void testMultivariateFactorization32() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(4, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1831,7 +1832,7 @@ public void testMultivariateFactorization33() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(5, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1856,7 +1857,7 @@ public void testMultivariateFactorization34() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(3, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1882,7 +1883,7 @@ public void testMultivariateFactorization35() throws Exception { System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(4, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1907,7 +1908,7 @@ public void testMultivariateFactorization36() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorPrimitiveInZ(base); Assert.assertEquals(3, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1934,7 +1935,7 @@ public void testMultivariateFactorization37() throws Exception { //System.out.println(i); PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.factorToPrimitive(base); + PolynomialFactorDecomposition> factors = MultivariateFactorization.factorToPrimitive(base); Assert.assertEquals(3, factors.size()); FactorDecompositionTest.assertFactorization(base, factors); //System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); @@ -1969,14 +1970,14 @@ public void testMultivariateFactorization39() throws Exception { MultivariatePolynomial.parse("a^6 + c^2 + a*c^2 + 1", vars).square() }, poly = multiply(pp); - FactorDecomposition> factors = MultivariateFactorization.Factor(poly); + PolynomialFactorDecomposition> factors = MultivariateFactorization.Factor(poly); Assert.assertEquals(6, factors.size()); - Assert.assertEquals(poly, factors.toPolynomial()); + Assert.assertEquals(poly, factors.multiply()); poly = poly.setRing(new IntegersZp(Integer.MAX_VALUE)); factors = MultivariateFactorization.Factor(poly); Assert.assertEquals(6, factors.size()); - Assert.assertEquals(poly, factors.toPolynomial()); + Assert.assertEquals(poly, factors.multiply()); } @@ -1994,9 +1995,9 @@ public void testMultivariateFactorization40() throws Exception { for (int i = 21; i < 22; i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = MultivariateFactorization.Factor(poly); + PolynomialFactorDecomposition> factors = MultivariateFactorization.Factor(poly); Assert.assertEquals(4, factors.size()); - Assert.assertEquals(poly, factors.toPolynomial()); + Assert.assertEquals(poly, factors.multiply()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } } @@ -2015,9 +2016,9 @@ public void testMultivariateFactorization41() throws Exception { for (int i = 21; i < 22; i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition>> factors = MultivariateFactorization.Factor(poly); + PolynomialFactorDecomposition>> factors = MultivariateFactorization.Factor(poly); Assert.assertEquals(4, factors.size()); - Assert.assertEquals(poly, factors.toPolynomial()); + Assert.assertEquals(poly, factors.multiply()); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); } } @@ -2074,9 +2075,9 @@ public void testNestedRing1() throws Exception { b = ring.randomElement(3, 5); AMultivariatePolynomial poly = multiply(a, b); - FactorDecomposition factors = Factor(poly); + PolynomialFactorDecomposition factors = Factor(poly); Assert.assertTrue(factors.sumExponents() >= 2); - Assert.assertEquals(poly, factors.toPolynomial()); + Assert.assertEquals(poly, factors.multiply()); } } } @@ -2111,10 +2112,10 @@ public void testNestedRing2() throws Exception { return r; }).reduce(ring.getOne(), (a, b) -> ring.multiply((UnivariatePolynomial) a, (UnivariatePolynomial) b)); - FactorDecomposition fs = Factor(poly); + PolynomialFactorDecomposition fs = Factor(poly); Assert.assertTrue(4 <= fs.sumExponents()); - Assert.assertEquals(poly, fs.toPolynomial()); + Assert.assertEquals(poly, fs.multiply()); } } @@ -2170,7 +2171,7 @@ void testFactorizationAlgorithm(FactorizationInput.SampleDecompositionSource sample = source.next(); - FactorDecomposition decomposition = null; + PolynomialFactorDecomposition decomposition = null; try { if (PRINT_FACTORS) { System.out.println("\n"); @@ -2224,9 +2225,9 @@ void testFactorizationAlgorithm(FactorizationInput.SampleDecompositionSource sample = source.next(); // System.out.println(sample.poly.ring); -// System.out.println(FactorDecomposition.create(Arrays.asList(sample.factors))); - FactorDecomposition lDecomposition = null; - FactorDecomposition> bDecomposition = null; +// System.out.println(PolynomialFactorDecomposition.create(Arrays.asList(sample.factors))); + PolynomialFactorDecomposition lDecomposition = null; + PolynomialFactorDecomposition> bDecomposition = null; try { if (PRINT_FACTORS) { System.out.println("\n"); diff --git a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateInterpolationTest.java b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateInterpolationTest.java index 4b08653..11e54a8 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateInterpolationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateInterpolationTest.java @@ -98,7 +98,7 @@ public void testRandom() throws Exception { int var = rndd.nextInt(0, nVars - 1); int degree = base.degrees()[var]; - MultivariateInterpolation.Interpolation interpolation = null; + MultivariateInterpolation.Interpolation interpolation = new MultivariateInterpolation.Interpolation<>(var, base); TIntHashSet seen = new TIntHashSet(); for (int i = 0; i <= degree + 2; i++) { int iPoint = rndd.nextInt(0, domain.modulus.intValue() - 1); @@ -109,10 +109,7 @@ public void testRandom() throws Exception { BigInteger point = BigInteger.valueOf(iPoint); MultivariatePolynomial evaluated = base.evaluate(var, point); - if (interpolation == null) - interpolation = new MultivariateInterpolation.Interpolation<>(var, point, evaluated); - else - interpolation.update(point, evaluated); + interpolation.update(point, evaluated); } BigInteger[] points = interpolation.getPoints().toArray(new BigInteger[0]); diff --git a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorizationTest.java b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorizationTest.java index 23e44ca..397164a 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorizationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/multivar/MultivariateSquareFreeFactorizationTest.java @@ -4,7 +4,7 @@ import cc.redberry.rings.Ring; import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.FactorDecompositionTest; import cc.redberry.rings.poly.FiniteField; import cc.redberry.rings.poly.univar.IrreduciblePolynomials; @@ -32,12 +32,12 @@ public void test1() throws Exception { for (int i = 0; i < AbstractTest.its(1, 5); i++) { long start = System.nanoTime(); - FactorDecomposition> yun = MultivariateSquareFreeFactorization.SquareFreeFactorizationYunZeroCharacteristics(poly); + PolynomialFactorDecomposition> yun = MultivariateSquareFreeFactorization.SquareFreeFactorizationYunZeroCharacteristics(poly); System.out.println("Yun: " + TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(poly, yun); start = System.nanoTime(); - FactorDecomposition> mus = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusserZeroCharacteristics(poly); + PolynomialFactorDecomposition> mus = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusserZeroCharacteristics(poly); System.out.println("Musser: " + TimeUnits.nanosecondsToString(System.nanoTime() - start)); FactorDecompositionTest.assertFactorization(poly, mus); @@ -96,7 +96,7 @@ public void test4() throws Exception { poly = a.square().multiply(b.square()).multiply(c.square()); MultivariatePolynomialZp64 lPoly = MultivariatePolynomial.asOverZp64(poly); - FactorDecomposition decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(lPoly); + PolynomialFactorDecomposition decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(lPoly); FactorDecompositionTest.assertFactorization(lPoly, decomposition); } @@ -109,7 +109,7 @@ public void test5() throws Exception { poly = a.square().multiply(b.square()); MultivariatePolynomialZp64 lPoly = MultivariatePolynomial.asOverZp64(poly); - FactorDecomposition decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(lPoly); + PolynomialFactorDecomposition decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(lPoly); FactorDecompositionTest.assertFactorization(lPoly, decomposition); } @@ -135,7 +135,7 @@ public void test5_finiteField() throws Exception { poly = a.square().multiply(b.square()).multiply(c.square()); - FactorDecomposition> decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(poly); + PolynomialFactorDecomposition> decomposition = MultivariateSquareFreeFactorization.SquareFreeFactorizationMusser(poly); FactorDecompositionTest.assertFactorization(poly, decomposition); } @@ -144,7 +144,7 @@ public void test6() throws Exception { String[] vars = {"a", "b", "c", "d", "e", "f", "g", "h"}; for (Ring ring : Arrays.>asList(new IntegersZp(2), Rings.Z)) { MultivariatePolynomial poly = MultivariatePolynomial.parse("a^2*b^4*c*e^5", ring, vars); - FactorDecomposition> expected = FactorDecomposition.empty(poly); + PolynomialFactorDecomposition> expected = PolynomialFactorDecomposition.empty(poly); expected.addFactor(MultivariatePolynomial.parse("a", ring, vars), 2); expected.addFactor(MultivariatePolynomial.parse("b", ring, vars), 4); expected.addFactor(MultivariatePolynomial.parse("c", ring, vars), 1); diff --git a/rings/src/test/java/cc/redberry/rings/poly/test/FactorizationInput.java b/rings/src/test/java/cc/redberry/rings/poly/test/FactorizationInput.java index 7f401ef..fdcd769 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/test/FactorizationInput.java +++ b/rings/src/test/java/cc/redberry/rings/poly/test/FactorizationInput.java @@ -1,6 +1,6 @@ package cc.redberry.rings.poly.test; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.IPolynomial; import cc.redberry.rings.util.TimeUnits; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; @@ -26,8 +26,8 @@ public SampleDecomposition(Poly[] factors) { assert Arrays.stream(factors).noneMatch(IPolynomial::isMonomial); } - public void assertFactorization(FactorDecomposition factorization) { - Assert.assertEquals(poly, factorization.toPolynomial()); + public void assertFactorization(PolynomialFactorDecomposition factorization) { + Assert.assertEquals(poly, factorization.multiply()); Assert.assertTrue(factors.length <= factorization.sumExponents()); } } @@ -74,10 +74,10 @@ public String statisticsToString() { } public static class FactorizationAlgorithm> { - public final Function> algorithm; + public final Function> algorithm; public final String name; - public FactorizationAlgorithm(Function> algorithm, String name) { + public FactorizationAlgorithm(Function> algorithm, String name) { this.algorithm = algorithm; this.name = name; } @@ -88,7 +88,7 @@ public String toString() { } public static > - FactorizationAlgorithm named(Function> algorithm, String name) { + FactorizationAlgorithm named(Function> algorithm, String name) { return new FactorizationAlgorithm<>(algorithm, name); } } @@ -122,7 +122,7 @@ void testFactorizationAlgorithms(SampleDecompositionSource source, } SampleDecomposition sample = source.next(); for (int i = 0; i < algorithms.length; i++) { - FactorDecomposition decomposition = null; + PolynomialFactorDecomposition decomposition = null; try { long start = System.nanoTime(); decomposition = algorithms[i].algorithm.apply(sample.poly); diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/DiophantineEquationsTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/DiophantineEquationsTest.java new file mode 100644 index 0000000..91ba86d --- /dev/null +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/DiophantineEquationsTest.java @@ -0,0 +1,48 @@ +package cc.redberry.rings.poly.univar; + +import cc.redberry.rings.IntegersZp64; +import cc.redberry.rings.Rings; +import cc.redberry.rings.poly.UnivariateRing; +import cc.redberry.rings.poly.test.APolynomialTest; +import cc.redberry.rings.util.RandomDataGenerator; +import org.apache.commons.math3.random.RandomGenerator; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; + +/** + * @author Stanislav Poslavsky + * @since 1.0 + */ +public class DiophantineEquationsTest extends APolynomialTest { + @Test + public void test1() throws Exception { + RandomGenerator rnd = getRandom(); + RandomDataGenerator rndd = getRandomData(); + for (long modulus : Arrays.asList(2, 3, 17, Integer.MAX_VALUE)) { + IntegersZp64 ring = Rings.Zp64(modulus); + UnivariateRing uring = Rings.UnivariateRingZp64(ring); + for (int i = 0; i < 1000; i++) { + int nPolynomials = rndd.nextInt(2, 10); + UnivariatePolynomialZp64[] polys = new UnivariatePolynomialZp64[nPolynomials]; + for (int j = 0; j < polys.length; j++) + polys[j] = RandomUnivariatePolynomials.randomMonicPoly(rndd.nextInt(15, 30), ring.modulus, rnd); + + UnivariatePolynomialZp64 gcd = UnivariateGCD.PolynomialGCD(polys); + UnivariatePolynomialZp64 rhs = RandomUnivariatePolynomials.randomMonicPoly(rndd.nextInt(0, 10), ring.modulus, rnd); + rhs.multiply(gcd); + + DiophantineEquations.DiophantineSolver solver = new DiophantineEquations.DiophantineSolver<>(polys); + UnivariatePolynomialZp64 g = uring.getZero(); + for (int l = 0; l < solver.solution.length; l++) + g.add(solver.solution[l].clone().multiply(polys[l])); + + UnivariatePolynomialZp64[] solve = solver.solve(rhs); + for (int j = 0; j < solve.length; j++) + rhs.subtract(solve[j].multiply(polys[j])); + Assert.assertTrue(rhs.isZero()); + } + } + } +} \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorizationTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorizationTest.java index 818c498..89c7426 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorizationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/DistinctDegreeFactorizationTest.java @@ -2,8 +2,7 @@ import cc.redberry.rings.IntegersZp; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; -import cc.redberry.rings.poly.test.APolynomialTest; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.univar.FactorizationTestUtil.PolynomialSource; import cc.redberry.rings.poly.univar.FactorizationTestUtil.RandomSource; import cc.redberry.rings.poly.univar.FactorizationTestUtil.ShoupSource; @@ -32,7 +31,7 @@ public class DistinctDegreeFactorizationTest extends AUnivariateTest { @Test public void test1() throws Exception { UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64.create(0, -1, -1, -1, 0, 1, -1, 1, 1).modulus(3); - FactorDecomposition f = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition f = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); assertDistinctDegreeFactorization(poly, f); } @@ -45,8 +44,8 @@ public void test2() throws Exception { .multiply(UnivariatePolynomialZ64 .create(3, 3, 1) .modulus(modulus)); - FactorDecomposition plain = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); - FactorDecomposition shoup = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); + PolynomialFactorDecomposition plain = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition shoup = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); assertDistinctDegreeFactorization(poly, plain); assertDistinctDegreeFactorization(poly, shoup); assertEquals(plain, shoup); @@ -61,8 +60,8 @@ public void test3() throws Exception { .multiply(UnivariatePolynomialZ64 .create(4, 9, 1) .modulus(modulus)); - FactorDecomposition plain = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); - FactorDecomposition shoup = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); + PolynomialFactorDecomposition plain = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition shoup = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); assertDistinctDegreeFactorization(poly, plain); assertDistinctDegreeFactorization(poly, shoup); assertEquals(plain, shoup); @@ -185,31 +184,31 @@ public void test2sa() throws Exception { enum DDFAlgorithm { Plain { - FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { + FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { long start = System.nanoTime(); - FactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); long timing = System.nanoTime() - start; return new FactorizationTestUtil.WithTiming<>(r, timing); } }, XPowers { - FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { + FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { long start = System.nanoTime(); - FactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationPrecomputedExponents(poly); + PolynomialFactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationPrecomputedExponents(poly); long timing = System.nanoTime() - start; return new FactorizationTestUtil.WithTiming<>(r, timing); } }, Shoup { - FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { + FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly) { long start = System.nanoTime(); - FactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); + PolynomialFactorDecomposition r = DistinctDegreeFactorization.DistinctDegreeFactorizationShoup(poly); long timing = System.nanoTime() - start; return new FactorizationTestUtil.WithTiming<>(r, timing); } }; - abstract FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly); + abstract FactorizationTestUtil.WithTiming> factor(UnivariatePolynomialZp64 poly); } final class BenchmarkRunner { @@ -276,14 +275,14 @@ void run() throws IOException { UnivariatePolynomialZp64 poly = source.take(modulus); degrees.addValue(poly.degree); try { - Map>> results = algorithms.stream().collect(Collectors.toMap(al -> al, al -> al.factor(poly))); + Map>> results = algorithms.stream().collect(Collectors.toMap(al -> al, al -> al.factor(poly))); DDFAlgorithm baseAlgorithm = algorithms.stream().findFirst().get(); - FactorDecomposition baseDecomposition = results.get(baseAlgorithm).val; + PolynomialFactorDecomposition baseDecomposition = results.get(baseAlgorithm).val; factors.addValue(baseDecomposition.factors.size()); results.forEach((alg, res) -> { performance.get(alg).addValue(res.nanoSeconds); - FactorDecomposition c = res.val; + PolynomialFactorDecomposition c = res.val; try { assertDistinctDegreeFactorization(poly, c); assertEquals(baseDecomposition.factors.size(), c.factors.size()); @@ -370,7 +369,7 @@ public void test35a() throws Exception { UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64 .create(19, 20, 13, 10, 26, 19, 6, 29, 13, 20, 10, 12, 20, 3, 21, 16, 25, 10, 26, 22, 25, 2, 23, 29, 21, 14, 8, 26, 16, 7, 7, 1) .modulus(31); - FactorDecomposition factorization = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition factorization = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); assertEquals(5, factorization.factors.size()); assertDistinctDegreeFactorization(poly, factorization); } @@ -380,7 +379,7 @@ public void test37a() throws Exception { UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64 .create(9, 7, 2, 3, 10, 1, 1) .modulus(11); - FactorDecomposition factorization = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); + PolynomialFactorDecomposition factorization = DistinctDegreeFactorization.DistinctDegreeFactorizationPlain(poly); assertDistinctDegreeFactorization(poly, factorization); } @@ -389,13 +388,13 @@ public void test38() throws Exception { UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64 .create(172, 85, 84, 151, 122, 53, 107, 117, 82, 152, 133, 151, 178, 1) .modulus(181); - FactorDecomposition fct = DistinctDegreeFactorization.DistinctDegreeFactorizationComplete(poly); + PolynomialFactorDecomposition fct = DistinctDegreeFactorization.DistinctDegreeFactorizationComplete(poly); assertFactorization(poly, fct); } @Test public void test5() throws Exception { - FactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); + PolynomialFactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); assertDistinctDegreeFactorization(bigPoly, ddf); assertEquals(2, ddf.factors.size()); } @@ -405,7 +404,7 @@ public void test5a() throws Exception { for (int i = 0; i < its(10, 50); i++) { UnivariatePolynomialZp64 bigPoly = this.bigPoly.setModulus(getModulusRandom(20)); long start = System.nanoTime(); - FactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); + PolynomialFactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); assertDistinctDegreeFactorization(bigPoly, ddf); System.out.println("Time (deg(poly) = " + bigPoly.degree + ", modulus = " + bigPoly.ring.modulus + "): " + TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -417,7 +416,7 @@ public void test5c() throws Exception { for (int i = 0; i < its(10, 50); i++) { UnivariatePolynomialZp64 bigPoly = this.bigPoly.setModulus(modulus); long start = System.nanoTime(); - FactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); + PolynomialFactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); assertDistinctDegreeFactorization(bigPoly, ddf); System.out.println("Time (deg(poly) = " + bigPoly.degree + ", modulus = " + bigPoly.ring.modulus + "): " + TimeUnits.nanosecondsToString(System.nanoTime() - start)); } @@ -429,7 +428,7 @@ public void test5b() throws Exception { for (int i = 0; i < its(100, 50); i++) { UnivariatePolynomialZp64 bigPoly = this.bigPoly.setModulus(getModulusRandom(20));//.truncate(15); long start = System.nanoTime(); - FactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); + PolynomialFactorDecomposition ddf = DistinctDegreeFactorization.DistinctDegreeFactorization(bigPoly); assertDistinctDegreeFactorization(bigPoly, ddf); long time = System.nanoTime() - start; boolean b = UnivariateGCD.EuclidGCD(bigPoly.toBigPoly().square(), bigPoly.toBigPoly().square().derivative()).isConstant(); @@ -450,7 +449,7 @@ public void test7() throws Exception { BigInteger modulus = BigInteger.LONG_MAX_VALUE; modulus = modulus.multiply(modulus).nextProbablePrime(); UnivariatePolynomial polyMod = poly.setRing(new IntegersZp(modulus)); - FactorDecomposition> f = DistinctDegreeFactorization(polyMod); + PolynomialFactorDecomposition> f = DistinctDegreeFactorization(polyMod); assertDistinctDegreeFactorization(polyMod, f); } } \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/FactorizationTestUtil.java b/rings/src/test/java/cc/redberry/rings/poly/univar/FactorizationTestUtil.java index 7261882..3035a99 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/FactorizationTestUtil.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/FactorizationTestUtil.java @@ -1,6 +1,6 @@ package cc.redberry.rings.poly.univar; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.util.ArraysUtil; import cc.redberry.rings.util.RandomDataGenerator; import org.apache.commons.math3.random.RandomGenerator; @@ -12,11 +12,11 @@ final class FactorizationTestUtil { public FactorizationTestUtil() {} - public static > void assertDistinctDegreeFactorization(T poly, FactorDecomposition factorization) { + public static > void assertDistinctDegreeFactorization(T poly, PolynomialFactorDecomposition factorization) { for (int i = 0; i < factorization.factors.size(); i++) assertEquals("Factor's degree is not divisible by d.d.f. exponent", 0, factorization.factors.get(i).degree() % factorization.exponents.get(i)); - assertEquals(poly, factorization.toPolynomialIgnoringExponents()); + assertEquals(poly, factorization.multiplyIgnoreExponents()); } diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/HenselLiftingTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/HenselLiftingTest.java index 143aa37..43bd035 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/HenselLiftingTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/HenselLiftingTest.java @@ -1,9 +1,10 @@ package cc.redberry.rings.poly.univar; import cc.redberry.rings.IntegersZp; +import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; import cc.redberry.rings.poly.FactorDecompositionTest; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.primes.SmallPrimes; import cc.redberry.rings.test.AbstractTest; import cc.redberry.rings.test.Benchmark; @@ -153,7 +154,7 @@ static void testMultiFactorHenselLifting(UnivariatePolynomial base, if (!UnivariateSquareFreeFactorization.isSquareFree(baseMod)) return; - FactorDecomposition modularFactors = UnivariateFactorization.FactorInGF(baseMod); + PolynomialFactorDecomposition modularFactors = UnivariateFactorization.FactorInGF(baseMod); FactorDecompositionTest.assertFactorization(baseMod, modularFactors); HenselLifting.LiftFactory factory = quadratic ? HenselLifting::createQuadraticLift : HenselLifting::createLinearLift; @@ -175,7 +176,8 @@ static void testMultiFactorHenselLifting(UnivariatePolynomial base, } static void testMultiFactorHenselLifting(UnivariatePolynomial base, long modulus) { - testMultiFactorHenselLifting(base, modulus, true); + if (modulus != 2) + testMultiFactorHenselLifting(base, modulus, true); testMultiFactorHenselLifting(base, modulus, false); } @@ -218,6 +220,13 @@ public void testHensel7_random() throws Exception { } } + @Test + public void testHensel7a() throws Exception { + // this test fails for quadratic lift! + UnivariatePolynomial p = UnivariatePolynomial.create(Rings.Z, new BigInteger("4271820198621840811"), new BigInteger("1768988355559832895"), new BigInteger("7107643281356923096"), new BigInteger("-7999375386840606827"), new BigInteger("7590582635453818114"), new BigInteger("4968505934869881522"), new BigInteger("1149778124801408034"), new BigInteger("3410967848693539681")); + testMultiFactorHenselLifting(p, 2, false); + } + @Test @Benchmark public void testHensel8_linear_vs_quadratic() throws Exception { @@ -337,7 +346,7 @@ public void testHensel9_random() throws Exception { while (!UnivariateSquareFreeFactorization.isSquareFree(poly.setRing(domain)) || polyMod.degree() != poly.degree()); BigInteger desiredBound = UnivariatePolynomial.mignotteBound(poly).shiftLeft(1).multiply(poly.lc()); - FactorDecomposition modularFactors = UnivariateFactorization.FactorInGF(UnivariatePolynomial.asOverZp64(polyMod)); + PolynomialFactorDecomposition modularFactors = UnivariateFactorization.FactorInGF(UnivariatePolynomial.asOverZp64(polyMod)); BigInteger bModulus = BigInteger.valueOf(modulus); long start; diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/IrreduciblePolynomialsTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/IrreduciblePolynomialsTest.java index 1cf1e29..eba81ba 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/IrreduciblePolynomialsTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/IrreduciblePolynomialsTest.java @@ -2,7 +2,7 @@ import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.util.RandomDataGenerator; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; @@ -24,7 +24,7 @@ public void testIrreducibleRandom1() throws Exception { for (int i = 0; i < nIterations; i++) { long modulus = getModulusRandom(rndd.nextInt(5, 15)); UnivariatePolynomialZp64 poly = RandomUnivariatePolynomials.randomMonicPoly(rndd.nextInt(5, 15), modulus, rnd); - FactorDecomposition factors = UnivariateFactorization.Factor(poly); + PolynomialFactorDecomposition factors = UnivariateFactorization.Factor(poly); try { Assert.assertEquals(factors.size() == 1, IrreduciblePolynomials.irreducibleQ(poly)); } catch (Throwable e) { diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateFactorizationTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateFactorizationTest.java index a2d1949..3846bf4 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateFactorizationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateFactorizationTest.java @@ -4,7 +4,7 @@ import cc.redberry.rings.Rational; import cc.redberry.rings.Rings; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.FactorDecompositionTest; import cc.redberry.rings.poly.FiniteField; import cc.redberry.rings.primes.SmallPrimes; @@ -38,7 +38,7 @@ public void test2() throws Exception { BigInteger.valueOf(Long.MAX_VALUE - 2)); for (int i = 0; i < 5; i++) poly = poly.square().add(poly.derivative()).increment(); - FactorDecomposition> fct = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition> fct = UnivariateFactorization.FactorInGF(poly); Assert.assertEquals(7, fct.size()); FactorDecompositionTest.assertFactorization(poly, fct); } @@ -76,15 +76,15 @@ public void test4_randomZp() throws Exception { } try { - FactorDecomposition lFactors = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition lFactors = UnivariateFactorization.FactorInGF(poly); assertTrue(lFactors.sumExponents() >= expectedNFactors); FactorDecompositionTest.assertFactorization(poly, lFactors); if (n % 100 == 0) { - FactorDecomposition> bFactors = UnivariateFactorization.FactorInGF(poly.toBigPoly()); - FactorDecomposition> converted = UnivariateFactorization.convertFactorizationToBigIntegers(lFactors); - converted.canonicalForm(); - bFactors.canonicalForm(); + PolynomialFactorDecomposition> bFactors = UnivariateFactorization.FactorInGF(poly.toBigPoly()); + PolynomialFactorDecomposition> converted = UnivariateFactorization.convertFactorizationToBigIntegers(lFactors); + converted.canonical(); + bFactors.canonical(); Assert.assertEquals(converted, bFactors); } } catch (Throwable e) { @@ -100,7 +100,7 @@ public void test4_randomZp() throws Exception { public void test4a() throws Exception { long modulus = 59; UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64.create(46, 16, 1, 54, 16, 57, 22, 15, 31, 21).modulus(modulus); - FactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, fct); assertEquals(5, fct.size()); assertEquals(6, fct.sumExponents()); @@ -112,7 +112,7 @@ public void test4b() throws Exception { PrivateRandom.getRandom().setSeed(i); long modulus = 3; UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64.parse("2*x^2+2*x^3+2*x^5+x^7+2*x^9+2*x^10+x^11+2*x^12+x^13+2*x^14+x^16+x^18+x^19+2*x^20+2*x^21").modulus(modulus); - FactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, fct); assertEquals(6, fct.size()); assertEquals(15, fct.sumExponents()); @@ -124,7 +124,7 @@ public void test4c() throws Exception { PrivateRandom.getRandom().setSeed(76); long modulus = 3; UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64.parse("2*x^2+2*x^3+2*x^5+x^7+2*x^9+2*x^10+x^11+2*x^12+x^13+2*x^14+x^16+x^18+x^19+2*x^20+2*x^21").modulus(modulus); - FactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, fct); assertEquals(6, fct.size()); assertEquals(15, fct.sumExponents()); @@ -135,7 +135,7 @@ public void test4e() throws Exception { PrivateRandom.getRandom().setSeed(4178); long modulus = 29; UnivariatePolynomialZp64 poly = UnivariatePolynomialZ64.parse("10+25*x+23*x^2+7*x^3+21*x^4+9*x^5+9*x^6+16*x^7+10*x^8+24*x^9+3*x^10+24*x^11+8*x^12").modulus(modulus); - FactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition fct = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, fct); assertEquals(8, fct.size()); assertEquals(9, fct.sumExponents()); @@ -160,7 +160,7 @@ public void test5_randomZ() throws Exception { break; } - FactorDecomposition> lFactors = UnivariateFactorization.FactorInZ(poly); + PolynomialFactorDecomposition> lFactors = UnivariateFactorization.FactorInZ(poly); assertTrue(lFactors.size() >= expectedNFactors); FactorDecompositionTest.assertFactorization(poly, lFactors); } @@ -186,7 +186,7 @@ public void test6_referenceZ() throws Exception { long start; start = System.nanoTime(); - FactorDecomposition factorsZp = UnivariateFactorization.FactorInGF(polyMod); + PolynomialFactorDecomposition factorsZp = UnivariateFactorization.FactorInGF(polyMod); long timeZp = System.nanoTime() - start; timingZp.addValue(timeZp); FactorDecompositionTest.assertFactorization(polyMod, factorsZp); @@ -194,7 +194,7 @@ public void test6_referenceZ() throws Exception { assertEquals(5, factorsZp.size()); start = System.nanoTime(); - FactorDecomposition factorsZ = UnivariateFactorization.FactorInZ(poly); + PolynomialFactorDecomposition factorsZ = UnivariateFactorization.FactorInZ(poly); long timeZ = System.nanoTime() - start; timingZ.addValue(timeZ); FactorDecompositionTest.assertFactorization(poly, factorsZ); @@ -251,7 +251,7 @@ public void test7_referenceZb() throws Exception { if (i == 1000) timing.clear(); long start = System.nanoTime(); - FactorDecomposition> factors = UnivariateFactorization.FactorInZ(poly); + PolynomialFactorDecomposition> factors = UnivariateFactorization.FactorInZ(poly); long time = System.nanoTime() - start; timing.addValue(time); assertEquals(9, factors.size()); @@ -297,7 +297,7 @@ public void testFiniteField1() throws Exception { poly2 = UnivariatePolynomial.create(domain, c5, c4, c3, c2, c1, c0), poly = poly1.clone().multiply(poly2).multiply(poly1.clone().add(poly2)); - FactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, factors); } @@ -345,7 +345,7 @@ private static void testFiniteFieldRandom(int minModulusBits, int maxModulusBits poly = poly.multiply(m); } - FactorDecomposition> lFactors = null; + PolynomialFactorDecomposition> lFactors = null; try { long start = System.nanoTime(); lFactors = UnivariateFactorization.FactorInGF(poly); @@ -383,7 +383,7 @@ public void testFiniteField2() throws Exception { UnivariatePolynomialZ64.create(1, 0, 1).modulus(2), UnivariatePolynomialZ64.create(0, 0, 1).modulus(2)); - FactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); + PolynomialFactorDecomposition> factors = UnivariateFactorization.FactorInGF(poly); FactorDecompositionTest.assertFactorization(poly, factors); } @@ -393,7 +393,7 @@ public void testFiniteField3a() throws Exception { FiniteField domain = new FiniteField<>(irreducible); UnivariatePolynomial input = UnivariatePolynomial.parse("(1+x+x^2)+(1+x+x^2)*x+(1+x+x^3)*x^4+x^6", domain); PrivateRandom.getRandom().setSeed(1); - FactorDecomposition> factors = UnivariateFactorization.Factor(input); + PolynomialFactorDecomposition> factors = UnivariateFactorization.Factor(input); assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(input, factors); } @@ -404,7 +404,7 @@ public void testFiniteField3b() throws Exception { FiniteField domain = new FiniteField<>(irreducible); UnivariatePolynomial input = UnivariatePolynomial.parse("(1+x+x^2)+(1+x+x^2)*x+(1+x+x^3)*x^4+x^6", domain); PrivateRandom.getRandom().setSeed(43); - FactorDecomposition> factors = UnivariateFactorization.Factor(input); + PolynomialFactorDecomposition> factors = UnivariateFactorization.Factor(input); assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(input, factors); } @@ -417,7 +417,7 @@ public void testFiniteField3() throws Exception { for (int i = 0; i < its(10, 10); i++) { PrivateRandom.getRandom().setSeed(i); long start = System.nanoTime(); - FactorDecomposition> factors = UnivariateFactorization.Factor(input); + PolynomialFactorDecomposition> factors = UnivariateFactorization.Factor(input); System.out.println(TimeUnits.nanosecondsToString(System.nanoTime() - start)); assertEquals(2, factors.size()); FactorDecompositionTest.assertFactorization(input, factors); @@ -432,8 +432,8 @@ public void testRationals() throws Exception { f3 = UnivariatePolynomial.parse("1 - x^2 + x^3", Rings.Q), poly = f1.createOne().multiply(f1, f2, f3); - FactorDecomposition>> fct = UnivariateFactorization.Factor(poly); + PolynomialFactorDecomposition>> fct = UnivariateFactorization.Factor(poly); Assert.assertEquals(3, fct.size()); - Assert.assertEquals(poly, fct.toPolynomial()); + Assert.assertEquals(poly, fct.multiply()); } } \ No newline at end of file diff --git a/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorizationTest.java b/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorizationTest.java index 232abb4..cbc3bec 100644 --- a/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorizationTest.java +++ b/rings/src/test/java/cc/redberry/rings/poly/univar/UnivariateSquareFreeFactorizationTest.java @@ -2,7 +2,7 @@ import cc.redberry.rings.IntegersZp; import cc.redberry.rings.bigint.BigInteger; -import cc.redberry.rings.poly.FactorDecomposition; +import cc.redberry.rings.poly.PolynomialFactorDecomposition; import cc.redberry.rings.poly.FiniteField; import cc.redberry.rings.poly.univar.FactorizationTestUtil.RandomSource; import cc.redberry.rings.test.Benchmark; @@ -63,11 +63,11 @@ public void testRandom2() throws Exception { } try { long start = System.nanoTime(); - FactorDecomposition yunFactorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationYun0(poly); + PolynomialFactorDecomposition yunFactorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationYun0(poly); yun.addValue(System.nanoTime() - start); start = System.nanoTime(); - FactorDecomposition musserFactorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationMusserZeroCharacteristics(poly); + PolynomialFactorDecomposition musserFactorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationMusserZeroCharacteristics(poly); musser.addValue(System.nanoTime() - start); assertEquals(yunFactorization.factors.size(), musserFactorization.factors.size()); @@ -88,7 +88,7 @@ public void testRandom2() throws Exception { @Test public void test3() throws Exception { UnivariatePolynomialZ64 poly = UnivariatePolynomialZ64.create(0, 0, -1458, 6561, -6561); - FactorDecomposition factorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationYun0(poly); + PolynomialFactorDecomposition factorization = UnivariateSquareFreeFactorization.SquareFreeFactorizationYun0(poly); assertFactorization(poly, factorization); } @@ -133,7 +133,7 @@ void run(int bound, int maxDegree, int maxNBase, int maxExponent, int nIteration arithmetics.addValue(System.nanoTime() - start); try { start = System.nanoTime(); - FactorDecomposition factorization = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); + PolynomialFactorDecomposition factorization = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); timings.addValue(System.nanoTime() - start); assertFactorization(poly, factorization); } catch (ArithmeticException exc) { @@ -231,7 +231,7 @@ public void test10() throws Exception { UnivariatePolynomial original = poly.add(poly.derivative()); UnivariatePolynomial squared = original.clone().square(); - FactorDecomposition> f = SquareFreeFactorization(squared); + PolynomialFactorDecomposition> f = SquareFreeFactorization(squared); assertEquals(1, f.size()); assertEquals(2, f.getExponent(0)); assertEquals(original, f.get(0)); @@ -239,7 +239,7 @@ public void test10() throws Exception { UnivariatePolynomial squaredMod = squared.setRing(new IntegersZp(BigInteger.LONG_MAX_VALUE.multiply(BigInteger.TWO).nextProbablePrime())); squaredMod = squaredMod.square(); - FactorDecomposition> fMod = SquareFreeFactorization(squaredMod); + PolynomialFactorDecomposition> fMod = SquareFreeFactorization(squaredMod); assertEquals(1, fMod.size()); assertEquals(4, fMod.getExponent(0)); assertFactorization(squaredMod, fMod); @@ -258,12 +258,12 @@ public void testRandom11() throws Exception { int exponent = rndd.nextInt(2, 4); poly = UnivariatePolynomialArithmetic.polyPow(poly, exponent, false); - FactorDecomposition> zf = SquareFreeFactorization(poly); + PolynomialFactorDecomposition> zf = SquareFreeFactorization(poly); assertTrue(zf.sumExponents() >= exponent); assertFactorization(poly, zf); UnivariatePolynomial polyMod = poly.setRing(new IntegersZp(RandomUtil.randomInt(bound, rnd).nextProbablePrime())); - FactorDecomposition> zpf = SquareFreeFactorization(polyMod); + PolynomialFactorDecomposition> zpf = SquareFreeFactorization(polyMod); assertTrue(zpf.sumExponents() >= exponent); assertFactorization(polyMod, zpf); } @@ -293,7 +293,7 @@ public void testFiniteField1() throws Exception { UnivariatePolynomialZ64.create(1, 0, 1).modulus(2), UnivariatePolynomialZ64.create(0, 0, 1).modulus(2)); - FactorDecomposition> factors = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); + PolynomialFactorDecomposition> factors = UnivariateSquareFreeFactorization.SquareFreeFactorization(poly); assertFactorization(poly, factors); } @@ -301,12 +301,12 @@ public void testFiniteField1() throws Exception { public void test12() throws Exception { for (int i = 1; i < 11; i++) { UnivariatePolynomialZ64 poly = UnivariatePolynomialZ64.monomial(1, i); - FactorDecomposition fct = SquareFreeFactorization(poly); + PolynomialFactorDecomposition fct = SquareFreeFactorization(poly); assertEquals(1, fct.size()); assertEquals(i, fct.getExponent(0)); assertEquals(1, fct.get(0).degree); - FactorDecomposition mfct = SquareFreeFactorization(poly.modulus(2)); + PolynomialFactorDecomposition mfct = SquareFreeFactorization(poly.modulus(2)); assertEquals(1, mfct.size()); assertEquals(i, mfct.getExponent(0)); assertEquals(1, mfct.get(0).degree);