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;
008import edu.wpi.first.units.mutable.GenericMutableMeasureImpl;
009
010/**
011 * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. An
012 * immutable measure is <i>immutable</i> and <i>type safe</i>, making it easy to use in concurrent
013 * situations and gives compile-time safety. Two measures with the same <i>unit</i> and
014 * <i>magnitude</i> are effectively equivalent objects.
015 *
016 * @param magnitude the magnitude of the measure in terms of its unit
017 * @param baseUnitMagnitude the magnitude of the measure in terms of its base unit
018 * @param unit the unit of the measurement
019 * @param <U> the unit type of the measure
020 */
021public record ImmutableMeasure<U extends Unit>(double magnitude, double baseUnitMagnitude, U unit)
022    implements Measure<U> {
023  /**
024   * Creates a new measure in the given unit with a magnitude equal to the given one in base units.
025   *
026   * @param <U> the type of the units of measure
027   * @param baseUnitMagnitude the magnitude of the measure, in terms of the base unit of measure
028   * @param unit the unit of measure
029   * @return a new measure
030   */
031  public static <U extends Unit> ImmutableMeasure<U> ofBaseUnits(double baseUnitMagnitude, U unit) {
032    return new ImmutableMeasure<>(unit.fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, unit);
033  }
034
035  /**
036   * Creates a new measure in the given unit with a magnitude in terms of that unit.
037   *
038   * @param <U> the type of the units of measure
039   * @param relativeMagnitude the magnitude of the measure
040   * @param unit the unit of measure
041   * @return a new measure
042   */
043  public static <U extends Unit> ImmutableMeasure<U> ofRelativeUnits(
044      double relativeMagnitude, U unit) {
045    return new ImmutableMeasure<>(relativeMagnitude, unit.toBaseUnits(relativeMagnitude), unit);
046  }
047
048  @Override
049  public Measure<U> copy() {
050    return this; // already immutable, no need to allocate a new object
051  }
052
053  @Override
054  public MutableMeasure<U, ?, ?> mutableCopy() {
055    return new GenericMutableMeasureImpl<>(magnitude, baseUnitMagnitude, unit);
056  }
057
058  @Override
059  public Measure<U> unaryMinus() {
060    return ofBaseUnits(0 - baseUnitMagnitude, unit);
061  }
062
063  @Override
064  public Measure<U> plus(Measure<? extends U> other) {
065    return ofBaseUnits(baseUnitMagnitude + other.baseUnitMagnitude(), unit);
066  }
067
068  @Override
069  public Measure<U> minus(Measure<? extends U> other) {
070    return ofBaseUnits(baseUnitMagnitude - other.baseUnitMagnitude(), unit);
071  }
072
073  @Override
074  public Measure<U> times(double multiplier) {
075    return ofBaseUnits(baseUnitMagnitude * multiplier, unit);
076  }
077
078  @Override
079  public Measure<U> times(Dimensionless multiplier) {
080    return ofBaseUnits(baseUnitMagnitude * multiplier.baseUnitMagnitude(), unit);
081  }
082
083  @Override
084  public Measure<U> div(double divisor) {
085    return ofBaseUnits(baseUnitMagnitude / divisor, unit);
086  }
087
088  @Override
089  public Measure<U> div(Dimensionless divisor) {
090    return ofBaseUnits(baseUnitMagnitude / divisor.baseUnitMagnitude(), unit);
091  }
092}