Skip to content

Commit

Permalink
SNSUNI-94: Added additional match functions: log(), log10(), sqrt(), …
Browse files Browse the repository at this point in the history
…pow(), and Trigonometric function for Angle unit: sin(), cos(), tg(), ctg() and their hyperbolic and reversed versions.
  • Loading branch information
pjazdzyk committed May 25, 2024
1 parent 317bf6c commit 824f16f
Show file tree
Hide file tree
Showing 10 changed files with 861 additions and 183 deletions.
62 changes: 52 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ features, such as overloaded operators.

Copy the Maven dependency provided below to your pom.xml file, and you are ready to go. For other package managers,
check maven central repository:
[UNITILITY](https://search.maven.org/artifact/com.synerset/unitility/2.3.0/jar?eh=).
[UNITILITY](https://search.maven.org/artifact/com.synerset/unitility/2.4.0/jar?eh=).

```xml
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-core</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
If you use frameworks to develop web applications, it is recommended to use Unitility extension modules,
Expand All @@ -79,15 +79,15 @@ Extension for the Spring Boot framework:
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-spring</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
Extension for the Quarkus framework:
```xml
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-quarkus</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
Extensions include CORE module, so you don't have to put it separate in your pom.
Expand Down Expand Up @@ -318,7 +318,6 @@ Temperature temperatureToAdd = Temperature.ofKelvins(20 + 273.15);
Temperature actualTemperature = sourceTemperature.add(temperatureToAdd); // results in: 40 °C
```


Performing addition or subtraction will yield a PhysicalQuantity with the same unit. The algorithm will convert the unit
of the addend quantity to match that of the augend, ensuring that the operation is conducted within a consistent unit.
The unit of the resulting quantity will be set to match that of the augend.
Expand All @@ -342,6 +341,49 @@ In the provided example, division and multiplication both yield a double value.
absence of a unit resolver within the developmental stage.
The existing unit values are directly employed for multiplication or division operations.

* natural logarithm, logarithm with base of 10

```java
Distance roadLength = Distance.ofKilometers(100);
Distance reducedDistance1 = roadLength.log(); // 4.60517(..)
Distance reducedDistance2 = roadLength.log10(); // 2.0
```

* trigonometric functions: sin(), cos(), tan(), ctg() including hyperbolic and reversed

```java
Angle exampleAngle = Angle.ofDegrees(90);
Angle sinResult = exampleAngle.sin(); // 1
Angle cosResult = exampleAngle.cos(); // 0

Angle angle45 = exampleAngle.withValue(45);
Angle tanResult = angle45.tan(); // 1
Angle cotResult = angle45.cot(); // 1

Angle angleRad1 = exampleAngle.toRadians().withValue(1);
Angle aSinResult = angleRad1.asin(); // 1.570796(..)
Angle aCosResult = angleRad1.acos(); // 0
Angle aTanResult = angleRad1.atan(); // 0.785398(..)
Angle aCotResult = angleRad1.acot(); // 0.785398(..)
```
Please keep in mind that not all values belong to the domain of a given trigonometric function.
Some might throw an exception if they hold invalid value for a specific function.
Value will be automatically converted to radians before using Java Math trigonometric functions.

* ceil, floor, roundHalfEven with relevant digits

```java
ThermalConductivity thermCond = ThermalConductivity.ofWattsPerMeterKelvin(0.00366);
ThermalConductivity ceilResult = thermCond.ceil(); // 1
ThermalConductivity floorResult = thermCond.floor(); // 0
ThermalConductivity roundedResult = thermCond.roundHalfEven(2); // 0.0037
```
Please note that rounding function is based on concept of relevant digits. It is NOT a simple truncation to a specified
number of decimal places. This function will evaluate where relevant digits starts and will attempt to keep the specified
number by user. For an example for roundHalfEven(3) will output: <br>
0.12345 -> roundHalfEven(3) -> 0.123 <br>
0.00012345 -> roundHalfEven(3) -> 0.000123 <br>

### 4.5 Equality and sorting

Each PhysicalQuantity class has implemented the equals and hashCode methods and implements the Comparable interface,
Expand Down Expand Up @@ -439,7 +481,7 @@ deserialization back to Java objects. To include this module in your project, us
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-jackson</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
PhysicalQuantity JSON structure for valid serialization / deserialization has been defined as in the following example:
Expand All @@ -456,15 +498,15 @@ obtain the appropriate parser depending on the class type. This module is part o
therefore, it does not need to be added explicitly if framework extensions are included in the project.

## 5.2 Spring Boot module
Module tested for Spring Boot platform version: **3.2.2** <br>
Module tested for Spring Boot version: **3.3.0** <br>
Spring Boot module includes **unitility-jackson** and **unitility-core** modules, and it will automatically
create required beans through the autoconfiguration dependency injection mechanism. To use Spring extension module,
add the following dependency:
```xml
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-spring</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
Adding Spring module to the project will automatically:
Expand Down Expand Up @@ -496,15 +538,15 @@ steps must be carried out to ensure that custom unit is properly resolved from J
see a section: [Registering custom quantity in Spring](#63-registering-custom-quantities-in-spring).<br>

## 5.3 Quarkus module
Module tested for Quarkus platform version: **3.5.1**<br>
Module tested for Quarkus platform version: **3.11.0**<br>
Quarkus module includes **unitility-jackson** and **unitility-core** modules, and it will be automatically
discovered through Jandex index and will create required CDI beans. To use Quarkus extension module,
add following dependency:
```xml
<dependency>
<groupId>com.synerset</groupId>
<artifactId>unitility-quarkus</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
Adding Quarkus module to the project will automatically:
Expand Down
16 changes: 8 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<properties>
<!-- MODULES VERSION -->
<project.version>2.3.1</project.version>
<project.version>2.4.0</project.version>

<!-- Maven Properties -->
<maven.compiler.source>17</maven.compiler.source>
Expand All @@ -54,26 +54,26 @@
<!-- Jackson module -->
<jackson-databind.version>2.17.1</jackson-databind.version>
<!-- SpringBoot module -->
<spring-boot-starter-web.version>3.2.5</spring-boot-starter-web.version>
<spring-boot-starter-web.version>3.3.0</spring-boot-starter-web.version>
<!-- Quarkus module -->
<quarkus-version>3.10.1</quarkus-version>
<quarkus-version>3.11.0</quarkus-version>
<!-- Jakarta validation module -->
<jakarta.validation-api.version>3.1.0</jakarta.validation-api.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
<jakarta.el.version>6.0.0</jakarta.el.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>

<!-- Test dependencies versions -->
<jacoco.version>0.8.11</jacoco.version>
<jacoco.version>0.8.12</jacoco.version>
<junit-jupiter.version>5.10.2</junit-jupiter.version>
<assertj-core.version>3.25.3</assertj-core.version>

<!-- Plugin versions -->
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<maven-javadoc-plugin.version>3.6.3</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.3.0</maven-source-plugin.version>
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
<jandex-maven-plugin.version>3.1.6</jandex-maven-plugin.version>
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
<jandex-maven-plugin.version>3.2.0</jandex-maven-plugin.version>

<!-- Sonar Cloud Properties-->
<sonar.organization>synerset</sonar.organization>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.synerset.unitility.unitsystem;

import com.synerset.unitility.unitsystem.exceptions.UnitSystemArgumentException;
import com.synerset.unitility.unitsystem.util.ValueFormatter;

/**
* Interface representing a calculable quantity with operations for basic arithmetics.
Expand All @@ -16,6 +17,7 @@ public interface CalculableQuantity<U extends Unit, Q extends CalculableQuantity
* @param value The value for the new physical quantity.
* @return A new physical quantity with the specified value.
*/
@Override
Q withValue(double value);

// Handling double as an input argument
Expand Down Expand Up @@ -113,6 +115,118 @@ default Q abs() {
return withValue(Math.abs(getValue()));
}

/**
* Multiplies the physical quantity by raising it to the power of the given exponent.<p>
* This method calculates the value of the physical quantity raised to the specified exponent
* and returns a new instance of the physical quantity with the updated value.
*
* @param exponent The exponent to which the current value is raised.
* @return A new physical quantity with the value raised to the given exponent.
*/
default Q power(double exponent) {
double newValue = Math.pow(getValue(), exponent);
return withValue(newValue);
}

/**
* Calculates the square root of the physical quantity's value. <p>
* This method computes the square root of the current value of the physical quantity
* and returns a new instance of the physical quantity with the updated value.
*
* @return A new physical quantity with the value as the square root of the original value.
*/
default Q sqrt() {
double newValue = Math.sqrt(getValue());
return withValue(newValue);
}

/**
* Calculates the natural logarithm of the physical quantity's value.
* This method computes the natural logarithm of the current value of the physical quantity
* and returns a new instance of the physical quantity with the updated value. <p>
* IMPORTANT: In some parts of the world (like Europe) natural logarithm is expressed as 'ln' symbol,
* and log means logarithm with base of 10. In this app, consistency with Math library was maintained,
* therefore log is natural logarithm (with e number in a base).
*
* @return A new physical quantity with the value as the natural logarithm of the original value.
* @throws UnitSystemArgumentException if the current value is not greater than zero.
*/
default Q log() {
double value = getValue();
if (value <= 0) {
throw new UnitSystemArgumentException("Cannot calculate logarithm for non-positive value: " + value);
}
double newValue = Math.log(value);
return withValue(newValue);
}

/**
* Calculates the base-10 logarithm of the physical quantity's value.
* This method computes the base-10 logarithm of the current value of the physical quantity
* and returns a new instance of the physical quantity with the updated value.<p>
* IMPORTANT: In some parts of the world (like Europe) natural logarithm is expressed as 'ln' symbol,
* and log means logarithm with base of 10. In this app, consistency with Math library was maintained,
* therefore log is natural logarithm (with e number in a base).<p>
*
* @return A new physical quantity with the value as the base-10 logarithm of the original value.
* @throws UnitSystemArgumentException if the current value is not greater than zero.
*/
default Q log10() {
double value = getValue();
if (value <= 0) {
throw new UnitSystemArgumentException("Cannot calculate logarithm for non-positive value: " + value);
}
double newValue = Math.log10(value);
return withValue(newValue);
}

// Ceiling, and rounding up

/**
* Returns a new physical quantity with the value rounded up to the nearest integer. <p>
* Examples: <p>
* ceil() for 10.123456 -> will result to 11 <p>
* ceil() for 0.123456 -> will result to 1 <p>
* ceil() for -10.123456- > will result to 10 (this one is contr intuitive)
*
* @return A new physical quantity with the value rounded up.
*/
default Q ceil() {
double newValue = Math.ceil(getValue());
return withValue(newValue);
}

/**
* Returns a new physical quantity with the value rounded down to the nearest integer.<p>
* Examples: <p>
* floor() for 10.123456 -> will result to 10 <p>
* floor() for 0.123456 -> will result to 0 <p>
* floor() for -10.123456- > will result to -11 (this one is contr intuitive)
*
* @return A new physical quantity with the value rounded down.
*/
default Q floor() {
double newValue = Math.floor(getValue());
return withValue(newValue);
}

/**
* Returns a new physical quantity with the value rounded in HALF_EVEN way to the specified number of relevant digits.
* Absolute value of an input argument for relevant digits is used.
* Examples: <p>
* roundHalfEven(0) for 10.123456 -> will result to 10 <p>
* roundHalfEven(1) for 0.153456 -> will result to 0.2 <p>
* roundHalfEven(2) for -10.123456- > will result to -10.12
*
* @param relevantDigits The number of relevant digits to round to.
* @return A new physical quantity with the value rounded to the specified number of relevant digits.
*/
default Q roundHalfEven(int relevantDigits) {
String formattedValue = ValueFormatter.toStringWithRelevantDigits(getValue(), relevantDigits);
double newValue = Double.parseDouble(formattedValue);
return withValue(newValue);
}

// Handling PhysicalQuantity as input argument

/**
Expand Down Expand Up @@ -203,4 +317,20 @@ default <V extends Unit, T extends PhysicalQuantity<V>> double div(T inputQuanti
return divide(inputQuantity);
}

/**
* Raises this physical quantity's value to the power of another physical quantity's value.<p>
* This method calculates the result of raising this quantity's value to the power of the value
* of the input quantity, and returns the result.
*
* @param inputQuantity The other physical quantity for raising to the power.
* @return The result of raising this quantity's value to the power of the other quantity's value.
*/
default <V extends Unit, T extends PhysicalQuantity<V>> double power(T inputQuantity) {
if (inputQuantity == null) {
return getValue();
}
double thisValue = getValue();
return Math.pow(thisValue, inputQuantity.getValue());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
*/
public interface PhysicalQuantity<U extends Unit> extends Comparable<PhysicalQuantity<U>> {

/**
* Create a new physical quantity with new value of the same unit.
*
* @param value The value for the new physical quantity.
* @return A new physical quantity with the specified value.
*/
PhysicalQuantity<U> withValue(double value);

/**
* Get the value of the physical quantity.
*
Expand Down
Loading

0 comments on commit 824f16f

Please sign in to comment.