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.collections.LongToObjectHashMap; 008import java.util.Objects; 009 010/** 011 * A combinatory unit type that is equivalent to the product of two other others. 012 * 013 * @param <A> the type of the first unit in the result 014 * @param <B> the type of the second unit in the result 015 */ 016public class Mult<A extends Unit<A>, B extends Unit<B>> extends Unit<Mult<A, B>> { 017 private final A m_unitA; 018 private final B m_unitB; 019 020 @SuppressWarnings("rawtypes") 021 private static final LongToObjectHashMap<Mult> cache = new LongToObjectHashMap<>(); 022 023 protected Mult(Class<? extends Mult<A, B>> baseType, A a, B b) { 024 super( 025 baseType, 026 a.toBaseUnits(1) * b.toBaseUnits(1), 027 a.name() + "-" + b.name(), 028 a.symbol() + "*" + b.symbol()); 029 m_unitA = a; 030 m_unitB = b; 031 } 032 033 /** 034 * Creates a new Mult unit derived from two arbitrary units multiplied together. 035 * 036 * <pre> 037 * Mult.combine(Volts, Meters) // Volt-Meters 038 * </pre> 039 * 040 * <p>It's recommended to use the convenience function {@link Unit#mult(Unit)} instead of calling 041 * this factory directly. 042 * 043 * @param <A> the type of the first unit 044 * @param <B> the type of the second unit 045 * @param a the first unit 046 * @param b the second unit 047 * @return the combined unit 048 */ 049 @SuppressWarnings({"unchecked", "rawtypes"}) 050 public static <A extends Unit<A>, B extends Unit<B>> Mult<A, B> combine(A a, B b) { 051 final long key = ((long) a.hashCode()) << 32L | ((long) b.hashCode()) & 0xFFFFFFFFL; 052 if (cache.containsKey(key)) { 053 return cache.get(key); 054 } 055 056 var mult = new Mult<A, B>((Class) Mult.class, a, b); 057 cache.put(key, mult); 058 return mult; 059 } 060 061 public A unitA() { 062 return m_unitA; 063 } 064 065 public B unitB() { 066 return m_unitB; 067 } 068 069 @Override 070 public String toString() { 071 return "(" + m_unitA.toString() + " * " + m_unitB.toString() + ")"; 072 } 073 074 @Override 075 public boolean equals(Object o) { 076 if (this == o) { 077 return true; 078 } 079 if (o == null || getClass() != o.getClass()) { 080 return false; 081 } 082 if (!super.equals(o)) { 083 return false; 084 } 085 Mult<?, ?> mult = (Mult<?, ?>) o; 086 return Objects.equals(m_unitA, mult.m_unitA) && Objects.equals(m_unitB, mult.m_unitB); 087 } 088 089 @Override 090 public int hashCode() { 091 return Objects.hash(super.hashCode(), m_unitA, m_unitB); 092 } 093}