# units / units.go

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94``` ```package units const ( kilogramPart = 2 meterPart = 3 secondPart = 5 amperePart = 7 kelvinPart = 11 ) type unit struct { numer uint32 denom uint32 } var ( Meter = unit{meterPart, 1} Second = unit{secondPart, 1} Kilogram = unit{kilogramPart, 1} Ampere = unit{amperePart, 1} Kelvin = unit{kelvinPart, 1} Unitless = unit{1, 1} Newton = Kilogram.times(Meter).per(Second).per(Second) Joule = Newton.times(Meter) Watt = Joule.per(Second) Pascal = Newton.per(Meter).per(Meter) Hertz = Unitless.per(Second) Coulomb = Ampere.times(Second) Volt = Joule.per(Coulomb) Ohm = Volt.per(Ampere) Farad = Coulomb.per(Volt) Weber = Volt.times(Second) Henry = Weber.per(Ampere) Tesla = Weber.per(Meter).per(Meter) ) func gcd(a, b uint32) uint32 { for b > 0 { a, b = b, a%b } return a } func (u unit) canonicalize() unit { if u.numer == 0 { u.numer = 1 } if u.denom == 0 { u.denom = 1 } d := gcd(u.numer, u.denom) return unit{u.numer / d, u.denom / d} } func (x unit) times(y unit) unit { x.numer *= y.numer x.denom *= y.denom return x.canonicalize() } func (x unit) per(y unit) unit { x.numer *= y.denom x.denom *= y.numer return x.canonicalize() } type Value struct { num float64 units unit } func (x Value) Mul(y Value) Value { return Value{x.num * y.num, x.units.times(y.units)} } func (x Value) Div(y Value) Value { return Value{x.num / y.num, x.units.per(y.units)} } func (x Value) Add(y Value) Value { if x.units != y.units { panic("cannot add different units") } return Value{x.num + y.num, x.units} } func (x Value) Sub(y Value) Value { if x.units != y.units { panic("cannot subtract different units") } return Value{x.num - y.num, x.units} } ```