//******************************************************************************************************
// SI.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 01/25/2008 - J. Ritchie Carroll
// Initial version of source generated.
// 09/11/2008 - J. Ritchie Carroll
// Converted to C#.
// 08/10/2009 - Josh L. Patterson
// Edited Comments.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
#region [ Contributor License Agreements ]
/**************************************************************************\
Copyright © 2009 - J. Ritchie Carroll
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\**************************************************************************/
#endregion
using System;
using System.Text;
namespace GSF.Units
{
///
/// Defines constant factors for SI units of measure to handle metric conversions.
///
// ReSharper disable RedundantNameQualifier
public static class SI
{
// Unit factor SI names
private static readonly string[] s_names = { "yocto", "zepto", "atto", "femto", "pico", "nano", "micro", "milli", "centi", "deci", "deca", "hecto", "kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta" };
// Unit factor SI symbols
private static readonly string[] s_symbols = { "y", "z", "a", "f", "p", "n", "µ", "m", "c", "d", "da", "h", "k", "M", "G", "T", "P", "E", "Z", "Y" };
// Unit factor SI factors
private static readonly double[] s_factors = { Yocto, Zepto, Atto, Femto, Pico, Nano, Micro, Milli, Centi, Deci, Deca, Hecto, Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta };
///
/// SI prefix Y, 10^24
///
public const double Yotta = 1.0e+24D;
///
/// SI prefix Z, 10^21
///
public const double Zetta = 1.0e+21D;
///
/// SI prefix E, 10^18
///
public const double Exa = 1.0e+18D;
///
/// SI prefix P, 10^15
///
public const double Peta = 1.0e+15D;
///
/// SI prefix T, 10^12
///
public const double Tera = 1.0e+12D;
///
/// SI prefix G, 10^9
///
public const double Giga = 1.0e+9D;
///
/// SI prefix M, 10^6
///
public const double Mega = 1.0e+6D;
///
/// SI prefix k, 10^3
///
public const double Kilo = 1.0e+3D;
///
/// SI prefix h, 10^2
///
public const double Hecto = 1.0e+2D;
///
/// SI prefix da, 10^1
///
public const double Deca = 1.0e+1D;
///
/// SI prefix d, 10^-1
///
public const double Deci = 1.0e-1D;
///
/// SI prefix c, 10^-2
///
public const double Centi = 1.0e-2D;
///
/// SI prefix m, 10^-3
///
public const double Milli = 1.0e-3D;
///
/// SI prefix µ, 10^-6
///
public const double Micro = 1.0e-6D;
///
/// SI prefix n, 10^-9
///
public const double Nano = 1.0e-9D;
///
/// SI prefix p, 10^-12
///
public const double Pico = 1.0e-12D;
///
/// SI prefix f, 10^-15
///
public const double Femto = 1.0e-15D;
///
/// SI prefix a, 10^-18
///
public const double Atto = 1.0e-18D;
///
/// SI prefix z, 10^-21
///
public const double Zepto = 1.0e-21D;
///
/// SI prefix y, 10^-24
///
public const double Yocto = 1.0e-24D;
///
/// Gets an array of all the defined unit factor SI names ordered from least () to greatest ().
///
public static string[] Names
{
get
{
return s_names;
}
}
///
/// Gets an array of all the defined unit factor SI prefix symbols ordered from least () to greatest ().
///
public static string[] Symbols
{
get
{
return s_symbols;
}
}
///
/// Gets an array of all the defined SI unit factors ordered from least () to greatest ().
///
public static double[] Factors
{
get
{
return s_factors;
}
}
///
/// Turns the given number of units into a textual representation with an appropriate unit scaling.
///
/// Total units to represent textually.
/// Name of unit display (e.g., you could use "m/h" for meters per hour).
/// Optional SI factor symbol or name array to use during textual conversion, defaults to .
/// Optional minimum SI factor. Defaults to .
/// Optional maximum SI factor. Defaults to .
///
/// The array needs one string entry for each defined SI item ordered from
/// least () to greatest (), see or
/// arrays for examples.
///
/// A representation of the number of units.
/// or is not defined in array.
public static string ToScaledString(double totalUnits, string unitName, string[] symbolNames = null, double minimumFactor = Yocto, double maximumFactor = Yotta)
{
return ToScaledString(totalUnits, 2, unitName, symbolNames, minimumFactor, maximumFactor);
}
///
/// Turns the given number of units into a textual representation with an appropriate unit scaling.
///
/// Total units to represent textually.
/// A numeric string format for scaled .
/// Name of unit display (e.g., you could use "m/h" for meters per hour).
/// Optional minimum SI factor. Defaults to .
/// Optional maximum SI factor. Defaults to .
///
/// array is used for displaying SI symbol prefix for .
///
/// A representation of the number of units.
/// or is not defined in array.
public static string ToScaledString(double totalUnits, string format, string unitName, double minimumFactor = Yocto, double maximumFactor = Yotta)
{
return ToScaledString(totalUnits, format, unitName, s_symbols, -1, minimumFactor, maximumFactor);
}
///
/// Turns the given number of units into a textual representation with an appropriate unit scaling.
///
/// Total units to represent textually.
/// Number of decimal places to display.
/// Name of unit display (e.g., you could use "m/h" for meters per hour).
/// Optional SI factor symbol or name array to use during textual conversion, defaults to .
/// Optional minimum SI factor. Defaults to .
/// Optional maximum SI factor. Defaults to .
///
/// The array needs one string entry for each defined SI item ordered from
/// least () to greatest (), see or
/// arrays for examples.
///
/// A representation of the number of units.
/// cannot be negative.
/// or is not defined in array.
public static string ToScaledString(double totalUnits, int decimalPlaces, string unitName, string[] symbolNames = null, double minimumFactor = Yocto, double maximumFactor = Yotta)
{
if (decimalPlaces < 0)
throw new ArgumentOutOfRangeException(nameof(decimalPlaces), "decimalPlaces cannot be negative");
return ToScaledString(totalUnits, "R", unitName, symbolNames ?? s_symbols, decimalPlaces, minimumFactor, maximumFactor);
}
///
/// Turns the given number of units into a textual representation with an appropriate unit scaling
/// given string array of factor names or symbols.
///
/// Total units to represent textually.
/// A numeric string format for scaled .
/// Name of unit display (e.g., you could use "m/h" for meters per hour).
/// SI factor symbol or name array to use during textual conversion.
/// Optional number of decimal places to display.
/// Optional minimum SI factor. Defaults to .
/// Optional maximum SI factor. Defaults to .
///
/// The array needs one string entry for each defined SI item ordered from
/// least () to greatest (), see or
/// arrays for examples.
///
/// A representation of the number of units.
/// or is not defined in array.
public static string ToScaledString(double totalUnits, string format, string unitName, string[] symbolNames, int decimalPlaces = -1, double minimumFactor = Yocto, double maximumFactor = Yotta)
{
StringBuilder image = new StringBuilder();
double factor;
int minimumIndex, maximumIndex;
minimumIndex = GetFactorIndex(minimumFactor);
if (minimumIndex < 0)
throw new ArgumentOutOfRangeException(nameof(minimumFactor), "Unknown SI factor " + minimumFactor);
maximumIndex = GetFactorIndex(maximumFactor);
if (maximumIndex < 0)
throw new ArgumentOutOfRangeException(nameof(maximumFactor), "Unknown SI factor " + maximumFactor);
for (int i = maximumIndex; i >= minimumIndex; i--)
{
// See if total number of units ranges in the specified factor range
factor = totalUnits / s_factors[i];
if (factor >= 1.0D)
{
if (decimalPlaces > -1)
factor = Math.Round(factor, decimalPlaces);
image.Append(factor.ToString(format));
image.Append(' ');
image.Append(symbolNames[i]);
image.Append(unitName);
break;
}
}
if (image.Length == 0)
{
// Display total number of units
if (decimalPlaces > -1)
totalUnits = Math.Round(totalUnits, decimalPlaces);
image.Append(totalUnits.ToString(format));
image.Append(' ');
image.Append(unitName);
}
return image.ToString();
}
private static int GetFactorIndex(double factor)
{
for (int i = 0; i < s_factors.Length; i++)
{
if (s_factors[i] == factor)
return i;
}
return -1;
}
}
}