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 mutable measurement can be used to keep a single object allocation and reference whose state is
011 * mutated or changed as it is used. This is helpful for optimizing memory usage to keep garbage
012 * collection time - and its associated loop overruns - to a minimum.
013 *
014 * @param <U> The dimension of measurement.
015 * @param <Base> The base measure type.
016 * @param <MutSelf> The self type. This MUST inherit from the base measure type.
017 */
018public interface MutableMeasure<
019        U extends Unit, Base extends Measure<U>, MutSelf extends MutableMeasure<U, Base, MutSelf>>
020    extends Measure<U> {
021  /**
022   * Overwrites the state of this measure with new values.
023   *
024   * @param magnitude the new magnitude in terms of the new unit
025   * @param newUnit the new unit
026   * @return this measure
027   */
028  MutSelf mut_replace(double magnitude, U newUnit);
029
030  /**
031   * Overwrites the state of this measure and replaces it completely with values from the given one.
032   * The magnitude, base unit magnitude, and unit will all be copied. This is functionally the same
033   * as calling {@code other.mutableCopy()}, but copying to a pre-existing mutable measure instead
034   * of instantiating a new one.
035   *
036   * @param other the other measure to copy values from
037   * @return this measure
038   */
039  default MutSelf mut_replace(Base other) {
040    return mut_replace(other.magnitude(), other.unit());
041  }
042
043  @Override
044  Base copy();
045
046  /**
047   * Sets the new magnitude of the measurement. The magnitude must be in terms of the {@link
048   * #unit()}.
049   *
050   * @param magnitude the new magnitude of the measurement
051   * @return this mutable measure
052   */
053  default MutSelf mut_setMagnitude(double magnitude) {
054    return mut_replace(magnitude, unit());
055  }
056
057  /**
058   * Sets the new magnitude of the measurement. The magnitude must be in terms of the base unit of
059   * the current unit.
060   *
061   * @param baseUnitMagnitude the new magnitude of the measurement
062   * @return this mutable measure
063   */
064  default MutSelf mut_setBaseUnitMagnitude(double baseUnitMagnitude) {
065    return mut_replace(unit().fromBaseUnits(baseUnitMagnitude), unit());
066  }
067
068  /**
069   * Increments the current magnitude of the measure by the given value. The value must be in terms
070   * of the current {@link #unit() unit}.
071   *
072   * @param raw the raw value to accumulate by
073   * @return the measure
074   */
075  default MutSelf mut_acc(double raw) {
076    return mut_setBaseUnitMagnitude(magnitude() + raw);
077  }
078
079  /**
080   * Increments the current magnitude of the measure by the amount of the given measure.
081   *
082   * @param other the measure whose value should be added to this one
083   * @return this measure
084   */
085  default MutSelf mut_acc(Base other) {
086    return mut_setMagnitude(magnitude() + unit().fromBaseUnits(other.baseUnitMagnitude()));
087  }
088
089  /**
090   * Adds another measurement to this one. This will mutate the object instead of generating a new
091   * measurement object.
092   *
093   * @param other the measurement to add
094   * @return this measure
095   */
096  default MutSelf mut_plus(Base other) {
097    return mut_acc(other);
098  }
099
100  /**
101   * Adds another measurement to this one. This will mutate the object instead of generating a new
102   * measurement object. This is a denormalized version of {@link #mut_plus(Measure)} to avoid
103   * having to wrap raw numbers in a {@code Measure} object and pay for an object allocation.
104   *
105   * @param magnitude the magnitude of the other measurement.
106   * @param otherUnit the unit of the other measurement
107   * @return this measure
108   */
109  default MutSelf mut_plus(double magnitude, U otherUnit) {
110    return mut_setBaseUnitMagnitude(magnitude() + otherUnit.toBaseUnits(magnitude));
111  }
112
113  /**
114   * Subtracts another measurement to this one. This will mutate the object instead of generating a
115   * new measurement object.
116   *
117   * @param other the measurement to subtract from this one
118   * @return this measure
119   */
120  default MutSelf mut_minus(Base other) {
121    return mut_setBaseUnitMagnitude(baseUnitMagnitude() - other.baseUnitMagnitude());
122  }
123
124  /**
125   * Subtracts another measurement from this one. This will mutate the object instead of generating
126   * a new measurement object. This is a denormalized version of {@link #mut_minus(Measure)} to
127   * avoid having to wrap raw numbers in a {@code Measure} object and pay for an object allocation.
128   *
129   * @param magnitude the magnitude of the other measurement.
130   * @param otherUnit the unit of the other measurement
131   * @return this measure
132   */
133  default MutSelf mut_minus(double magnitude, U otherUnit) {
134    return mut_setBaseUnitMagnitude(baseUnitMagnitude() - otherUnit.toBaseUnits(magnitude));
135  }
136
137  /**
138   * Multiplies this measurement by some constant value. This will mutate the object instead of
139   * generating a new measurement object.
140   *
141   * @param multiplier the multiplier to scale the measurement by
142   * @return this measure
143   */
144  default MutSelf mut_times(double multiplier) {
145    return mut_setBaseUnitMagnitude(baseUnitMagnitude() * multiplier);
146  }
147
148  /**
149   * Multiplies this measurement by some constant value. This will mutate the object instead of
150   * generating a new measurement object.
151   *
152   * @param multiplier the multiplier to scale the measurement by
153   * @return this measure
154   */
155  default MutSelf mut_times(Dimensionless multiplier) {
156    return mut_times(multiplier.baseUnitMagnitude());
157  }
158
159  /**
160   * Divides this measurement by some constant value. This will mutate the object instead of
161   * generating a new measurement object.
162   *
163   * @param divisor the divisor to scale the measurement by
164   * @return this measure
165   */
166  default MutSelf mut_divide(double divisor) {
167    return mut_times(1 / divisor);
168  }
169
170  /**
171   * Divides this measurement by some constant value. This will mutate the object instead of
172   * generating a new measurement object.
173   *
174   * @param divisor the divisor to scale the measurement by
175   * @return this measure
176   */
177  default MutSelf mut_divide(Dimensionless divisor) {
178    return mut_divide(divisor.baseUnitMagnitude());
179  }
180}