diff --git a/README.md b/README.md
index 044096c..638f08c 100644
--- a/README.md
+++ b/README.md
@@ -82,8 +82,8 @@ For using Rings solely in Java there is Maven artifact:
```
-Examples: algebra, GCDs, factorization
---------------------------------------
+Examples: algebra, GCDs, factorization, programming
+---------------------------------------------------
Below examples can be evaluated directly in the Rings.repl. If using Rings in Scala, the following preambula will import all required things from Rings library:
@@ -336,6 +336,97 @@ implicit val ring = MultivariateRing(cfRing, Array("a", "b", "c"))
val poly = ring("1 - (1 - z^3) * a^6*b + (1 - 2*z) * c^33 + a^66")
```
+
+------------------------------------------------------------------------
+
+Implement generic function for solving linear Diophantine equations:
+
+```scala
+/**
+ * Solves equation \sum f_i s_i = gcd(f_1, \dots, f_N) for given f_i and unknown 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))
+ }
+```
+
+Implement generic function for computing partial fraction decomposition:
+
+```scala
+/** 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)))(_ + _)
+}
+```
+
+
+Apply that function to elements of different rings:
+
+```scala
+// 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)") )
+```
+
+
+------------------------------------------------------------------------
+
+Implement Lagrange method for univariate interpolation:
+
+```latex
+ p(x) = \sum_i p(x_i) \Pi_{j \ne i} \frac{x_{\phantom{i}} - x_j}{x_i -x_j}
+```
+
+```scala
+/** Lagrange polynomial interpolation formula */
+def interpolate[Poly <: IUnivariatePolynomial[Poly], Coef]
+ (points: Seq[(Coef, Coef)])
+ (implicit ring: IUnivariateRing[Poly, Coef]) = {
+ // implicit coefficient ring (setups algebraic operators on type Coef)
+ implicit val cfRing: Ring[Coef] = ring.cfRing
+ if (!cfRing.isField) throw new IllegalArgumentException
+ points.indices
+ .foldLeft(ring(0)) { case (sum, i) =>
+ sum + points.indices
+ .filter(_ != i)
+ .foldLeft(ring(points(i)._2)) { case (product, j) =>
+ product * (ring.`x` - points(j)._1) / (points(i)._1 - points(j)._1)
+ }
+ }
+ }
+```
+
+
+Interpolate polynomial from `Frac(Z_{13}[a,b,c])[x]`:
+
+
+```scala
+// coefficient ring Frac(Z/13[a,b,c])
+val cfRing = Frac(MultivariateRingZp64(2, Array("a", "b", "c")))
+val (a, b, c) = cfRing("a", "b", "c")
+
+implicit val ring = UnivariateRing(cfRing, "x")
+// interpolate with Lagrange formula
+val data = Seq(a -> b, b -> c, c -> a)
+val poly = interpolate(data)
+assert(data.forall { case (p, v) => poly.eval(p) == v })
+```
+
Highlighted benchmarks
----------------------
diff --git a/doc/quickstart.rst b/doc/quickstart.rst
index 033bd7d..fc17a1f 100644
--- a/doc/quickstart.rst
+++ b/doc/quickstart.rst
@@ -71,8 +71,8 @@ For using |Rings| solely in Java there is Maven artifact:
2.1
-Examples: algebra, GCDs, factorization
-======================================
+Examples: algebra, GCDs, factorization, programming
+===================================================
Below examples can be evaluated directly in the |Rings|\ *.repl*. For Scala/Java the following preambula will import all required things from |Rings| library:
@@ -617,6 +617,110 @@ Ring of multivariate polynomials over elements of Galois field :math:`GF(7^{3})[
poly = ring.parse("1 - (1 - z^3) * a^6*b + (1 - 2*z) * c^33 + a^66");
+----
+
+Implement generic function for solving linear Diophantine equations:
+
+
+.. tabs::
+
+ .. code-tab:: scala
+
+ /**
+ * Solves equation \sum f_i s_i = gcd(f_1, \dots, f_N) for given f_i and unknown 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))
+ }
+
+
+Implement generic function for computing partial fraction decomposition:
+
+.. tabs::
+
+ .. code-tab:: scala
+
+ /** 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)))(_ + _)
+ }
+
+
+Apply that function to elements of different rings:
+
+
+.. tabs::
+
+ .. code-tab:: scala
+
+ // 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)") )
+
+
+----
+
+Implement Lagrange method for univariate interpolation:
+
+.. math::
+
+ p(x) = \sum_i p(x_i) \Pi_{j \ne i} \frac{x_{\phantom{i}} - x_j}{x_i -x_j}
+
+
+.. tabs::
+
+ .. code-tab:: scala
+
+ /** Lagrange polynomial interpolation formula */
+ def interpolate[Poly <: IUnivariatePolynomial[Poly], Coef]
+ (points: Seq[(Coef, Coef)])
+ (implicit ring: IUnivariateRing[Poly, Coef]) = {
+ // implicit coefficient ring (setups algebraic operators on type Coef)
+ implicit val cfRing: Ring[Coef] = ring.cfRing
+ if (!cfRing.isField) throw new IllegalArgumentException
+ points.indices
+ .foldLeft(ring(0)) { case (sum, i) =>
+ sum + points.indices
+ .filter(_ != i)
+ .foldLeft(ring(points(i)._2)) { case (product, j) =>
+ product * (ring.`x` - points(j)._1) / (points(i)._1 - points(j)._1)
+ }
+ }
+ }
+
+
+Interpolate polynomial from :math:`Frac(Z_{13}[a,b,c])[x]`:
+
+
+.. tabs::
+
+ .. code-tab:: scala
+
+ // coefficient ring Frac(Z/13[a,b,c])
+ val cfRing = Frac(MultivariateRingZp64(2, Array("a", "b", "c")))
+ val (a, b, c) = cfRing("a", "b", "c")
+
+ implicit val ring = UnivariateRing(cfRing, "x")
+ // interpolate with Lagrange formula
+ val data = Seq(a -> b, b -> c, c -> a)
+ val poly = interpolate(data)
+ assert(data.forall { case (p, v) => poly.eval(p) == v })
+
.. _ref-some-benchamrks: