HellCreator Project by Dmitry Salomatine
sdihellcreator@bezeqint.net
Israel 2003
Original file name: ml_fco.lua
http://sdihchp.users3.50megs.com

   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

Lua source files to HTML converted 06/04/03 14:13:32