This package should look like Unitful.jl but behave like DynamicQuantities.jl under the hood

Tasks:
1.  Build out documentation and a docs badge
    -   Include all-stops-out tutorial on defining a new dimension "RadDims"
    -   Add angle to the dimension list
    -   Create a new unit registry with that dimension 
    -   Re-tool sin, cos, tan rules on this particular dimension
2.  Add "unit_info(u::Union{Dimension, AbstractUnit{Dimension}})" 
    -   Maps dimensions to a meaning (like Force or Inductance) and lists other units of that dimension
    -   This can be done without documentation 
        -   Use Dict{Dimension,String} to find dimension "meaning" (determine this by unique dimensions)
        -   Iterate over registry and list other units that match the query dimension
3. Consider a special object QuantTransform(scale::AbstractArray, units::UnitTransform)<:AbstractArray{<:Quantity}
    -   For a matrix multiplication with a column vector to work, the matrix must be dimensionally consistent
    -   All CONSISTENT quantity transforms mQ can be broken down into mQ.scale, mQ.units = {mU.rownum, mU.rowdenom}
        -   Multiplication of a vector quantity "v" with a quantity transform mQ can be expressed as 
            -   mQ.rownumer.*(mQ.scale)*(v./mQ.rowdenom)
        -   Let mU be a matrix of units
        -   Every valid transform can be decomposed to (rownumer, rowdenom)
        -   rowdenom = unit.(mQ[begin,:])/unit(mQ[begin,begin])
            -   Must be the same for every row otherwise it is inconsistent
        -   rownumer = unit.(mQ[:,begin])
        -   The expression mQ.rownumer.*(mQ.scale)*(v./mQ.rowdenom) can be further simplified to
            -   rowunit = unit(v[ii])/mQ.rowdenom[ii] (must be the same for all elements)
            -   new expression is (mQ.scale*value.(v)).*rowunit.*mQ.rownumer
        -   mU can be easily inverted
            -   inv(mU) = UnitTransform(rownum=inv.(mU.rowdenom), rowdenom=inv.(mU.rownum))
    -   All SELF-CONSISTENT quantity transforms (SelfQuantTransform) mQ can be further broken down as mQ.units = {mU.bulkdim, mU.rownum} 
        -   Unit matrix can be reconstructed as mU = mU.bulkdim.*inv.(mU.rownum).*mU.rownum'
        -   This is essentially an eigendecomposition of a rank-1 matrix (single eigvenvalue/eigenvector pair)
        -   Self-consistent matrices can be "powered"
        -   Self-consistent matrices with a dimensionless "bulkdim" can be exponentiated
    -   This is a KILLER FEATURE because this makes common matrix operations MUCH faster than Unitful


import DynamicQuantities
import Unitful
using BenchmarkTools

v1flex = ubase.([1u"m/s", 1u"J/kg", 1u"A/V"])
v1uni  = [1*Unitful.u"m/s", 1*Unitful.u"J/kg", 1*Unitful.u"A/V"]
v1dyn  = [1*DynamicQuantities.u"m/s", 1*DynamicQuantities.u"J/kg", 1*DynamicQuantities.u"A/V"]

@btime sum(x->x^0.0, v1uni)
@btime sum(x->x^0.0, v1flex)
@btime sum(x->x^0.0, v1dyn)

t1flex = ubase.((1u"m/s", 1u"J/kg", 1u"A/V"))
t1uni  = (1*Unitful.u"m/s", 1*Unitful.u"J/kg", 1*Unitful.u"A/V")
t1dyn  = (1*DynamicQuantities.u"m/s", 1*DynamicQuantities.u"J/kg", 1*DynamicQuantities.u"A/V")

@btime sum(x->x^0, t1uni)
@btime sum(x->x^0, t1flex)
@btime sum(x->x^0, t1dyn)

Considerations:
N.  Consider commutative macro for promote_rule to prevent repetition
        https://discourse.julialang.org/t/techniques-for-defining-commutative-functions/113406/5
