Пример #1
0
        /// <summary>
        /// Returns the unit of strongly typed metric unit to unit with sub units as base units
        /// and add the prefix to the expanded base units.
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static Unit ExpandMetricUnit(MetricUnit unit)
        {
            List <Unit> DefaultUnits = new List <Unit>();

            if (unit.IsBaseUnit)
            {
                //if baseunit then why we would convert it
                // put it immediately
                return(unit);
            }
            else
            {
                QuantityDimension qdim = QuantityDimension.DimensionFrom(unit.QuantityType);

                if (unit is MetricUnit)
                {
                    //pure unit without sub units like Pa, N, and L

                    Unit u = DiscoverUnit(qdim);

                    List <Unit> baseUnits = u.SubUnits;

                    //add prefix to the first unit in the array

                    ((MetricUnit)baseUnits[0]).UnitPrefix += ((MetricUnit)unit).UnitPrefix;

                    DefaultUnits.AddRange(baseUnits);
                }

                return(new Unit(unit._QuantityType, DefaultUnits.ToArray()));
            }
        }
        /// <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();
            }
        }
Пример #3
0
        public DerivedQuantity(QuantityDimension dimension)
        {
            //create quantity for each sub quantity
            List <AnyQuantity <T> > quantities = new List <AnyQuantity <T> >();

            if (dimension.Mass.Exponent != 0)
            {
                quantities.Add(new Mass <T>(dimension.Mass.Exponent));
            }

            {
                if (dimension.Length.RegularExponent != 0)
                {
                    quantities.Add(new Length <T>(dimension.Length.RegularExponent));
                }

                if (dimension.Length.PolarExponent != 0)
                {
                    quantities.Add(new PolarLength <T>(dimension.Length.PolarExponent));
                }
            }

            if (dimension.Time.Exponent != 0)
            {
                quantities.Add(new Time <T>(dimension.Time.Exponent));
            }

            if (dimension.Temperature.Exponent != 0)
            {
                quantities.Add(new Temperature <T>(dimension.Temperature.Exponent));
            }

            if (dimension.LuminousIntensity.Exponent != 0)
            {
                quantities.Add(new LuminousIntensity <T>(dimension.LuminousIntensity.Exponent));
            }

            if (dimension.AmountOfSubstance.Exponent != 0)
            {
                quantities.Add(new AmountOfSubstance <T>(dimension.AmountOfSubstance.Exponent));
            }

            if (dimension.ElectricCurrent.Exponent != 0)
            {
                quantities.Add(new ElectricalCurrent <T>(dimension.ElectricCurrent.Exponent));
            }

            if (dimension.Currency.Exponent != 0)
            {
                quantities.Add(new Currency <T>(dimension.Currency.Exponent));
            }

            if (dimension.Digital.Exponent != 0)
            {
                quantities.Add(new Digital <T>(dimension.Digital.Exponent));
            }

            InternalQuantities = quantities.ToArray();
        }
