/* * 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()); } } }