Files
gonum/unittype.go
2013-09-17 17:22:23 -07:00

132 lines
3.1 KiB
Go

package unit
// Uniter is an interface representing a type that can be converted
// to a unit.
type Uniter interface {
Unit() *Unit
}
// Dimensions is a struct containing the SI base dimensions. Dimensions
// can be used in conjuntion with CreateUnit to create a
type Dimensions struct {
Current int
Length int
Luminosity int
Mass int
Temperature int
Time int
Chemamt int
}
// Unit is a type a value with generic SI units. Most useful for
// translating between dimensions, for example, by multiplying
// an acceleration with a mass to get a force
type Unit struct {
current int
length int
luminosity int
mass int
temperature int
time int
chemamt int // For mol
value float64
}
// CreateUnit creates a new variable of type Unit which has the value
// specified by value and the dimensions specified by the
// base units struct. The value is always in SI Units.
//
// Example: To create an acceleration of 3 m/s^2, one could do
// myvar := CreateUnit(3.0, &Dimensions{length: 1, time: -2})
func CreateUnit(value float64, d *Dimensions) *Unit {
return &Unit{
current: d.Current,
length: d.Length,
luminosity: d.Luminosity,
mass: d.Mass,
temperature: d.Temperature,
time: d.Time,
chemamt: d.Chemamt,
value: value,
}
}
// DimensionsMatch checks if the dimensions of two Uniters are the same
func DimensionsMatch(aU, bU Uniter) bool {
a := aU.Unit()
b := bU.Unit()
if a.length != b.length {
return false
}
if a.time != b.time {
return false
}
if a.mass != b.mass {
return false
}
if a.current != b.current {
return false
}
if a.temperature != b.temperature {
return false
}
if a.luminosity != b.luminosity {
return false
}
if a.chemamt != b.chemamt {
return false
}
return true
}
// Add adds the function argument to the reciever. Panics if the units of
// the receiver and the argument don't match.
func (u *Unit) Add(aU Uniter) *Unit {
a := aU.Unit()
if !DimensionsMatch(u, a) {
panic("Attempted to add the values of two units whose dimensions do not match.")
}
u.value += a.value
return u
}
// Unit allows unit to satisfy the uniter interface
func (u *Unit) Unit() *Unit {
return u
}
// Mul multiply the receiver by the unit changing the dimensions
// of the receiver as appropriate
func (u *Unit) Mul(aU Uniter) *Unit {
a := aU.Unit()
u.length += a.length
u.time += a.time
u.mass += a.mass
u.current += a.current
u.temperature += a.temperature
u.luminosity += a.luminosity
u.value *= a.value
return u
}
// Div divides the receiver by the argument changing the
// dimensions of the receiver as appropriate
func (u *Unit) Div(aU Uniter) *Unit {
a := aU.Unit()
u.length -= a.length
u.time -= a.time
u.mass -= a.mass
u.current -= a.current
u.temperature -= a.temperature
u.luminosity -= a.luminosity
u.value /= a.value
return u
}
// Value return the raw value of the unit as a float64. Use of this
// method is not recommended, instead it is recommended to use a
// FromUnit type of a specific dimension
func (u *Unit) Value() float64 {
return u.value
}