Пример #4
0
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Mass`1 Constructor
        ///</summary>
        public void MassConstructorTestHelper <T>()
        {
            Mass <T> target = new Mass <T>();

            QuantityDimension MassDimension = new QuantityDimension(1, 0, 0);


            Assert.AreEqual(MassDimension, target.Dimension);
        }
        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);
        }
Пример #6
0
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion



        /// <summary>
        ///A test for Dimension
        ///</summary>
        public void DimensionTestHelper <T>()
        {
            Length <T> target = new Length <T>(); // TODO: Initialize to an appropriate value


            QuantityDimension LengthDimension = new QuantityDimension(0, 1, 0);


            Assert.AreEqual(LengthDimension, target.Dimension);
        }
Пример #7
0
        /// <summary>
        /// This constructor creates a unit from several units.
        /// </summary>
        /// <param name="units"></param>
        internal Unit(Type quantityType, params Unit[] units)
        {
            SubUnits = new List <Unit>();

            foreach (Unit un in units)
            {
                SubUnits.Add(un);
            }


            SubUnits = GroupUnits(SubUnits); //group similar units

            this._Symbol = GenerateUnitSymbolFromSubBaseUnits();

            // if the passed type is AnyQuantity<object> for example
            //     then I want to get the type without type parameters AnyQuantity<>
            if (quantityType != null)
            {
                if (!quantityType.IsGenericTypeDefinition)
                {
                    quantityType = quantityType.GetGenericTypeDefinition();
                }
            }


            if (quantityType != typeof(DerivedQuantity <>) && quantityType != null)
            {
                if (quantityType != typeof(DimensionlessQuantity <>))
                {
                    this._IsDefaultUnit = true;
                }

                this._QuantityType = quantityType;

                //get the unit dimension from the passed type.
                _UnitDimension = QuantityDimension.DimensionFrom(quantityType);
            }
            else
            {
                //passed type is derivedQuantity which indicates that the units representing unknow derived quantity to the system
                //so that quantityType should be kept as derived quantity type.
                this._QuantityType = quantityType;


                //get the unit dimension from the passed units.
                this._UnitDimension = QuantityDimension.Dimensionless;
                foreach (Unit uu in SubUnits)
                {
                    this._UnitDimension += uu.UnitDimension;
                }
            }


            this._IsBaseUnit = false;
        }
Пример #8
0
        public Unit RaiseUnitPower(float power)
        {
            //make short-cut when power equal zero return dimensionless unit immediatly
            //  because if I left the execution to the end
            //  the dimensionless unit is created and wrapping the original unit under sub unit
            //    and this made errors in conversion between dimensionless units :).
            if (power == 0)
            {
                return(Unit.DiscoverUnit(QuantityDimension.Dimensionless));
            }

            Unit u = (Unit)this.MemberwiseClone();

            if (SubUnits != null)
            {
                u.SubUnits = new List <Unit>(SubUnits.Count);

                for (int i = 0; i < SubUnits.Count; i++)
                {
                    u.SubUnits.Add(SubUnits[i].RaiseUnitPower(power));
                }
            }
            else
            {
                u.unitExponent *= power;   //the exponent is changing in strongly typed units
            }


            u._UnitDimension = this._UnitDimension * power; //must change the unit dimension of the unit
            // however because the unit is having sub units we don't have to modify the exponent of it
            //  note: unit that depend on sub units is completly unaware of its exponent
            //    or I should say it is always equal = 1

            u._QuantityType = QuantityDimension.GetQuantityTypeFrom(u._UnitDimension);



            if (u.SubUnits == null && u.unitExponent == 1)
            {
                //no sub units and exponent ==1  then no need to processing
                return(u);
            }
            else if (u.SubUnits == null)
            {
                //exponent != 1  like ^5 ^0.3  we need processing
                return(new Unit(u._QuantityType, u));
            }
            else
            {
                //consist of sub units definitly we need processing.
                return(new Unit(u._QuantityType, u.SubUnits.ToArray()));
            }
        }
Пример #9
0
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Angle`1 Constructor
        ///</summary>
        public void AngleConstructorTestHelper <T>()
        {
            Angle <T> target = new Angle <T>();


            //test the dimension of the Angle
            QuantityDimension AngleDimension = new QuantityDimension();

            AngleDimension.Length = new QuantitySystem.DimensionDescriptors.LengthDescriptor(1, -1);


            Assert.AreEqual(AngleDimension, target.Dimension);
        }
        public void QuantityDimensionConstructorTest1()
        {
            QuantityDimension target = new QuantityDimension();

            Assert.AreEqual(0, target.Mass.Exponent);
            Assert.AreEqual(0, target.Length.Exponent);
            Assert.AreEqual(0, target.Time.Exponent);

            Assert.AreEqual(0, target.Temperature.Exponent);
            Assert.AreEqual(0, target.LuminousIntensity.Exponent);
            Assert.AreEqual(0, target.ElectricCurrent.Exponent);
            Assert.AreEqual(0, target.AmountOfSubstance.Exponent);
        }
Пример #11
0
        /// <summary>
        /// Resturns the name of the quantity associated with this dimension
        /// </summary>
        /// <param name="dimension"></param>
        /// <returns></returns>
        public static QsValue FromDimension(QsParameter dimension)
        {
            string ss = dimension.ParameterRawText;

            if (dimension.QsNativeValue is QsText)
            {
                ss = ((QsText)dimension.QsNativeValue).Text;
            }
            var q = QuantityDimension.Parse(ss);

            string qt = QuantityDimension.GetQuantityTypeFrom(q).Name;

            return(new QsText(qt.Substring(0, qt.Length - 2)));
        }
        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);
        }
