Fractions.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. #ifndef FRACTIONS_H
  19. #define FRACTIONS_H
  20. //=======================
  21. #include "System.h"
  22. //====================
  23. /*****************************************************************
  24. This header depends on the rest QuickMath, but is not necessary
  25. for use of Quickmath, and deals primarily with high speed fraction
  26. operations.
  27. /*****************************************************************
  28. Hungarian: fr = either generic fraction or signed 16 (S16 + S16 [ / U16] )
  29. pfr = pointer to fraction
  30. frS32 = (S32 + S32 [ / U32] )
  31. type = RFracS32, members = "frac" and "mod" and "set"
  32. frS16 = S16 + S16 [ / U16]
  33. frU16 = S16 + U16 [ / U16]
  34. type = RFracU16, same members, etc., etc.
  35. & = implicit pass by reference, do NOT use a pointer
  36. & is used in almost all cases to prevent VC from creating
  37. a local stack frame which would slow things down by 20 times.
  38. NOTE: The integral value of the fraction is always a SIGNED quantity.
  39. The S/U refers to whether or not the NUMERATOR of the fraction is
  40. signed or unsigned.
  41. NOTE: Some functions can take a long AS an frS16. Understand that this is
  42. a memory cast as a frS16 and does NOT represent the actual long "value"!
  43. Use Get and Set "Value" functions to translate integers to fixed point!
  44. /*****************************************************************
  45. RFracS32 { mod, frac, set }
  46. RFracS16 { mod, frac, set }
  47. RFracU16 { mod, frac, set }
  48. inline void rspfrDiv(&frDst,sNum,sDen) // sDen > 0
  49. inline void rspfrSet(&frDst,lVal) // a memset!
  50. inline void rspfrAdd(&frDst,frAdd,short sDen)
  51. inline void rspfrSub(&frDst,frSub,short sDen)
  52. inline void rspfrAddHalf(&frDst,short sDen) // useful for rounding
  53. inline void rspfrSetValue(&frDst,double dVal,short sDen)
  54. inline void rspMakeProper(&frU16Dst,usNum,usDen)
  55. inline RFracU16* rspfrU16Strafe256(usNum,usDen) // gives 0..255 * fraction!
  56. //*********************** HIGH INTENSITY SPEED! ***********************
  57. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lAdd,PROPER,POSITIVE)
  58. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lAdd,IMPROPER,POSITIVE)
  59. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lAdd,IMPROPER,POSITIVE)
  60. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lAdd,PROPER,NEGATIVE)
  61. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lAdd,IMPROPER,NEGATIVE)
  62. inline void rspfrAdd32(&lVal,&lNum,&lDel,&lInc,&lDen,&lPixSize)
  63. /****************************************************************/
  64. typedef union
  65. {
  66. struct {
  67. U16 mod;
  68. U16 frac;
  69. };
  70. U32 set;
  71. } RFracU16; // No denominator, unsigned values...
  72. //=======================================
  73. typedef union {
  74. long set;
  75. struct
  76. {
  77. short mod;
  78. short frac;
  79. };
  80. } RFracS16;
  81. //=======================================
  82. typedef union {
  83. S64 set;
  84. struct
  85. {
  86. long mod;
  87. long frac;
  88. };
  89. } RFracS32; // good for compound fractions
  90. //************* ALERT ALERT!!! FRACTION STUFF HERE!!!!! *******************
  91. // There should be more functions to handle simplified cases!
  92. // sDen MUST be positive!
  93. inline void rspfrDiv(RFracS16& fr,short sNum,short sDen)
  94. {
  95. fr.mod = sNum / sDen;
  96. fr.frac = sNum % sDen;
  97. if (sNum < 0) // special case
  98. if (fr.frac != 0) // put on correct side of negative number!
  99. {
  100. fr.mod--;
  101. fr.frac += sDen;
  102. }
  103. }
  104. inline void rspfrSet(RFracS16& fr,long lVal) { fr.set = lVal; }
  105. // Signed can go either way... use unsigned for speed!
  106. // This also assumes it can add greater than one!
  107. inline void rspfrAdd(RFracS16& frDst,RFracS16& frAdd,short sDen)
  108. {
  109. frDst.mod += frAdd.mod;
  110. frDst.frac += frAdd.frac;
  111. if (frDst.frac >= sDen) {frDst.mod++;frDst.frac -= sDen;}
  112. if (frDst.frac < 0) {frDst.mod--;frDst.frac += sDen;}
  113. }
  114. inline void rspfrSub(RFracS16& frDst,RFracS16& frSub,short sDen)
  115. {
  116. frDst.mod -= frSub.mod;
  117. frDst.frac -= frSub.frac;
  118. if (frDst.frac < 0) {frDst.mod--;frDst.frac += sDen;}
  119. if (frDst.frac >= sDen) {frDst.mod++;frDst.frac -= sDen;}
  120. }
  121. inline void rspfrAddHalf(RFracS16& frDst,short sDen) // useful for rounding
  122. {
  123. frDst.frac += (sDen >> 1);
  124. if (frDst.frac >= sDen) {frDst.mod++;frDst.frac -= sDen;}
  125. }
  126. //========================= debugging only! (slow)
  127. inline void rspfrSetValue(RFracS16& frDst,double dVal,short sDen)
  128. {
  129. frDst.mod = (short) floor(dVal);
  130. frDst.frac = (short) ((dVal - floor(dVal))*sDen);
  131. }
  132. // add two fractions of identical denominators...
  133. // both fraction MUST be PROPER!
  134. // UNSIGNED!!!!
  135. //
  136. inline void rspfrAdd(RFracU16& pDst,RFracU16& pAdd,short sDen)
  137. {
  138. pDst.mod += pAdd.mod;
  139. if ( (pDst.frac += pAdd.frac) >= sDen)
  140. {
  141. pDst.mod++; // ONLY adding proper fractions
  142. pDst.frac -= sDen;
  143. }
  144. }
  145. // Creates a proper fraction from an improper one:
  146. // The sizes MUST be appropriate!
  147. //
  148. inline void rspMakeProper(RFracU16& pDst,USHORT usNum,USHORT usDen)
  149. {
  150. pDst.mod = usNum / usDen;
  151. pDst.frac = usNum % usDen;
  152. //pDst.frac = usNum - pDst.mod * usDen;// overflow problem
  153. }
  154. // Creates an array of 256 fractions, uch that 0 is 0,
  155. // 1 is tha base fraction, and 255 is 255 * the base fraction.
  156. // Both must be unsigned! (uses calloc)
  157. //
  158. inline RFracU16* rspfrU16Strafe256(USHORT usNum,USHORT usDen)
  159. {
  160. RFracU16* pu16fNew = (RFracU16*) calloc(256,sizeof(RFracU16));
  161. RFracU16 u16fInc;
  162. rspMakeProper(u16fInc,usNum,usDen); // the 2 part mod
  163. ULONG ulNumInc = 0;
  164. for (short i = 1; i < 256 ; i++)
  165. {
  166. pu16fNew[i].mod = pu16fNew[i-1].mod + u16fInc.mod;
  167. pu16fNew[i].frac = pu16fNew[i-1].frac + u16fInc.frac;
  168. if (pu16fNew[i].frac >= usDen)
  169. {
  170. pu16fNew[i].frac -= usDen;
  171. pu16fNew[i].mod++; // unsigned positive increment only!
  172. }
  173. }
  174. return pu16fNew;
  175. }
  176. //-------------------------- 32 bit signed integer calculus stuff:
  177. //*********************** HIGH INTENSITY SPEED! ***********************
  178. typedef U32 POSITIVE;
  179. typedef S32 NEGATIVE;
  180. typedef U32 PROPER;
  181. typedef S32 IMPROPER;
  182. // lDel is unused here...
  183. // all values are signed, including lInc & lDel ...
  184. //
  185. inline void rspfrAdd32(long &lVal,long &lNum,long &lDel,long &lInc,
  186. long &lDen,long &lAdd,PROPER,POSITIVE)
  187. {
  188. lNum += lInc;
  189. if (lNum >= lDen) { lNum -= lDen; lVal += lAdd; }
  190. }
  191. // all values are signed, including lInc & lDel ...
  192. //
  193. inline void rspfrAdd32(long &lVal,long &lNum,long &lDel,long &lInc,
  194. long &lDen,long &lAdd,IMPROPER,POSITIVE)
  195. {
  196. lVal += lDel;
  197. lNum += lInc;
  198. if (lNum >= lDen) { lNum -= lDen; lVal += lAdd; }
  199. }
  200. // lDel is unused here...
  201. // all values are signed, including lInc & lDel & lAdd ...
  202. //
  203. inline void rspfrAdd32(long &lVal,long &lNum,long &lDel,long &lInc,
  204. long &lDen,long &lAdd,PROPER,NEGATIVE)
  205. {
  206. lNum += lInc;
  207. if (lNum < 0) { lNum += lDen; lVal -= lAdd; }
  208. }
  209. // all values are signed, including lInc & lDel & lAdd ...
  210. //
  211. inline void rspfrAdd32(long &lVal,long &lNum,long &lDel,long &lInc,
  212. long &lDen,long &lAdd,IMPROPER,NEGATIVE)
  213. {
  214. lVal += lDel;
  215. lNum += lInc;
  216. if (lNum < 0) { lNum += lDen; lVal -= lAdd; }
  217. }
  218. // all values are signed, including lInc & lDel & lAdd ...
  219. // General (slowest) form... Improper and UNKNOWN SIGN
  220. //
  221. inline void rspfrAdd32(long &lVal,long &lNum,long &lDel,long &lInc,
  222. long &lDen,long &lPixSize)
  223. {
  224. lVal += lDel;
  225. lNum += lInc;
  226. if (lNum < 0) { lNum += lDen; lVal -= lPixSize; }
  227. if (lNum >= lDen) { lNum -= lDen; lVal += lPixSize; }
  228. }
  229. //=======================
  230. #endif