mirror of
https://github.com/gonum/gonum.git
synced 2025-10-13 02:43:59 +08:00
136 lines
2.8 KiB
Go
136 lines
2.8 KiB
Go
package unit
|
|
|
|
// A uniter is a type that can be converted
|
|
// to a unit. These functions declare the
|
|
// power of the basic dimension of the unit
|
|
type Uniter interface {
|
|
Unit() *Unit
|
|
}
|
|
|
|
// A list of the base units as defined by the SI system.
|
|
// Used to create a new unit
|
|
type Dimensions struct {
|
|
Current int
|
|
Length int
|
|
Luminosity int
|
|
Mass int
|
|
Temperature int
|
|
Time int
|
|
Chemamt int
|
|
}
|
|
|
|
// A generic unit type. Mostly used for doing math involving units
|
|
type Unit struct {
|
|
current int
|
|
length int
|
|
luminosity int
|
|
mass int
|
|
temperature int
|
|
time int
|
|
chemamt int // For mol
|
|
value float64
|
|
}
|
|
|
|
// TODO: Some oddities with chemamt. Not sure what to do
|
|
|
|
// Create a new variable of type Unit having the value
|
|
// specified by value and the dimensions specified by the
|
|
// base units struct.
|
|
//
|
|
// 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,
|
|
}
|
|
}
|
|
|
|
// Check if the dimensions of two units 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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (u *Unit) Unit() *Unit {
|
|
return u
|
|
}
|
|
|
|
// Multiply the receiver by the unit
|
|
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
|
|
}
|
|
|
|
// Divide the receive by the unit
|
|
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
|
|
}
|
|
|
|
// Convert to a different dimension
|
|
func (u *Unit) In(a Uniter) float64 {
|
|
u2 := a.Unit()
|
|
if !DimensionsMatch(u, u2) {
|
|
panic("Attempt to assign to the wrong dimension")
|
|
}
|
|
return u.value / u2.value
|
|
}
|
|
|
|
// Return the value of the unit (will always be in SI units).
|
|
// If it is wanted as a specific dimension, see ToLength, etc.
|
|
func (u *Unit) Value() float64 {
|
|
return u.value
|
|
}
|