using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using CategoryTheory;
using DiagramUI;
using System.IO;
using DiagramUI.Labels;
using DataPerformer.Interfaces;
namespace DataPerformer
{
/// <summary>
/// Table of two parameters
/// This table uses linear interpolation
/// </summary>
[Serializable()]
public class Table2D : CategoryObject, ISerializable, IDataConsumer, IMeasurements, IPostSetArrow
{
#region Fields
/// <summary>
/// Output measurements
/// </summary>
private IMeasure output;
/// <summary>
/// Results of calculation
/// </summary>
private double[] result = new double[2];
/// <summary>
/// Arguments
/// </summary>
private string[] arguments;
/// <summary>
/// Input measurements
/// </summary>
private IMeasure[] input = new IMeasure[2];
/// <summary>
/// The x, y - arguments
/// </summary>
private readonly string[] xy = new string[] { "x", "y" };
/// <summary>
/// Arguments values
/// </summary>
private double[][] args = new double[2][];
/// <summary>
/// Function values
/// </summary>
private double[,] fun;
/// <summary>
/// Arguments
/// </summary>
private double[] arg = new double[2];
/// <summary>
/// Grid node coordinates
/// </summary>
private int[] nm = new int[2];
/// <summary>
/// derivations
/// </summary>
private double[] der = new double[2];
/// <summary>
/// Measurements
/// </summary>
private List<IMeasurements> measurements = new List<IMeasurements>();
/// <summary>
/// The "is updated" sign
/// </summary>
private bool isUpdated;
/// <summary>
/// The "has derivation" sign
/// </summary>
private bool hasDerivation;
/// <summary>
/// The "throws out of range exception" sign
/// </summary>
private bool throwsOutOfRangeException = true;
#endregion
#region Ctor
/// <summary>
/// Default constructor
/// </summary>
public Table2D()
{
arguments = new string[] { "", "" };
init();
}
/// <summary>
/// Deserilaization constructor
/// </summary>
/// <param name="info">Serialization Info</param>
/// <param name="context">Streaming Context</param>
protected Table2D(SerializationInfo info, StreamingContext context)
{
arguments = (string[])info.GetValue("Arguments", typeof(string[]));
args = (double[][])info.GetValue("Args", typeof(double[][]));
fun = (double[,])info.GetValue("Fun", typeof(double[,]));
Double a = 0;
output = new MeasureDerivation(a, new Func<object>(getFunction), new Measure(getDerivation, "Der_Value"), "Value");
try
{
throwsOutOfRangeException =
info.GetBoolean("ThrowsOutOfRangeException");
}
catch (Exception ex)
{
ex.Log();
}
}
#endregion
#region ISerializable Members
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Arguments", arguments);
info.AddValue("Args", args);
info.AddValue("Fun", fun);
info.AddValue("ThrowsOutOfRangeException", throwsOutOfRangeException);
}
#endregion
#region IDataConsumer Members
void IDataConsumer.Add(IMeasurements measurements)
{
this.measurements.Add(measurements);
}
void IDataConsumer.Remove(IMeasurements measurements)
{
this.measurements.Remove(measurements);
}
void IDataConsumer.UpdateChildrenData()
{
StaticDataPerformer.UpdateChildrenData(measurements);
}
int IDataConsumer.Count
{
get { return measurements.Count; }
}
IMeasurements IDataConsumer.this[int n]
{
get { return measurements[n]; }
}
void IDataConsumer.Reset()
{
this.FullReset();
}
#endregion
#region IMeasurements Members
int IMeasurements.Count
{
get { return 1; }
}
IMeasure IMeasurements.this[int n]
{
get { return output; }
}
void IMeasurements.UpdateMeasurements()
{
if (isUpdated)
{
return;
}
try
{
IDataConsumer c = this;
c.UpdateChildrenData();
for (int i = 0; i < 2; i++)
{
arg[i] = (double)input[i].Parameter();
if ((arg[i] < args[i][0]) | (arg[i] > args[i][args[i].Length - 1]))
{
if (throwsOutOfRangeException)
{
throw new Exception("Out of range");
}
}
for (int j = 0; j < args[i].Length - 1; j++)
{
if (arg[i] >= args[i][j] & arg[i] <= args[i][j + 1])
{
nm[i] = j;
goto m;
}
}
nm[i] = args[i].Length - 1;
m:
continue;
}
double f = fun[nm[0], nm[1]];
result[0] = f;
result[1] = 0;
double delta = 0;
for (int i = 0; i < 2; i++)
{
double d = 0;
if (i == 0)
{
int k = nm[0] + 1;
if (k >= args[0].Length)
{
k = args[0].Length - 1;
}
d = fun[k, nm[1]];
delta = args[0][k] - args[0][nm[0]];
}
else
{
int k = nm[1] + 1;
if (k >= args[1].Length)
{
k = args[1].Length - 1;
}
d = fun[nm[0], k];
delta = args[1][k] - args[1][nm[1]];
}
double dx = (d - f) / delta;
result[0] += dx * (arg[i] - args[i][nm[i]]);
if (!hasDerivation)
{
continue;
}
IDerivation der = input[i] as IDerivation;
result[1] += dx * (double)der.Derivation.Parameter();
}
isUpdated = true;
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
bool IMeasurements.IsUpdated
{
get
{
return isUpdated;
}
set
{
isUpdated = value;
}
}
#endregion
#region IPostSetArrow Members
void IPostSetArrow.PostSetArrow()
{
try
{
acceptArguments();
}
catch (Exception ex)
{
ex.Log();
}
}
#endregion
#region Specific Members
/// <summary>
/// Arguments
/// </summary>
public string[] Arguments
{
get
{
return arguments;
}
}
/// <summary>
/// Loading
/// </summary>
/// <param name="stream">The stream to load</param>
public void Load(Stream stream)
{
BinaryReader reader = new BinaryReader(stream);
int n = reader.ReadInt32();
int m = reader.ReadInt32();
args[0] = new double[n];
args[1] = new double[m];
for (int i = 0; i < args.Length; i++)
{
for (int j = 0; j < args[i].Length; j++)
{
args[i][j] = reader.ReadDouble();
}
}
fun = new double[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
fun[i, j] = reader.ReadDouble();
}
}
}
/// <summary>
/// Saving
/// </summary>
/// <param name="stream">The stream to save</param>
public void Save(Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(args[0].Length);
writer.Write(args[1].Length);
for (int i = 0; i < args.Length; i++)
{
for (int j = 0; j < args[i].Length; j++)
{
writer.Write(args[i][j]);
}
}
for (int i = 0; i < fun.GetLength(0); i++)
{
for (int j = 0; j < fun.GetLength(1); j++)
{
writer.Write(fun[i, j]);
}
}
}
/// <summary>
/// Count of x coordinates
/// </summary>
public int XCount
{
get
{
return args[0].Length;
}
}
/// <summary>
/// Count of y coordinates
/// </summary>
public int YCount
{
get
{
return args[1].Length;
}
}
/// <summary>
/// Gets i - th x coordinate
/// </summary>
/// <param name="i">Coordinate number</param>
/// <returns>The coordinate</returns>
public double GetX(int i)
{
return args[0][i];
}
/// <summary>
/// Gets i - th y coordinate
/// </summary>
/// <param name="i">Coordinate number</param>
/// <returns>The coordinate</returns>
public double GetY(int i)
{
return args[1][i];
}
/// <summary>
/// Bounds of arguments
/// </summary>
public double[,] Bounds
{
get
{
double[,] b = new double[2, 2];
b[0, 0] = args[0][0];
b[0, 1] = args[0][args[0].Length - 1];
b[1, 0] = args[1][0];
b[1, 1] = args[1][args[1].Length - 1];
return b;
}
}
/// <summary>
/// Array of extremums
/// </summary>
public double[] Extremums
{
get
{
double[] e = new double[] { fun[0, 0], fun[0, 0] };
for (int i = 0; i < fun.GetLength(0); i++)
{
for (int j = 0; j < fun.GetLength(1); j++)
{
double x = fun[i, j];
if (x < e[0])
{
e[0] = x;
}
if (x > e[1])
{
e[1] = x;
}
}
}
return e;
}
}
/// <summary>
/// Access to i, j function
/// </summary>
public double this[int i, int j]
{
get
{
return fun[i, j];
}
}
/// <summary>
/// The "throws out of range exception" sign
/// </summary>
public bool ThrowsOutOfRangeException
{
get
{
return throwsOutOfRangeException;
}
set
{
throwsOutOfRangeException = value;
}
}
/// <summary>
/// Gets function value
/// </summary>
/// <returns>The value</returns>
private object getFunction()
{
return result[0];
}
/// <summary>
/// Gets function derivation
/// </summary>
/// <returns>The derivation</returns>
private object getDerivation()
{
return result[1];
}
/// <summary>
/// Accepts arguments
/// </summary>
private void acceptArguments()
{
foreach (IMeasurements measurements in this.measurements)
{
IAssociatedObject cont = measurements as IAssociatedObject;
INamedComponent c = cont.Object as INamedComponent;
string name = c.Name;
for (int i = 0; i < measurements.Count; i++)
{
IMeasure measure = measurements[i];
string p = name + "." + measure.Name;
for (int j = 0; j < 2; j++)
{
if (arguments[j].Equals(p))
{
input[j] = measure;
break;
}
}
}
}
for (int i = 0; i < 2; i++)
{
if (arguments[i].Equals("Time"))
{
input[i] = StaticDataPerformer.Factory.TimeProvider.TimeMeasure;
}
}
hasDerivation = true;
for (int i = 0; i < input.Length; i++)
{
IDerivation der = input[i] as IDerivation;
if (der == null)
{
hasDerivation = false;
break;
}
}
}
void init()
{
args[0] = new double[10];
args[1] = new double[10];
for (int i = 0; i < args.Length; i++)
{
for (int j = 0; j < args[i].Length; j++)
{
args[i][j] = j;
}
}
fun = new double[args[0].Length, args[1].Length];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
fun[i, j] = i + j;
}
}
}
#endregion
}
}