Would you like to make this site your homepage? It's fast and easy...
Yes, Please make this my home page!
1 -- SDI_HellCreator
2 -- Salomatine Dmitry.
3 -- sdihellcreator@bezeqint.net
4 -- Israel
5 -- start 26.05.2003
6 -- revision 03.06.2003
7
8 require("ml_cd");--first check for core class lua
9 require("ml_util");-- useful utills
10
11 --Fraction class actualy have qotient remainder and divisor data
12 --completly replaces floating numbers in matrices operations
13
14 --define the accuracy scope of floating number breaking mashine
15 -- right values [0-64] more then 32 make it slower but fine calculation
16 --since lua work in double 64 bit data type
17 gv_frac_accuracy=64;--you can access and change it at run time
18
19 Frac={};
20 local Frac_mt = Class(Frac);
21 -- via new function must provide arguments
22 -- Q it is qotient
23 -- R it is remainder
24 -- D it is divisor
25
26 function Frac:new(tq,tr,td)
27 if tq then--we have first parameter
28 if tr then--we have second parameter too
29 if td then--we have third parameter
30 if isNum3(tq,tr,td) then--all three parameters as numbers
31 return setmetatable({Q=tq,R=tr,D=td}, Frac_mt);
32 end
33 else
34 if isNum2(tq,tr) then--only remainder and divisor passed as numbers
35 return setmetatable({Q=0,R=tq,D=tr}, Frac_mt);
36 end
37 end
38 else
39 if isNum(tq) then--only qotient passed
40 return setmetatable({Q=tq,R=0,D=1}, Frac_mt);
41 end
42 end
43 --else
44 --make default and valid values
45 --return setmetatable({Q=0,R=0,D=1}, Frac_mt);
46 end
47 return setmetatable({Q=0,R=0,D=1}, Frac_mt);
48 end
49 --default constructor for object via new
50 function Frac:Frac()
51 return Frac:new();--default have zero value
52 end
53 --function actualy down the number to fractions
54 --it is verry important function to this class
55 function Frac:Broke(num)
56 local accuracy=gv_frac_accuracy;--maximum loops accuracy
57 local numc=num;--just make copy
58 local tqv,trv,tdv=math.floor(numc),0,1;
59 --find how deep after point we have
60 local pod,sq;
61 pod=0;--power of dec
62 sq=tqv;
63 --algorithm of broking down floatin number by
64 --self floor decreasing
65 --even period numbers can be down to fraction
66 --in goten scope of accuracy
67 while numc~=0 and accuracy>0 do
68 numc=numc-sq;
69 numc=numc*10;
70 pod=pod+1;
71 sq=math.floor(numc);
72 trv=trv*10+sq;
73 accuracy=accuracy-1;
74 end
75 tdv=10^pod;
76 --now we have the actualy all fractions of number
77 --make some optimization if we can by dividing
78 --booth remainder and divisor by same value from 2 to tr/2-1
79 --local tsv=math.floor(math.abs(trv/2));
80 --it is ugly algorithm i will think about some beter
81 --for i=2,math.floor(math.abs(trv/2)) do
82 --if math.abs(trv)>1 then
83 --if math.mod(trv,ii)==0 and math.mod(tdv,ii)==0 then
84 --print("optimizing"..trv,tdv,ii);
85 --trv=trv/ii;
86 --tdv=tdv/ii;
87 --end
88 --end
89 --end
90 return tqv,trv,tdv;
91 end
92 --broke number into fractioned
93 function Frac:BrokeNum(o)
94 if o then--we have parameter o
95 if getmetatable(o)==getmetatable(self) then--o have the same type
96 return o.Q,o.R,o.D;
97 else--a not numeric
98 if isNum(o) then --o is numeric value
99 return self:Broke(o);
100 else
101 print("unknown type");
102 return 0,0,1;
103 end
104 end
105 else--not a parameter passed return the self data already broke
106 return self.Q,self.R,self.D;
107 end
108 end
109 --set
110 function Frac:Set(tq,tr,td)
111 if isNum3(tq,tr,td) then
112 self.Q=tq;
113 self.R=tr;
114 self.D=td;
115 else
116 print("one of arguments not number");
117 end
118 end
119 --set floating point or another Frac
120 function Frac:SetF(o)
121 self:Set(self:BrokeNum(o));
122 end
123 --get
124 function Frac:Get()
125 return self.Q,self.R,self.D;
126 end
127 --get floating
128 function Frac:GetFP(tq,tr,td)
129 if tq or tr or td then
130 local tv=Frac:new(tq,tr,td);
131 return tv:GetFP();
132 else
133 if self.D and self.D~=0 then
134 return (self.Q*self.D+self.R)/self.D;
135 else
136 print(self.Q,self.R,self.D,"Division 0 ERROR");
137 return 0;
138 end
139 end
140 end
141 --add
142 function Frac:Add(tq,tr,td)
143 local tv=Frac:new(tq,tr,td);
144 return self.Add(tv);
145 end
146 --add floating point or another Frac
147 function Frac:Add(o)
148 local tq,tr,td=0,0,1;
149 if isNum(o) then--o is number
150 tq,tr,td=self:BrokeNum(o);
151 else
152 if getmetattable(o)==getmetattable(self) then--o is a same type
153 tq,tr,td=o:Get();
154 else
155 print("unknown type");
156 return tq,tr,td;
157 end
158 end
159 --here do add
160 local codivider,tv1,tv2;
161 codivider=self.D*td;
162 tv1=((self.Q*self.D)+self.R)*codivider/self.D;
163 tv2=((tq*td)+tr)*codivider/td;
164 --add reminders and divide it by codivider
165 return self:BrokeNum((tv1+tv2)/codivider);
166 end
167 --sub
168 function Frac:Sub(tq,tr,td)
169 local tv=Frac:new(tq,tr,td);
170 return self.Sub(tv);
171 end
172 --sub floating point or another Frac
173 function Frac:Sub(o)
174 local tq,tr,td=0,0,1;
175 if isNum(o) then--o is number
176 tq,tr,td=self:BrokeNum(o);
177 else
178 if getmetattable(o)==getmetattable(self) then--o is a same type
179 tq,tr,td=o:Get();
180 else
181 print("unknown type");
182 return tq,tr,td;
183 end
184 end
185 --here do add
186 local codivider,tv1,tv2;
187 codivider=self.D*td;
188 tv1=((self.Q*self.D)+self.R)*codivider/self.D;
189 tv2=((tq*td)+tr)*codivider/td;
190 --minus reminders and divide it by codivider
191 return self:BrokeNum((tv1-tv2)/codivider);
192 end
193 --multiple
194 function Frac:Mul(tq,tr,td)
195 local tv=Frac:new(tq,tr,td);
196 return self.Mul(tv);
197 end
198 --multiple floating point or another Frac
199 function Frac:Mul(o)
200 local tq,tr,td=0,0,1;
201 if isNum(o) then--o is number
202 tq,tr,td=self:BrokeNum(o);
203 else
204 if getmetattable(o)==getmetattable(self) then--o is a same type
205 tq,tr,td=o:Get();
206 else
207 print("unknown type");
208 return tq,tr,td;
209 end
210 end
211 --here do multiplication
212 local tv1,tv2;
213 tv2=self.D*td;
214 tv1=((self.Q*self.D)+self.R)*((tq*td)+tr);
215 return self:BrokeNum(tv1/tv2);
216 end
217 --divide
218 function Frac:Div(tq,tr,td)
219 local tv=Frac:new(tq,tr,td);
220 return self.Div(tv);
221 end
222 --divide floating point or another Frac
223 function Frac:Div(o)
224 local tq,tr,td=0,0,1;
225 if isNum(o) then--o is number
226 tq,tr,td=self:BrokeNum(o);
227 else
228 if getmetattable(o)==getmetattable(self) then--o is a same type
229 tq,tr,td=o:Get();
230 else
231 print("unknown type");
232 return tq,tr,td;
233 end
234 end
235 --here do division
236 local tv1,tv2;
237 tv1=((self.Q*self.D)+self.R)*td;
238 tv2=((tq*td)+tr)*self.D;
239 if tv2==0 then
240 print("Warning zero division");
241 end
242 return self:BrokeNum(tv1/tv2);
243 end
244 --pow or ^
245 function Frac:Pow(tq,tr,td)
246 local tv=Frac:new(tq,tr,td);
247 return self.Pow(tv);
248 end
249 --pow floating point or another Frac
250 function Frac:Pow(o)
251 local tq,tr,td=0,0,1;
252 if isNum(o) then--o is number
253 tq,tr,td=self:BrokeNum(o);
254 else
255 if getmetattable(o)==getmetattable(self) then--o is a same type
256 tq,tr,td=o:Get();
257 else
258 print("unknown type");
259 return tq,tr,td;
260 end
261 end
262 --here do power
263 local tv1,tv2;
264 tv1=self:GetFP();
265 tv2=self:GetFP(tq,tr,td);
266 return self:BrokeNum(math.pow(tv1,tv2));
267 end
268 --this function brings fractioned number to r/d number w/o qotient
269 function Frac:ToRaDo()
270 self.R=(self.Q*self.D)+self.R;
271 self.Q=0;
272 end
273 --function print in stile QLRLD like in casio DF-x
274 function Frac:Print()
275 print(self.Q.."L"..self.R.."L"..self.D);
276 end