Пример #13
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 void QuantityDimensionConstructorTest()
        {
            int mass   = 1; // TODO: Initialize to an appropriate value
            int length = 2; // TODO: Initialize to an appropriate value
            int time   = 3; // TODO: Initialize to an appropriate value
            QuantityDimension target = new QuantityDimension(mass, length, time);

            Assert.AreEqual(1, target.Mass.Exponent);
            Assert.AreEqual(2, target.Length.Exponent);
            Assert.AreEqual(3, target.Time.Exponent);


            Assert.AreEqual(0, target.Temperature.Exponent);
            Assert.AreEqual(0, target.LuminousIntensity.Exponent);
            Assert.AreEqual(0, target.ElectricCurrent.Exponent);
            Assert.AreEqual(0, target.AmountOfSubstance.Exponent);
        }
Пример #15
0
        /// <summary>
        /// Returns a value from the dimension of this quantity.
        /// </summary>
        /// <param name="dimension"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static QsValue FromDimension(QsParameter dimension, QsParameter value)
        {
            string ss = dimension.ParameterRawText;

            if (dimension.QsNativeValue is QsText)
            {
                ss = ((QsText)dimension.QsNativeValue).Text;
            }
            var q = QuantityDimension.Parse(ss);

            var unit = QuantitySystem.Units.Unit.DiscoverUnit(q);
            var qval = unit.GetThisUnitQuantity <double>(double.Parse(value.ParameterRawText, CultureInfo.InvariantCulture));

            var qs = new QsScalar(ScalarTypes.NumericalQuantity)
            {
                NumericalQuantity = qval
            };

            return(qs);
        }
Пример #16
0
        public void PathToUnitTest()
        {
            double expected = 63360;

            Mile mil = new Mile();
            Inch i   = new Inch();

            UnitPathStack actual = mil.PathToUnit(i);

            Assert.AreEqual(expected, actual.ConversionFactor);


            Gram g = new Gram();

            g.UnitPrefix = MetricPrefix.None;

            Gram Mg = new Gram();

            Mg.UnitPrefix = MetricPrefix.Mega;

            actual = g.PathToUnit(Mg);

            Assert.AreEqual(1e-6, actual.ConversionFactor);


            Metre mr = new Metre();

            actual = i.PathToUnit(mr);

            Assert.AreEqual(0.0254, actual.ConversionFactor);

            //now the idea is to make any combination of units to go to any combination of units
            QuantityDimension qd = QuantityDimension.ParseMLT("M1L0T-1");
            Unit u = Unit.DiscoverUnit(qd);

            Assert.AreEqual("<kg/s>", u.Symbol);
            Assert.AreEqual(qd, u.UnitDimension);
        }
Пример #17
0
        public static MetricUnit UnitOf <TQuantity>() where TQuantity : BaseQuantity, new()
        {
            //try direct mapping
            MetricUnit unit = Activator.CreateInstance(Unit.GetDefaultSIUnitTypeOf(typeof(TQuantity))) as MetricUnit;


            if (unit != null)
            {
                return(unit);
            }
            else
            {
                //if failed you should generate it
                //try first the child quantities in the quantity instance if its base is dervied quantity
                // and DerivedQuantity itself.

                QuantityDimension dimension = QuantityDimension.DimensionFrom(typeof(TQuantity));

                //return a derived unit.
                //return new DerivedSIUnit(dimension);
                throw new NotImplementedException();
            }
        }
