/*
* Karinto Library Project
*
* This software is distributed under a zlib-style license.
* See license.txt for more information.
*/
using System;
using System.Collections.Generic;
namespace Karinto
{
///
/// 多項式
///
public class Polynomial : ICloneable
{
///
/// 実質的な次数
///
public int Degree
{
get;
private set;
}
public PointList Extrema
{
get
{
switch (Degree)
{
case 0:
case 1:
return new PointList();
case 2:
return GetExtremaQuadratic();
default:
throw new NotImplementedException();
}
}
}
public List Coefficients { get; private set; }
public Polynomial(double[] coefficients)
{
Coefficients = new List(coefficients);
Degree = CountDegree();
}
public Polynomial(int degree)
{
Coefficients = new List(degree);
degree = 0;
}
public double GetValueAt(double x)
{
double v = 0;
for (int i = Degree; i >= 0; --i)
{
v *= x;
v += Coefficients[i];
}
return v;
}
public double[] GetValues(Range range, double step)
{
if (Math.Abs(step) < Double.Epsilon)
{
throw new ArgumentException("step must be non-zero value");
}
return null;
}
public double[] GetValues(double[] xArray)
{
double[] yArray = new double[xArray.Length];
for (int i = 0; i < xArray.Length; ++i)
{
yArray[i] = GetValueAt(xArray[i]);
}
return yArray;
}
public void Add(Polynomial src)
{
if (null == src) return; //エラーにする?
if (Degree > src.Degree)
{
for (int i = 0; i <= src.Degree; ++i)
{
Coefficients[i] += src.Coefficients[i];
}
return;
}
for (int i = 0; i <= src.Degree; ++i)
{
if (i <= Degree)
{
Coefficients[i] += src.Coefficients[i];
}
else
{
Coefficients.Insert(i, src.Coefficients[i]);
}
}
Degree = CountDegree();
}
public void Neg()
{
for (int i = 0; i <= Degree; ++i)
{
Coefficients[i] = -Coefficients[i];
}
}
public void Sub(Polynomial src)
{
Polynomial srcClone = (Polynomial)src.Clone();
srcClone.Neg();
Add(srcClone);
}
public void Mul(Polynomial src)
{
double[] newCoefficients = new double[src.Degree + Degree + 1];
for (int i = 0; i <= src.Degree; ++i)
{
double scale = src.Coefficients[i];
for (int j = 0; j <= Degree; ++j)
{
newCoefficients[i + j] = Coefficients[j] * scale;
}
}
Coefficients = new List(newCoefficients);
Degree = CountDegree();
}
public void Div(Polynomial src)
{
throw new NotImplementedException();
}
public void Integrate()
{
Integrate(0.0);
}
///
/// 不定積分
///
///
public void Integrate(double constant)
{
throw new NotImplementedException();
}
///
/// 定積分
///
///
public void Integrate(Range range)
{
throw new NotImplementedException();
}
private PointList GetExtremaQuadratic()
{
PointList list = new PointList();
double x = -0.5 * Coefficients[1] / Coefficients[2];
double y = Coefficients[0] - 0.25 * Coefficients[1] * Coefficients[1] / Coefficients[2];
list.Add(x, y);
return list;
}
public override string ToString()
{
if (Degree < 6)
{
string s = "Polynomial f(x) =";
for (int i = Degree; i >= 0; --i)
{
string num;
double c = Coefficients[i];
if (Math.Abs(c) < Double.Epsilon) continue;
if (c % 1.0 < Double.Epsilon)
{
num = c.ToString();
}
else
{
num = c.ToString();
}
string sign = (c > 0) ? " +" : " ";
s += sign + num;
switch (i)
{
case 0:
break;
case 1:
s += " x";
break;
default:
s += " x^" + i.ToString();
break;
}
}
return s;
}
return base.ToString();
}
private int CountDegree()
{
int d = Coefficients.Count;
while (--d >= 0)
{
if (Math.Abs(Coefficients[d]) > Double.Epsilon) break;
}
return d;
}
public override bool Equals(object obj)
{
Polynomial poly = obj as Polynomial;
if (null == poly) return false;
if (poly.Degree != Degree) return false;
for (int i = 0; i < Degree; ++i)
{
if (Math.Abs(poly.Coefficients[i] - Coefficients[i]) >= Double.Epsilon)
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
int hash = Degree;
double s = 1.0;
foreach (double c in Coefficients)
{
hash ^= (int)(c * s) & 0x7FFFFFFF;
s += s;
}
return hash;
}
public object Clone()
{
return new Polynomial(Coefficients.ToArray());
}
}
}