fmod.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. fmod.c
  9. Abstract:
  10. This module implements support for the modulo function.
  11. Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  12. Developed at SunPro, a Sun Microsystems, Inc. business.
  13. Permission to use, copy, modify, and distribute this
  14. software is freely granted, provided that this notice
  15. is preserved.
  16. Author:
  17. Evan Green 29-Aug-2013
  18. Environment:
  19. User Mode C Library
  20. --*/
  21. //
  22. // ------------------------------------------------------------------- Includes
  23. //
  24. #include "../libcp.h"
  25. #include "mathp.h"
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. //
  36. // -------------------------------------------------------------------- Globals
  37. //
  38. //
  39. // ------------------------------------------------------------------ Functions
  40. //
  41. LIBC_API
  42. double
  43. fmod (
  44. double Dividend,
  45. double Divisor
  46. )
  47. /*++
  48. Routine Description:
  49. This routine computes the remainder of dividing the given two values.
  50. Arguments:
  51. Dividend - Supplies the numerator of the division.
  52. Divisor - Supplies the denominator of the division.
  53. Return Value:
  54. Returns the remainder of the division on success.
  55. NaN if the divisor is zero, either value is NaN, or the dividend is
  56. infinite.
  57. Returns the dividend if the dividend is not infinite and the denominator is.
  58. --*/
  59. {
  60. LONG BitNumber;
  61. LONG DividendExponent;
  62. LONG DividendHigh;
  63. ULONG DividendLow;
  64. LONG DividendSign;
  65. LONG DivisorExponent;
  66. LONG DivisorHigh;
  67. ULONG DivisorLow;
  68. LONG ExponentIndex;
  69. ULONG ExponentShift;
  70. LONG OneExponent;
  71. DOUBLE_PARTS Parts;
  72. LONG SubtractionHigh;
  73. ULONG SubtractionLow;
  74. Parts.Double = Dividend;
  75. DividendHigh = Parts.Ulong.High;
  76. DividendLow = Parts.Ulong.Low;
  77. Parts.Double = Divisor;
  78. DivisorHigh = Parts.Ulong.High;
  79. DivisorLow = Parts.Ulong.Low;
  80. DividendSign = DividendHigh & (DOUBLE_SIGN_BIT >> DOUBLE_HIGH_WORD_SHIFT);
  81. ExponentShift = DOUBLE_EXPONENT_SHIFT - DOUBLE_HIGH_WORD_SHIFT;
  82. OneExponent = 1 << ExponentShift;
  83. //
  84. // Get the absolute value of the dividend.
  85. //
  86. DividendHigh ^= DividendSign;
  87. //
  88. // Get the absolute value of the divisor.
  89. //
  90. DivisorHigh &= ((~DOUBLE_SIGN_BIT) >> DOUBLE_HIGH_WORD_SHIFT);
  91. //
  92. // Handle cases where the divisor is zero, the dividend is not finite, or
  93. // the divisor is NaN.
  94. //
  95. if (((DivisorHigh | DivisorLow) == 0) || (DividendHigh >= NAN_HIGH_WORD) ||
  96. ((DivisorHigh | ((DivisorLow | -DivisorLow) >> 31)) > NAN_HIGH_WORD)) {
  97. return (Dividend * Divisor) / (Dividend * Divisor);
  98. }
  99. if (DividendHigh <= DivisorHigh) {
  100. //
  101. // If |Dividend| < |Divisor|, return Dividend.
  102. //
  103. if ((DividendHigh < DivisorHigh) || (DividendLow < DivisorLow)) {
  104. return Dividend;
  105. }
  106. //
  107. // If |Dividend| = |Divisor| then return Dividend * 0.
  108. //
  109. if (DividendLow == DivisorLow) {
  110. if (DividendSign != 0) {
  111. return -ClDoubleZero;
  112. }
  113. return ClDoubleZero;
  114. }
  115. }
  116. //
  117. // Determine ilogb(Dividend).
  118. //
  119. if (DividendHigh < OneExponent) {
  120. if (DividendHigh == 0) {
  121. DividendExponent = -1043;
  122. for (ExponentIndex = DividendLow;
  123. ExponentIndex > 0;
  124. ExponentIndex <<= 1) {
  125. DividendExponent -= 1;
  126. }
  127. } else {
  128. DividendExponent = -1022;
  129. for (ExponentIndex = (DividendHigh << 11);
  130. ExponentIndex > 0;
  131. ExponentIndex <<= 1) {
  132. DividendExponent -= 1;
  133. }
  134. }
  135. } else {
  136. DividendExponent = (DividendHigh >> ExponentShift) - 1023;
  137. }
  138. //
  139. // Determine ilogb(Divisor).
  140. //
  141. if (DivisorHigh < OneExponent) {
  142. if (DivisorHigh == 0) {
  143. DivisorExponent = -1043;
  144. for (ExponentIndex = DivisorLow;
  145. ExponentIndex > 0;
  146. ExponentIndex <<= 1) {
  147. DivisorExponent -= 1;
  148. }
  149. } else {
  150. DivisorExponent = -1022;
  151. for (ExponentIndex = (DivisorHigh << 11);
  152. ExponentIndex > 0;
  153. ExponentIndex <<= 1) {
  154. DivisorExponent -= 1;
  155. }
  156. }
  157. } else {
  158. DivisorExponent = (DivisorHigh >> ExponentShift) - 1023;
  159. }
  160. //
  161. // Set up {DividendHigh,DividendLow}, {DivisorHigh,DivisorLow} and align
  162. // Divisor to Dividend.
  163. //
  164. if (DividendExponent >= -1022) {
  165. DividendHigh = OneExponent | (DOUBLE_HIGH_VALUE_MASK & DividendHigh);
  166. } else {
  167. //
  168. // This is a subnormal dividend, shift it to be normal.
  169. //
  170. BitNumber = -1022 - DividendExponent;
  171. if (BitNumber <= 31) {
  172. DividendHigh = (DividendHigh << BitNumber) |
  173. (DividendLow >> (32 - BitNumber));
  174. DividendLow <<= BitNumber;
  175. } else {
  176. DividendHigh = DividendLow << (BitNumber - 32);
  177. DividendLow = 0;
  178. }
  179. }
  180. if (DivisorExponent >= -1022) {
  181. DivisorHigh = OneExponent | (DOUBLE_HIGH_VALUE_MASK & DivisorHigh);
  182. } else {
  183. //
  184. // This is a subnormal divisor, shift it to be normal.
  185. //
  186. BitNumber = -1022 - DivisorExponent;
  187. if (BitNumber <= 31) {
  188. DivisorHigh = (DivisorHigh << BitNumber) |
  189. (DivisorLow >> (32 - BitNumber));
  190. DivisorLow <<= BitNumber;
  191. } else {
  192. DivisorHigh = DivisorLow << (BitNumber - 32);
  193. DivisorLow = 0;
  194. }
  195. }
  196. //
  197. // Now do fixed point modulo.
  198. //
  199. BitNumber = DividendExponent - DivisorExponent;
  200. while (BitNumber != 0) {
  201. BitNumber -= 1;
  202. SubtractionHigh = DividendHigh - DivisorHigh;
  203. SubtractionLow = DividendLow - DivisorLow;
  204. if (DividendLow < DivisorLow) {
  205. SubtractionHigh -= 1;
  206. }
  207. if (SubtractionHigh < 0) {
  208. DividendHigh = DividendHigh + DividendHigh + (DividendLow >> 31);
  209. DividendLow = DividendLow+DividendLow;
  210. } else {
  211. if ((SubtractionHigh | SubtractionLow) == 0) {
  212. //
  213. // Return sign(Dividend) * 0.
  214. //
  215. if (DividendSign != 0) {
  216. return -ClDoubleZero;
  217. }
  218. return ClDoubleZero;
  219. }
  220. DividendHigh = SubtractionHigh + SubtractionHigh +
  221. (SubtractionLow >> 31);
  222. DividendLow = SubtractionLow + SubtractionLow;
  223. }
  224. }
  225. SubtractionHigh = DividendHigh - DivisorHigh;
  226. SubtractionLow = DividendLow - DivisorLow;
  227. if (DividendLow < DivisorLow) {
  228. SubtractionHigh -= 1;
  229. }
  230. if (SubtractionHigh >= 0) {
  231. DividendHigh = SubtractionHigh;
  232. DividendLow = SubtractionLow;
  233. }
  234. //
  235. // Convert back to floating point and restore the sign.
  236. //
  237. if ((DividendHigh | DividendLow) == 0) {
  238. //
  239. // Return sign(Dividend) * 0.
  240. //
  241. if (DividendSign != 0) {
  242. return -ClDoubleZero;
  243. }
  244. return ClDoubleZero;
  245. }
  246. //
  247. // Normalize the dividend.
  248. //
  249. while (DividendHigh < OneExponent) {
  250. DividendHigh = DividendHigh + DividendHigh + (DividendLow >> 31);
  251. DividendLow = DividendLow + DividendLow;
  252. DivisorExponent -= 1;
  253. }
  254. //
  255. // Normalize the output.
  256. //
  257. if (DivisorExponent >= -1022) {
  258. DividendHigh = ((DividendHigh - OneExponent) |
  259. ((DivisorExponent + 1023) << ExponentShift));
  260. Parts.Ulong.High = DividendHigh | DividendSign;
  261. Parts.Ulong.Low = DividendLow;
  262. Dividend = Parts.Double;
  263. //
  264. // Handle a subnormal output.
  265. //
  266. } else {
  267. BitNumber = -1022 - DivisorExponent;
  268. if (BitNumber <= ExponentShift) {
  269. DividendLow = (DividendLow >> BitNumber) |
  270. ((ULONG)DividendHigh << (32 - BitNumber));
  271. DividendHigh >>= BitNumber;
  272. } else if (BitNumber <= 31) {
  273. DividendLow = (DividendHigh << (32 - BitNumber)) |
  274. (DividendLow >> BitNumber);
  275. DividendHigh = DividendSign;
  276. } else {
  277. DividendLow = DividendHigh >> (BitNumber - 32);
  278. DividendHigh = DividendSign;
  279. }
  280. Parts.Ulong.High = DividendHigh | DividendSign;
  281. Parts.Ulong.Low = DividendLow;
  282. Dividend = Parts.Double;
  283. //
  284. // Create a signal if necessary.
  285. //
  286. Dividend *= ClDoubleOne;
  287. }
  288. return Dividend;
  289. }
  290. //
  291. // --------------------------------------------------------- Internal Functions
  292. //