001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.units;
006
007import edu.wpi.first.units.measure.Dimensionless;
008
009/**
010 * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. An
011 * immutable measure is <i>immutable</i> and <i>type safe</i>, making it easy to use in concurrent
012 * situations and gives compile-time safety. Two measures with the same <i>unit</i> and
013 * <i>magnitude</i> are effectively equivalent objects.
014 *
015 * @param magnitude the magnitude of the measure in terms of its unit
016 * @param baseUnitMagnitude the magnitude of the measure in terms of its base unit
017 * @param unit the unit of the measurement
018 * @param <U> the unit type of the measure
019 */
020public record ImmutableMeasure<U extends Unit>(double magnitude, double baseUnitMagnitude, U unit)
021    implements Measure<U> {
022  /**
023   * Creates a new measure in the given unit with a magnitude equal to the given one in base units.
024   *
025   * @param <U> the type of the units of measure
026   * @param baseUnitMagnitude the magnitude of the measure, in terms of the base unit of measure
027   * @param unit the unit of measure
028   * @return a new measure
029   */
030  public static <U extends Unit> ImmutableMeasure<U> ofBaseUnits(double baseUnitMagnitude, U unit) {
031    return new ImmutableMeasure<>(unit.fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, unit);
032  }
033
034  /**
035   * Creates a new measure in the given unit with a magnitude in terms of that unit.
036   *
037   * @param <U> the type of the units of measure
038   * @param relativeMagnitude the magnitude of the measure
039   * @param unit the unit of measure
040   * @return a new measure
041   */
042  public static <U extends Unit> ImmutableMeasure<U> ofRelativeUnits(
043      double relativeMagnitude, U unit) {
044    return new ImmutableMeasure<>(relativeMagnitude, unit.toBaseUnits(relativeMagnitude), unit);
045  }
046
047  @Override
048  public Measure<U> unaryMinus() {
049    return ofBaseUnits(0 - baseUnitMagnitude, unit);
050  }
051
052  @Override
053  public Measure<U> plus(Measure<? extends U> other) {
054    return ofBaseUnits(baseUnitMagnitude + other.baseUnitMagnitude(), unit);
055  }
056
057  @Override
058  public Measure<U> minus(Measure<? extends U> other) {
059    return ofBaseUnits(baseUnitMagnitude - other.baseUnitMagnitude(), unit);
060  }
061
062  @Override
063  public Measure<U> times(double multiplier) {
064    return ofBaseUnits(baseUnitMagnitude * multiplier, unit);
065  }
066
067  @Override
068  public Measure<U> times(Dimensionless multiplier) {
069    return ofBaseUnits(baseUnitMagnitude * multiplier.baseUnitMagnitude(), unit);
070  }
071
072  @Override
073  public Measure<U> div(double divisor) {
074    return ofBaseUnits(baseUnitMagnitude / divisor, unit);
075  }
076
077  @Override
078  public Measure<U> div(Dimensionless divisor) {
079    return ofBaseUnits(baseUnitMagnitude / divisor.baseUnitMagnitude(), unit);
080  }
081}