/// <summary> /// SetValueScaled: change value from another ScaledType value, check for convertability of scales. /// </summary> /// <param name="value">New value (possibly in different scale)</param> /// <param name="copy">Action to be done by the child to get the correct value.</param> /// <returns>True if scales were convertable and a new value is set.</returns> /// <remarks> /// A value in DoubleST is required for scaling. /// Scaling is done with factors and these are (by design) doubles. /// </remarks> protected bool SetValueScaled(DoubleST value, Action <DoubleST> copy) { if (Scale == value.Scale) { copy(null); return(true); } var v1b = BaseFactor(); var v2b = value.BaseFactor(); if (v1b.Scale == v2b.Scale) { var v1n = BaseNormal(); var v2n = value.BaseNormal(); // var v2 = value * v1n / v2n copy(value * v1n / v2n); return(true); // extra check: //var result = (scale == v2.scale); //if (result) Value = v2.Value; //return result; } return(false); }
/// <summary> /// Mul operator *: Multiply two values. /// </summary> /// <param name="left">A value to multiply with</param> /// <param name="right">A value to multiply</param> /// <returns>(left.value * right.value, [Normalised(left.scale right.scale)])</returns> public static DoubleST Mul(DoubleST left, DoubleST right) { var result = new DoubleST(left.Value * right.Value, left.Scale); result.Append(right.Scale); return(result); }
/// <summary> /// Assign: assign a new value to this instance /// </summary> /// <param name="value">The new value</param> /// <exception cref="ArgumentOutOfRangeException">Scales of this and the other must be (syntactical) equivalents</exception> /// <remarks>It is not possible to override operator=()</remarks> public void Assign(DoubleST other) { if (ReferenceEquals(this, other)) { return; } base.Assign(other); Value = other.Value; }
/// <summary> /// Sub operator -: Subtract two values with equal scale. /// </summary> /// <param name="left">A value to subtract from</param> /// <param name="right">A value to subtract</param> /// <exception cref="ArgumentOutOfRangeException">left scale is not (semantical) equal to right scale.</exception> /// <returns>(left.value - right.value, [scale])</returns> public static DoubleST Sub(DoubleST left, DoubleST right) { if (left.Scale != right.Scale) { var msg = $"DoubleST: operation not supported: {left.Scale} - {right.Scale}"; //log.Debug(msg); throw new ArgumentOutOfRangeException(msg); } return(new DoubleST(left.Value - right.Value, left.Scale)); }
/// <summary> /// BaseFactor: expressing the ScaleType (1, [target]) in basic Units of the ScaleType /// </summary> /// <remarks> /// Example: ScaleType (1, [cm]) /// The BaseUnit for [cm] is Unit.Base, the meter [m] /// BaseNormal = (0.01, [m]), (1, [cm]) = (0.01, [m]) /// /// This value is usefull for checking if a conversion is possible from one value /// to another. Both value BaseFactors must have identical scales. /// /// Pitfall: Do not use for conversion! /// e.g.: /// (C1, [m]) = (1, [ft]) = BaseFactor([ft]) /// (C2, [m]) = (1, [cm]) = BaseFactor([cm]) /// then /// (y, [ft]) = (x, [cm])*(C2, [m])/(C1, [m]) /// = (x*C2/C1, [cm]) /// The value appears to be correct but the scale is incorrect. /// /// Note: The relation between /// (c1, [Unit.Base]) = BaseNormal([Unit]) and /// (C1, [Unit]) = BaseFactor([Unit]) /// is c1 = 1/C1 /// </remarks> /// <seealso cref="BaseNormal"/> /// <param name="target">A list of ScaledUnit instances that form the scale to use.</param> /// <returns> /// (x, [Unit.Base]), the conversion of (1, [Unit]) where Unit.Base is in { [m], [g], [s],... } /// </returns> static DoubleST BaseFactor(Scale target) { var result = new DoubleST(1.0); foreach (var s in target) { result.Append(s.Unit.Base(), s.Exp); result = result / s.Factor(); } return(result); }
/// <summary> /// Div operator /: Divide two values. /// </summary> /// <param name="left">A value to divide to</param> /// <param name="right">A value to divide with</param> /// <returns>(left.value / right.value, [Normalised(left.scale, right.scale^-1)])</returns> public static DoubleST Div(DoubleST left, DoubleST right) { if (right.Value == 0.0) { throw new DivideByZeroException($"{left} / {right} "); } var result = new DoubleST(left.Value / right.Value, left.Scale); result.Append(right.Scale, reciproce: true); return(result); }
/// <summary> /// .ctor: copy constructor. /// </summary> /// <param name="other">Data to copy.</param> public DoubleST(DoubleST other) : base(other.Scale) { Value = other.value; }