/// <summary>
        /// Adding quantities with different storage types
        /// </summary>
        /// <typeparam name="Q">Second Quantity Type</typeparam>
        /// <param name="firstQuantity"></param>
        /// <param name="secondQuantity"></param>
        /// <returns></returns>
        public static AnyQuantity <T> Add <Q>(AnyQuantity <T> firstQuantity, AnyQuantity <Q> secondQuantity)
        {
            if (firstQuantity.Equals(secondQuantity))
            {
                AnyQuantity <T> AQ = null;
                try
                {
                    AQ = QuantityDimension.QuantityFrom <T>(firstQuantity.Dimension);
                    //exception happen when adding two derived quantities together
                }
                catch (QuantityNotFoundException)
                {
                    //keep the first quantity configuration.
                    AQ = (AnyQuantity <T>)firstQuantity.Clone();
                }


                T firstVal = (firstQuantity.Value);

                Q secondVal = (secondQuantity.Value);

                //correct the values according to left unit or first unit.
                //the resulted quantity has the values of the first unit.

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    //factor from second unit to first unit
                    UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit);

                    secondVal = MultiplyScalarByGeneric <Q>(stof.ConversionFactor, secondVal);
                }


                var expr = Expression.Add(Expression.Constant(firstVal), Expression.Constant(secondVal));

                // Construct Lambda function which return one object.
                Expression <Func <T> > cq = Expression.Lambda <Func <T> >(expr);

                // compile the function
                Func <T> aqf = cq.Compile();

                // execute the function
                T result = aqf();

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    //assign the unit of first quantity to the result.
                    AQ.Unit = firstQuantity.Unit;
                }


                AQ.Value = result;

                return(AQ);
            }
            else
            {
                throw new QuantitiesNotDimensionallyEqualException();
            }
        }
        /// <summary>
        /// This is a specific raise to double storage quantity power.
        /// </summary>
        /// <param name="quantity"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        public static AnyQuantity <T> Power(AnyQuantity <T> quantity, AnyQuantity <double> exponent)
        {
            if (!exponent.Dimension.IsDimensionless)
            {
                throw new QuantityException("Raising Quantity to a non dimensionless quantity is not implemented", new NotImplementedException());
            }


            // and I am ignoring the units conversion also

            Unit unit = quantity.Unit.RaiseUnitPower((float)exponent.Value);


            AnyQuantity <T> result = null;

            if (unit.QuantityType != typeof(DerivedQuantity <>))
            {
                result = unit.MakeQuantity <T>(RaiseGenericByScalar(quantity.Value, exponent.Value));
            }
            else
            {
                result       = new DerivedQuantity <T>(unit.UnitDimension);
                result.Value = RaiseGenericByScalar(quantity.Value, exponent.Value);
                result.Unit  = unit;
            }

            Debug.Assert(result.Dimension.Equals(result.Unit.UnitDimension), "Dimensions are not equal after power");
            return(result);
        }
        public static AnyQuantity <T> Divide(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity)
        {
            //to preserve the units we make a derivedquantity with passed quantities
            // then we take the derived unit in temporary store
            // then we try to get strongly typed Quantity
            // then assign the unit to the generated quantity.
            // this way we won't have to know the unit system of the quantity.

            AnyQuantity <T> sec_qty = (AnyQuantity <T>)secondQuantity.Invert(); //this is a divide process we must make 1/exponenet :)


            AnyQuantity <T> qresult = (AnyQuantity <T>)ConstructDerivedQuantity(firstQuantity, sec_qty);


            try
            {
                qresult = QuantityDimension.QuantityFrom <T>(qresult.Dimension);
            }
            catch (QuantityNotFoundException)
            {
            }


            if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short))
            {
                qresult.Value = (T)(object)(((double)(object)firstQuantity.Value) * ((double)(object)sec_qty.Value));

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, sec_qty.Unit);
                    qresult.Unit = un;
                    if (un.IsOverflowed)
                    {
                        qresult.Value = (T)(object)(un.GetUnitOverflow() * ((double)(object)qresult.Value));
                    }
                }
            }
            else
            {
                qresult.Value = DivideGenericByGeneric(firstQuantity.Value, secondQuantity.Value);

                //check if any of the two quantities have a valid unit
                // to be able to derive the current quantity

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, sec_qty.Unit);
                    qresult.Unit = un;
                    if (un.IsOverflowed)
                    {
                        qresult.Value = MultiplyScalarByGeneric(un.GetUnitOverflow(), qresult.Value);
                    }
                }
            }

            return(qresult);
        }
        /// <summary>
        /// Raising power of the same storage types.
        /// </summary>
        /// <param name="firstQuantity"></param>
        /// <param name="secondQuantity"></param>
        /// <returns></returns>
        public static AnyQuantity <T> Power(AnyQuantity <T> quantity, AnyQuantity <T> exponent)
        {
            if (!(exponent.Dimension.IsDimensionless & quantity.Dimension.IsDimensionless))
            {
                throw new QuantityException("All quantities should be dimensionless, because I don't have a clue about your object power technique", new NotImplementedException());
            }


            AnyQuantity <T> result = new DimensionlessQuantities.DimensionlessQuantity <T>();

            result.Value = RaiseGenericByGeneric(quantity.Value, exponent.Value);

            return(result);
        }