Пример #18
0
        /// <summary>
        /// Returns the unit corresponding to the passed string.
        /// Suppors units with exponent.
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        internal static Unit ParseUnit(string un)
        {
            if (un == "1")
            {
                //this is dimensionless value
                return(new Unit(typeof(Quantities.DimensionlessQuantities.DimensionlessQuantity <>)));
            }

            //find '^'

            string[] upower = un.Split('^');


            string unit = upower[0];

            int power = 1;

            if (upower.Length > 1)
            {
                power = int.Parse(upower[1], CultureInfo.InvariantCulture);
            }

            Unit FinalUnit = null;

            //Phase 1: try direct mapping.
            try
            {
                FinalUnit = FindUnit(unit);
            }
            catch (UnitNotFoundException)
            {
                //try to find if it as a Metric unit with prefix
                //loop through all prefixes.
                for (int i = 10; i >= -10; i -= 1)
                {
                    if (i == 0)
                    {
                        i--;         //skip the None prefix
                    }
                    if (unit.StartsWith(MetricPrefix.GetPrefix(i).Symbol, StringComparison.Ordinal))
                    {
                        //found

                        MetricPrefix mp    = MetricPrefix.GetPrefix(i);
                        string       upart = unit.Substring(mp.Symbol.Length);

                        //then it should be MetricUnit otherwise die :)

                        MetricUnit u = FindUnit(upart) as MetricUnit;

                        if (u == null)
                        {
                            goto nounit;
                        }

                        u.UnitPrefix = mp;

                        FinalUnit = u;
                        break;
                    }
                }
            }


            if (FinalUnit == null)
            {
                goto nounit;
            }

            if (power > 1)
            {
                //discover the new type
                QuantityDimension ud = FinalUnit.UnitDimension * power;

                Unit[] chobits = new Unit[power];  //what is chobits any way :O

                for (int iy = 0; iy < power; iy++)
                {
                    chobits[iy] = (Unit)FinalUnit.MemberwiseClone();
                }


                Type uQType = null;

                uQType = QuantityDimension.GetQuantityTypeFrom(ud);


                FinalUnit = new Unit(uQType, chobits);
            }

            return(FinalUnit);



nounit:
            throw new UnitNotFoundException(un);
        }
        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();
            }
        }
Пример #20
0
        /// <summary>
        /// Construct a unit based on the quantity type in SI Base units.
        /// Any Dimensionless quantity will return  in its unit.
        /// </summary>
        /// <param name="quantityType"></param>
        public Unit(Type quantityType)
        {
            SubUnits = new List <Unit>();

            //try direct mapping first to get the unit

            Type InnerUnitType = Unit.GetDefaultSIUnitTypeOf(quantityType);

            if (InnerUnitType == null)
            {
                QuantityDimension dimension = QuantityDimension.DimensionFrom(quantityType);


                if (dimension.Mass.Exponent != 0)
                {
                    Unit u = new Metric.SI.Gram();
                    u.UnitExponent  = dimension.Mass.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Mass.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.Length.Exponent != 0)
                {
                    Unit u = new Metric.SI.Metre();
                    u.UnitExponent  = dimension.Length.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Length.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.Time.Exponent != 0)
                {
                    Unit u = new Shared.Second();
                    u.UnitExponent  = dimension.Time.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Time.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.Temperature.Exponent != 0)
                {
                    Unit u = new Metric.SI.Kelvin();
                    u.UnitExponent  = dimension.Temperature.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Temperature.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.LuminousIntensity.Exponent != 0)
                {
                    Unit u = new Metric.SI.Candela();
                    u.UnitExponent  = dimension.LuminousIntensity.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.LuminousIntensity.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.AmountOfSubstance.Exponent != 0)
                {
                    Unit u = new Metric.SI.Mole();
                    u.UnitExponent  = dimension.AmountOfSubstance.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.AmountOfSubstance.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.ElectricCurrent.Exponent != 0)
                {
                    Unit u = new Metric.SI.Ampere();
                    u.UnitExponent  = dimension.ElectricCurrent.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.ElectricCurrent.Exponent;

                    SubUnits.Add(u);
                }


                if (dimension.Currency.Exponent != 0)
                {
                    Unit u = new Currency.Coin();
                    u.UnitExponent  = dimension.Currency.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Currency.Exponent;

                    SubUnits.Add(u);
                }

                if (dimension.Digital.Exponent != 0)
                {
                    Unit u = new Digital.Bit();
                    u.UnitExponent  = dimension.Digital.Exponent;
                    u.UnitDimension = u.UnitDimension * dimension.Digital.Exponent;

                    SubUnits.Add(u);
                }
            }

            else
            {
                //subclass of AnyQuantity
                //use direct mapping with the exponent of the quantity

                Unit un = (Unit)Activator.CreateInstance(InnerUnitType);

                SubUnits.Add(un);
            }

            this._Symbol = GenerateUnitSymbolFromSubBaseUnits();


            this._IsDefaultUnit = true;

            //the quantity may be derived quantity which shouldn't be referenced :check here.
            this._QuantityType = quantityType;


            _UnitDimension = QuantityDimension.DimensionFrom(this._QuantityType);

            this._IsBaseUnit = false;
        }
