Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Added support for generating logarithmic units #45

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 11 additions & 4 deletions Src/Scripts/GenerateUnits.ps1
Expand Up @@ -162,10 +162,17 @@ get-childitem -path $templatesDir -filter "*.json" | % {
$json = (Get-Content $templateFile | Out-String)
$unitClass = $json | ConvertFrom-Json

# Set default values
if (!$unitClass.BaseType) {
$unitClass | Add-Member BaseType "double";
}
# Set default values
if (!$unitClass.BaseType) {
$unitClass | Add-Member BaseType "double";
}
# 'Logarithmic' is optional in the .json file and assumed to be false if not specified
if (!$unitClass.Logarithmic) {
$unitClass | Add-Member Logarithmic "False"
}
if (!$unitClass.LogarithmicScalingFactor) {
$unitClass | Add-Member LogarithmicScalingFactor "1"
}

# Expand unit prefixes into units
$unitClass.Units = GetUnits $unitClass;
Expand Down
108 changes: 108 additions & 0 deletions Src/Scripts/Include-GenerateLogarithmicCode.ps1
@@ -0,0 +1,108 @@
<#
.SYNOPSIS
Generates the C# source code for logarithmic arithmetic operators.

.PARAMETER className
The name of the unit.

.PARAMETER baseUnitFieldName
The name of the backing field used to store the unit's value.

.PARAMETER baseType
The data type of the backing field used to store the unit's value.

.PARAMETER scalingFactor
The scaling factor used in logarithmic calculations. In most cases this is equal to 1.
#>
function GenerateUnitClassSourceCode([string]$className, [string]$baseUnitFieldName, [string]$baseType, [int]$scalingFactor)
{
# Most logarithmic operators need a simple scaling factor of 10. However, certain units such as voltage ratio need to
# use 20 instead of 10.
$x = 10 * $scalingFactor;

@"

#region Logarithmic Arithmetic Operators

public static $className operator -($className right)
{
return new $className(-right.$baseUnitFieldName);
}

public static $className operator +($className left, $className right)
{
// Logarithmic addition
// Formula: $x*log10(10^(x/$x) + 10^(y/$x))
return new $className($x*Math.Log10(Math.Pow(10, left.$baseUnitFieldName/$x) + Math.Pow(10, right.$baseUnitFieldName/$x)));
}

public static $className operator -($className left, $className right)
{
// Logarithmic subtraction
// Formula: $x*log10(10^(x/$x) - 10^(y/$x))
return new $className($x*Math.Log10(Math.Pow(10, left.$baseUnitFieldName/$x) - Math.Pow(10, right.$baseUnitFieldName/$x)));
}

public static $className operator *($baseType left, $className right)
{
// Logarithmic multiplication = addition
return new $className(left + right.$baseUnitFieldName);
}

public static $className operator *($className left, double right)
{
// Logarithmic multiplication = addition
return new $className(left.$baseUnitFieldName + ($baseType)right);
}

public static $className operator /($className left, double right)
{
// Logarithmic division = subtraction
return new $className(left.$baseUnitFieldName - ($baseType)right);
}

public static double operator /($className left, $className right)
{
// Logarithmic division = subtraction
return Convert.ToDouble(left.$baseUnitFieldName - right.$baseUnitFieldName);
}

#endregion
"@;
}


<#
.SYNOPSIS
Generates the C# source code for logarithmic arithmetic operator unit tests.

.PARAMETER className
The name of the unit.

.PARAMETER baseUnitPluralName
The plural name of the backing field used to store the unit's value.

.PARAMETER unit
The actual unit type.
#>
function GenerateTestBaseClassSourceCode([string]$className, [string]$baseUnitPluralName, $unit)
{
@"
[Test]
public void LogarithmicArithmeticOperators()
{
$className v = $className.From$baseUnitPluralName(40);
Assert.AreEqual(-40, -v.$baseUnitPluralName, $($unit.PluralName)Tolerance);
AssertLogarithmicAddition();
AssertLogarithmicSubtraction();
Assert.AreEqual(50, (v*10).$baseUnitPluralName, $($unit.PluralName)Tolerance);
Assert.AreEqual(50, (10*v).$baseUnitPluralName, $($unit.PluralName)Tolerance);
Assert.AreEqual(35, (v/5).$baseUnitPluralName, $($unit.PluralName)Tolerance);
Assert.AreEqual(35, v/$className.From$baseUnitPluralName(5), $($unit.PluralName)Tolerance);
}

protected abstract void AssertLogarithmicAddition();

protected abstract void AssertLogarithmicSubtraction();
"@;
}
8 changes: 8 additions & 0 deletions Src/Scripts/Include-GenerateUnitClassSourceCode.ps1
Expand Up @@ -127,6 +127,13 @@ namespace UnitsNet
}

#endregion
"@; if ($unitClass.Logarithmic -eq $true) {
# Dot into the script to load its functions into the global scope so we can access them.
. .\Include-GenerateLogarithmicCode.ps1;
# Call another script function to generate logarithm-specific arithmetic operator code.
GenerateUnitClassSourceCode -className $className -baseUnitFieldName $baseUnitFieldName -baseType $baseType -scalingFactor $unitClass.LogarithmicScalingFactor
}
else {@"

#region Arithmetic Operators

Expand Down Expand Up @@ -166,6 +173,7 @@ namespace UnitsNet
}

#endregion
"@; }@"

#region Equality / IComparable

Expand Down
8 changes: 8 additions & 0 deletions Src/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1
Expand Up @@ -92,6 +92,13 @@ namespace UnitsNet.Tests
"@; }@"
}

"@; if ($unitClass.Logarithmic -eq $true) {
# Dot into the script to load its functions into the global scope so we can access them.
. .\Include-GenerateLogarithmicCode.ps1;
# Call another script function to generate logarithm-specific arithmetic operator test code.
GenerateTestBaseClassSourceCode -className $className -baseUnitPluralName $baseUnitPluralName -unit $unit
}
else {@"
[Test]
public void ArithmeticOperators()
{
Expand All @@ -104,6 +111,7 @@ namespace UnitsNet.Tests
Assert.AreEqual(2, ($className.From$baseUnitPluralName(10)/5).$baseUnitPluralName, $($unit.PluralName)Tolerance);
Assert.AreEqual(2, $className.From$baseUnitPluralName(10)/$className.From$baseUnitPluralName(5), $($unit.PluralName)Tolerance);
}
"@; }@"

[Test]
public void ComparisonOperators()
Expand Down