Пример #5
0
        public override QuantitySystem.Quantities.BaseQuantities.BaseQuantity Invert()
        {
            AnyQuantity <T> q = (AnyQuantity <T>)base.Invert();


            q.Value = DivideScalarByGeneric(1.0, q.Value);

            if (q.Unit != null)
            {
                q.Unit = this.Unit.Invert();
            }

            return(q);
        }
        public static AnyQuantity <T> Multiply(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity)
        {
            AnyQuantity <T> qresult = (AnyQuantity <T>)ConstructDerivedQuantity <T>(firstQuantity, secondQuantity);

            try
            {
                //correct quantities and units
                qresult = QuantityDimension.QuantityFrom <T>(qresult.Dimension);
            }
            catch (QuantityNotFoundException)
            {
            }

            if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short))
            {
                qresult.Value = (T)(object)(((double)(object)firstQuantity.Value) * ((double)(object)secondQuantity.Value));

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, secondQuantity.Unit);
                    qresult.Unit = un;
                    if (un.IsOverflowed)
                    {
                        qresult.Value = (T)(object)(un.GetUnitOverflow() * ((double)(object)qresult.Value));
                    }
                }
            }
            else
            {
                qresult.Value = MultiplyGenericByGeneric(firstQuantity.Value, secondQuantity.Value);

                //check if any of the two quantities have a valid unit
                // to be able to derive the current quantity

                if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                {
                    Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, secondQuantity.Unit);
                    qresult.Unit = un;
                    if (un.IsOverflowed)
                    {
                        qresult.Value = MultiplyScalarByGeneric(un.GetUnitOverflow(), qresult.Value);
                    }
                }
            }


            return(qresult);
        }
        public static AnyQuantity <T> Mod(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity)
        {
            AnyQuantity <T> qresult = (AnyQuantity <T>)firstQuantity.Clone();


            if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short))
            {
                qresult.Value = (T)(object)(((double)(object)firstQuantity.Value) % ((double)(object)secondQuantity.Value));
            }
            else
            {
                qresult.Value = ModuloGenericByGeneric(firstQuantity.Value, secondQuantity.Value);
            }

            return(qresult);
        }