Пример #21
0
        }                                         //the list shouldn't been modified by sub classes

        /// <summary>
        /// Create the unit directly from the specfied dimension in its SI base units.
        /// </summary>
        /// <param name="dimension"></param>
        public static Unit DiscoverUnit(QuantityDimension dimension)
        {
            return(DiscoverUnit(dimension, "Metric.SI"));
        }
Пример #22
0
        /// <summary>
        /// Create the unit directly from the specfied dimension based on the unit system given.
        /// </summary>
        /// <param name="dimension"></param>
        public static Unit DiscoverUnit(QuantityDimension dimension, string unitSystem)
        {
            List <Unit> SubUnits = new List <Unit>();

            if (dimension.Currency.Exponent != 0)
            {
                Unit u = new Currency.Coin();
                u.UnitExponent  = dimension.Currency.Exponent;
                u.UnitDimension = new QuantityDimension {
                    Currency = new DimensionDescriptors.CurrencyDescriptor(dimension.Currency.Exponent)
                };
                SubUnits.Add(u);
            }

            if (dimension.Mass.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Mass <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.Mass.Exponent;
                u.UnitDimension = new QuantityDimension(dimension.Mass.Exponent, 0, 0);

                SubUnits.Add(u);
            }

            if (dimension.Length.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Length <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.Length.Exponent;
                u.UnitDimension = new QuantityDimension()
                {
                    Length = dimension.Length
                };

                SubUnits.Add(u);
            }

            if (dimension.Time.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Time <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.Time.Exponent;
                u.UnitDimension = new QuantityDimension()
                {
                    Time = dimension.Time
                };

                SubUnits.Add(u);
            }

            if (dimension.Temperature.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Temperature <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.Temperature.Exponent;
                u.UnitDimension = new QuantityDimension()
                {
                    Temperature = dimension.Temperature
                };

                SubUnits.Add(u);
            }

            if (dimension.LuminousIntensity.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(LuminousIntensity <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.LuminousIntensity.Exponent;
                u.UnitDimension = new QuantityDimension()
                {
                    LuminousIntensity = dimension.LuminousIntensity
                };

                SubUnits.Add(u);
            }

            if (dimension.AmountOfSubstance.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(AmountOfSubstance <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.AmountOfSubstance.Exponent;
                u.UnitDimension = new QuantityDimension(0, 0, 0, 0, 0, dimension.AmountOfSubstance.Exponent, 0);

                SubUnits.Add(u);
            }

            if (dimension.ElectricCurrent.Exponent != 0)
            {
                Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(ElectricalCurrent <>), unitSystem);

                Unit u = (Unit)Activator.CreateInstance(UnitType);

                u.UnitExponent  = dimension.ElectricCurrent.Exponent;
                u.UnitDimension = new QuantityDimension()
                {
                    ElectricCurrent = dimension.ElectricCurrent
                };


                SubUnits.Add(u);
            }


            if (dimension.Currency.Exponent != 0)
            {
                Unit u = new Currency.Coin();
                u.UnitExponent  = dimension.Currency.Exponent;
                u.UnitDimension = u.UnitDimension * dimension.Currency.Exponent;

                SubUnits.Add(u);
            }

            if (dimension.Digital.Exponent != 0)
            {
                Unit u = new Digital.Bit();
                u.UnitExponent  = dimension.Digital.Exponent;
                u.UnitDimension = u.UnitDimension * dimension.Digital.Exponent;

                SubUnits.Add(u);
            }



            Unit un = null;

            try
            {
                Type qType = QuantityDimension.QuantityTypeFrom(dimension);
                un = new Unit(qType, SubUnits.ToArray());
            }
            catch (QuantityNotFoundException)
            {
                un = new Unit(null, SubUnits.ToArray());
            }

            return(un);
        }
Пример #23
0
        /// <summary>
        /// Parse units with exponent and one division '/' with many '.'
        /// i.e. m/s m/s^2 kg.m/s^2
        /// </summary>
        /// <param name="units"></param>
        /// <returns></returns>
        public static Unit Parse(string units)
        {
            //  if found  treat store its value.
            //  m/s^2   m.K/m.s
            //  kg^2/in^2.s

            // sea
            //search for '/'

            string[] uny = units.Split('/');

            string[] numa = uny[0].Split('.');

            List <Unit> dunits = new List <Unit>();

            foreach (string num in numa)
            {
                dunits.Add(ParseUnit(num));
            }

            if (uny.Length > 1)
            {
                string[] dena = uny[1].Split('.');
                foreach (string den in dena)
                {
                    var uu = ParseUnit(den);
                    if (uu.SubUnits != null)
                    {
                        //then it is unit with sub units in it
                        if (uu.SubUnits.Count == 1)
                        {
                            uu = uu.SubUnits[0];
                        }
                    }
                    dunits.Add(uu.Invert());
                }
            }

            if (dunits.Count == 1)
            {
                return(dunits[0]);
            }

            //get the dimension of all units
            QuantityDimension ud = QuantityDimension.Dimensionless;

            foreach (Unit un in dunits)
            {
                ud += un.UnitDimension;
            }


            Type uQType = null;

            uQType = QuantityDimension.GetQuantityTypeFrom(ud);


            Unit FinalUnit = new Unit(uQType, dunits.ToArray());

            return(FinalUnit);
        }
Пример #24
0
        /// <summary>
        /// Fill the instance of the unit with the attributes
        /// found on it.
        /// </summary>
        protected Unit()
        {
            //only called on the strongly typed units
            _IsStronglyTyped = true;

            UnitValues uv;

            if (CachedUnitsValues.TryGetValue(this.GetType(), out uv))
            {
                _Symbol                   = uv._Symbol;
                _QuantityType             = uv._QuantityType;
                _UnitDimension            = uv._UnitDimension;
                _IsDefaultUnit            = uv._IsDefaultUnit;
                _IsBaseUnit               = uv._IsBaseUnit;
                _ReferenceUnit            = uv._ReferenceUnit;
                _ReferenceUnitNumerator   = uv._ReferenceUnitNumerator;
                _ReferenceUnitDenominator = uv._ReferenceUnitDenominator;
            }
            else
            {
                //read the current attributes

                MemberInfo info = this.GetType();

                object[] attributes = (object[])info.GetCustomAttributes(true);

                //get the UnitAttribute
                UnitAttribute ua = (UnitAttribute)attributes.SingleOrDefault <object>(ut => ut is UnitAttribute);

                if (ua != null)
                {
                    _Symbol        = ua.Symbol;
                    _QuantityType  = ua.QuantityType;
                    _UnitDimension = QuantityDimension.DimensionFrom(_QuantityType);


                    if (ua is DefaultUnitAttribute)
                    {
                        _IsDefaultUnit = true;  //indicates that this unit is the default when creating the quantity in this system
                        //also default unit is the unit that relate its self to the SI Unit.
                    }
                    else
                    {
                        _IsDefaultUnit = false;
                    }
                }
                else
                {
                    throw new UnitException("Unit Attribute not found");
                }

                if (_QuantityType.Namespace == "QuantitySystem.Quantities.BaseQuantities")
                {
                    _IsBaseUnit = true;
                }
                else
                {
                    _IsBaseUnit = false;
                }

                //Get the reference attribute
                ReferenceUnitAttribute dua = (ReferenceUnitAttribute)attributes.SingleOrDefault <object>(ut => ut is ReferenceUnitAttribute);

                if (dua != null)
                {
                    if (dua.UnitType != null)
                    {
                        _ReferenceUnit = (Unit)Activator.CreateInstance(dua.UnitType);
                    }
                    else
                    {
                        //get the SI Unit Type for this quantity
                        //first search for direct mapping
                        Type SIUnitType = GetDefaultSIUnitTypeOf(_QuantityType);
                        if (SIUnitType != null)
                        {
                            _ReferenceUnit = (Unit)Activator.CreateInstance(SIUnitType);
                        }
                        else
                        {
                            //try dynamic creation of the unit.
                            _ReferenceUnit = new Unit(_QuantityType);
                        }
                    }

                    _ReferenceUnitNumerator   = dua.Numerator;
                    _ReferenceUnitDenominator = dua.Denominator;
                }


                uv._Symbol                   = _Symbol;
                uv._QuantityType             = _QuantityType;
                uv._UnitDimension            = _UnitDimension;
                uv._IsDefaultUnit            = _IsDefaultUnit;
                uv._IsBaseUnit               = _IsBaseUnit;
                uv._ReferenceUnit            = _ReferenceUnit;
                uv._ReferenceUnitNumerator   = _ReferenceUnitNumerator;
                uv._ReferenceUnitDenominator = _ReferenceUnitDenominator;

                CachedUnitsValues.Add(this.GetType(), uv);
            }
        }