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