Пример #8
0
        /// <summary>
        /// Parse the input name and return the quantity object from it.
        /// </summary>
        /// <typeparam name="T">container type of the value</typeparam>
        /// <param name="quantityName"></param>
        /// <returns></returns>
        public static AnyQuantity <T> Parse(string quantityName)
        {
            Type QuantityType = QuantityDimension.QuantityTypeFrom(quantityName);

            if (QuantityType == null)
            {
                throw new QuantityNotFoundException();
            }
            else
            {
                //QuantityType = QuantityType.MakeGenericType(typeof(T));
                //AnyQuantity<T> qty = (AnyQuantity<T>)Activator.CreateInstance(QuantityType);

                AnyQuantity <T> qty = QuantityDimension.QuantityFrom <T>(QuantityDimension.DimensionFrom(QuantityType));
                return(qty);
            }
        }
        public static bool Inequality(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity)
        {
            if (firstQuantity.Equals(secondQuantity))
            {
                if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short))
                {
                    #region Premitive
                    //use direct calculations

                    double firstVal = (double)(object)firstQuantity.Value;

                    double secondVal = (double)(object)secondQuantity.Value;


                    //correct the values according to left unit or first unit.
                    //the resulted quantity has the values of the first unit.

                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //factor from second unit to first unit
                        UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit);

                        secondVal = stof.ConversionFactor * secondVal;
                    }

                    return(firstVal != secondVal);

                    #endregion
                }
                else
                {
                    #region Custom Types



                    T firstVal = (firstQuantity.Value);

                    T secondVal = (secondQuantity.Value);

                    //correct the values according to left unit or first unit.
                    //the resulted quantity has the values of the first unit.

                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //factor from second unit to first unit
                        UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit);


                        secondVal = MultiplyScalarByGeneric(stof.ConversionFactor, secondVal);
                    }

                    var expr = Expression.NotEqual(Expression.Constant(firstVal), Expression.Constant(secondVal));

                    // Construct Lambda function which return one object.
                    Expression <Func <bool> > cq = Expression.Lambda <Func <bool> >(expr);

                    // compile the function
                    Func <bool> aqf = cq.Compile();

                    // execute the function
                    bool result = aqf();

                    return(result);

                    #endregion
                }
            }
            else
            {
                throw new QuantitiesNotDimensionallyEqualException();
            }
        }
        public static AnyQuantity <T> Subtract(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity)
        {
            if (firstQuantity.Equals(secondQuantity))
            {
                AnyQuantity <T> AQ = null;
                try
                {
                    AQ = QuantityDimension.QuantityFrom <T>(firstQuantity.Dimension);

                    //exception happen when adding two derived quantities together
                }
                catch (QuantityNotFoundException)
                {
                    //keep the first quantity configuration.
                    AQ = (AnyQuantity <T>)firstQuantity.Clone();
                }


                if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short))
                {
                    //use direct calculations

                    double firstVal = (double)(object)firstQuantity.Value;

                    double secondVal = (double)(object)secondQuantity.Value;

                    //correct the values according to left unit or first unit.
                    //the resulted quantity has the values of the first unit.

                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //factor from second unit to first unit
                        UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit);

                        secondVal = stof.ConversionFactor * secondVal;
                    }



                    ////sum the values

                    double result = firstVal - secondVal;

                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //assign the unit of first quantity to the result.
                        AQ.Unit = (Unit)firstQuantity.Unit.Clone();
                    }


                    AQ.Value = (T)(object)result;

                    return(AQ);
                }
                else
                {
                    T firstVal  = (firstQuantity.Value);
                    T secondVal = (secondQuantity.Value);

                    //correct the values according to left unit or first unit.
                    //the resulted quantity has the values of the first unit.

                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //factor from second unit to first unit
                        UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit);

                        secondVal = MultiplyScalarByGeneric(stof.ConversionFactor, secondVal);
                    }


                    var expr = Expression.Subtract(Expression.Constant(firstVal), Expression.Constant(secondVal));

                    // Construct Lambda function which return one object.
                    Expression <Func <T> > cq = Expression.Lambda <Func <T> >(expr);

                    // compile the function
                    Func <T> aqf = cq.Compile();

                    // execute the function
                    T result = aqf();


                    if (firstQuantity.Unit != null && secondQuantity.Unit != null)
                    {
                        //assign the unit of first quantity to the result.
                        AQ.Unit = firstQuantity.Unit;
                    }

                    AQ.Value = result;

                    return(AQ);
                }
            }
            else
            {
                throw new QuantitiesNotDimensionallyEqualException();
            }
        }