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 static edu.wpi.first.units.Units.Value;
008
009import edu.wpi.first.units.measure.Frequency;
010import edu.wpi.first.units.measure.ImmutableFrequency;
011import edu.wpi.first.units.measure.MutFrequency;
012
013/** A unit of frequency like {@link edu.wpi.first.units.Units#Hertz}. */
014public final class FrequencyUnit extends PerUnit<DimensionlessUnit, TimeUnit> {
015  private static final CombinatoryUnitCache<DimensionlessUnit, TimeUnit, FrequencyUnit> cache =
016      new CombinatoryUnitCache<>(FrequencyUnit::new);
017
018  FrequencyUnit(DimensionlessUnit numerator, TimeUnit denominator) {
019    super(
020        numerator.isBaseUnit() && denominator.isBaseUnit()
021            ? null
022            : combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
023        numerator,
024        denominator);
025  }
026
027  FrequencyUnit(
028      FrequencyUnit baseUnit,
029      UnaryFunction toBaseConverter,
030      UnaryFunction fromBaseConverter,
031      String name,
032      String symbol) {
033    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
034  }
035
036  /**
037   * Combines a dimensionless unit and a cycle period to create a frequency.
038   *
039   * @param dim the dimensionless unit
040   * @param period the unit of time
041   * @return the combined unit of frequency
042   */
043  public static FrequencyUnit combine(DimensionlessUnit dim, TimeUnit period) {
044    return cache.combine(dim, period);
045  }
046
047  @Override
048  public FrequencyUnit getBaseUnit() {
049    return (FrequencyUnit) super.getBaseUnit();
050  }
051
052  /**
053   * Inverts a unit of time to get its corresponding frequency (as if the unit of time is the period
054   * of the frequency).
055   *
056   * @param time period of the associated frequency
057   * @return the frequency associated with the period
058   */
059  public static FrequencyUnit inverse(TimeUnit time) {
060    return combine(Value, time);
061  }
062
063  @Override
064  public Frequency of(double magnitude) {
065    return new ImmutableFrequency(magnitude, toBaseUnits(magnitude), this);
066  }
067
068  @Override
069  public Frequency ofBaseUnits(double baseUnitMagnitude) {
070    return new ImmutableFrequency(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
071  }
072
073  @Override
074  public Frequency zero() {
075    return (Frequency) super.zero();
076  }
077
078  @Override
079  public Frequency one() {
080    return (Frequency) super.one();
081  }
082
083  @Override
084  public MutFrequency mutable(double initialMagnitude) {
085    return new MutFrequency(initialMagnitude, toBaseUnits(initialMagnitude), this);
086  }
087
088  @Override
089  public VelocityUnit<FrequencyUnit> per(TimeUnit time) {
090    return VelocityUnit.combine(this, time);
091  }
092
093  /**
094   * Creates a ratio unit between this unit and an arbitrary other unit.
095   *
096   * @param other the other unit
097   * @param <U> the type of the other unit
098   * @return the ratio unit
099   */
100  public <U extends Unit> PerUnit<FrequencyUnit, U> per(U other) {
101    return PerUnit.combine(this, other);
102  }
103
104  /**
105   * Converts a measurement value in terms of another unit to this unit.
106   *
107   * @param magnitude the magnitude of the measurement in terms of the other unit
108   * @param otherUnit the other unit
109   * @return the value of the measurement in terms of this unit
110   */
111  public double convertFrom(double magnitude, FrequencyUnit otherUnit) {
112    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
113  }
114}