// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. package edu.wpi.first.units; import edu.wpi.first.units.collections.LongToObjectHashMap; import java.util.Objects; /** * Generic combinatory unit type that represents the proportion of one unit to another, such as * Meters per Second or Radians per Celsius. * *

Note that due to restrictions with the Java type system, velocities (change per unit time) are * represented by the {@link Velocity} class. Accelerations are represented by {@code * Velocity>}, and so on. * * @param the type of the numerator unit * @param the type of the denominator unit */ public class Per, D extends Unit> extends Unit> { private final N m_numerator; private final D m_denominator; /** * Keep a cache of created instances so expressions like Volts.per(Meter) don't do any allocations * after the first. */ @SuppressWarnings("rawtypes") private static final LongToObjectHashMap cache = new LongToObjectHashMap<>(); protected Per(Class> baseType, N numerator, D denominator) { super( baseType, numerator.toBaseUnits(1) / denominator.toBaseUnits(1), numerator.name() + " per " + denominator.name(), numerator.symbol() + "/" + denominator.symbol()); m_numerator = numerator; m_denominator = denominator; } /** * Creates a new Per unit derived from an arbitrary numerator and time denominator units. Using a * denominator with a unit of time is discouraged; use {@link Velocity} instead. * *

   *   Per.combine(Volts, Meters) // possible PID constant
   * 
* *

It's recommended to use the convenience function {@link Unit#per(Unit)} instead of calling * this factory directly. * * @param the type of the numerator unit * @param the type of the denominator unit * @param numerator the numerator unit * @param denominator the denominator for unit time * @return the combined unit */ @SuppressWarnings({"unchecked", "rawtypes"}) public static , D extends Unit> Per combine( N numerator, D denominator) { final long key = ((long) numerator.hashCode()) << 32L | ((long) denominator.hashCode()) & 0xFFFFFFFFL; var existing = cache.get(key); if (existing != null) { return existing; } var newUnit = new Per((Class) Per.class, numerator, denominator); cache.put(key, newUnit); return newUnit; } public N numerator() { return m_numerator; } public D denominator() { return m_denominator; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } Per per = (Per) o; return Objects.equals(m_numerator, per.m_numerator) && Objects.equals(m_denominator, per.m_denominator); } @Override public int hashCode() { return Objects.hash(super.hashCode(), m_numerator, m_denominator); } }