export {
listEqual,
calcProductCoef,
calcProductCoefByList,
normalizePolynomList,
polynomListEqual,
combineSimilarTerms,
removeZeroTerms,
sortTermsByDeg,
normalizePolynom,
monomEqual,
polynomEqual,
}
type nat = number;
type someSemiring = number;
function calcProductCoef(n: nat,
p: (i: nat) => someSemiring, q: (j: nat) => someSemiring)
: someSemiring
{
let r: someSemiring = 0;
for (let i: nat = 0; i <= n; i++) {
r += p(i) * q(n - i);
}
return r;
}
function calcProductCoefByList(n: nat,
p: List<someSemiring>, q: List<someSemiring>)
: someSemiring
{
let r: someSemiring = 0;
for (let i: nat = 0; i <= n; i++) {
if (i < p.length && (n - i) < q.length) {
r += p[i] * q[n - i];
}
}
return r;
}
type EqType = number;
function listEqual(list1: Array<EqType>, list2: Array<EqType>)
: boolean
{
if (list1.length != list2.length) return false;
for (let i = 0; i < list1.length; i++) {
if (list1[i] != list1[i]) return false;
}
return true;
}
type List<X> = Array<X>;
function normalizePolynomList(list: List<someSemiring>)
:List<someSemiring>
{
let k:nat = list.length - 1;
while (k >= 0) {
if (list[k] != 0) break;
k--;
}
return list.slice(0, k + 1);
}
function polynomListEqual(list1: List<someSemiring>, list2: List<someSemiring>)
:boolean
{
let normalized_1 = normalizePolynomList(list1);
let normalized_2 = normalizePolynomList(list2);
return listEqual(normalized_1, normalized_2);
}
type Monom<R> = { coef: R, deg: nat };
type Polynom<R> = List<Monom<R>>;
function sumUpCoefs(list: List<Monom<someSemiring>>)
:someSemiring
{
let total:someSemiring = 0
for (let monom of list) {
total += monom.coef;
}
return total;
}
function combineSimilarTerms(p:Polynom<someSemiring>)
:Polynom<someSemiring>
{
let map:Map<nat, List<Monom<someSemiring>>>;
map = new Map<nat, List<Monom<someSemiring>>>();
for (let monom of p) {
if (!map.has(monom.deg)) {
map.set(monom.deg, []);
}
let a = map.get(monom.deg);
a!.push(monom);
}
let result:Polynom<someSemiring> = [];
for (let [deg, monomList] of map) {
let totalCoef:someSemiring = sumUpCoefs(monomList);
let combinedTerm:Monom<someSemiring> = {coef:totalCoef, deg:deg};
result.push(combinedTerm);
}
return result;
}
function removeZeroTerms(p:Polynom<someSemiring>)
:Polynom<someSemiring>
{
let result:Polynom<someSemiring> = [];
for (let monom of p) {
if (monom.coef == 0) continue;
result.push(monom);
}
return result;
}
function compareByDeg(m1: Monom<someSemiring>, m2: Monom<someSemiring>)
: number
{
return m1.deg > m2.deg ? 1 : (m1.deg == m2.deg ? 0 : -1);
}
function sortTermsByDeg(p:Polynom<someSemiring>)
:Polynom<someSemiring>
{
return p.slice().sort(compareByDeg);
}
function normalizePolynom(p:Polynom<someSemiring>)
:Polynom<someSemiring>
{
let q:Polynom<someSemiring> = p;
q = combineSimilarTerms(q);
q = removeZeroTerms(q);
q = sortTermsByDeg(q);
return q;
}
function monomEqual(m:Monom<someSemiring>,
n:Monom<someSemiring>)
:boolean
{
return m.coef == n.coef && m.deg == n.deg;
}
function polynomEqual(p:Polynom<someSemiring>,
q:Polynom<someSemiring>)
:boolean
{
let p1:Polynom<someSemiring> = normalizePolynom(p);
let q1:Polynom<someSemiring> = normalizePolynom(q);
if (p1.length != q1.length) return false;
for (let i = 0; i < p1.length; i++) {
if (!monomEqual(p1[i], q1[i])) return false;
}
return true;
}