| 1 |
/************************ |
|---|
| 2 |
Author: Benjamin Shropshire |
|---|
| 3 |
|
|---|
| 4 |
This is a unit bearing type that handles unit conversion and uses compile time |
|---|
| 5 |
checks to protect against errors like adding distance and time value. |
|---|
| 6 |
|
|---|
| 7 |
************************ |
|---|
| 8 |
|
|---|
| 9 |
Boost Software License - Version 1.0 - August 17th, 2003 |
|---|
| 10 |
|
|---|
| 11 |
Permission is hereby granted, free of charge, to any person or organization |
|---|
| 12 |
obtaining a copy of the software and accompanying documentation covered by |
|---|
| 13 |
this license (the "Software") to use, reproduce, display, distribute, |
|---|
| 14 |
execute, and transmit the Software, and to prepare derivative works of the |
|---|
| 15 |
Software, and to permit third-parties to whom the Software is furnished to |
|---|
| 16 |
do so, all subject to the following: |
|---|
| 17 |
|
|---|
| 18 |
The copyright notices in the Software and this entire statement, including |
|---|
| 19 |
the above license grant, this restriction and the following disclaimer, |
|---|
| 20 |
must be included in all copies of the Software, in whole or in part, and |
|---|
| 21 |
all derivative works of the Software, unless such copies or derivative |
|---|
| 22 |
works are solely in the form of machine-executable object code generated by |
|---|
| 23 |
a source language processor. |
|---|
| 24 |
|
|---|
| 25 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|---|
| 26 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|---|
| 27 |
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
|---|
| 28 |
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
|---|
| 29 |
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
|---|
| 30 |
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|---|
| 31 |
DEALINGS IN THE SOFTWARE. |
|---|
| 32 |
|
|---|
| 33 |
************************/ |
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
import std.stdio; |
|---|
| 38 |
import std.math; |
|---|
| 39 |
import std.traits; |
|---|
| 40 |
|
|---|
| 41 |
import rational; |
|---|
| 42 |
|
|---|
| 43 |
template T(Tp...){alias Tp T;} |
|---|
| 44 |
|
|---|
| 45 |
version(FullSI) /// For most cases Lumins and Moles are not needed and just add bulk |
|---|
| 46 |
{ |
|---|
| 47 |
|
|---|
| 48 |
private alias T!(0,0) extra; |
|---|
| 49 |
private alias T!(0,1,0,1) extra2; |
|---|
| 50 |
|
|---|
| 51 |
template Batch( |
|---|
| 52 |
int LengthN, int LengthD, |
|---|
| 53 |
int MassN, int MassD, |
|---|
| 54 |
int TimeN, int TimeD, |
|---|
| 55 |
int TempN, int TempD, |
|---|
| 56 |
int CurrentN, int CurrentD, |
|---|
| 57 |
int LumiN, int LumiD, |
|---|
| 58 |
int MoleN, int MoleD |
|---|
| 59 |
) |
|---|
| 60 |
{ |
|---|
| 61 |
// sanity check |
|---|
| 62 |
static assert (Reduce!(LengthN, LengthD).Reduced, "Length must be in reduced form"); |
|---|
| 63 |
static assert (Reduce!(MassN, MassD).Reduced, "Mass must be in reduced form"); |
|---|
| 64 |
static assert (Reduce!(TimeN, TimeD).Reduced, "Time must be in reduced form"); |
|---|
| 65 |
static assert (Reduce!(TempN, TempD).Reduced, "Temp must be in reduced form"); |
|---|
| 66 |
static assert (Reduce!(CurrentN, CurrentD).Reduced,"Current must be in reduced form"); |
|---|
| 67 |
static assert (Reduce!(LumiN, LumiD).Reduced, "Luminous intensity must be in reduced form"); |
|---|
| 68 |
static assert (Reduce!(MoleN, MoleD).Reduced, "Quantity must be in reduced form"); |
|---|
| 69 |
|
|---|
| 70 |
/// visable units |
|---|
| 71 |
enum LenN = LengthN, LenD = LengthD; |
|---|
| 72 |
enum MasN = MassN, MasD = MassD; /// |
|---|
| 73 |
enum TimN = TimeN, TimD = TimeD; /// |
|---|
| 74 |
enum TmpN = TempN, TmpD = TempD; /// |
|---|
| 75 |
enum CurN = CurrentN, CurD = CurrentD; /// |
|---|
| 76 |
enum LumN = LumiN, LumD = LumiD; /// |
|---|
| 77 |
enum MolN = MoleN, MolD = MoleD; /// |
|---|
| 78 |
} |
|---|
| 79 |
|
|---|
| 80 |
template SI(int LengthN, int MassN, int TimeN, int TempN, int CurrentN, int LumiN, int MoleN, T = real) |
|---|
| 81 |
{ |
|---|
| 82 |
alias SIB!(Batch!( |
|---|
| 83 |
/// visable units |
|---|
| 84 |
LengthN, 1, |
|---|
| 85 |
MassN, 1, |
|---|
| 86 |
TimeN, 1, |
|---|
| 87 |
TempN, 1, |
|---|
| 88 |
CurrentN, 1, |
|---|
| 89 |
LumiN, 1, |
|---|
| 90 |
MoleN, 1 |
|---|
| 91 |
), T) SI; |
|---|
| 92 |
} |
|---|
| 93 |
template SI( |
|---|
| 94 |
int LengthN, int LengthD, |
|---|
| 95 |
int MassN, int MassD, |
|---|
| 96 |
int TimeN, int TimeD, |
|---|
| 97 |
int TempN, int TempD, |
|---|
| 98 |
int CurrentN, int CurrentD, |
|---|
| 99 |
int LuminN, int LuminD, |
|---|
| 100 |
int MoleN, int MoleD, |
|---|
| 101 |
T = real |
|---|
| 102 |
) |
|---|
| 103 |
{ |
|---|
| 104 |
alias SIB!(Batch!( |
|---|
| 105 |
/// visable units |
|---|
| 106 |
LengthN, LengthD, |
|---|
| 107 |
MassN, MassD, |
|---|
| 108 |
TimeN, TimeD, |
|---|
| 109 |
TempN, TempD, |
|---|
| 110 |
CurrentN, CurrentD, |
|---|
| 111 |
LuminN, LuminD, |
|---|
| 112 |
MoleN, MoleD |
|---|
| 113 |
), T ) SI; |
|---|
| 114 |
} |
|---|
| 115 |
} |
|---|
| 116 |
else |
|---|
| 117 |
{ |
|---|
| 118 |
private alias T!() extra; |
|---|
| 119 |
private alias T!() extra2; |
|---|
| 120 |
template Batch( |
|---|
| 121 |
int LengthN, int LengthD, |
|---|
| 122 |
int MassN, int MassD, |
|---|
| 123 |
int TimeN, int TimeD, |
|---|
| 124 |
int TempN, int TempD, |
|---|
| 125 |
int CurrentN, int CurrentD |
|---|
| 126 |
) |
|---|
| 127 |
{ |
|---|
| 128 |
// sanity check |
|---|
| 129 |
static assert (Reduce!(LengthN, LengthD).Reduced, "Length must be in reduced form"); |
|---|
| 130 |
static assert (Reduce!(MassN, MassD).Reduced, "Mass must be in reduced form"); |
|---|
| 131 |
static assert (Reduce!(TimeN, TimeD).Reduced, "Time must be in reduced form"); |
|---|
| 132 |
static assert (Reduce!(TempN, TempD).Reduced, "Temp must be in reduced form"); |
|---|
| 133 |
static assert (Reduce!(CurrentN, CurrentD).Reduced,"Current must be in reduced form"); |
|---|
| 134 |
|
|---|
| 135 |
/// visable units |
|---|
| 136 |
enum LenN = LengthN, LenD = LengthD; |
|---|
| 137 |
enum MasN = MassN, MasD = MassD; /// |
|---|
| 138 |
enum TimN = TimeN, TimD = TimeD; /// |
|---|
| 139 |
enum TmpN = TempN, TmpD = TempD; /// |
|---|
| 140 |
enum CurN = CurrentN, CurD = CurrentD; /// |
|---|
| 141 |
} |
|---|
| 142 |
|
|---|
| 143 |
template SI(int LengthN, int MassN, int TimeN, int TempN, int CurrentN, T = real) |
|---|
| 144 |
{ |
|---|
| 145 |
alias SIB!(Batch!( |
|---|
| 146 |
/// visable units |
|---|
| 147 |
LengthN, 1, |
|---|
| 148 |
MassN, 1, |
|---|
| 149 |
TimeN, 1, |
|---|
| 150 |
TempN, 1, |
|---|
| 151 |
CurrentN, 1 |
|---|
| 152 |
), T ) SI; |
|---|
| 153 |
} |
|---|
| 154 |
template SI( |
|---|
| 155 |
int LengthN, int LengthD, |
|---|
| 156 |
int MassN, int MassD, |
|---|
| 157 |
int TimeN, int TimeD, |
|---|
| 158 |
int TempN, int TempD, |
|---|
| 159 |
int CurrentN, int CurrentD, |
|---|
| 160 |
T = real |
|---|
| 161 |
) |
|---|
| 162 |
{ |
|---|
| 163 |
|
|---|
| 164 |
alias SIB!(Batch!( |
|---|
| 165 |
/// visable units |
|---|
| 166 |
LengthN, LengthD, |
|---|
| 167 |
MassN, MassD, |
|---|
| 168 |
TimeN, TimeD, |
|---|
| 169 |
TempN, TempD, |
|---|
| 170 |
CurrentN, CurrentD |
|---|
| 171 |
), T ) SI; |
|---|
| 172 |
} |
|---|
| 173 |
} |
|---|
| 174 |
|
|---|
| 175 |
struct SIB(alias Exp_, U) |
|---|
| 176 |
{ |
|---|
| 177 |
|
|---|
| 178 |
alias Exp_ Exp; |
|---|
| 179 |
|
|---|
| 180 |
|
|---|
| 181 |
// generate a usable name string |
|---|
| 182 |
static if(Exp.LenD == 1) private enum sLen = Exp.LenN.stringof; else private enum sLen = Exp.LenN.stringof~"/"~Exp.LenD.stringof; |
|---|
| 183 |
static if(Exp.MasD == 1) private enum sMas = Exp.MasN.stringof; else private enum sMas = Exp.MasN.stringof~"/"~Exp.MasD.stringof; |
|---|
| 184 |
static if(Exp.TimD == 1) private enum sTim = Exp.TimN.stringof; else private enum sTim = Exp.TimN.stringof~"/"~Exp.TimD.stringof; |
|---|
| 185 |
static if(Exp.TmpD == 1) private enum sTmp = Exp.TmpN.stringof; else private enum sTmp = Exp.TmpN.stringof~"/"~Exp.TmpD.stringof; |
|---|
| 186 |
static if(Exp.CurD == 1) private enum sCur = Exp.CurN.stringof; else private enum sCur = Exp.CurN.stringof~"/"~Exp.CurD.stringof; |
|---|
| 187 |
/// The type name |
|---|
| 188 |
version(FullSI) |
|---|
| 189 |
{ |
|---|
| 190 |
static if(Exp.LumD == 1) private enum sLum = Exp.LumN.stringof; else private enum sLum = Exp.LumN.stringof~"/"~Exp.LumD.stringof; |
|---|
| 191 |
static if(Exp.MolD == 1) private enum sMol = Exp.MolN.stringof; else private enum sMol = Exp.MolN.stringof~"/"~Exp.MolD.stringof; |
|---|
| 192 |
public enum Stringof = "SI!("~sLen~","~sMas~","~sTim~","~sTmp~","~sCur~","~sLum~","~sMol~","~U.stringof~")"; |
|---|
| 193 |
} |
|---|
| 194 |
else public enum Stringof = "SI!("~sLen~","~sMas~","~sTim~","~sTmp~","~sCur~","~U.stringof~")"; |
|---|
| 195 |
|
|---|
| 196 |
/// the value |
|---|
| 197 |
private U value; |
|---|
| 198 |
|
|---|
| 199 |
/// a more meaningful name |
|---|
| 200 |
private alias SIB This; |
|---|
| 201 |
|
|---|
| 202 |
// check to make shure it's right! |
|---|
| 203 |
static assert(is(SIB!(Exp,U) == This)); |
|---|
| 204 |
|
|---|
| 205 |
template Using(V) { alias SIB!(Exp,V) Using; } |
|---|
| 206 |
|
|---|
| 207 |
template Alike2(V) |
|---|
| 208 |
{ |
|---|
| 209 |
version(FullSI) enum bool Alike2 = |
|---|
| 210 |
Exp.LumN == V.Exp.LumN && Exp.LumD == V.Exp.LumD && |
|---|
| 211 |
Exp.MolN == V.Exp.MolN && Exp.MolD == V.Exp.MolD; |
|---|
| 212 |
else enum bool Alike2 = true; |
|---|
| 213 |
} |
|---|
| 214 |
template Alike(V) |
|---|
| 215 |
{ |
|---|
| 216 |
enum bool Alike = Alike2!(V) && |
|---|
| 217 |
Exp.LenN == V.Exp.LenN && Exp.LenD == V.Exp.LenD && |
|---|
| 218 |
Exp.MasN == V.Exp.MasN && Exp.MasD == V.Exp.MasD && |
|---|
| 219 |
Exp.TimN == V.Exp.TimN && Exp.TimD == V.Exp.TimD && |
|---|
| 220 |
Exp.TmpN == V.Exp.TmpN && Exp.TmpD == V.Exp.TmpD && |
|---|
| 221 |
Exp.CurN == V.Exp.CurN && Exp.CurD == V.Exp.CurD; |
|---|
| 222 |
} |
|---|
| 223 |
|
|---|
| 224 |
|
|---|
| 225 |
/// find the type of "This * T" |
|---|
| 226 |
private template Mul2(U) |
|---|
| 227 |
{ |
|---|
| 228 |
version(FullSI) alias T!( |
|---|
| 229 |
Reduce!(Exp.LumN*U.Exp.LumD + Exp.LumD*U.Exp.LumN, Exp.LumD*U.Exp.LumD).V, |
|---|
| 230 |
Reduce!(Exp.MolN*U.Exp.MolD + Exp.MolD*U.Exp.MolN, Exp.MolD*U.Exp.MolD).V) Mul2; |
|---|
| 231 |
else alias T!() Mul2; |
|---|
| 232 |
} |
|---|
| 233 |
private template Mul(T) |
|---|
| 234 |
{ |
|---|
| 235 |
static if(is(T : U)) |
|---|
| 236 |
alias This Mul; |
|---|
| 237 |
else |
|---|
| 238 |
alias SIB!(Batch!( |
|---|
| 239 |
Reduce!(Exp.LenN*T.Exp.LenD + Exp.LenD*T.Exp.LenN, Exp.LenD*T.Exp.LenD).V, |
|---|
| 240 |
Reduce!(Exp.MasN*T.Exp.MasD + Exp.MasD*T.Exp.MasN, Exp.MasD*T.Exp.MasD).V, |
|---|
| 241 |
Reduce!(Exp.TimN*T.Exp.TimD + Exp.TimD*T.Exp.TimN, Exp.TimD*T.Exp.TimD).V, |
|---|
| 242 |
Reduce!(Exp.TmpN*T.Exp.TmpD + Exp.TmpD*T.Exp.TmpN, Exp.TmpD*T.Exp.TmpD).V, |
|---|
| 243 |
Reduce!(Exp.CurN*T.Exp.CurD + Exp.CurD*T.Exp.CurN, Exp.CurD*T.Exp.CurD).V, |
|---|
| 244 |
Mul2!(T)), |
|---|
| 245 |
U |
|---|
| 246 |
) Mul; |
|---|
| 247 |
} |
|---|
| 248 |
|
|---|
| 249 |
/// find the type of "This / T" |
|---|
| 250 |
private template Div2(U) |
|---|
| 251 |
{ |
|---|
| 252 |
version(FullSI) alias T!( |
|---|
| 253 |
Reduce!(Exp.LumN*U.Exp.LumD - Exp.LumD*U.Exp.LumN, Exp.LumD*U.Exp.LumD).V, |
|---|
| 254 |
Reduce!(Exp.MolN*U.Exp.MolD - Exp.MolD*U.Exp.MolN, Exp.MolD*U.Exp.MolD).V) Div2; |
|---|
| 255 |
else alias T!() Div2; |
|---|
| 256 |
} |
|---|
| 257 |
private template Div(T) |
|---|
| 258 |
{ |
|---|
| 259 |
static if(is(T : U)) |
|---|
| 260 |
alias This Div; |
|---|
| 261 |
else |
|---|
| 262 |
alias SIB!(Batch!( |
|---|
| 263 |
Reduce!(Exp.LenN*T.Exp.LenD - Exp.LenD*T.Exp.LenN, Exp.LenD*T.Exp.LenD).V, |
|---|
| 264 |
Reduce!(Exp.MasN*T.Exp.MasD - Exp.MasD*T.Exp.MasN, Exp.MasD*T.Exp.MasD).V, |
|---|
| 265 |
Reduce!(Exp.TimN*T.Exp.TimD - Exp.TimD*T.Exp.TimN, Exp.TimD*T.Exp.TimD).V, |
|---|
| 266 |
Reduce!(Exp.TmpN*T.Exp.TmpD - Exp.TmpD*T.Exp.TmpN, Exp.TmpD*T.Exp.TmpD).V, |
|---|
| 267 |
Reduce!(Exp.CurN*T.Exp.CurD - Exp.CurD*T.Exp.CurN, Exp.CurD*T.Exp.CurD).V, |
|---|
| 268 |
Div2!(T)), |
|---|
| 269 |
U |
|---|
| 270 |
) Div; |
|---|
| 271 |
} |
|---|
| 272 |
|
|---|
| 273 |
/// find the type of "This ^ 1/i" |
|---|
| 274 |
private template Root2(int i) |
|---|
| 275 |
{ |
|---|
| 276 |
version(FullSI) alias T!( |
|---|
| 277 |
Reduce!(Exp.LumN,Exp.LumD*i).V, |
|---|
| 278 |
Reduce!(Exp.MolN,Exp.MolD*i).V) Root2; |
|---|
| 279 |
else alias T!() Root2; |
|---|
| 280 |
} |
|---|
| 281 |
private static template RootT(int i) |
|---|
| 282 |
{ |
|---|
| 283 |
alias SIB!(Batch!( |
|---|
| 284 |
Reduce!(Exp.LenN, Exp.LenD*i).V, |
|---|
| 285 |
Reduce!(Exp.MasN, Exp.MasD*i).V, |
|---|
| 286 |
Reduce!(Exp.TimN, Exp.TimD*i).V, |
|---|
| 287 |
Reduce!(Exp.TmpN, Exp.TmpD*i).V, |
|---|
| 288 |
Reduce!(Exp.CurN, Exp.CurD*i).V, |
|---|
| 289 |
Root2!(i) |
|---|
| 290 |
), |
|---|
| 291 |
U) RootT; |
|---|
| 292 |
} |
|---|
| 293 |
|
|---|
| 294 |
/// find the type of "This ^ i" |
|---|
| 295 |
private template Power2(int i) |
|---|
| 296 |
{ |
|---|
| 297 |
version(FullSI) alias T!( |
|---|
| 298 |
Reduce!(Exp.LumN*i,Exp.LumD).V, |
|---|
| 299 |
Reduce!(Exp.MolN*i,Exp.MolD).V) Power2; |
|---|
| 300 |
else alias T!() Power2; |
|---|
| 301 |
} |
|---|
| 302 |
private template Power(int i) |
|---|
| 303 |
{ |
|---|
| 304 |
alias SIB!(Batch!( |
|---|
| 305 |
Reduce!(Exp.LenN*i, Exp.LenD).V, |
|---|
| 306 |
Reduce!(Exp.MasN*i, Exp.MasD).V, |
|---|
| 307 |
Reduce!(Exp.TimN*i, Exp.TimD).V, |
|---|
| 308 |
Reduce!(Exp.TmpN*i, Exp.TmpD).V, |
|---|
| 309 |
Reduce!(Exp.CurN*i, Exp.CurD).V, |
|---|
| 310 |
Power2!(i) |
|---|
| 311 |
), |
|---|
| 312 |
U) Power; |
|---|
| 313 |
} |
|---|
| 314 |
|
|---|
| 315 |
// I don't think I need this anymore |
|---|
| 316 |
//This opCall(This ret) { return ret; } |
|---|
| 317 |
|
|---|
| 318 |
|
|---|
| 319 |
private this(U u) { value = u; } |
|---|
| 320 |
|
|---|
| 321 |
int opCmp(This that) |
|---|
| 322 |
{ |
|---|
| 323 |
if(this.value < that.value) return -1; |
|---|
| 324 |
if(this.value > that.value) return +1; |
|---|
| 325 |
return 0; |
|---|
| 326 |
} |
|---|
| 327 |
|
|---|
| 328 |
int opCmp(U that) |
|---|
| 329 |
{ |
|---|
| 330 |
if(this.value < that) return -1; |
|---|
| 331 |
if(this.value > that) return +1; |
|---|
| 332 |
return 0; |
|---|
| 333 |
} |
|---|
| 334 |
|
|---|
| 335 |
/// Homomorphic math operators |
|---|
| 336 |
This opNeg() { return This(- this.value);} |
|---|
| 337 |
This opPos() { return this; } /// |
|---|
| 338 |
|
|---|
| 339 |
This opAdd(This that) { return This(this.value + that.value);} /// |
|---|
| 340 |
This opSub(This that) { return This(this.value - that.value);} /// |
|---|
| 341 |
This opAddAssign(This that) { this.value += that.value; return this; } /// |
|---|
| 342 |
This opSubAssign(This that) { this.value -= that.value; return this; } /// |
|---|
| 343 |
|
|---|
| 344 |
This opMulAssign(U r) { this.value *= r; return this; } |
|---|
| 345 |
This opDivAssign(U r) { this.value /= r; return this; } /// |
|---|
| 346 |
|
|---|
| 347 |
This opMul_r(U that) { return This(this.value * that); } /// |
|---|
| 348 |
|
|---|
| 349 |
/// non-Homomorphic math operators |
|---|
| 350 |
auto opDiv_r(U that) { return Power!(-1)(that / this.value); } /// |
|---|
| 351 |
|
|---|
| 352 |
version(FullSI) private enum unitless2 = Exp.LumN == 0 && Exp.MolN == 0; |
|---|
| 353 |
else private enum unitless2 = true; |
|---|
| 354 |
static if(Exp.LenN == 0 && Exp.MasN == 0 && Exp.TimN == 0 && Exp.TmpN == 0 && Exp.CurN == 0 && unitless2) |
|---|
| 355 |
alias value this; |
|---|
| 356 |
else |
|---|
| 357 |
{ |
|---|
| 358 |
// these conflict if the "alias value this" is in effect |
|---|
| 359 |
|
|---|
| 360 |
/// non-Homomorphic math operators |
|---|
| 361 |
auto opMul(T)(T that) |
|---|
| 362 |
{ |
|---|
| 363 |
static if(is(T : U)) return Mul!(T)(this.value * that); |
|---|
| 364 |
else return Mul!(T)(this.value * that.value); |
|---|
| 365 |
} |
|---|
| 366 |
auto opDiv(T)(T that) /// |
|---|
| 367 |
{ |
|---|
| 368 |
static if(is(T : U)) return Div!(T)(this.value / that); |
|---|
| 369 |
else return Div!(T)(this.value / that.value); |
|---|
| 370 |
} |
|---|
| 371 |
} |
|---|
| 372 |
|
|---|
| 373 |
/// test if these are close enough |
|---|
| 374 |
bool Near(This that, int count = 5) |
|---|
| 375 |
{ |
|---|
| 376 |
static if(isFloatingPoint!(U)) |
|---|
| 377 |
return std.math.feqrel!(U)(this.value,that.value) + count >= U.mant_dig; |
|---|
| 378 |
else |
|---|
| 379 |
return this.value == that.value; |
|---|
| 380 |
} |
|---|
| 381 |
|
|---|
| 382 |
/// common math functions |
|---|
| 383 |
auto Root(int i)(){return RootT!(i)(std.math.sqrt(this.value));} |
|---|
| 384 |
auto Pow(int i)(){return Power!(i)(std.math.pow(this.value,i));} /// |
|---|
| 385 |
This Abs() { return This(std.math.abs(this.value)); } /// |
|---|
| 386 |
|
|---|
| 387 |
|
|---|
| 388 |
/// convert to real from type "s" |
|---|
| 389 |
U opDispatch(string s)() |
|---|
| 390 |
{ |
|---|
| 391 |
static if(!is(Unit!(s).type)) static assert(false, "SI has no member named "~s~" nor is it a known type"); |
|---|
| 392 |
else |
|---|
| 393 |
{ |
|---|
| 394 |
static assert(This.Alike!(Unit!(s).type), "Can't convert type "~This.Stringof~" to \""~s~"\" of type "~Unit!(s).type.Stringof); |
|---|
| 395 |
return value / Unit!(s).mul; |
|---|
| 396 |
} |
|---|
| 397 |
} |
|---|
| 398 |
|
|---|
| 399 |
} |
|---|
| 400 |
|
|---|
| 401 |
/// convert from real to type "s" |
|---|
| 402 |
struct OfType |
|---|
| 403 |
{ |
|---|
| 404 |
static auto opDispatch(string s, U)(U v) /// |
|---|
| 405 |
{ |
|---|
| 406 |
static if(!is(Unit!(s).type)) static assert(false, "OfType."~s~" is not a known type"); |
|---|
| 407 |
else return Unit!(s).type.Using!(U)(cast(U)(v * Unit!(s).mul)); |
|---|
| 408 |
} |
|---|
| 409 |
} |
|---|
| 410 |
|
|---|
| 411 |
|
|---|
| 412 |
/// Basic types |
|---|
| 413 |
public struct Types |
|---|
| 414 |
{ |
|---|
| 415 |
alias SI!( 0, 0, 0, 0, 0, extra) Value; /// |
|---|
| 416 |
alias SI!( 1, 0, 0, 0, 0, extra) Distance; /// |
|---|
| 417 |
alias SI!( 0, 1, 0, 0, 0, extra) Mass; /// |
|---|
| 418 |
alias SI!( 0, 0, 1, 0, 0, extra) Time; /// |
|---|
| 419 |
alias SI!( 0, 0, 0, 1, 0, extra) Temp; /// |
|---|
| 420 |
alias SI!( 0, 0, 0, 0, 1, extra) Current; /// |
|---|
| 421 |
version(FullSI) |
|---|
| 422 |
{ |
|---|
| 423 |
alias SI!( 0, 0, 0, 0, 0, 1, 0) Luminosity; /// |
|---|
| 424 |
alias SI!( 0, 0, 0, 0, 0, 0, 1) Quantity; /// |
|---|
| 425 |
} |
|---|
| 426 |
|
|---|
| 427 |
alias SI!(-3, 1, 0, 0, 0, extra) MassDensity; /// |
|---|
| 428 |
|
|---|
| 429 |
alias SI!(-2,-1, 3, 0, 2, extra) Resistance; /// |
|---|
| 430 |
alias SI!(-2,-1, 4, 0, 2, extra) Capacitance; /// |
|---|
| 431 |
|
|---|
| 432 |
alias SI!(-1, 1,-2, 0, 0, extra) Pressure; /// |
|---|
| 433 |
alias SI!(-1, 1,-1, 0, 0, extra) Viscosity; /// |
|---|
| 434 |
|
|---|
| 435 |
alias SI!( 0, 0,-1, 0, 0, extra) Frequency; /// |
|---|
| 436 |
alias SI!( 0, 0, 1, 0, 1, extra) Charge; /// |
|---|
| 437 |
alias SI!( 0, 1,-1, 0, 0, extra) MassFlow; /// |
|---|
| 438 |
alias SI!( 0, 1,-2, 0,-1, extra) MagneticFluxD; /// |
|---|
| 439 |
|
|---|
| 440 |
alias SI!( 1, 1,-2, 0, 0, extra) Force; /// |
|---|
| 441 |
alias SI!( 1, 0,-2, 0, 0, extra) Acceleration; /// |
|---|
| 442 |
alias SI!( 1, 0,-1, 0, 0, extra) Speed; /// |
|---|
| 443 |
|
|---|
| 444 |
|
|---|
| 445 |
alias SI!( 2, 1,-3, 0,-1, extra) Voltage; /// |
|---|
| 446 |
alias SI!( 2, 1,-3, 0, 0, extra) Power; /// |
|---|
| 447 |
alias SI!( 2, 1,-2, 0,-2, extra) Inductance; /// |
|---|
| 448 |
alias SI!( 2, 1,-2, 0, 0, extra) Energy; /// |
|---|
| 449 |
alias SI!( 2, 0, 0, 0, 0, extra) Area; /// |
|---|
| 450 |
alias SI!( 2, 0,-1, 0, 0, extra) KViscosity; /// |
|---|
| 451 |
|
|---|
| 452 |
alias SI!( 3, 0,-1, 0, 0, extra) VolumeFlow; /// |
|---|
| 453 |
alias SI!( 3, 0, 0, 0, 0, extra) Volume; /// |
|---|
| 454 |
} |
|---|
| 455 |
|
|---|
| 456 |
/// Some less common types |
|---|
| 457 |
public struct Engr |
|---|
| 458 |
{ |
|---|
| 459 |
/// |
|---|
| 460 |
public struct Thermal |
|---|
| 461 |
{ |
|---|
| 462 |
alias SI!( 2, 0,-2,-1, 0, extra) ThermalCap; /// |
|---|
| 463 |
alias SI!( 1, 1,-3,-1, 0, extra) ThermalCond; /// |
|---|
| 464 |
alias SI!( 0, 1,-3,-1, 0, extra) ConvectionCoeff; /// |
|---|
| 465 |
} |
|---|
| 466 |
/// |
|---|
| 467 |
public struct FracturMechanics |
|---|
| 468 |
{ |
|---|
| 469 |
alias SI!(-1,2, 1,1,-2,1, 0,1, 0,1, extra2) StressIntensity;/// |
|---|
| 470 |
} |
|---|
| 471 |
} |
|---|
| 472 |
|
|---|
| 473 |
/// Base SI units |
|---|
| 474 |
template Unit(string name : "value") { enum mul = 1.0; alias Value type; } |
|---|
| 475 |
template Unit(string name : "meter") { enum mul = 1.0; alias Types.Distance type; } /// |
|---|
| 476 |
template Unit(string name : "kilogram") { enum mul = 1.0; alias Types.Mass type; } /// |
|---|
| 477 |
template Unit(string name : "second") { enum mul = 1.0; alias Types.Time type; } /// |
|---|
| 478 |
template Unit(string name : "kelvin") { enum mul = 1.0; alias Types.Temp type; } /// |
|---|
| 479 |
template Unit(string name : "ampere") { enum mul = 1.0; alias Types.Current type; } /// |
|---|
| 480 |
version(FullSI) |
|---|
| 481 |
{ |
|---|
| 482 |
//template Unit(string name : "candela") { enum mul = 1.0; alias Types.Luminosity type; } /// This one is named wrong |
|---|
| 483 |
template Unit(string name : "mole") { enum mul = 1.0; alias Types.Quantity type; } /// |
|---|
| 484 |
} |
|---|
| 485 |
|
|---|
| 486 |
/// Distance Unit Types |
|---|
| 487 |
template Unit(string name : "Angstrom") { enum mul = 1e-10; alias Types.Distance type; } |
|---|
| 488 |
template Unit(string name : "Micron") { enum mul = 1e-6; alias Types.Distance type; } /// |
|---|
| 489 |
template Unit(string name : "mm") { enum mul = 1e-3; alias Types.Distance type; } /// |
|---|
| 490 |
template Unit(string name : "cm") { enum mul = 1e-2; alias Types.Distance type; } /// |
|---|
| 491 |
template Unit(string name : "km") { enum mul = 1e3; alias Types.Distance type; } /// |
|---|
| 492 |
template Unit(string name : "inch") { enum mul = 2.54e-2; alias Types.Distance type; } /// |
|---|
| 493 |
template Unit(string name : "foot") { enum mul = 3.04799835e-1; alias Types.Distance type; } /// |
|---|
| 494 |
template Unit(string name : "yard") { enum mul = 9.14399506e-1; alias Types.Distance type; } /// |
|---|
| 495 |
template Unit(string name : "mile") { enum mul = 1.609343130e3; alias Types.Distance type; } /// |
|---|
| 496 |
template Unit(string name : "parsec") { enum mul = 3.085677473598e13; alias Types.Distance type; } /// |
|---|
| 497 |
|
|---|
| 498 |
/// Mass Unit Types |
|---|
| 499 |
template Unit(string name : "gram") { enum mul = 1e-3; alias Types.Mass type; } |
|---|
| 500 |
template Unit(string name : "lb") { enum mul = 4.5359237e-1; alias Types.Mass type; } /// |
|---|
| 501 |
template Unit(string name : "Ounce") { enum mul = 2.834952e-2; alias Types.Mass type; } /// |
|---|
| 502 |
|
|---|
| 503 |
/// Time Unit Types |
|---|
| 504 |
template Unit(string name : "minute") { enum mul = 60.0; alias Types.Time type; } |
|---|
| 505 |
template Unit(string name : "hour") { enum mul = 3600.0; alias Types.Time type; } /// |
|---|
| 506 |
template Unit(string name : "day") { enum mul = 86400.0; alias Types.Time type; } /// |
|---|
| 507 |
|
|---|
| 508 |
/// Temperature Unit Types |
|---|
| 509 |
template Unit(string name : "R") { enum mul = 0.5555555555; alias Types.Temp type; } |
|---|
| 510 |
|
|---|
| 511 |
/// Force Unit Types |
|---|
| 512 |
template Unit(string name : "newton") { enum mul = 1.0; alias Types.Force type; } |
|---|
| 513 |
template Unit(string name : "dyne") { enum mul = 1e-5; alias Types.Force type; } /// |
|---|
| 514 |
template Unit(string name : "lbf") { enum mul = 4.44822246806; alias Types.Force type; } /// |
|---|
| 515 |
|
|---|
| 516 |
/// Charge Unit Types |
|---|
| 517 |
template Unit(string name : "coulomb") { enum mul = 1.0; alias Types.Charge type; } |
|---|
| 518 |
|
|---|
| 519 |
/// Magnetic flux density |
|---|
| 520 |
template Unit(string name : "tesla") { enum mul = 1.0; alias Types.MagneticFluxD type; } |
|---|
| 521 |
|
|---|
| 522 |
/// magnetic flux |
|---|
| 523 |
template Unit(string name : "weber") { enum mul = 1.0; alias SI!(2,1,-2,0,1) type; } |
|---|
| 524 |
|
|---|
| 525 |
/// inductance |
|---|
| 526 |
template Unit(string name : "henry") { enum mul = 1.0; alias Types.Inductance type; } |
|---|
| 527 |
|
|---|
| 528 |
/// Energy Unit Types |
|---|
| 529 |
template Unit(string name : "joule") { enum mul = 1.0; alias Types.Energy type; } |
|---|
| 530 |
template Unit(string name : "Erg") { enum mul = 1e-7L; alias Types.Energy type; } /// |
|---|
| 531 |
template Unit(string name : "cal") { enum mul = 4.1868L; alias Types.Energy type; } /// |
|---|
| 532 |
template Unit(string name : "eV") { enum mul = 1.602176462e-19L; alias Types.Energy type; } /// |
|---|
| 533 |
template Unit(string name : "BTU") { enum mul = 1.0550558526e3L; alias Types.Energy type; } /// |
|---|
| 534 |
|
|---|
| 535 |
/// Voltage Unit Types |
|---|
| 536 |
template Unit(string name : "volt") { enum mul = 1.0; alias Types.Voltage type; } |
|---|
| 537 |
|
|---|
| 538 |
/// Frequency Unit Types |
|---|
| 539 |
template Unit(string name : "hertz") { enum mul = 1.0; alias Types.Frequency type; } |
|---|
| 540 |
|
|---|
| 541 |
/// Resistance Unit Types |
|---|
| 542 |
template Unit(string name : "ohm") { enum mul = 1.0; alias Types.Resistance type; } |
|---|
| 543 |
|
|---|
| 544 |
/// Pressure Unit Types |
|---|
| 545 |
template Unit(string name : "pascal") { enum mul = 1.0; alias Types.Pressure type; } |
|---|
| 546 |
template Unit(string name : "Bar") { enum mul = 1e5L; alias Types.Pressure type; } /// |
|---|
| 547 |
template Unit(string name : "Atm") { enum mul = 1.01325e5L; alias Types.Pressure type; } /// |
|---|
| 548 |
template Unit(string name : "psi") { enum mul = 6.89475729e3; alias Types.Pressure type; } /// |
|---|
| 549 |
|
|---|
| 550 |
/// Viscosity |
|---|
| 551 |
// |
|---|
| 552 |
template Unit(string name : "poise") { enum mul = 0.1; alias Types.Viscosity type; } |
|---|
| 553 |
// |
|---|
| 554 |
template Unit(string name : "stokes") { enum mul = 0.0001; alias Types.KViscosity type; } |
|---|
| 555 |
|
|---|
| 556 |
/// Power Unit Types |
|---|
| 557 |
template Unit(string name : "watt") { enum mul = 1.0; alias Types.Power type; } |
|---|
| 558 |
template Unit(string name : "kWatt") { enum mul = 1000; alias Types.Power type; } /// |
|---|
| 559 |
template Unit(string name : "Hp") { enum mul = 745.69987158L; alias Types.Power type; } /// |
|---|
| 560 |
|
|---|
| 561 |
/// Volume Unit Types |
|---|
| 562 |
template Unit(string name : "steres") { enum mul = 1.0; alias Types.Volume type; } |
|---|
| 563 |
template Unit(string name : "litre") { enum mul = 0.001L; alias Types.Volume type; } /// |
|---|
| 564 |
template Unit(string name : "Gal") { enum mul = 0.0037854120L; alias Types.Volume type; } /// |
|---|
| 565 |
template Unit(string name : "Cup") { enum mul = 0.0002365883L; alias Types.Volume type; } /// |
|---|
| 566 |
|
|---|
| 567 |
/// volume rate |
|---|
| 568 |
template Unit(string name : "gpm") { enum mul = 6.30901995e-5L; alias Types.VolumeFlow type; } |
|---|
| 569 |
template Unit(string name : "cfm") { enum mul = 4.71947443e-4L; alias Types.VolumeFlow type; } /// |
|---|
| 570 |
|
|---|
| 571 |
/// Speed Unit Types |
|---|
| 572 |
template Unit(string name : "mps") { enum mul = 1L; alias Types.Speed type; } |
|---|
| 573 |
template Unit(string name : "Knots") { enum mul = 1.51444L; alias Types.Speed type; } /// |
|---|
| 574 |
template Unit(string name : "mph") { enum mul = 0.44704L; alias Types.Speed type; } /// |
|---|
| 575 |
template Unit(string name : "kph") { enum mul = 0.27778L; alias Types.Speed type; } /// |
|---|
| 576 |
template Unit(string name : "fps") { enum mul = 0.3048L; alias Types.Speed type; } /// |
|---|
| 577 |
|
|---|
| 578 |
/// Capacitance Unit Types |
|---|
| 579 |
template Unit(string name : "farad") { enum mul = 1.0; alias Types.Capacitance type; } |
|---|
| 580 |
|
|---|
| 581 |
/// Area Unit Types |
|---|
| 582 |
template Unit(string name : "Acre") { enum mul = 4046.856421L; alias Types.Area type; } |
|---|
| 583 |
|
|---|
| 584 |
/// Acceleration Unit Types |
|---|
| 585 |
template Unit(string name : "G") { enum mul = 9.80665L; alias Types.Acceleration type; } |
|---|
| 586 |
|
|---|
| 587 |
/// alterant names |
|---|
| 588 |
private: |
|---|
| 589 |
|
|---|
| 590 |
template Alt(string name : "C") { enum Alt = "coulomb"; } |
|---|
| 591 |
template Alt(string name : "N") { enum Alt = "newton"; } |
|---|
| 592 |
template Alt(string name : "J") { enum Alt = "joule"; } |
|---|
| 593 |
template Alt(string name : "V") { enum Alt = "volt"; } |
|---|
| 594 |
template Alt(string name : "Hz") { enum Alt = "hertz"; } |
|---|
| 595 |
template Alt(string name : "Pa") { enum Alt = "pascal"; } |
|---|
| 596 |
template Alt(string name : "P") { enum Alt =" poise"; } |
|---|
| 597 |
template Alt(string name : "W") { enum Alt = "watt"; } |
|---|
| 598 |
template Alt(string name : "L") { enum Alt = "litre"; } |
|---|
| 599 |
template Alt(string name : "liter") { enum Alt = "litre"; } |
|---|
| 600 |
template Alt(string name : "F") { enum Alt = "farad"; } |
|---|
| 601 |
template Alt(string name : "H") { enum Alt = "henry"; } |
|---|
| 602 |
template Alt(string name : "Wb") { enum Alt = "weber"; } |
|---|
| 603 |
template Alt(string name : "T") { enum Alt = "tesla"; } |
|---|
| 604 |
version(FullSI) |
|---|
| 605 |
{ |
|---|
| 606 |
template Alt(string name : "mol"){ enum Alt = "mole"; } |
|---|
| 607 |
template Alt(string name : "cd") { enum Alt = "candela"; } |
|---|
| 608 |
} |
|---|
| 609 |
|
|---|
| 610 |
public: |
|---|
| 611 |
|
|---|
| 612 |
template Unit(string name) { alias Unit!(Alt!(name)) Unit; } |
|---|
| 613 |
|
|---|
| 614 |
|
|---|
| 615 |
unittest |
|---|
| 616 |
{ |
|---|
| 617 |
writef("%s\n", OfType.foot(3.0).meter); |
|---|
| 618 |
|
|---|
| 619 |
Types.Distance v; //pragma(msg,"v:\t"~typeof(v).stringof); |
|---|
| 620 |
|
|---|
| 621 |
auto v2 = v * v; //pragma(msg,"v2:\t"~typeof(v2).stringof); |
|---|
| 622 |
auto v3 = v2 / v; //pragma(msg,"v3:\t"~typeof(v3).stringof); |
|---|
| 623 |
auto v4 = v / v; //pragma(msg,"v4:\t"~typeof(v4).stringof); |
|---|
| 624 |
real r = v4; |
|---|
| 625 |
auto v5 = v4 / v; //pragma(msg,"v5:\t"~typeof(v5).stringof); |
|---|
| 626 |
//auto v6a = v2 + v; |
|---|
| 627 |
auto v6b = v3 + v; |
|---|
| 628 |
auto v7 = v.Root!(2)(); //pragma(msg,"v7:\t"~typeof(v7).stringof); |
|---|
| 629 |
auto v8 = v7.Pow!(4)(); //pragma(msg,"v8:\t"~typeof(v8).stringof); |
|---|
| 630 |
|
|---|
| 631 |
Engr.FracturMechanics.StressIntensity k; |
|---|
| 632 |
auto k2 = k*k; |
|---|
| 633 |
auto p = OfType.psi(0.0L); |
|---|
| 634 |
k2 = p*p*OfType.foot(3.0L); |
|---|
| 635 |
|
|---|
| 636 |
auto newton = OfType.N(5); |
|---|
| 637 |
} |
|---|