/* Math.Nhtsa.Differentiation.cs 24 November 2009 - Adapted from old Dave codebase to generic DTS utility, with appropriate name change. $Log: Math.Nhtsa.ChannelDifferentiation.cs,v $ Revision 1.2 2007/04/20 17:40:42 Paul Hrissikopoulos Fixed bad range checking in sample rate property set accessor. Revision 1.1 2007/02/05 17:17:08 Paul Hrissikopoulos Finished installing generic channel math framework + basic calculus operations. Copyright © 2007 Diversified Technical Systems, Inc. All Rights Reserved */ using System; using System.Collections.Generic; using System.Text; using DTS.Common.Utilities.DotNetProgrammingConstructs; namespace DTS.Common.Utilities.Math.Nhtsa { //////////////////////////////////////////////////////////////////////////////// /// /// Representation of a NHTSA-based differentiation channel operation. /// public class Differentiation : DoubleListOperation { //////////////////////////////////////////////////////////////////////////////// /// /// Get/set the sample rate for this data to be differentiated. /// public double SampleRate { get => _SampleRate.Value; set => _SampleRate.Value = value; } private Property _SampleRate = new Property( typeof(Differentiation).FullName + ".SampleRate", 0.0, false ); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Initialize an instance of the ChannelDifferentiation class. /// /// /// /// The System.Collections.Generic.IList of domain for /// this operation. /// /// public Differentiation(IList domain) : base(domain) { // // I'd prefer to do this statically, but I don't know of any C# way to place a constraint // on a generic type that's already been determined by some ancestor we're inheriting from, // so for now we'll have to dynamically check it on object instantiation. // if (!(domain is ICloneable)) throw new InvalidCastException("the domain type for " + typeof(Differentiation).FullName + " must be ICloneable"); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Initialize an instance of the Iso.ChannelDifferentiation class. /// /// /// /// The System.Collections.Generic.IList of domain for /// this operation. /// /// /// /// The sample rate of the channel to be differentiated. /// /// public Differentiation(IList domain, int sampleRate) : this(domain) { try { SampleRate = sampleRate; } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Get the System.Collections.Generic.IList of result of /// the operation on the target domain. /// public override IList Range { get { try { if (null == Domain) throw new ArgumentNullException("attempted to differentiate null channel reference"); else if (0 >= SampleRate) throw new ArgumentOutOfRangeException("SampleRate must be greater than zero"); else if (!(Domain is ICloneable)) throw new InvalidCastException("the domain type for " + typeof(Differentiation).FullName + " must be ICloneable"); else { var IndexOfLastSample = Domain.Count - 1; var deltaT = SampleRate / 2; var range = ((ICloneable)Domain).Clone() as IList; for (var t = 1; t < IndexOfLastSample; t++) range[t] = (Domain[t + 1] - Domain[t - 1]) * deltaT; range[0] = (-7 * Domain[0] + 6 * Domain[1] + 3 * Domain[2] - 2 * Domain[3]) * deltaT / 3; range[IndexOfLastSample] = (-7 * Domain[IndexOfLastSample] + 6 * Domain[IndexOfLastSample - 1] + 3 * Domain[IndexOfLastSample - 2] - 2 * Domain[IndexOfLastSample - 3]) * deltaT / 3; return range; } } catch (System.Exception ex) { throw new Exception("encountered problem doing " + GetType().FullName + " operation", ex); } } } //////////////////////////////////////////////////////////////////////////////// } //////////////////////////////////////////////////////////////////////////////// }