# root/trunk/units/unit.d

Revision 515, 5.8 kB (checked in by BCS, 6 years ago) |
---|

Line | |
---|---|

1 | module unit; |

2 | |

3 | private import std.math; |

4 | |

5 | import rational; |

6 | |

7 | struct Unit( |

8 | int LengthN, int LengthD, |

9 | int MassN, int MassD, |

10 | int TimeN, int TimeD, |

11 | int TempN, int TempD, |

12 | int CurrentN, int CurrentD |

13 | ) |

14 | { |

15 | void _rawSet(real v){value = v;} |

16 | real _rawGet(){return value;} |

17 | |

18 | static const LenN = LengthN, LenD = LengthD; |

19 | static const MasN = MassN, MasD = MassD; |

20 | static const TimN = TimeN, TimD = TimeD; |

21 | static const TmpN = TempN, TmpD = TempD; |

22 | static const CurN = CurrentN, CurD = CurrentD; |

23 | |

24 | static assert (Reduce!(LengthN, LengthD).Reduced, "Length must be in reduced form"); |

25 | static assert (Reduce!(MassN, MassD).Reduced, "Mass must be in reduced form"); |

26 | static assert (Reduce!(TimeN, TimeD).Reduced, "Time must be in reduced form"); |

27 | static assert (Reduce!(TempN, TempD).Reduced, "Temp must be in reduced form"); |

28 | static assert (Reduce!(CurrentN, CurrentD).Reduced,"Current must be in reduced form"); |

29 | |

30 | private real value; |

31 | |

32 | private alias Unit!(LengthN, LengthD, MassN, MassD, TimeN, TimeD, TempN, TempD, CurrentN, CurrentD) This; |

33 | |

34 | private template Mul(T) |

35 | { |

36 | static if(is(T : real)) |

37 | alias This Mul; |

38 | else |

39 | alias Unit! |

40 | ( |

41 | Reduce!(LengthN*T.LenD + LengthD*T.LenN, LengthD * T.LenD).V, |

42 | Reduce!(MassN*T.MasD + MassD*T.MasN, MassD*T.MasD).V, |

43 | Reduce!(TimeN*T.TimD + TimeD*T.TimN, TimeD*T.TimD).V, |

44 | Reduce!(TempN*T.TmpD + TempD*T.TmpN, TempD*T.TmpD).V, |

45 | Reduce!(CurrentN*T.CurD + CurrentD*T.CurN, CurrentD*T.CurD).V |

46 | ) Mul; |

47 | } |

48 | public template Div(T) |

49 | { |

50 | static if(is(T : real)) |

51 | alias This Div; |

52 | else |

53 | alias Unit! |

54 | ( |

55 | Reduce!(LengthN*T.LenD - LengthD*T.LenN, LengthD * T.LenD).V, |

56 | Reduce!(MassN*T.MasD - MassD*T.MasN, MassD*T.MasD).V, |

57 | Reduce!(TimeN*T.TimD - TimeD*T.TimN, TimeD*T.TimD).V, |

58 | Reduce!(TempN*T.TmpD - TempD*T.TmpN, TempD*T.TmpD).V, |

59 | Reduce!(CurrentN*T.CurD - CurrentD*T.CurN, CurrentD*T.CurD).V |

60 | ) Div; |

61 | } |

62 | |

63 | static public template RootT(int i) |

64 | { |

65 | alias Unit!( |

66 | Reduce!(LenN, LenD*i).V, |

67 | Reduce!(MasN, MasD*i).V, |

68 | Reduce!(TimN, TimD*i).V, |

69 | Reduce!(TmpN, TmpD*i).V, |

70 | Reduce!(CurN, CurD*i).V |

71 | ) RootT; |

72 | } |

73 | |

74 | public template Power(int i) |

75 | { |

76 | alias Unit!( |

77 | Reduce!(LenN*i, LenD).V, |

78 | Reduce!(MasN*i, MasD).V, |

79 | Reduce!(TimN*i, TimD).V, |

80 | Reduce!(TmpN*i, TmpD).V, |

81 | Reduce!(CurN*i, CurD).V |

82 | ) Power; |

83 | } |

84 | |

85 | This opCall(This ret) { return ret; } |

86 | |

87 | This opNeg() { This ret; ret.value = - this.value; return ret; } |

88 | This opPos() { return *this; } |

89 | |

90 | This opAdd(This that) { This ret; ret.value = this.value + that.value; return ret; } |

91 | This opSub(This that) { This ret; ret.value = this.value - that.value; return ret; } |

92 | This opAddAssign(This that) { this.value += that.value; return *this; } |

93 | This opSubAssign(This that) { this.value -= that.value; return *this; } |

94 | |

95 | int opCmp(This that) |

96 | { |

97 | if(this.value < that.value) return -1; |

98 | if(this.value > that.value) return +1; |

99 | return 0; |

100 | } |

101 | |

102 | int opCmp(real that) |

103 | { |

104 | if(this.value < that) return -1; |

105 | if(this.value > that) return +1; |

106 | return 0; |

107 | } |

108 | |

109 | static if(LengthN == 0 && MassN == 0 && TimeN == 0 && TempN == 0 && CurrentN == 0) |

110 | { |

111 | static This opCall(real v) { This ret; ret.value = v; return ret; } |

112 | |

113 | This opAdd(real that) { This ret; ret.value = this.value + that; return ret; } |

114 | This opSub(real that) { This ret; ret.value = this.value - that; return ret; } |

115 | This opAddAssign(real that) { this.value += that; return *this; } |

116 | This opSubAssign(real that) { this.value -= that; return *this; } |

117 | This opAdd_r(real that) { This ret; ret.value = that + this.value; return ret; } |

118 | This opSub_r(real that) { This ret; ret.value = that - this.value; return ret; } |

119 | real opCast() { return value; } |

120 | |

121 | This exp() |

122 | { |

123 | This ret; |

124 | ret.value = std.math.exp(this.value); |

125 | return ret; |

126 | } |

127 | This log() |

128 | { |

129 | This ret; |

130 | ret.value = std.math.log(this.value); |

131 | return ret; |

132 | } |

133 | This pow(real p) |

134 | { |

135 | This ret; |

136 | ret.value = std.math.pow(this.value,p); |

137 | return ret; |

138 | } |

139 | } |

140 | |

141 | bool Near(This that, int count = 5) |

142 | { |

143 | return std.math.feqrel!(real)(this.value,that.value) + count >= real.mant_dig; |

144 | } |

145 | |

146 | //static if(is(This == Unit!(1,1, 0,1, 0,1, 0,1, 0,1))) pragma(msg, Mul!(Unit!(1,1, 0,1, 0,1, 0,1, 0,1)).stringof); |

147 | |

148 | Mul!(T) opMul(T)(T that) { Mul!(T) ret; static if(is(T : real)) ret.value = this.value * that; else ret.value = this.value * that.value; return ret; } |

149 | Div!(T) opDiv(T)(T that) { Div!(T) ret; static if(is(T : real)) ret.value = this.value / that; else ret.value = this.value / that.value; return ret; } |

150 | |

151 | This opMulAssign(real r) { this.value *= r; return *this; } |

152 | This opDivAssign(real r) { this.value /= r; return *this; } |

153 | |

154 | This opMul_r(real that) { This ret; ret.value = this.value * that; return ret; } |

155 | Power!(-1) opDiv_r(real that) { Power!(-1) ret; ret.value = that / this.value; return ret; } |

156 | |

157 | RootT!(i) Root(int i)(){RootT!(i) ret; ret.value = std.math.sqrt(this.value); return ret;} |

158 | Power!(i) Pow(int i)(){Power!(i) ret; ret.value = std.math.pow(this.value,i); return ret;} |

159 | This Abs() { This ret; ret.value = std.math.abs(this.value); return ret; } |

160 | } |

161 | |

162 | template Product(T1, T...) |

163 | { |

164 | static if(T.length == 0) |

165 | alias T1 Product; |

166 | else |

167 | alias T1.Mul!(Product!(T)) Product; |

168 | } |

169 | |

170 | unittest |

171 | { |

172 | Unit!(1,1, 0,1, 0,1, 0,1, 0,1) v; //pragma(msg,"v:\t"~typeof(v).stringof); |

173 | |

174 | auto v2 = v * v; //pragma(msg,"v2:\t"~typeof(v2).stringof); |

175 | auto v3 = v2 / v; //pragma(msg,"v3:\t"~typeof(v3).stringof); |

176 | auto v4 = v / v; //pragma(msg,"v4:\t"~typeof(v4).stringof); |

177 | auto v5 = v4 / v; //pragma(msg,"v5:\t"~typeof(v5).stringof); |

178 | //auto v6a = v2 + v; |

179 | auto v6b = v3 + v; |

180 | auto v7 = v.Root!(2)(); //pragma(msg,"v7:\t"~typeof(v7).stringof); |

181 | auto v8 = v7.Pow!(4)(); //pragma(msg,"v8:\t"~typeof(v8).stringof); |

182 | } |

**Note:**See TracBrowser for help on using the browser.