| 1 |
/** |
|---|
| 2 |
* Set of real world units to work with |
|---|
| 3 |
*/ |
|---|
| 4 |
module si; |
|---|
| 5 |
|
|---|
| 6 |
import std.string; |
|---|
| 7 |
|
|---|
| 8 |
import unit; |
|---|
| 9 |
import rational; |
|---|
| 10 |
|
|---|
| 11 |
/// generate an encoder and decoder |
|---|
| 12 |
template Option(char[] name, real v, int l, int m, int t, int T, int i) |
|---|
| 13 |
{ |
|---|
| 14 |
const char[] ls = l.stringof; |
|---|
| 15 |
const char[] ms = m.stringof; |
|---|
| 16 |
const char[] ts = t.stringof; |
|---|
| 17 |
const char[] Ts = T.stringof; |
|---|
| 18 |
const char[] Is = i.stringof; |
|---|
| 19 |
const char[] type = "Unit!("~ls~",1,"~ms~",1,"~ts~",1,"~Ts~",1,"~Is~",1)"; |
|---|
| 20 |
|
|---|
| 21 |
/// unit encoder: stuff the value in the correct type with convertions |
|---|
| 22 |
const char[] Make = |
|---|
| 23 |
"static "~type~name~"(real val)" |
|---|
| 24 |
"{"~ |
|---|
| 25 |
type~" ret;" |
|---|
| 26 |
"ret._rawSet(val*"~v.stringof~");" |
|---|
| 27 |
"return ret;" |
|---|
| 28 |
"}" |
|---|
| 29 |
"static "~type~name~"()" |
|---|
| 30 |
"{"~ |
|---|
| 31 |
type~" ret;" |
|---|
| 32 |
"ret._rawSet("~v.stringof~");" |
|---|
| 33 |
"return ret;" |
|---|
| 34 |
"}" |
|---|
| 35 |
\n; |
|---|
| 36 |
|
|---|
| 37 |
/// unit decoder: if the unit classes match, create a function that extracts, converts and returns the value. |
|---|
| 38 |
const char[] From = |
|---|
| 39 |
"static if(is(T == "~type~"))" |
|---|
| 40 |
"{" |
|---|
| 41 |
"real "~name~"()" |
|---|
| 42 |
"{" |
|---|
| 43 |
"return t._rawGet()/"~v.stringof~";" |
|---|
| 44 |
"}" |
|---|
| 45 |
"}" |
|---|
| 46 |
\n; |
|---|
| 47 |
//pragma(msg,From); |
|---|
| 48 |
} |
|---|
| 49 |
|
|---|
| 50 |
/// unwinds a set of unit defs into an implemntation of encoders or decoders |
|---|
| 51 |
template BuildSet(char[] suf, T...) |
|---|
| 52 |
{ |
|---|
| 53 |
static if(T.length == 0) |
|---|
| 54 |
const BuildSet = ""; |
|---|
| 55 |
else static if (T.length == 1) |
|---|
| 56 |
const BuildSet = (mixin(`Option!(`~T[0]~`).`~suf)); |
|---|
| 57 |
else |
|---|
| 58 |
const BuildSet = BuildSet!(suf,T[0..$/2]) ~ BuildSet!(suf,T[$/2..$]); |
|---|
| 59 |
} |
|---|
| 60 |
|
|---|
| 61 |
/// The set of unit defs |
|---|
| 62 |
alias Tpl!( |
|---|
| 63 |
`"value", 1.0, 0,0,0,0,0`, |
|---|
| 64 |
`"meter", 1.0, 1,0,0,0,0`, |
|---|
| 65 |
`"kilogram", 1.0, 0,1,0,0,0`, |
|---|
| 66 |
`"second", 1.0, 0,0,1,0,0`, |
|---|
| 67 |
`"kelvin", 1.0, 0,0,0,1,0`, |
|---|
| 68 |
`"ampere", 1.0, 0,0,0,0,1`, |
|---|
| 69 |
|
|---|
| 70 |
/// Distance Unit Types |
|---|
| 71 |
`"Angstrom", 1e-10, 1,0,0,0,0`, |
|---|
| 72 |
`"Micron", 1e-6, 1,0,0,0,0`, |
|---|
| 73 |
`"mm", 1e-3, 1,0,0,0,0`, |
|---|
| 74 |
`"cm", 1e-2, 1,0,0,0,0`, |
|---|
| 75 |
`"km", 1e3, 1,0,0,0,0`, |
|---|
| 76 |
`"inch", 2.54e-2, 1,0,0,0,0`, |
|---|
| 77 |
`"foot", 3.04799835e-1, 1,0,0,0,0`, |
|---|
| 78 |
`"yard", 9.14399506e-1, 1,0,0,0,0`, |
|---|
| 79 |
`"mile", 1.609343130e3, 1,0,0,0,0`, |
|---|
| 80 |
`"parsec", 3.085677473598e13, 1,0,0,0,0`, |
|---|
| 81 |
|
|---|
| 82 |
/// Mass Unit Types |
|---|
| 83 |
`"gram", 1e-3, 0,1,0,0,0`, |
|---|
| 84 |
`"lb", 4.5359237e-1,0,1,0,0,0`, |
|---|
| 85 |
`"Ounce", 2.834952e-2, 0,1,0,0,0`, |
|---|
| 86 |
|
|---|
| 87 |
/// Time Unit Types |
|---|
| 88 |
`"minute", 60.0, 0,0,1,0,0`, |
|---|
| 89 |
`"hour", 3600.0, 0,0,1,0,0`, |
|---|
| 90 |
`"day", 86400.0, 0,0,1,0,0`, |
|---|
| 91 |
|
|---|
| 92 |
/// Temperature Unit Types |
|---|
| 93 |
`"R", 0.5555555555, 0,0,0,1,0`, |
|---|
| 94 |
|
|---|
| 95 |
/// Force Unit Types |
|---|
| 96 |
`"Newton", 1.0, 1,1,-2,0,0`, |
|---|
| 97 |
`"dyne", 1e-5, 1,1,-2,0,0`, |
|---|
| 98 |
`"lbf", 4.44822246806, 1,1,-2,0,0`, |
|---|
| 99 |
|
|---|
| 100 |
/// Charge Unit Types |
|---|
| 101 |
`"Coulomb", 1.0, 0,0,1,0,1`, |
|---|
| 102 |
|
|---|
| 103 |
/// Magnetic flux density |
|---|
| 104 |
`"T", 1.0, 0,1,-2,0,-1`, |
|---|
| 105 |
|
|---|
| 106 |
/// magnetic flux |
|---|
| 107 |
`"Wb", 1.0, 2,1,-2,0,1`, |
|---|
| 108 |
|
|---|
| 109 |
/// inductance |
|---|
| 110 |
`"H", 1.0, 2,1,-2,0,-2`, |
|---|
| 111 |
|
|---|
| 112 |
/// Energy Unit Types |
|---|
| 113 |
`"Joule", 1.0, 2,1,-2,0,0`, |
|---|
| 114 |
`"Erg", 1e-7L, 2,1,-2,0,0`, |
|---|
| 115 |
`"cal", 4.1868L, 2,1,-2,0,0`, |
|---|
| 116 |
`"eV", 1.602176462e-19L, 2,1,-2,0,0`, |
|---|
| 117 |
`"BTU", 1.0550558526e3L, 2,1,-2,0,0`, |
|---|
| 118 |
|
|---|
| 119 |
/// Voltage Unit Types |
|---|
| 120 |
`"Volt", 1.0, 2,1,-3,0,-1`, |
|---|
| 121 |
|
|---|
| 122 |
/// Frequency Unit Types |
|---|
| 123 |
`"Hz", 1.0, 0,0,-1,0,0`, |
|---|
| 124 |
|
|---|
| 125 |
/// Resistance Unit Types |
|---|
| 126 |
`"Ohm", 1.0, -2,-1,3,0,2`, |
|---|
| 127 |
|
|---|
| 128 |
/// Pressure Unit Types |
|---|
| 129 |
`"Pa", 1.0, -1,1,-2,0,0`, |
|---|
| 130 |
`"Bar", 1e5L, -1,1,-2,0,0`, |
|---|
| 131 |
`"Atm", 1.01325e5L, -1,1,-2,0,0`, |
|---|
| 132 |
`"psi", 6.89475729e3,-1,1,-2,0,0`, |
|---|
| 133 |
|
|---|
| 134 |
/// Viscosity |
|---|
| 135 |
// |
|---|
| 136 |
`"Poise", 0.1, -1,1,-1,0,0`, |
|---|
| 137 |
// |
|---|
| 138 |
`"stokes", 0.0001, 2,0,-1,0,0`, |
|---|
| 139 |
|
|---|
| 140 |
/// Power Unit Types |
|---|
| 141 |
`"Watt", 1.0, 2,1,-3,0,0`, |
|---|
| 142 |
`"kWatt", 1000, 2,1,-3,0,0`, |
|---|
| 143 |
`"Hp", 745.69987158L,2,1,-3,0,0`, |
|---|
| 144 |
|
|---|
| 145 |
/// Volume Unit Types |
|---|
| 146 |
`"Steres", 1.0, 3,0,0,0,0`, |
|---|
| 147 |
`"Liter", 0.001L, 3,0,0,0,0`, |
|---|
| 148 |
`"Gal", 0.0037854120L,3,0,0,0,0`, |
|---|
| 149 |
`"Cup", 0.0002365883L,3,0,0,0,0`, |
|---|
| 150 |
|
|---|
| 151 |
/// volume rate |
|---|
| 152 |
`"gpm", 6.30901995e-5L, 3,0,-1,0,0`, |
|---|
| 153 |
`"cfm", 4.71947443e-4L, 3,0,-1,0,0`, |
|---|
| 154 |
|
|---|
| 155 |
/// Speed Unit Types |
|---|
| 156 |
`"mps", 1L, 1,0,-1,0,0`, |
|---|
| 157 |
`"Knots", 1.51444L, 1,0,-1,0,0`, |
|---|
| 158 |
`"mph", 0.44704L, 1,0,-1,0,0`, |
|---|
| 159 |
`"kph", 0.27778L, 1,0,-1,0,0`, |
|---|
| 160 |
`"fps", 0.3048L, 1,0,-1,0,0`, |
|---|
| 161 |
|
|---|
| 162 |
/// Capacitance Unit Types |
|---|
| 163 |
`"Farad", 1.0, -2,-1,4,0,2`, |
|---|
| 164 |
|
|---|
| 165 |
/// Area Unit Types |
|---|
| 166 |
`"Acre", 4046.856421L, 2,0,0,0,0`, |
|---|
| 167 |
|
|---|
| 168 |
/// Acceleration Unit Types |
|---|
| 169 |
`"G", 9.80665L, 1,0,-2,0,0` |
|---|
| 170 |
|
|---|
| 171 |
) unitsSet; |
|---|
| 172 |
|
|---|
| 173 |
|
|---|
| 174 |
static if(false) |
|---|
| 175 |
{ |
|---|
| 176 |
pragma(msg,BuildSet!("Make", unitsSet)); |
|---|
| 177 |
pragma(msg,BuildSet!("From", unitsSet)); |
|---|
| 178 |
} |
|---|
| 179 |
|
|---|
| 180 |
|
|---|
| 181 |
/// Name space to carry Unit encoders |
|---|
| 182 |
struct SI |
|---|
| 183 |
{ |
|---|
| 184 |
mixin(BuildSet!("Make", unitsSet)); |
|---|
| 185 |
|
|---|
| 186 |
static Unit!( 0,1, 0,1, 0,1, 1,1, 0,1) degF(real val) |
|---|
| 187 |
{ |
|---|
| 188 |
Unit!( 0,1, 0,1, 0,1, 1,1, 0,1) ret; |
|---|
| 189 |
ret._rawSet(val*0.5555555555 + 273.15); |
|---|
| 190 |
return ret; |
|---|
| 191 |
} |
|---|
| 192 |
|
|---|
| 193 |
static Unit!( 0,1, 0,1, 0,1, 1,1, 0,1) degC(real val) |
|---|
| 194 |
{ |
|---|
| 195 |
Unit!( 0,1, 0,1, 0,1, 1,1, 0,1) ret; |
|---|
| 196 |
ret._rawSet(val + 273.15); |
|---|
| 197 |
return ret; |
|---|
| 198 |
} |
|---|
| 199 |
|
|---|
| 200 |
} |
|---|
| 201 |
|
|---|
| 202 |
/// Type to build decoders on. |
|---|
| 203 |
struct To_back(T) |
|---|
| 204 |
{ |
|---|
| 205 |
T t; |
|---|
| 206 |
mixin(BuildSet!("From", unitsSet)); |
|---|
| 207 |
|
|---|
| 208 |
static if(is(T == Unit!( 0,1, 0,1, 0,1, 1,1, 0,1))) |
|---|
| 209 |
{ |
|---|
| 210 |
real degF() { return (t._rawGet()-273.15)/0.5555555555; } |
|---|
| 211 |
real degC() { return t._rawGet()-273.15; } |
|---|
| 212 |
} |
|---|
| 213 |
|
|---|
| 214 |
} |
|---|
| 215 |
|
|---|
| 216 |
/// Wrap a unit in a To_Back and retun it |
|---|
| 217 |
To_back!(T) From(T)(T t) |
|---|
| 218 |
{ |
|---|
| 219 |
To_back!(T) ret; |
|---|
| 220 |
ret.t = t; |
|---|
| 221 |
return ret; |
|---|
| 222 |
} |
|---|
| 223 |
|
|---|
| 224 |
static if(!false) |
|---|
| 225 |
{ |
|---|
| 226 |
import std.stdio; |
|---|
| 227 |
unittest |
|---|
| 228 |
{ |
|---|
| 229 |
//pragma(msg, Product!(SI.Meter,SI.Second).Div!(SI.Kilogram).stringof); |
|---|
| 230 |
writef("1 meter is %s in\n",From(SI.meter(1)).inch()); |
|---|
| 231 |
/+ |
|---|
| 232 |
1 meter is 39.3701 in |
|---|
| 233 |
+/ |
|---|
| 234 |
|
|---|
| 235 |
auto force = SI.lbf(10); |
|---|
| 236 |
auto distance = SI.foot(1); |
|---|
| 237 |
auto time = SI.second(10); |
|---|
| 238 |
auto energy = force * distance; |
|---|
| 239 |
auto power = energy / time; |
|---|
| 240 |
auto pressure = force/ distance.Pow!(2); |
|---|
| 241 |
|
|---|
| 242 |
writef("force %s N\n", From(force).Newton); |
|---|
| 243 |
writef("energy %s Joule\n", From(energy).Joule); |
|---|
| 244 |
writef("power %s Watt\n", From(power).Watt); |
|---|
| 245 |
writef("pressure %s Pa\n", From(pressure).Pa); |
|---|
| 246 |
/+ |
|---|
| 247 |
force 44.4822 N |
|---|
| 248 |
energy 13.5582 Joule |
|---|
| 249 |
power 135.582 Watt |
|---|
| 250 |
pressure 4.13253 Pa |
|---|
| 251 |
+/ |
|---|
| 252 |
} |
|---|
| 253 |
void main(){} |
|---|
| 254 |
} |
|---|