Decimal.DecCalc.cs 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Diagnostics;
  5. using System.Runtime.CompilerServices;
  6. using System.Runtime.InteropServices;
  7. using Internal.Runtime.CompilerServices;
  8. using X86 = System.Runtime.Intrinsics.X86;
  9. namespace System
  10. {
  11. public partial struct Decimal
  12. {
  13. // Low level accessors used by a DecCalc and formatting
  14. internal uint High => (uint)hi;
  15. internal uint Low => (uint)lo;
  16. internal uint Mid => (uint)mid;
  17. internal bool IsNegative => flags < 0;
  18. internal int Scale => (byte)(flags >> ScaleShift);
  19. #if BIGENDIAN
  20. private ulong Low64 => ((ulong)Mid << 32) | Low;
  21. #else
  22. private ulong Low64 => Unsafe.As<int, ulong>(ref Unsafe.AsRef(in lo));
  23. #endif
  24. private static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As<decimal, DecCalc>(ref d);
  25. #region APIs need by number formatting.
  26. internal static uint DecDivMod1E9(ref decimal value)
  27. {
  28. return DecCalc.DecDivMod1E9(ref AsMutable(ref value));
  29. }
  30. #endregion
  31. /// <summary>
  32. /// Class that contains all the mathematical calculations for decimal. Most of which have been ported from oleaut32.
  33. /// </summary>
  34. [StructLayout(LayoutKind.Explicit)]
  35. private struct DecCalc
  36. {
  37. // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal.
  38. [FieldOffset(0)]
  39. private uint uflags;
  40. [FieldOffset(4)]
  41. private uint uhi;
  42. [FieldOffset(8)]
  43. private uint ulo;
  44. [FieldOffset(12)]
  45. private uint umid;
  46. /// <summary>
  47. /// The low and mid fields combined in little-endian order
  48. /// </summary>
  49. [FieldOffset(8)]
  50. private ulong ulomidLE;
  51. private uint High
  52. {
  53. get => uhi;
  54. set => uhi = value;
  55. }
  56. private uint Low
  57. {
  58. get => ulo;
  59. set => ulo = value;
  60. }
  61. private uint Mid
  62. {
  63. get => umid;
  64. set => umid = value;
  65. }
  66. private bool IsNegative => (int)uflags < 0;
  67. private int Scale => (byte)(uflags >> ScaleShift);
  68. private ulong Low64
  69. {
  70. #if BIGENDIAN
  71. get { return ((ulong)umid << 32) | ulo; }
  72. set { umid = (uint)(value >> 32); ulo = (uint)value; }
  73. #else
  74. get => ulomidLE;
  75. set => ulomidLE = value;
  76. #endif
  77. }
  78. private const uint SignMask = 0x80000000;
  79. private const uint ScaleMask = 0x00FF0000;
  80. private const int DEC_SCALE_MAX = 28;
  81. private const uint TenToPowerNine = 1000000000;
  82. private const ulong TenToPowerEighteen = 1000000000000000000;
  83. // The maximum power of 10 that a 32 bit integer can store
  84. private const int MaxInt32Scale = 9;
  85. // The maximum power of 10 that a 64 bit integer can store
  86. private const int MaxInt64Scale = 19;
  87. // Fast access for 10^n where n is 0-9
  88. private static readonly uint[] s_powers10 = new uint[] {
  89. 1,
  90. 10,
  91. 100,
  92. 1000,
  93. 10000,
  94. 100000,
  95. 1000000,
  96. 10000000,
  97. 100000000,
  98. 1000000000
  99. };
  100. // Fast access for 10^n where n is 1-19
  101. private static readonly ulong[] s_ulongPowers10 = new ulong[] {
  102. 10,
  103. 100,
  104. 1000,
  105. 10000,
  106. 100000,
  107. 1000000,
  108. 10000000,
  109. 100000000,
  110. 1000000000,
  111. 10000000000,
  112. 100000000000,
  113. 1000000000000,
  114. 10000000000000,
  115. 100000000000000,
  116. 1000000000000000,
  117. 10000000000000000,
  118. 100000000000000000,
  119. 1000000000000000000,
  120. 10000000000000000000,
  121. };
  122. private static readonly double[] s_doublePowers10 = new double[] {
  123. 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
  124. 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
  125. 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
  126. 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
  127. 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
  128. 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
  129. 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
  130. 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
  131. 1e80
  132. };
  133. #region Decimal Math Helpers
  134. private static unsafe uint GetExponent(float f)
  135. {
  136. // Based on pulling out the exp from this single struct layout
  137. //typedef struct {
  138. // ULONG mant:23;
  139. // ULONG exp:8;
  140. // ULONG sign:1;
  141. //} SNGSTRUCT;
  142. return (byte)(*(uint*)&f >> 23);
  143. }
  144. private static unsafe uint GetExponent(double d)
  145. {
  146. // Based on pulling out the exp from this double struct layout
  147. //typedef struct {
  148. // DWORDLONG mant:52;
  149. // DWORDLONG signexp:12;
  150. // } DBLSTRUCT;
  151. return (uint)(*(ulong*)&d >> 52) & 0x7FFu;
  152. }
  153. private static ulong UInt32x32To64(uint a, uint b)
  154. {
  155. return (ulong)a * (ulong)b;
  156. }
  157. private static void UInt64x64To128(ulong a, ulong b, ref DecCalc result)
  158. {
  159. ulong low = UInt32x32To64((uint)a, (uint)b); // lo partial prod
  160. ulong mid = UInt32x32To64((uint)a, (uint)(b >> 32)); // mid 1 partial prod
  161. ulong high = UInt32x32To64((uint)(a >> 32), (uint)(b >> 32));
  162. high += mid >> 32;
  163. low += mid <<= 32;
  164. if (low < mid) // test for carry
  165. high++;
  166. mid = UInt32x32To64((uint)(a >> 32), (uint)b);
  167. high += mid >> 32;
  168. low += mid <<= 32;
  169. if (low < mid) // test for carry
  170. high++;
  171. if (high > uint.MaxValue)
  172. Number.ThrowOverflowException(TypeCode.Decimal);
  173. result.Low64 = low;
  174. result.High = (uint)high;
  175. }
  176. /// <summary>
  177. /// Do full divide, yielding 96-bit result and 32-bit remainder.
  178. /// </summary>
  179. /// <param name="bufNum">96-bit dividend as array of uints, least-sig first</param>
  180. /// <param name="den">32-bit divisor</param>
  181. /// <returns>Returns remainder. Quotient overwrites dividend.</returns>
  182. private static uint Div96By32(ref Buf12 bufNum, uint den)
  183. {
  184. // TODO: https://github.com/dotnet/coreclr/issues/3439
  185. ulong tmp, div;
  186. if (bufNum.U2 != 0)
  187. {
  188. tmp = bufNum.High64;
  189. div = tmp / den;
  190. bufNum.High64 = div;
  191. tmp = ((tmp - (uint)div * den) << 32) | bufNum.U0;
  192. if (tmp == 0)
  193. return 0;
  194. uint div32 = (uint)(tmp / den);
  195. bufNum.U0 = div32;
  196. return (uint)tmp - div32 * den;
  197. }
  198. tmp = bufNum.Low64;
  199. if (tmp == 0)
  200. return 0;
  201. div = tmp / den;
  202. bufNum.Low64 = div;
  203. return (uint)(tmp - div * den);
  204. }
  205. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  206. private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
  207. {
  208. #if BIT64
  209. ulong div64 = high64 / pow;
  210. uint div = (uint)((((high64 - div64 * pow) << 32) + low) / pow);
  211. if (low == div * pow)
  212. {
  213. high64 = div64;
  214. low = div;
  215. return true;
  216. }
  217. #else
  218. // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
  219. Debug.Assert(pow <= ushort.MaxValue);
  220. uint num, mid32, low16, div;
  221. if (high64 <= uint.MaxValue)
  222. {
  223. num = (uint)high64;
  224. mid32 = num / pow;
  225. num = (num - mid32 * pow) << 16;
  226. num += low >> 16;
  227. low16 = num / pow;
  228. num = (num - low16 * pow) << 16;
  229. num += (ushort)low;
  230. div = num / pow;
  231. if (num == div * pow)
  232. {
  233. high64 = mid32;
  234. low = (low16 << 16) + div;
  235. return true;
  236. }
  237. }
  238. else
  239. {
  240. num = (uint)(high64 >> 32);
  241. uint high32 = num / pow;
  242. num = (num - high32 * pow) << 16;
  243. num += (uint)high64 >> 16;
  244. mid32 = num / pow;
  245. num = (num - mid32 * pow) << 16;
  246. num += (ushort)high64;
  247. div = num / pow;
  248. num = (num - div * pow) << 16;
  249. mid32 = div + (mid32 << 16);
  250. num += low >> 16;
  251. low16 = num / pow;
  252. num = (num - low16 * pow) << 16;
  253. num += (ushort)low;
  254. div = num / pow;
  255. if (num == div * pow)
  256. {
  257. high64 = ((ulong)high32 << 32) | mid32;
  258. low = (low16 << 16) + div;
  259. return true;
  260. }
  261. }
  262. #endif
  263. return false;
  264. }
  265. /// <summary>
  266. /// Normalize (unscale) the number by trying to divide out 10^8, 10^4, 10^2, and 10^1.
  267. /// If a division by one of these powers returns a zero remainder, then we keep the quotient.
  268. /// </summary>
  269. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  270. private static void Unscale(ref uint low, ref ulong high64, ref int scale)
  271. {
  272. // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 we can extract.
  273. // We use this as a quick test on whether to try a given power.
  274. #if BIT64
  275. while ((byte)low == 0 && scale >= 8 && Div96ByConst(ref high64, ref low, 100000000))
  276. scale -= 8;
  277. if ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
  278. scale -= 4;
  279. #else
  280. while ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
  281. scale -= 4;
  282. #endif
  283. if ((low & 3) == 0 && scale >= 2 && Div96ByConst(ref high64, ref low, 100))
  284. scale -= 2;
  285. if ((low & 1) == 0 && scale >= 1 && Div96ByConst(ref high64, ref low, 10))
  286. scale--;
  287. }
  288. /// <summary>
  289. /// Do partial divide, yielding 32-bit result and 64-bit remainder.
  290. /// Divisor must be larger than upper 64 bits of dividend.
  291. /// </summary>
  292. /// <param name="bufNum">96-bit dividend as array of uints, least-sig first</param>
  293. /// <param name="den">64-bit divisor</param>
  294. /// <returns>Returns quotient. Remainder overwrites lower 64-bits of dividend.</returns>
  295. private static uint Div96By64(ref Buf12 bufNum, ulong den)
  296. {
  297. Debug.Assert(den > bufNum.High64);
  298. uint quo;
  299. ulong num;
  300. uint num2 = bufNum.U2;
  301. if (num2 == 0)
  302. {
  303. num = bufNum.Low64;
  304. if (num < den)
  305. // Result is zero. Entire dividend is remainder.
  306. return 0;
  307. // TODO: https://github.com/dotnet/coreclr/issues/3439
  308. quo = (uint)(num / den);
  309. num -= quo * den; // remainder
  310. bufNum.Low64 = num;
  311. return quo;
  312. }
  313. uint denHigh32 = (uint)(den >> 32);
  314. if (num2 >= denHigh32)
  315. {
  316. // Divide would overflow. Assume a quotient of 2^32, and set
  317. // up remainder accordingly.
  318. //
  319. num = bufNum.Low64;
  320. num -= den << 32;
  321. quo = 0;
  322. // Remainder went negative. Add divisor back in until it's positive,
  323. // a max of 2 times.
  324. //
  325. do
  326. {
  327. quo--;
  328. num += den;
  329. } while (num >= den);
  330. bufNum.Low64 = num;
  331. return quo;
  332. }
  333. // Hardware divide won't overflow
  334. //
  335. ulong num64 = bufNum.High64;
  336. if (num64 < denHigh32)
  337. // Result is zero. Entire dividend is remainder.
  338. //
  339. return 0;
  340. // TODO: https://github.com/dotnet/coreclr/issues/3439
  341. quo = (uint)(num64 / denHigh32);
  342. num = bufNum.U0 | ((num64 - quo * denHigh32) << 32); // remainder
  343. // Compute full remainder, rem = dividend - (quo * divisor).
  344. //
  345. ulong prod = UInt32x32To64(quo, (uint)den); // quo * lo divisor
  346. num -= prod;
  347. if (num > ~prod)
  348. {
  349. // Remainder went negative. Add divisor back in until it's positive,
  350. // a max of 2 times.
  351. //
  352. do
  353. {
  354. quo--;
  355. num += den;
  356. } while (num >= den);
  357. }
  358. bufNum.Low64 = num;
  359. return quo;
  360. }
  361. /// <summary>
  362. /// Do partial divide, yielding 32-bit result and 96-bit remainder.
  363. /// Top divisor uint must be larger than top dividend uint. This is
  364. /// assured in the initial call because the divisor is normalized
  365. /// and the dividend can't be. In subsequent calls, the remainder
  366. /// is multiplied by 10^9 (max), so it can be no more than 1/4 of
  367. /// the divisor which is effectively multiplied by 2^32 (4 * 10^9).
  368. /// </summary>
  369. /// <param name="bufNum">128-bit dividend as array of uints, least-sig first</param>
  370. /// <param name="bufDen">96-bit divisor</param>
  371. /// <returns>Returns quotient. Remainder overwrites lower 96-bits of dividend.</returns>
  372. private static uint Div128By96(ref Buf16 bufNum, ref Buf12 bufDen)
  373. {
  374. Debug.Assert(bufDen.U2 > bufNum.U3);
  375. ulong dividend = bufNum.High64;
  376. uint den = bufDen.U2;
  377. if (dividend < den)
  378. // Result is zero. Entire dividend is remainder.
  379. //
  380. return 0;
  381. // TODO: https://github.com/dotnet/coreclr/issues/3439
  382. uint quo = (uint)(dividend / den);
  383. uint remainder = (uint)dividend - quo * den;
  384. // Compute full remainder, rem = dividend - (quo * divisor).
  385. //
  386. ulong prod1 = UInt32x32To64(quo, bufDen.U0); // quo * lo divisor
  387. ulong prod2 = UInt32x32To64(quo, bufDen.U1); // quo * mid divisor
  388. prod2 += prod1 >> 32;
  389. prod1 = (uint)prod1 | (prod2 << 32);
  390. prod2 >>= 32;
  391. ulong num = bufNum.Low64;
  392. num -= prod1;
  393. remainder -= (uint)prod2;
  394. // Propagate carries
  395. //
  396. if (num > ~prod1)
  397. {
  398. remainder--;
  399. if (remainder < ~(uint)prod2)
  400. goto PosRem;
  401. }
  402. else if (remainder <= ~(uint)prod2)
  403. goto PosRem;
  404. {
  405. // Remainder went negative. Add divisor back in until it's positive,
  406. // a max of 2 times.
  407. //
  408. prod1 = bufDen.Low64;
  409. for (;;)
  410. {
  411. quo--;
  412. num += prod1;
  413. remainder += den;
  414. if (num < prod1)
  415. {
  416. // Detected carry. Check for carry out of top
  417. // before adding it in.
  418. //
  419. if (remainder++ < den)
  420. break;
  421. }
  422. if (remainder < den)
  423. break; // detected carry
  424. }
  425. }
  426. PosRem:
  427. bufNum.Low64 = num;
  428. bufNum.U2 = remainder;
  429. return quo;
  430. }
  431. /// <summary>
  432. /// Multiply the two numbers. The low 96 bits of the result overwrite
  433. /// the input. The last 32 bits of the product are the return value.
  434. /// </summary>
  435. /// <param name="bufNum">96-bit number as array of uints, least-sig first</param>
  436. /// <param name="power">Scale factor to multiply by</param>
  437. /// <returns>Returns highest 32 bits of product</returns>
  438. private static uint IncreaseScale(ref Buf12 bufNum, uint power)
  439. {
  440. ulong tmp = UInt32x32To64(bufNum.U0, power);
  441. bufNum.U0 = (uint)tmp;
  442. tmp >>= 32;
  443. tmp += UInt32x32To64(bufNum.U1, power);
  444. bufNum.U1 = (uint)tmp;
  445. tmp >>= 32;
  446. tmp += UInt32x32To64(bufNum.U2, power);
  447. bufNum.U2 = (uint)tmp;
  448. return (uint)(tmp >> 32);
  449. }
  450. private static void IncreaseScale64(ref Buf12 bufNum, uint power)
  451. {
  452. ulong tmp = UInt32x32To64(bufNum.U0, power);
  453. bufNum.U0 = (uint)tmp;
  454. tmp >>= 32;
  455. tmp += UInt32x32To64(bufNum.U1, power);
  456. bufNum.High64 = tmp;
  457. }
  458. /// <summary>
  459. /// See if we need to scale the result to fit it in 96 bits.
  460. /// Perform needed scaling. Adjust scale factor accordingly.
  461. /// </summary>
  462. /// <param name="bufRes">Array of uints with value, least-significant first</param>
  463. /// <param name="hiRes">Index of last non-zero value in bufRes</param>
  464. /// <param name="scale">Scale factor for this value, range 0 - 2 * DEC_SCALE_MAX</param>
  465. /// <returns>Returns new scale factor. bufRes updated in place, always 3 uints.</returns>
  466. private static unsafe int ScaleResult(Buf24* bufRes, uint hiRes, int scale)
  467. {
  468. Debug.Assert(hiRes < bufRes->Length);
  469. uint* result = (uint*)bufRes;
  470. // See if we need to scale the result. The combined scale must
  471. // be <= DEC_SCALE_MAX and the upper 96 bits must be zero.
  472. //
  473. // Start by figuring a lower bound on the scaling needed to make
  474. // the upper 96 bits zero. hiRes is the index into result[]
  475. // of the highest non-zero uint.
  476. //
  477. int newScale = 0;
  478. if (hiRes > 2)
  479. {
  480. newScale = (int)hiRes * 32 - 64 - 1;
  481. newScale -= X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(result[hiRes]) : LeadingZeroCount(result[hiRes]);
  482. // Multiply bit position by log10(2) to figure it's power of 10.
  483. // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
  484. // with a multiply saves a 96-byte lookup table. The power returned
  485. // is <= the power of the number, so we must add one power of 10
  486. // to make it's integer part zero after dividing by 256.
  487. //
  488. // Note: the result of this multiplication by an approximation of
  489. // log10(2) have been exhaustively checked to verify it gives the
  490. // correct result. (There were only 95 to check...)
  491. //
  492. newScale = ((newScale * 77) >> 8) + 1;
  493. // newScale = min scale factor to make high 96 bits zero, 0 - 29.
  494. // This reduces the scale factor of the result. If it exceeds the
  495. // current scale of the result, we'll overflow.
  496. //
  497. if (newScale > scale)
  498. goto ThrowOverflow;
  499. }
  500. // Make sure we scale by enough to bring the current scale factor
  501. // into valid range.
  502. //
  503. if (newScale < scale - DEC_SCALE_MAX)
  504. newScale = scale - DEC_SCALE_MAX;
  505. if (newScale != 0)
  506. {
  507. // Scale by the power of 10 given by newScale. Note that this is
  508. // NOT guaranteed to bring the number within 96 bits -- it could
  509. // be 1 power of 10 short.
  510. //
  511. scale -= newScale;
  512. uint sticky = 0;
  513. uint quotient, remainder = 0;
  514. for (;;)
  515. {
  516. sticky |= remainder; // record remainder as sticky bit
  517. uint power;
  518. // Scaling loop specialized for each power of 10 because division by constant is an order of magnitude faster (especially for 64-bit division that's actually done by 128bit DIV on x64)
  519. switch (newScale)
  520. {
  521. case 1:
  522. power = DivByConst(result, hiRes, out quotient, out remainder, 10);
  523. break;
  524. case 2:
  525. power = DivByConst(result, hiRes, out quotient, out remainder, 100);
  526. break;
  527. case 3:
  528. power = DivByConst(result, hiRes, out quotient, out remainder, 1000);
  529. break;
  530. case 4:
  531. power = DivByConst(result, hiRes, out quotient, out remainder, 10000);
  532. break;
  533. #if BIT64
  534. case 5:
  535. power = DivByConst(result, hiRes, out quotient, out remainder, 100000);
  536. break;
  537. case 6:
  538. power = DivByConst(result, hiRes, out quotient, out remainder, 1000000);
  539. break;
  540. case 7:
  541. power = DivByConst(result, hiRes, out quotient, out remainder, 10000000);
  542. break;
  543. case 8:
  544. power = DivByConst(result, hiRes, out quotient, out remainder, 100000000);
  545. break;
  546. default:
  547. power = DivByConst(result, hiRes, out quotient, out remainder, TenToPowerNine);
  548. break;
  549. #else
  550. default:
  551. goto case 4;
  552. #endif
  553. }
  554. result[hiRes] = quotient;
  555. // If first quotient was 0, update hiRes.
  556. //
  557. if (quotient == 0 && hiRes != 0)
  558. hiRes--;
  559. #if BIT64
  560. newScale -= MaxInt32Scale;
  561. #else
  562. newScale -= 4;
  563. #endif
  564. if (newScale > 0)
  565. continue; // scale some more
  566. // If we scaled enough, hiRes would be 2 or less. If not,
  567. // divide by 10 more.
  568. //
  569. if (hiRes > 2)
  570. {
  571. if (scale == 0)
  572. goto ThrowOverflow;
  573. newScale = 1;
  574. scale--;
  575. continue; // scale by 10
  576. }
  577. // Round final result. See if remainder >= 1/2 of divisor.
  578. // If remainder == 1/2 divisor, round up if odd or sticky bit set.
  579. //
  580. power >>= 1; // power of 10 always even
  581. if (power <= remainder && (power < remainder || ((result[0] & 1) | sticky) != 0) && ++result[0] == 0)
  582. {
  583. uint cur = 0;
  584. do
  585. {
  586. Debug.Assert(cur + 1 < bufRes->Length);
  587. }
  588. while (++result[++cur] == 0);
  589. if (cur > 2)
  590. {
  591. // The rounding caused us to carry beyond 96 bits.
  592. // Scale by 10 more.
  593. //
  594. if (scale == 0)
  595. goto ThrowOverflow;
  596. hiRes = cur;
  597. sticky = 0; // no sticky bit
  598. remainder = 0; // or remainder
  599. newScale = 1;
  600. scale--;
  601. continue; // scale by 10
  602. }
  603. }
  604. break;
  605. } // for(;;)
  606. }
  607. return scale;
  608. ThrowOverflow:
  609. Number.ThrowOverflowException(TypeCode.Decimal);
  610. return 0;
  611. }
  612. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  613. private static unsafe uint DivByConst(uint* result, uint hiRes, out uint quotient, out uint remainder, uint power)
  614. {
  615. uint high = result[hiRes];
  616. remainder = high - (quotient = high / power) * power;
  617. for (uint i = hiRes - 1; (int)i >= 0; i--)
  618. {
  619. #if BIT64
  620. ulong num = result[i] + ((ulong)remainder << 32);
  621. remainder = (uint)num - (result[i] = (uint)(num / power)) * power;
  622. #else
  623. // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
  624. Debug.Assert(power <= ushort.MaxValue);
  625. #if BIGENDIAN
  626. const int low16 = 2, high16 = 0;
  627. #else
  628. const int low16 = 0, high16 = 2;
  629. #endif
  630. // byte* is used here because Roslyn doesn't do constant propagation for pointer arithmetic
  631. uint num = *(ushort*)((byte*)result + i * 4 + high16) + (remainder << 16);
  632. uint div = num / power;
  633. remainder = num - div * power;
  634. *(ushort*)((byte*)result + i * 4 + high16) = (ushort)div;
  635. num = *(ushort*)((byte*)result + i * 4 + low16) + (remainder << 16);
  636. div = num / power;
  637. remainder = num - div * power;
  638. *(ushort*)((byte*)result + i * 4 + low16) = (ushort)div;
  639. #endif
  640. }
  641. return power;
  642. }
  643. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  644. private static int LeadingZeroCount(uint value)
  645. {
  646. Debug.Assert(value > 0);
  647. int c = 1;
  648. if ((value & 0xFFFF0000) == 0)
  649. {
  650. value <<= 16;
  651. c += 16;
  652. }
  653. if ((value & 0xFF000000) == 0)
  654. {
  655. value <<= 8;
  656. c += 8;
  657. }
  658. if ((value & 0xF0000000) == 0)
  659. {
  660. value <<= 4;
  661. c += 4;
  662. }
  663. if ((value & 0xC0000000) == 0)
  664. {
  665. value <<= 2;
  666. c += 2;
  667. }
  668. return c + ((int)value >> 31);
  669. }
  670. /// <summary>
  671. /// Adjust the quotient to deal with an overflow.
  672. /// We need to divide by 10, feed in the high bit to undo the overflow and then round as required.
  673. /// </summary>
  674. private static int OverflowUnscale(ref Buf12 bufQuo, int scale, bool sticky)
  675. {
  676. if (--scale < 0)
  677. Number.ThrowOverflowException(TypeCode.Decimal);
  678. Debug.Assert(bufQuo.U2 == 0);
  679. // We have overflown, so load the high bit with a one.
  680. const ulong highbit = 1UL << 32;
  681. bufQuo.U2 = (uint)(highbit / 10);
  682. ulong tmp = ((highbit % 10) << 32) + bufQuo.U1;
  683. uint div = (uint)(tmp / 10);
  684. bufQuo.U1 = div;
  685. tmp = ((tmp - div * 10) << 32) + bufQuo.U0;
  686. div = (uint)(tmp / 10);
  687. bufQuo.U0 = div;
  688. uint remainder = (uint)(tmp - div * 10);
  689. // The remainder is the last digit that does not fit, so we can use it to work out if we need to round up
  690. if (remainder > 5 || remainder == 5 && (sticky || (bufQuo.U0 & 1) != 0))
  691. Add32To96(ref bufQuo, 1);
  692. return scale;
  693. }
  694. /// <summary>
  695. /// Determine the max power of 10, &lt;= 9, that the quotient can be scaled
  696. /// up by and still fit in 96 bits.
  697. /// </summary>
  698. /// <param name="bufQuo">96-bit quotient</param>
  699. /// <param name="scale ">Scale factor of quotient, range -DEC_SCALE_MAX to DEC_SCALE_MAX-1</param>
  700. /// <returns>power of 10 to scale by</returns>
  701. private static int SearchScale(ref Buf12 bufQuo, int scale)
  702. {
  703. const uint OVFL_MAX_9_HI = 4;
  704. const uint OVFL_MAX_8_HI = 42;
  705. const uint OVFL_MAX_7_HI = 429;
  706. const uint OVFL_MAX_6_HI = 4294;
  707. const uint OVFL_MAX_5_HI = 42949;
  708. const uint OVFL_MAX_4_HI = 429496;
  709. const uint OVFL_MAX_3_HI = 4294967;
  710. const uint OVFL_MAX_2_HI = 42949672;
  711. const uint OVFL_MAX_1_HI = 429496729;
  712. const ulong OVFL_MAX_9_MIDLO = 5441186219426131129;
  713. uint resHi = bufQuo.U2;
  714. ulong resMidLo = bufQuo.Low64;
  715. int curScale = 0;
  716. // Quick check to stop us from trying to scale any more.
  717. //
  718. if (resHi > OVFL_MAX_1_HI)
  719. {
  720. goto HaveScale;
  721. }
  722. var powerOvfl = PowerOvflValues;
  723. if (scale > DEC_SCALE_MAX - 9)
  724. {
  725. // We can't scale by 10^9 without exceeding the max scale factor.
  726. // See if we can scale to the max. If not, we'll fall into
  727. // standard search for scale factor.
  728. //
  729. curScale = DEC_SCALE_MAX - scale;
  730. if (resHi < powerOvfl[curScale - 1].Hi)
  731. goto HaveScale;
  732. }
  733. else if (resHi < OVFL_MAX_9_HI || resHi == OVFL_MAX_9_HI && resMidLo <= OVFL_MAX_9_MIDLO)
  734. return 9;
  735. // Search for a power to scale by < 9. Do a binary search.
  736. //
  737. if (resHi > OVFL_MAX_5_HI)
  738. {
  739. if (resHi > OVFL_MAX_3_HI)
  740. {
  741. curScale = 2;
  742. if (resHi > OVFL_MAX_2_HI)
  743. curScale--;
  744. }
  745. else
  746. {
  747. curScale = 4;
  748. if (resHi > OVFL_MAX_4_HI)
  749. curScale--;
  750. }
  751. }
  752. else
  753. {
  754. if (resHi > OVFL_MAX_7_HI)
  755. {
  756. curScale = 6;
  757. if (resHi > OVFL_MAX_6_HI)
  758. curScale--;
  759. }
  760. else
  761. {
  762. curScale = 8;
  763. if (resHi > OVFL_MAX_8_HI)
  764. curScale--;
  765. }
  766. }
  767. // In all cases, we already found we could not use the power one larger.
  768. // So if we can use this power, it is the biggest, and we're done. If
  769. // we can't use this power, the one below it is correct for all cases
  770. // unless it's 10^1 -- we might have to go to 10^0 (no scaling).
  771. //
  772. if (resHi == powerOvfl[curScale - 1].Hi && resMidLo > powerOvfl[curScale - 1].MidLo)
  773. curScale--;
  774. HaveScale:
  775. // curScale = largest power of 10 we can scale by without overflow,
  776. // curScale < 9. See if this is enough to make scale factor
  777. // positive if it isn't already.
  778. //
  779. if (curScale + scale < 0)
  780. Number.ThrowOverflowException(TypeCode.Decimal);
  781. return curScale;
  782. }
  783. /// <summary>
  784. /// Add a 32-bit uint to an array of 3 uints representing a 96-bit integer.
  785. /// </summary>
  786. /// <returns>Returns false if there is an overflow</returns>
  787. private static bool Add32To96(ref Buf12 bufNum, uint value)
  788. {
  789. if ((bufNum.Low64 += value) < value)
  790. {
  791. if (++bufNum.U2 == 0)
  792. return false;
  793. }
  794. return true;
  795. }
  796. /// <summary>
  797. /// Adds or subtracts two decimal values.
  798. /// On return, d1 contains the result of the operation and d2 is trashed.
  799. /// </summary>
  800. /// <param name="sign">True means subtract and false means add.</param>
  801. internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign)
  802. {
  803. ulong low64 = d1.Low64;
  804. uint high = d1.High, flags = d1.uflags, d2flags = d2.uflags;
  805. uint xorflags = d2flags ^ flags;
  806. sign ^= (xorflags & SignMask) != 0;
  807. if ((xorflags & ScaleMask) == 0)
  808. {
  809. // Scale factors are equal, no alignment necessary.
  810. //
  811. goto AlignedAdd;
  812. }
  813. else
  814. {
  815. // Scale factors are not equal. Assume that a larger scale
  816. // factor (more decimal places) is likely to mean that number
  817. // is smaller. Start by guessing that the right operand has
  818. // the larger scale factor. The result will have the larger
  819. // scale factor.
  820. //
  821. uint d1flags = flags;
  822. flags = d2flags & ScaleMask | flags & SignMask; // scale factor of "smaller", but sign of "larger"
  823. int scale = (int)(flags - d1flags) >> ScaleShift;
  824. if (scale < 0)
  825. {
  826. // Guessed scale factor wrong. Swap operands.
  827. //
  828. scale = -scale;
  829. flags = d1flags;
  830. if (sign)
  831. flags ^= SignMask;
  832. low64 = d2.Low64;
  833. high = d2.High;
  834. d2 = d1;
  835. }
  836. uint power;
  837. ulong tmp64, tmpLow;
  838. // d1 will need to be multiplied by 10^scale so
  839. // it will have the same scale as d2. We could be
  840. // extending it to up to 192 bits of precision.
  841. // Scan for zeros in the upper words.
  842. //
  843. if (high == 0)
  844. {
  845. if (low64 <= uint.MaxValue)
  846. {
  847. if ((uint)low64 == 0)
  848. {
  849. // Left arg is zero, return right.
  850. //
  851. uint signFlags = flags & SignMask;
  852. if (sign)
  853. signFlags ^= SignMask;
  854. d1 = d2;
  855. d1.uflags = d2.uflags & ScaleMask | signFlags;
  856. return;
  857. }
  858. do
  859. {
  860. if (scale <= MaxInt32Scale)
  861. {
  862. low64 = UInt32x32To64((uint)low64, s_powers10[scale]);
  863. goto AlignedAdd;
  864. }
  865. scale -= MaxInt32Scale;
  866. low64 = UInt32x32To64((uint)low64, TenToPowerNine);
  867. } while (low64 <= uint.MaxValue);
  868. }
  869. do
  870. {
  871. power = TenToPowerNine;
  872. if (scale < MaxInt32Scale)
  873. power = s_powers10[scale];
  874. tmpLow = UInt32x32To64((uint)low64, power);
  875. tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
  876. low64 = (uint)tmpLow + (tmp64 << 32);
  877. high = (uint)(tmp64 >> 32);
  878. if ((scale -= MaxInt32Scale) <= 0)
  879. goto AlignedAdd;
  880. } while (high == 0);
  881. }
  882. while (true)
  883. {
  884. // Scaling won't make it larger than 4 uints
  885. //
  886. power = TenToPowerNine;
  887. if (scale < MaxInt32Scale)
  888. power = s_powers10[scale];
  889. tmpLow = UInt32x32To64((uint)low64, power);
  890. tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
  891. low64 = (uint)tmpLow + (tmp64 << 32);
  892. tmp64 >>= 32;
  893. tmp64 += UInt32x32To64(high, power);
  894. scale -= MaxInt32Scale;
  895. if (tmp64 > uint.MaxValue)
  896. break;
  897. high = (uint)tmp64;
  898. // Result fits in 96 bits. Use standard aligned add.
  899. if (scale <= 0)
  900. goto AlignedAdd;
  901. }
  902. // Have to scale by a bunch. Move the number to a buffer where it has room to grow as it's scaled.
  903. //
  904. Buf24 bufNum;
  905. _ = &bufNum; // workaround for CS0165
  906. bufNum.Low64 = low64;
  907. bufNum.Mid64 = tmp64;
  908. uint hiProd = 3;
  909. // Scaling loop, up to 10^9 at a time. hiProd stays updated with index of highest non-zero uint.
  910. //
  911. for (; scale > 0; scale -= MaxInt32Scale)
  912. {
  913. power = TenToPowerNine;
  914. if (scale < MaxInt32Scale)
  915. power = s_powers10[scale];
  916. tmp64 = 0;
  917. uint* rgulNum = (uint*)&bufNum;
  918. for (uint cur = 0; ;)
  919. {
  920. Debug.Assert(cur < bufNum.Length);
  921. tmp64 += UInt32x32To64(rgulNum[cur], power);
  922. rgulNum[cur] = (uint)tmp64;
  923. cur++;
  924. tmp64 >>= 32;
  925. if (cur > hiProd)
  926. break;
  927. }
  928. if ((uint)tmp64 != 0)
  929. {
  930. // We're extending the result by another uint.
  931. Debug.Assert(hiProd + 1 < bufNum.Length);
  932. rgulNum[++hiProd] = (uint)tmp64;
  933. }
  934. }
  935. // Scaling complete, do the add. Could be subtract if signs differ.
  936. //
  937. tmp64 = bufNum.Low64;
  938. low64 = d2.Low64;
  939. uint tmpHigh = bufNum.U2;
  940. high = d2.High;
  941. if (sign)
  942. {
  943. // Signs differ, subtract.
  944. //
  945. low64 = tmp64 - low64;
  946. high = tmpHigh - high;
  947. // Propagate carry
  948. //
  949. if (low64 > tmp64)
  950. {
  951. high--;
  952. if (high < tmpHigh)
  953. goto NoCarry;
  954. }
  955. else if (high <= tmpHigh)
  956. goto NoCarry;
  957. // Carry the subtraction into the higher bits.
  958. //
  959. uint* number = (uint*)&bufNum;
  960. uint cur = 3;
  961. do
  962. {
  963. Debug.Assert(cur < bufNum.Length);
  964. } while (number[cur++]-- == 0);
  965. Debug.Assert(hiProd < bufNum.Length);
  966. if (number[hiProd] == 0 && --hiProd <= 2)
  967. goto ReturnResult;
  968. }
  969. else
  970. {
  971. // Signs the same, add.
  972. //
  973. low64 += tmp64;
  974. high += tmpHigh;
  975. // Propagate carry
  976. //
  977. if (low64 < tmp64)
  978. {
  979. high++;
  980. if (high > tmpHigh)
  981. goto NoCarry;
  982. }
  983. else if (high >= tmpHigh)
  984. goto NoCarry;
  985. uint* number = (uint*)&bufNum;
  986. for (uint cur = 3; ++number[cur++] == 0;)
  987. {
  988. Debug.Assert(cur < bufNum.Length);
  989. if (hiProd < cur)
  990. {
  991. number[cur] = 1;
  992. hiProd = cur;
  993. break;
  994. }
  995. }
  996. }
  997. NoCarry:
  998. bufNum.Low64 = low64;
  999. bufNum.U2 = high;
  1000. scale = ScaleResult(&bufNum, hiProd, (byte)(flags >> ScaleShift));
  1001. flags = (flags & ~ScaleMask) | ((uint)scale << ScaleShift);
  1002. low64 = bufNum.Low64;
  1003. high = bufNum.U2;
  1004. goto ReturnResult;
  1005. }
  1006. SignFlip:
  1007. {
  1008. // Got negative result. Flip its sign.
  1009. flags ^= SignMask;
  1010. high = ~high;
  1011. low64 = (ulong)-(long)low64;
  1012. if (low64 == 0)
  1013. high++;
  1014. goto ReturnResult;
  1015. }
  1016. AlignedScale:
  1017. {
  1018. // The addition carried above 96 bits.
  1019. // Divide the value by 10, dropping the scale factor.
  1020. //
  1021. if ((flags & ScaleMask) == 0)
  1022. Number.ThrowOverflowException(TypeCode.Decimal);
  1023. flags -= 1 << ScaleShift;
  1024. const uint den = 10;
  1025. ulong num = high + (1UL << 32);
  1026. high = (uint)(num / den);
  1027. num = ((num - high * den) << 32) + (low64 >> 32);
  1028. uint div = (uint)(num / den);
  1029. num = ((num - div * den) << 32) + (uint)low64;
  1030. low64 = div;
  1031. low64 <<= 32;
  1032. div = (uint)(num / den);
  1033. low64 += div;
  1034. div = (uint)num - div * den;
  1035. // See if we need to round up.
  1036. //
  1037. if (div >= 5 && (div > 5 || (low64 & 1) != 0))
  1038. {
  1039. if (++low64 == 0)
  1040. high++;
  1041. }
  1042. goto ReturnResult;
  1043. }
  1044. AlignedAdd:
  1045. {
  1046. ulong d1Low64 = low64;
  1047. uint d1High = high;
  1048. if (sign)
  1049. {
  1050. // Signs differ - subtract
  1051. //
  1052. low64 = d1Low64 - d2.Low64;
  1053. high = d1High - d2.High;
  1054. // Propagate carry
  1055. //
  1056. if (low64 > d1Low64)
  1057. {
  1058. high--;
  1059. if (high >= d1High)
  1060. goto SignFlip;
  1061. }
  1062. else if (high > d1High)
  1063. goto SignFlip;
  1064. }
  1065. else
  1066. {
  1067. // Signs are the same - add
  1068. //
  1069. low64 = d1Low64 + d2.Low64;
  1070. high = d1High + d2.High;
  1071. // Propagate carry
  1072. //
  1073. if (low64 < d1Low64)
  1074. {
  1075. high++;
  1076. if (high <= d1High)
  1077. goto AlignedScale;
  1078. }
  1079. else if (high < d1High)
  1080. goto AlignedScale;
  1081. }
  1082. goto ReturnResult;
  1083. }
  1084. ReturnResult:
  1085. d1.uflags = flags;
  1086. d1.High = high;
  1087. d1.Low64 = low64;
  1088. return;
  1089. }
  1090. #endregion
  1091. /// <summary>
  1092. /// Convert Decimal to Currency (similar to OleAut32 api.)
  1093. /// </summary>
  1094. internal static long VarCyFromDec(ref DecCalc pdecIn)
  1095. {
  1096. long value;
  1097. int scale = pdecIn.Scale - 4;
  1098. // Need to scale to get 4 decimal places. -4 <= scale <= 24.
  1099. //
  1100. if (scale < 0)
  1101. {
  1102. if (pdecIn.High != 0)
  1103. goto ThrowOverflow;
  1104. uint pwr = s_powers10[-scale];
  1105. ulong high = UInt32x32To64(pwr, pdecIn.Mid);
  1106. if (high > uint.MaxValue)
  1107. goto ThrowOverflow;
  1108. ulong low = UInt32x32To64(pwr, pdecIn.Low);
  1109. low += high <<= 32;
  1110. if (low < high)
  1111. goto ThrowOverflow;
  1112. value = (long)low;
  1113. }
  1114. else
  1115. {
  1116. if (scale != 0)
  1117. InternalRound(ref pdecIn, (uint)scale, RoundingMode.ToEven);
  1118. if (pdecIn.High != 0)
  1119. goto ThrowOverflow;
  1120. value = (long)pdecIn.Low64;
  1121. }
  1122. if (value < 0 && (value != long.MinValue || !pdecIn.IsNegative))
  1123. goto ThrowOverflow;
  1124. if (pdecIn.IsNegative)
  1125. value = -value;
  1126. return value;
  1127. ThrowOverflow:
  1128. throw new OverflowException(SR.Overflow_Currency);
  1129. }
  1130. /// <summary>
  1131. /// Decimal Compare updated to return values similar to ICompareTo
  1132. /// </summary>
  1133. internal static int VarDecCmp(in decimal d1, in decimal d2)
  1134. {
  1135. if ((d2.Low | d2.Mid | d2.High) == 0)
  1136. {
  1137. if ((d1.Low | d1.Mid | d1.High) == 0)
  1138. return 0;
  1139. return (d1.flags >> 31) | 1;
  1140. }
  1141. if ((d1.Low | d1.Mid | d1.High) == 0)
  1142. return -((d2.flags >> 31) | 1);
  1143. int sign = (d1.flags >> 31) - (d2.flags >> 31);
  1144. if (sign != 0)
  1145. return sign;
  1146. return VarDecCmpSub(in d1, in d2);
  1147. }
  1148. private static int VarDecCmpSub(in decimal d1, in decimal d2)
  1149. {
  1150. int flags = d2.flags;
  1151. int sign = (flags >> 31) | 1;
  1152. int scale = flags - d1.flags;
  1153. ulong low64 = d1.Low64;
  1154. uint high = d1.High;
  1155. ulong d2Low64 = d2.Low64;
  1156. uint d2High = d2.High;
  1157. if (scale != 0)
  1158. {
  1159. scale >>= ScaleShift;
  1160. // Scale factors are not equal. Assume that a larger scale factor (more decimal places) is likely to mean that number is smaller.
  1161. // Start by guessing that the right operand has the larger scale factor.
  1162. if (scale < 0)
  1163. {
  1164. // Guessed scale factor wrong. Swap operands.
  1165. scale = -scale;
  1166. sign = -sign;
  1167. ulong tmp64 = low64;
  1168. low64 = d2Low64;
  1169. d2Low64 = tmp64;
  1170. uint tmp = high;
  1171. high = d2High;
  1172. d2High = tmp;
  1173. }
  1174. // d1 will need to be multiplied by 10^scale so it will have the same scale as d2.
  1175. // Scaling loop, up to 10^9 at a time.
  1176. do
  1177. {
  1178. uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale];
  1179. ulong tmpLow = UInt32x32To64((uint)low64, power);
  1180. ulong tmp = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
  1181. low64 = (uint)tmpLow + (tmp << 32);
  1182. tmp >>= 32;
  1183. tmp += UInt32x32To64(high, power);
  1184. // If the scaled value has more than 96 significant bits then it's greater than d2
  1185. if (tmp > uint.MaxValue)
  1186. return sign;
  1187. high = (uint)tmp;
  1188. } while ((scale -= MaxInt32Scale) > 0);
  1189. }
  1190. uint cmpHigh = high - d2High;
  1191. if (cmpHigh != 0)
  1192. {
  1193. // check for overflow
  1194. if (cmpHigh > high)
  1195. sign = -sign;
  1196. return sign;
  1197. }
  1198. ulong cmpLow64 = low64 - d2Low64;
  1199. if (cmpLow64 == 0)
  1200. sign = 0;
  1201. // check for overflow
  1202. else if (cmpLow64 > low64)
  1203. sign = -sign;
  1204. return sign;
  1205. }
  1206. /// <summary>
  1207. /// Decimal Multiply
  1208. /// </summary>
  1209. internal static unsafe void VarDecMul(ref DecCalc d1, ref DecCalc d2)
  1210. {
  1211. int scale = (byte)(d1.uflags + d2.uflags >> ScaleShift);
  1212. ulong tmp;
  1213. uint hiProd;
  1214. Buf24 bufProd;
  1215. _ = &bufProd; // workaround for CS0165
  1216. if ((d1.High | d1.Mid) == 0)
  1217. {
  1218. if ((d2.High | d2.Mid) == 0)
  1219. {
  1220. // Upper 64 bits are zero.
  1221. //
  1222. ulong low64 = UInt32x32To64(d1.Low, d2.Low);
  1223. if (scale > DEC_SCALE_MAX)
  1224. {
  1225. // Result scale is too big. Divide result by power of 10 to reduce it.
  1226. // If the amount to divide by is > 19 the result is guaranteed
  1227. // less than 1/2. [max value in 64 bits = 1.84E19]
  1228. //
  1229. if (scale > DEC_SCALE_MAX + MaxInt64Scale)
  1230. goto ReturnZero;
  1231. scale -= DEC_SCALE_MAX + 1;
  1232. ulong power = s_ulongPowers10[scale];
  1233. // TODO: https://github.com/dotnet/coreclr/issues/3439
  1234. tmp = low64 / power;
  1235. ulong remainder = low64 - tmp * power;
  1236. low64 = tmp;
  1237. // Round result. See if remainder >= 1/2 of divisor.
  1238. // Divisor is a power of 10, so it is always even.
  1239. //
  1240. power >>= 1;
  1241. if (remainder >= power && (remainder > power || ((uint)low64 & 1) > 0))
  1242. low64++;
  1243. scale = DEC_SCALE_MAX;
  1244. }
  1245. d1.Low64 = low64;
  1246. d1.uflags = ((d2.uflags ^ d1.uflags) & SignMask) | ((uint)scale << ScaleShift);
  1247. return;
  1248. }
  1249. else
  1250. {
  1251. // Left value is 32-bit, result fits in 4 uints
  1252. tmp = UInt32x32To64(d1.Low, d2.Low);
  1253. bufProd.U0 = (uint)tmp;
  1254. tmp = UInt32x32To64(d1.Low, d2.Mid) + (tmp >> 32);
  1255. bufProd.U1 = (uint)tmp;
  1256. tmp >>= 32;
  1257. if (d2.High != 0)
  1258. {
  1259. tmp += UInt32x32To64(d1.Low, d2.High);
  1260. if (tmp > uint.MaxValue)
  1261. {
  1262. bufProd.Mid64 = tmp;
  1263. hiProd = 3;
  1264. goto SkipScan;
  1265. }
  1266. }
  1267. if ((uint)tmp != 0)
  1268. {
  1269. bufProd.U2 = (uint)tmp;
  1270. hiProd = 2;
  1271. goto SkipScan;
  1272. }
  1273. hiProd = 1;
  1274. }
  1275. }
  1276. else if ((d2.High | d2.Mid) == 0)
  1277. {
  1278. // Right value is 32-bit, result fits in 4 uints
  1279. tmp = UInt32x32To64(d2.Low, d1.Low);
  1280. bufProd.U0 = (uint)tmp;
  1281. tmp = UInt32x32To64(d2.Low, d1.Mid) + (tmp >> 32);
  1282. bufProd.U1 = (uint)tmp;
  1283. tmp >>= 32;
  1284. if (d1.High != 0)
  1285. {
  1286. tmp += UInt32x32To64(d2.Low, d1.High);
  1287. if (tmp > uint.MaxValue)
  1288. {
  1289. bufProd.Mid64 = tmp;
  1290. hiProd = 3;
  1291. goto SkipScan;
  1292. }
  1293. }
  1294. if ((uint)tmp != 0)
  1295. {
  1296. bufProd.U2 = (uint)tmp;
  1297. hiProd = 2;
  1298. goto SkipScan;
  1299. }
  1300. hiProd = 1;
  1301. }
  1302. else
  1303. {
  1304. // Both operands have bits set in the upper 64 bits.
  1305. //
  1306. // Compute and accumulate the 9 partial products into a
  1307. // 192-bit (24-byte) result.
  1308. //
  1309. // [l-h][l-m][l-l] left high, middle, low
  1310. // x [r-h][r-m][r-l] right high, middle, low
  1311. // ------------------------------
  1312. //
  1313. // [0-h][0-l] l-l * r-l
  1314. // [1ah][1al] l-l * r-m
  1315. // [1bh][1bl] l-m * r-l
  1316. // [2ah][2al] l-m * r-m
  1317. // [2bh][2bl] l-l * r-h
  1318. // [2ch][2cl] l-h * r-l
  1319. // [3ah][3al] l-m * r-h
  1320. // [3bh][3bl] l-h * r-m
  1321. // [4-h][4-l] l-h * r-h
  1322. // ------------------------------
  1323. // [p-5][p-4][p-3][p-2][p-1][p-0] prod[] array
  1324. //
  1325. tmp = UInt32x32To64(d1.Low, d2.Low);
  1326. bufProd.U0 = (uint)tmp;
  1327. ulong tmp2 = UInt32x32To64(d1.Low, d2.Mid) + (tmp >> 32);
  1328. tmp = UInt32x32To64(d1.Mid, d2.Low);
  1329. tmp += tmp2; // this could generate carry
  1330. bufProd.U1 = (uint)tmp;
  1331. if (tmp < tmp2) // detect carry
  1332. tmp2 = (tmp >> 32) | (1UL << 32);
  1333. else
  1334. tmp2 = tmp >> 32;
  1335. tmp = UInt32x32To64(d1.Mid, d2.Mid) + tmp2;
  1336. if ((d1.High | d2.High) > 0)
  1337. {
  1338. // Highest 32 bits is non-zero. Calculate 5 more partial products.
  1339. //
  1340. tmp2 = UInt32x32To64(d1.Low, d2.High);
  1341. tmp += tmp2; // this could generate carry
  1342. uint tmp3 = 0;
  1343. if (tmp < tmp2) // detect carry
  1344. tmp3 = 1;
  1345. tmp2 = UInt32x32To64(d1.High, d2.Low);
  1346. tmp += tmp2; // this could generate carry
  1347. bufProd.U2 = (uint)tmp;
  1348. if (tmp < tmp2) // detect carry
  1349. tmp3++;
  1350. tmp2 = ((ulong)tmp3 << 32) | (tmp >> 32);
  1351. tmp = UInt32x32To64(d1.Mid, d2.High);
  1352. tmp += tmp2; // this could generate carry
  1353. tmp3 = 0;
  1354. if (tmp < tmp2) // detect carry
  1355. tmp3 = 1;
  1356. tmp2 = UInt32x32To64(d1.High, d2.Mid);
  1357. tmp += tmp2; // this could generate carry
  1358. bufProd.U3 = (uint)tmp;
  1359. if (tmp < tmp2) // detect carry
  1360. tmp3++;
  1361. tmp = ((ulong)tmp3 << 32) | (tmp >> 32);
  1362. bufProd.High64 = UInt32x32To64(d1.High, d2.High) + tmp;
  1363. hiProd = 5;
  1364. }
  1365. else if (tmp != 0)
  1366. {
  1367. bufProd.Mid64 = tmp;
  1368. hiProd = 3;
  1369. }
  1370. else
  1371. hiProd = 1;
  1372. }
  1373. // Check for leading zero uints on the product
  1374. //
  1375. uint* product = (uint*)&bufProd;
  1376. while (product[(int)hiProd] == 0)
  1377. {
  1378. if (hiProd == 0)
  1379. goto ReturnZero;
  1380. hiProd--;
  1381. }
  1382. SkipScan:
  1383. if (hiProd > 2 || scale > DEC_SCALE_MAX)
  1384. {
  1385. scale = ScaleResult(&bufProd, hiProd, scale);
  1386. }
  1387. d1.Low64 = bufProd.Low64;
  1388. d1.High = bufProd.U2;
  1389. d1.uflags = ((d2.uflags ^ d1.uflags) & SignMask) | ((uint)scale << ScaleShift);
  1390. return;
  1391. ReturnZero:
  1392. d1 = default;
  1393. }
  1394. /// <summary>
  1395. /// Convert float to Decimal
  1396. /// </summary>
  1397. internal static void VarDecFromR4(float input, out DecCalc result)
  1398. {
  1399. result = default;
  1400. // The most we can scale by is 10^28, which is just slightly more
  1401. // than 2^93. So a float with an exponent of -94 could just
  1402. // barely reach 0.5, but smaller exponents will always round to zero.
  1403. //
  1404. const uint SNGBIAS = 126;
  1405. int exp = (int)(GetExponent(input) - SNGBIAS);
  1406. if (exp < -94)
  1407. return; // result should be zeroed out
  1408. if (exp > 96)
  1409. Number.ThrowOverflowException(TypeCode.Decimal);
  1410. uint flags = 0;
  1411. if (input < 0)
  1412. {
  1413. input = -input;
  1414. flags = SignMask;
  1415. }
  1416. // Round the input to a 7-digit integer. The R4 format has
  1417. // only 7 digits of precision, and we want to keep garbage digits
  1418. // out of the Decimal were making.
  1419. //
  1420. // Calculate max power of 10 input value could have by multiplying
  1421. // the exponent by log10(2). Using scaled integer multiplcation,
  1422. // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
  1423. //
  1424. double dbl = input;
  1425. int power = 6 - ((exp * 19728) >> 16);
  1426. // power is between -22 and 35
  1427. if (power >= 0)
  1428. {
  1429. // We have less than 7 digits, scale input up.
  1430. //
  1431. if (power > DEC_SCALE_MAX)
  1432. power = DEC_SCALE_MAX;
  1433. dbl *= s_doublePowers10[power];
  1434. }
  1435. else
  1436. {
  1437. if (power != -1 || dbl >= 1E7)
  1438. dbl /= s_doublePowers10[-power];
  1439. else
  1440. power = 0; // didn't scale it
  1441. }
  1442. Debug.Assert(dbl < 1E7);
  1443. if (dbl < 1E6 && power < DEC_SCALE_MAX)
  1444. {
  1445. dbl *= 10;
  1446. power++;
  1447. Debug.Assert(dbl >= 1E6);
  1448. }
  1449. // Round to integer
  1450. //
  1451. uint mant;
  1452. // with SSE4.1 support ROUNDSD can be used
  1453. if (X86.Sse41.IsSupported)
  1454. mant = (uint)(int)Math.Round(dbl);
  1455. else
  1456. {
  1457. mant = (uint)(int)dbl;
  1458. dbl -= (int)mant; // difference between input & integer
  1459. if (dbl > 0.5 || dbl == 0.5 && (mant & 1) != 0)
  1460. mant++;
  1461. }
  1462. if (mant == 0)
  1463. return; // result should be zeroed out
  1464. if (power < 0)
  1465. {
  1466. // Add -power factors of 10, -power <= (29 - 7) = 22.
  1467. //
  1468. power = -power;
  1469. if (power < 10)
  1470. {
  1471. result.Low64 = UInt32x32To64(mant, s_powers10[power]);
  1472. }
  1473. else
  1474. {
  1475. // Have a big power of 10.
  1476. //
  1477. if (power > 18)
  1478. {
  1479. ulong low64 = UInt32x32To64(mant, s_powers10[power - 18]);
  1480. UInt64x64To128(low64, TenToPowerEighteen, ref result);
  1481. }
  1482. else
  1483. {
  1484. ulong low64 = UInt32x32To64(mant, s_powers10[power - 9]);
  1485. ulong hi64 = UInt32x32To64(TenToPowerNine, (uint)(low64 >> 32));
  1486. low64 = UInt32x32To64(TenToPowerNine, (uint)low64);
  1487. result.Low = (uint)low64;
  1488. hi64 += low64 >> 32;
  1489. result.Mid = (uint)hi64;
  1490. hi64 >>= 32;
  1491. result.High = (uint)hi64;
  1492. }
  1493. }
  1494. }
  1495. else
  1496. {
  1497. // Factor out powers of 10 to reduce the scale, if possible.
  1498. // The maximum number we could factor out would be 6. This
  1499. // comes from the fact we have a 7-digit number, and the
  1500. // MSD must be non-zero -- but the lower 6 digits could be
  1501. // zero. Note also the scale factor is never negative, so
  1502. // we can't scale by any more than the power we used to
  1503. // get the integer.
  1504. //
  1505. int lmax = power;
  1506. if (lmax > 6)
  1507. lmax = 6;
  1508. if ((mant & 0xF) == 0 && lmax >= 4)
  1509. {
  1510. const uint den = 10000;
  1511. uint div = mant / den;
  1512. if (mant == div * den)
  1513. {
  1514. mant = div;
  1515. power -= 4;
  1516. lmax -= 4;
  1517. }
  1518. }
  1519. if ((mant & 3) == 0 && lmax >= 2)
  1520. {
  1521. const uint den = 100;
  1522. uint div = mant / den;
  1523. if (mant == div * den)
  1524. {
  1525. mant = div;
  1526. power -= 2;
  1527. lmax -= 2;
  1528. }
  1529. }
  1530. if ((mant & 1) == 0 && lmax >= 1)
  1531. {
  1532. const uint den = 10;
  1533. uint div = mant / den;
  1534. if (mant == div * den)
  1535. {
  1536. mant = div;
  1537. power--;
  1538. }
  1539. }
  1540. flags |= (uint)power << ScaleShift;
  1541. result.Low = mant;
  1542. }
  1543. result.uflags = flags;
  1544. }
  1545. /// <summary>
  1546. /// Convert double to Decimal
  1547. /// </summary>
  1548. internal static void VarDecFromR8(double input, out DecCalc result)
  1549. {
  1550. result = default;
  1551. // The most we can scale by is 10^28, which is just slightly more
  1552. // than 2^93. So a float with an exponent of -94 could just
  1553. // barely reach 0.5, but smaller exponents will always round to zero.
  1554. //
  1555. const uint DBLBIAS = 1022;
  1556. int exp = (int)(GetExponent(input) - DBLBIAS);
  1557. if (exp < -94)
  1558. return; // result should be zeroed out
  1559. if (exp > 96)
  1560. Number.ThrowOverflowException(TypeCode.Decimal);
  1561. uint flags = 0;
  1562. if (input < 0)
  1563. {
  1564. input = -input;
  1565. flags = SignMask;
  1566. }
  1567. // Round the input to a 15-digit integer. The R8 format has
  1568. // only 15 digits of precision, and we want to keep garbage digits
  1569. // out of the Decimal were making.
  1570. //
  1571. // Calculate max power of 10 input value could have by multiplying
  1572. // the exponent by log10(2). Using scaled integer multiplcation,
  1573. // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
  1574. //
  1575. double dbl = input;
  1576. int power = 14 - ((exp * 19728) >> 16);
  1577. // power is between -14 and 43
  1578. if (power >= 0)
  1579. {
  1580. // We have less than 15 digits, scale input up.
  1581. //
  1582. if (power > DEC_SCALE_MAX)
  1583. power = DEC_SCALE_MAX;
  1584. dbl *= s_doublePowers10[power];
  1585. }
  1586. else
  1587. {
  1588. if (power != -1 || dbl >= 1E15)
  1589. dbl /= s_doublePowers10[-power];
  1590. else
  1591. power = 0; // didn't scale it
  1592. }
  1593. Debug.Assert(dbl < 1E15);
  1594. if (dbl < 1E14 && power < DEC_SCALE_MAX)
  1595. {
  1596. dbl *= 10;
  1597. power++;
  1598. Debug.Assert(dbl >= 1E14);
  1599. }
  1600. // Round to int64
  1601. //
  1602. ulong mant;
  1603. // with SSE4.1 support ROUNDSD can be used
  1604. if (X86.Sse41.IsSupported)
  1605. mant = (ulong)(long)Math.Round(dbl);
  1606. else
  1607. {
  1608. mant = (ulong)(long)dbl;
  1609. dbl -= (long)mant; // difference between input & integer
  1610. if (dbl > 0.5 || dbl == 0.5 && (mant & 1) != 0)
  1611. mant++;
  1612. }
  1613. if (mant == 0)
  1614. return; // result should be zeroed out
  1615. if (power < 0)
  1616. {
  1617. // Add -power factors of 10, -power <= (29 - 15) = 14.
  1618. //
  1619. power = -power;
  1620. if (power < 10)
  1621. {
  1622. var pow10 = s_powers10[power];
  1623. ulong low64 = UInt32x32To64((uint)mant, pow10);
  1624. ulong hi64 = UInt32x32To64((uint)(mant >> 32), pow10);
  1625. result.Low = (uint)low64;
  1626. hi64 += low64 >> 32;
  1627. result.Mid = (uint)hi64;
  1628. hi64 >>= 32;
  1629. result.High = (uint)hi64;
  1630. }
  1631. else
  1632. {
  1633. // Have a big power of 10.
  1634. //
  1635. Debug.Assert(power <= 14);
  1636. UInt64x64To128(mant, s_ulongPowers10[power - 1], ref result);
  1637. }
  1638. }
  1639. else
  1640. {
  1641. // Factor out powers of 10 to reduce the scale, if possible.
  1642. // The maximum number we could factor out would be 14. This
  1643. // comes from the fact we have a 15-digit number, and the
  1644. // MSD must be non-zero -- but the lower 14 digits could be
  1645. // zero. Note also the scale factor is never negative, so
  1646. // we can't scale by any more than the power we used to
  1647. // get the integer.
  1648. //
  1649. int lmax = power;
  1650. if (lmax > 14)
  1651. lmax = 14;
  1652. if ((byte)mant == 0 && lmax >= 8)
  1653. {
  1654. const uint den = 100000000;
  1655. ulong div = mant / den;
  1656. if ((uint)mant == (uint)(div * den))
  1657. {
  1658. mant = div;
  1659. power -= 8;
  1660. lmax -= 8;
  1661. }
  1662. }
  1663. if (((uint)mant & 0xF) == 0 && lmax >= 4)
  1664. {
  1665. const uint den = 10000;
  1666. ulong div = mant / den;
  1667. if ((uint)mant == (uint)(div * den))
  1668. {
  1669. mant = div;
  1670. power -= 4;
  1671. lmax -= 4;
  1672. }
  1673. }
  1674. if (((uint)mant & 3) == 0 && lmax >= 2)
  1675. {
  1676. const uint den = 100;
  1677. ulong div = mant / den;
  1678. if ((uint)mant == (uint)(div * den))
  1679. {
  1680. mant = div;
  1681. power -= 2;
  1682. lmax -= 2;
  1683. }
  1684. }
  1685. if (((uint)mant & 1) == 0 && lmax >= 1)
  1686. {
  1687. const uint den = 10;
  1688. ulong div = mant / den;
  1689. if ((uint)mant == (uint)(div * den))
  1690. {
  1691. mant = div;
  1692. power--;
  1693. }
  1694. }
  1695. flags |= (uint)power << ScaleShift;
  1696. result.Low64 = mant;
  1697. }
  1698. result.uflags = flags;
  1699. }
  1700. /// <summary>
  1701. /// Convert Decimal to float
  1702. /// </summary>
  1703. internal static float VarR4FromDec(in decimal value)
  1704. {
  1705. return (float)VarR8FromDec(in value);
  1706. }
  1707. /// <summary>
  1708. /// Convert Decimal to double
  1709. /// </summary>
  1710. internal static double VarR8FromDec(in decimal value)
  1711. {
  1712. // Value taken via reverse engineering the double that corresponds to 2^64. (oleaut32 has ds2to64 = DEFDS(0, 0, DBLBIAS + 65, 0))
  1713. const double ds2to64 = 1.8446744073709552e+019;
  1714. double dbl = ((double)value.Low64 +
  1715. (double)value.High * ds2to64) / s_doublePowers10[value.Scale];
  1716. if (value.IsNegative)
  1717. dbl = -dbl;
  1718. return dbl;
  1719. }
  1720. internal static int GetHashCode(in decimal d)
  1721. {
  1722. if ((d.Low | d.Mid | d.High) == 0)
  1723. return 0;
  1724. uint flags = (uint)d.flags;
  1725. if ((flags & ScaleMask) == 0 || (d.Low & 1) != 0)
  1726. return (int)(flags ^ d.High ^ d.Mid ^ d.Low);
  1727. int scale = (byte)(flags >> ScaleShift);
  1728. uint low = d.Low;
  1729. ulong high64 = ((ulong)d.High << 32) | d.Mid;
  1730. Unscale(ref low, ref high64, ref scale);
  1731. flags = ((flags) & ~ScaleMask) | (uint)scale << ScaleShift;
  1732. return (int)(flags ^ (uint)(high64 >> 32) ^ (uint)high64 ^ low);
  1733. }
  1734. /// <summary>
  1735. /// Divides two decimal values.
  1736. /// On return, d1 contains the result of the operation.
  1737. /// </summary>
  1738. internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2)
  1739. {
  1740. Buf12 bufQuo;
  1741. _ = &bufQuo; // workaround for CS0165
  1742. uint power;
  1743. int curScale;
  1744. int scale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
  1745. bool unscale = false;
  1746. uint tmp;
  1747. if ((d2.High | d2.Mid) == 0)
  1748. {
  1749. // Divisor is only 32 bits. Easy divide.
  1750. //
  1751. uint den = d2.Low;
  1752. if (den == 0)
  1753. throw new DivideByZeroException();
  1754. bufQuo.Low64 = d1.Low64;
  1755. bufQuo.U2 = d1.High;
  1756. uint remainder = Div96By32(ref bufQuo, den);
  1757. for (;;)
  1758. {
  1759. if (remainder == 0)
  1760. {
  1761. if (scale < 0)
  1762. {
  1763. curScale = Math.Min(9, -scale);
  1764. goto HaveScale;
  1765. }
  1766. break;
  1767. }
  1768. // We need to unscale if and only if we have a non-zero remainder
  1769. unscale = true;
  1770. // We have computed a quotient based on the natural scale
  1771. // ( <dividend scale> - <divisor scale> ). We have a non-zero
  1772. // remainder, so now we should increase the scale if possible to
  1773. // include more quotient bits.
  1774. //
  1775. // If it doesn't cause overflow, we'll loop scaling by 10^9 and
  1776. // computing more quotient bits as long as the remainder stays
  1777. // non-zero. If scaling by that much would cause overflow, we'll
  1778. // drop out of the loop and scale by as much as we can.
  1779. //
  1780. // Scaling by 10^9 will overflow if bufQuo[2].bufQuo[1] >= 2^32 / 10^9
  1781. // = 4.294 967 296. So the upper limit is bufQuo[2] == 4 and
  1782. // bufQuo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since
  1783. // quotient bits in bufQuo[0] could be all 1's, then 1,266,874,888
  1784. // is the largest value in bufQuo[1] (when bufQuo[2] == 4) that is
  1785. // assured not to overflow.
  1786. //
  1787. if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
  1788. {
  1789. // No more scaling to be done, but remainder is non-zero.
  1790. // Round quotient.
  1791. //
  1792. tmp = remainder << 1;
  1793. if (tmp < remainder || tmp >= den && (tmp > den || (bufQuo.U0 & 1) != 0))
  1794. goto RoundUp;
  1795. break;
  1796. }
  1797. HaveScale:
  1798. power = s_powers10[curScale];
  1799. scale += curScale;
  1800. if (IncreaseScale(ref bufQuo, power) != 0)
  1801. goto ThrowOverflow;
  1802. ulong num = UInt32x32To64(remainder, power);
  1803. // TODO: https://github.com/dotnet/coreclr/issues/3439
  1804. uint div = (uint)(num / den);
  1805. remainder = (uint)num - div * den;
  1806. if (!Add32To96(ref bufQuo, div))
  1807. {
  1808. scale = OverflowUnscale(ref bufQuo, scale, remainder != 0);
  1809. break;
  1810. }
  1811. } // for (;;)
  1812. }
  1813. else
  1814. {
  1815. // Divisor has bits set in the upper 64 bits.
  1816. //
  1817. // Divisor must be fully normalized (shifted so bit 31 of the most
  1818. // significant uint is 1). Locate the MSB so we know how much to
  1819. // normalize by. The dividend will be shifted by the same amount so
  1820. // the quotient is not changed.
  1821. //
  1822. tmp = d2.High;
  1823. if (tmp == 0)
  1824. tmp = d2.Mid;
  1825. curScale = X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(tmp) : LeadingZeroCount(tmp);
  1826. // Shift both dividend and divisor left by curScale.
  1827. //
  1828. Buf16 bufRem;
  1829. _ = &bufRem; // workaround for CS0165
  1830. bufRem.Low64 = d1.Low64 << curScale;
  1831. bufRem.High64 = (d1.Mid + ((ulong)d1.High << 32)) >> (32 - curScale);
  1832. ulong divisor = d2.Low64 << curScale;
  1833. if (d2.High == 0)
  1834. {
  1835. // Have a 64-bit divisor in sdlDivisor. The remainder
  1836. // (currently 96 bits spread over 4 uints) will be < divisor.
  1837. //
  1838. bufQuo.U1 = Div96By64(ref *(Buf12*)&bufRem.U1, divisor);
  1839. bufQuo.U0 = Div96By64(ref *(Buf12*)&bufRem, divisor);
  1840. for (;;)
  1841. {
  1842. if (bufRem.Low64 == 0)
  1843. {
  1844. if (scale < 0)
  1845. {
  1846. curScale = Math.Min(9, -scale);
  1847. goto HaveScale64;
  1848. }
  1849. break;
  1850. }
  1851. // We need to unscale if and only if we have a non-zero remainder
  1852. unscale = true;
  1853. // Remainder is non-zero. Scale up quotient and remainder by
  1854. // powers of 10 so we can compute more significant bits.
  1855. //
  1856. if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
  1857. {
  1858. // No more scaling to be done, but remainder is non-zero.
  1859. // Round quotient.
  1860. //
  1861. ulong tmp64 = bufRem.Low64;
  1862. if ((long)tmp64 < 0 || (tmp64 <<= 1) > divisor ||
  1863. (tmp64 == divisor && (bufQuo.U0 & 1) != 0))
  1864. goto RoundUp;
  1865. break;
  1866. }
  1867. HaveScale64:
  1868. power = s_powers10[curScale];
  1869. scale += curScale;
  1870. if (IncreaseScale(ref bufQuo, power) != 0)
  1871. goto ThrowOverflow;
  1872. IncreaseScale64(ref *(Buf12*)&bufRem, power);
  1873. tmp = Div96By64(ref *(Buf12*)&bufRem, divisor);
  1874. if (!Add32To96(ref bufQuo, tmp))
  1875. {
  1876. scale = OverflowUnscale(ref bufQuo, scale, bufRem.Low64 != 0);
  1877. break;
  1878. }
  1879. } // for (;;)
  1880. }
  1881. else
  1882. {
  1883. // Have a 96-bit divisor in bufDivisor.
  1884. //
  1885. // Start by finishing the shift left by curScale.
  1886. //
  1887. Buf12 bufDivisor;
  1888. _ = &bufDivisor; // workaround for CS0165
  1889. bufDivisor.Low64 = divisor;
  1890. bufDivisor.U2 = (uint)((d2.Mid + ((ulong)d2.High << 32)) >> (32 - curScale));
  1891. // The remainder (currently 96 bits spread over 4 uints) will be < divisor.
  1892. //
  1893. bufQuo.Low64 = Div128By96(ref bufRem, ref bufDivisor);
  1894. for (;;)
  1895. {
  1896. if ((bufRem.Low64 | bufRem.U2) == 0)
  1897. {
  1898. if (scale < 0)
  1899. {
  1900. curScale = Math.Min(9, -scale);
  1901. goto HaveScale96;
  1902. }
  1903. break;
  1904. }
  1905. // We need to unscale if and only if we have a non-zero remainder
  1906. unscale = true;
  1907. // Remainder is non-zero. Scale up quotient and remainder by
  1908. // powers of 10 so we can compute more significant bits.
  1909. //
  1910. if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
  1911. {
  1912. // No more scaling to be done, but remainder is non-zero.
  1913. // Round quotient.
  1914. //
  1915. if ((int)bufRem.U2 < 0)
  1916. {
  1917. goto RoundUp;
  1918. }
  1919. tmp = bufRem.U1 >> 31;
  1920. bufRem.Low64 <<= 1;
  1921. bufRem.U2 = (bufRem.U2 << 1) + tmp;
  1922. if (bufRem.U2 > bufDivisor.U2 || bufRem.U2 == bufDivisor.U2 &&
  1923. (bufRem.Low64 > bufDivisor.Low64 || bufRem.Low64 == bufDivisor.Low64 &&
  1924. (bufQuo.U0 & 1) != 0))
  1925. goto RoundUp;
  1926. break;
  1927. }
  1928. HaveScale96:
  1929. power = s_powers10[curScale];
  1930. scale += curScale;
  1931. if (IncreaseScale(ref bufQuo, power) != 0)
  1932. goto ThrowOverflow;
  1933. bufRem.U3 = IncreaseScale(ref *(Buf12*)&bufRem, power);
  1934. tmp = Div128By96(ref bufRem, ref bufDivisor);
  1935. if (!Add32To96(ref bufQuo, tmp))
  1936. {
  1937. scale = OverflowUnscale(ref bufQuo, scale, (bufRem.Low64 | bufRem.High64) != 0);
  1938. break;
  1939. }
  1940. } // for (;;)
  1941. }
  1942. }
  1943. Unscale:
  1944. if (unscale)
  1945. {
  1946. uint low = bufQuo.U0;
  1947. ulong high64 = bufQuo.High64;
  1948. Unscale(ref low, ref high64, ref scale);
  1949. d1.Low = low;
  1950. d1.Mid = (uint)high64;
  1951. d1.High = (uint)(high64 >> 32);
  1952. }
  1953. else
  1954. {
  1955. d1.Low64 = bufQuo.Low64;
  1956. d1.High = bufQuo.U2;
  1957. }
  1958. d1.uflags = ((d1.uflags ^ d2.uflags) & SignMask) | ((uint)scale << ScaleShift);
  1959. return;
  1960. RoundUp:
  1961. {
  1962. if (++bufQuo.Low64 == 0 && ++bufQuo.U2 == 0)
  1963. {
  1964. scale = OverflowUnscale(ref bufQuo, scale, true);
  1965. }
  1966. goto Unscale;
  1967. }
  1968. ThrowOverflow:
  1969. Number.ThrowOverflowException(TypeCode.Decimal);
  1970. }
  1971. /// <summary>
  1972. /// Computes the remainder between two decimals.
  1973. /// On return, d1 contains the result of the operation and d2 is trashed.
  1974. /// </summary>
  1975. internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2)
  1976. {
  1977. if ((d2.ulo | d2.umid | d2.uhi) == 0)
  1978. throw new DivideByZeroException();
  1979. if ((d1.ulo | d1.umid | d1.uhi) == 0)
  1980. return;
  1981. // In the operation x % y the sign of y does not matter. Result will have the sign of x.
  1982. d2.uflags = (d2.uflags & ~SignMask) | (d1.uflags & SignMask);
  1983. int cmp = VarDecCmpSub(in Unsafe.As<DecCalc, decimal>(ref d1), in Unsafe.As<DecCalc, decimal>(ref d2));
  1984. if (cmp == 0)
  1985. {
  1986. d1.ulo = 0;
  1987. d1.umid = 0;
  1988. d1.uhi = 0;
  1989. if (d2.uflags > d1.uflags)
  1990. d1.uflags = d2.uflags;
  1991. return;
  1992. }
  1993. if ((cmp ^ (int)(d1.uflags & SignMask)) < 0)
  1994. return;
  1995. // The divisor is smaller than the dividend and both are non-zero. Calculate the integer remainder using the larger scaling factor.
  1996. int scale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
  1997. if (scale > 0)
  1998. {
  1999. // Divisor scale can always be increased to dividend scale for remainder calculation.
  2000. do
  2001. {
  2002. uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale];
  2003. ulong tmp = UInt32x32To64(d2.Low, power);
  2004. d2.Low = (uint)tmp;
  2005. tmp >>= 32;
  2006. tmp += (d2.Mid + ((ulong)d2.High << 32)) * power;
  2007. d2.Mid = (uint)tmp;
  2008. d2.High = (uint)(tmp >> 32);
  2009. } while ((scale -= MaxInt32Scale) > 0);
  2010. scale = 0;
  2011. }
  2012. do
  2013. {
  2014. if (scale < 0)
  2015. {
  2016. d1.uflags = d2.uflags;
  2017. // Try to scale up dividend to match divisor.
  2018. Buf12 bufQuo;
  2019. unsafe
  2020. { _ = &bufQuo; } // workaround for CS0165
  2021. bufQuo.Low64 = d1.Low64;
  2022. bufQuo.U2 = d1.High;
  2023. do
  2024. {
  2025. int iCurScale = SearchScale(ref bufQuo, DEC_SCALE_MAX + scale);
  2026. if (iCurScale == 0)
  2027. break;
  2028. uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iCurScale];
  2029. scale += iCurScale;
  2030. ulong tmp = UInt32x32To64(bufQuo.U0, power);
  2031. bufQuo.U0 = (uint)tmp;
  2032. tmp >>= 32;
  2033. bufQuo.High64 = tmp + bufQuo.High64 * power;
  2034. if (power != TenToPowerNine)
  2035. break;
  2036. }
  2037. while (scale < 0);
  2038. d1.Low64 = bufQuo.Low64;
  2039. d1.High = bufQuo.U2;
  2040. }
  2041. if (d1.High == 0)
  2042. {
  2043. Debug.Assert(d2.High == 0);
  2044. Debug.Assert(scale == 0);
  2045. d1.Low64 %= d2.Low64;
  2046. return;
  2047. }
  2048. else if ((d2.High | d2.Mid) == 0)
  2049. {
  2050. uint den = d2.Low;
  2051. ulong tmp = ((ulong)d1.High << 32) | d1.Mid;
  2052. tmp = ((tmp % den) << 32) | d1.Low;
  2053. d1.Low64 = tmp % den;
  2054. d1.High = 0;
  2055. }
  2056. else
  2057. {
  2058. VarDecModFull(ref d1, ref d2, scale);
  2059. return;
  2060. }
  2061. } while (scale < 0);
  2062. }
  2063. private static unsafe void VarDecModFull(ref DecCalc d1, ref DecCalc d2, int scale)
  2064. {
  2065. // Divisor has bits set in the upper 64 bits.
  2066. //
  2067. // Divisor must be fully normalized (shifted so bit 31 of the most significant uint is 1).
  2068. // Locate the MSB so we know how much to normalize by.
  2069. // The dividend will be shifted by the same amount so the quotient is not changed.
  2070. //
  2071. uint tmp = d2.High;
  2072. if (tmp == 0)
  2073. tmp = d2.Mid;
  2074. int shift = X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(tmp) : LeadingZeroCount(tmp);
  2075. Buf28 b;
  2076. _ = &b; // workaround for CS0165
  2077. b.Buf24.Low64 = d1.Low64 << shift;
  2078. b.Buf24.Mid64 = (d1.Mid + ((ulong)d1.High << 32)) >> (32 - shift);
  2079. // The dividend might need to be scaled up to 221 significant bits.
  2080. // Maximum scaling is required when the divisor is 2^64 with scale 28 and is left shifted 31 bits
  2081. // and the dividend is decimal.MaxValue: (2^96 - 1) * 10^28 << 31 = 221 bits.
  2082. uint high = 3;
  2083. while (scale < 0)
  2084. {
  2085. uint power = scale <= -MaxInt32Scale ? TenToPowerNine : s_powers10[-scale];
  2086. uint* buf = (uint*)&b;
  2087. ulong tmp64 = UInt32x32To64(b.Buf24.U0, power);
  2088. b.Buf24.U0 = (uint)tmp64;
  2089. for (int i = 1; i <= high; i++)
  2090. {
  2091. tmp64 >>= 32;
  2092. tmp64 += UInt32x32To64(buf[i], power);
  2093. buf[i] = (uint)tmp64;
  2094. }
  2095. // The high bit of the dividend must not be set.
  2096. if (tmp64 > int.MaxValue)
  2097. {
  2098. Debug.Assert(high + 1 < b.Length);
  2099. buf[++high] = (uint)(tmp64 >> 32);
  2100. }
  2101. scale += MaxInt32Scale;
  2102. }
  2103. if (d2.High == 0)
  2104. {
  2105. ulong divisor = d2.Low64 << shift;
  2106. switch (high)
  2107. {
  2108. case 6:
  2109. Div96By64(ref *(Buf12*)&b.Buf24.U4, divisor);
  2110. goto case 5;
  2111. case 5:
  2112. Div96By64(ref *(Buf12*)&b.Buf24.U3, divisor);
  2113. goto case 4;
  2114. case 4:
  2115. Div96By64(ref *(Buf12*)&b.Buf24.U2, divisor);
  2116. break;
  2117. }
  2118. Div96By64(ref *(Buf12*)&b.Buf24.U1, divisor);
  2119. Div96By64(ref *(Buf12*)&b, divisor);
  2120. d1.Low64 = b.Buf24.Low64 >> shift;
  2121. d1.High = 0;
  2122. }
  2123. else
  2124. {
  2125. Buf12 bufDivisor;
  2126. _ = &bufDivisor; // workaround for CS0165
  2127. bufDivisor.Low64 = d2.Low64 << shift;
  2128. bufDivisor.U2 = (uint)((d2.Mid + ((ulong)d2.High << 32)) >> (32 - shift));
  2129. switch (high)
  2130. {
  2131. case 6:
  2132. Div128By96(ref *(Buf16*)&b.Buf24.U3, ref bufDivisor);
  2133. goto case 5;
  2134. case 5:
  2135. Div128By96(ref *(Buf16*)&b.Buf24.U2, ref bufDivisor);
  2136. goto case 4;
  2137. case 4:
  2138. Div128By96(ref *(Buf16*)&b.Buf24.U1, ref bufDivisor);
  2139. break;
  2140. }
  2141. Div128By96(ref *(Buf16*)&b, ref bufDivisor);
  2142. d1.Low64 = (b.Buf24.Low64 >> shift) + ((ulong)b.Buf24.U2 << (32 - shift) << 32);
  2143. d1.High = b.Buf24.U2 >> shift;
  2144. }
  2145. }
  2146. internal enum RoundingMode
  2147. {
  2148. ToEven = 0,
  2149. AwayFromZero = 1,
  2150. Truncate = 2,
  2151. Floor = 3,
  2152. Ceiling = 4,
  2153. }
  2154. /// <summary>
  2155. /// Does an in-place round by the specified scale
  2156. /// </summary>
  2157. internal static void InternalRound(ref DecCalc d, uint scale, RoundingMode mode)
  2158. {
  2159. // the scale becomes the desired decimal count
  2160. d.uflags -= scale << ScaleShift;
  2161. uint remainder, sticky = 0, power;
  2162. // First divide the value by constant 10^9 up to three times
  2163. while (scale >= MaxInt32Scale)
  2164. {
  2165. scale -= MaxInt32Scale;
  2166. const uint divisor = TenToPowerNine;
  2167. uint n = d.uhi;
  2168. if (n == 0)
  2169. {
  2170. ulong tmp = d.Low64;
  2171. ulong div = tmp / divisor;
  2172. d.Low64 = div;
  2173. remainder = (uint)(tmp - div * divisor);
  2174. }
  2175. else
  2176. {
  2177. uint q;
  2178. d.uhi = q = n / divisor;
  2179. remainder = n - q * divisor;
  2180. n = d.umid;
  2181. if ((n | remainder) != 0)
  2182. {
  2183. d.umid = q = (uint)((((ulong)remainder << 32) | n) / divisor);
  2184. remainder = n - q * divisor;
  2185. }
  2186. n = d.ulo;
  2187. if ((n | remainder) != 0)
  2188. {
  2189. d.ulo = q = (uint)((((ulong)remainder << 32) | n) / divisor);
  2190. remainder = n - q * divisor;
  2191. }
  2192. }
  2193. power = divisor;
  2194. if (scale == 0)
  2195. goto checkRemainder;
  2196. sticky |= remainder;
  2197. }
  2198. {
  2199. power = s_powers10[scale];
  2200. // TODO: https://github.com/dotnet/coreclr/issues/3439
  2201. uint n = d.uhi;
  2202. if (n == 0)
  2203. {
  2204. ulong tmp = d.Low64;
  2205. if (tmp == 0)
  2206. {
  2207. if (mode <= RoundingMode.Truncate)
  2208. goto done;
  2209. remainder = 0;
  2210. goto checkRemainder;
  2211. }
  2212. ulong div = tmp / power;
  2213. d.Low64 = div;
  2214. remainder = (uint)(tmp - div * power);
  2215. }
  2216. else
  2217. {
  2218. uint q;
  2219. d.uhi = q = n / power;
  2220. remainder = n - q * power;
  2221. n = d.umid;
  2222. if ((n | remainder) != 0)
  2223. {
  2224. d.umid = q = (uint)((((ulong)remainder << 32) | n) / power);
  2225. remainder = n - q * power;
  2226. }
  2227. n = d.ulo;
  2228. if ((n | remainder) != 0)
  2229. {
  2230. d.ulo = q = (uint)((((ulong)remainder << 32) | n) / power);
  2231. remainder = n - q * power;
  2232. }
  2233. }
  2234. }
  2235. checkRemainder:
  2236. if (mode == RoundingMode.Truncate)
  2237. goto done;
  2238. else if (mode == RoundingMode.ToEven)
  2239. {
  2240. // To do IEEE rounding, we add LSB of result to sticky bits so either causes round up if remainder * 2 == last divisor.
  2241. remainder <<= 1;
  2242. if ((sticky | d.ulo & 1) != 0)
  2243. remainder++;
  2244. if (power >= remainder)
  2245. goto done;
  2246. }
  2247. else if (mode == RoundingMode.AwayFromZero)
  2248. {
  2249. // Round away from zero at the mid point.
  2250. remainder <<= 1;
  2251. if (power > remainder)
  2252. goto done;
  2253. }
  2254. else if (mode == RoundingMode.Floor)
  2255. {
  2256. // Round toward -infinity if we have chopped off a non-zero amount from a negative value.
  2257. if ((remainder | sticky) == 0 || !d.IsNegative)
  2258. goto done;
  2259. }
  2260. else
  2261. {
  2262. Debug.Assert(mode == RoundingMode.Ceiling);
  2263. // Round toward infinity if we have chopped off a non-zero amount from a positive value.
  2264. if ((remainder | sticky) == 0 || d.IsNegative)
  2265. goto done;
  2266. }
  2267. if (++d.Low64 == 0)
  2268. d.uhi++;
  2269. done:
  2270. return;
  2271. }
  2272. internal static uint DecDivMod1E9(ref DecCalc value)
  2273. {
  2274. ulong high64 = ((ulong)value.uhi << 32) + value.umid;
  2275. ulong div64 = high64 / TenToPowerNine;
  2276. value.uhi = (uint)(div64 >> 32);
  2277. value.umid = (uint)div64;
  2278. ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo;
  2279. uint div = (uint)(num / TenToPowerNine);
  2280. value.ulo = div;
  2281. return (uint)num - div * TenToPowerNine;
  2282. }
  2283. struct PowerOvfl
  2284. {
  2285. public readonly uint Hi;
  2286. public readonly ulong MidLo;
  2287. public PowerOvfl(uint hi, uint mid, uint lo)
  2288. {
  2289. Hi = hi;
  2290. MidLo = ((ulong)mid << 32) + lo;
  2291. }
  2292. }
  2293. static readonly PowerOvfl[] PowerOvflValues = new[]
  2294. {
  2295. // This is a table of the largest values that can be in the upper two
  2296. // uints of a 96-bit number that will not overflow when multiplied
  2297. // by a given power. For the upper word, this is a table of
  2298. // 2^32 / 10^n for 1 <= n <= 8. For the lower word, this is the
  2299. // remaining fraction part * 2^32. 2^32 = 4294967296.
  2300. //
  2301. new PowerOvfl(429496729, 2576980377, 2576980377), // 10^1 remainder 0.6
  2302. new PowerOvfl(42949672, 4123168604, 687194767), // 10^2 remainder 0.16
  2303. new PowerOvfl(4294967, 1271310319, 2645699854), // 10^3 remainder 0.616
  2304. new PowerOvfl(429496, 3133608139, 694066715), // 10^4 remainder 0.1616
  2305. new PowerOvfl(42949, 2890341191, 2216890319), // 10^5 remainder 0.51616
  2306. new PowerOvfl(4294, 4154504685, 2369172679), // 10^6 remainder 0.551616
  2307. new PowerOvfl(429, 2133437386, 4102387834), // 10^7 remainder 0.9551616
  2308. new PowerOvfl(42, 4078814305, 410238783), // 10^8 remainder 0.09991616
  2309. };
  2310. [StructLayout(LayoutKind.Explicit)]
  2311. private struct Buf12
  2312. {
  2313. [FieldOffset(0 * 4)]
  2314. public uint U0;
  2315. [FieldOffset(1 * 4)]
  2316. public uint U1;
  2317. [FieldOffset(2 * 4)]
  2318. public uint U2;
  2319. [FieldOffset(0)]
  2320. private ulong ulo64LE;
  2321. [FieldOffset(4)]
  2322. private ulong uhigh64LE;
  2323. public ulong Low64
  2324. {
  2325. #if BIGENDIAN
  2326. get => ((ulong)U1 << 32) | U0;
  2327. set { U1 = (uint)(value >> 32); U0 = (uint)value; }
  2328. #else
  2329. get => ulo64LE;
  2330. set => ulo64LE = value;
  2331. #endif
  2332. }
  2333. /// <summary>
  2334. /// U1-U2 combined (overlaps with Low64)
  2335. /// </summary>
  2336. public ulong High64
  2337. {
  2338. #if BIGENDIAN
  2339. get => ((ulong)U2 << 32) | U1;
  2340. set { U2 = (uint)(value >> 32); U1 = (uint)value; }
  2341. #else
  2342. get => uhigh64LE;
  2343. set => uhigh64LE = value;
  2344. #endif
  2345. }
  2346. }
  2347. [StructLayout(LayoutKind.Explicit)]
  2348. private struct Buf16
  2349. {
  2350. [FieldOffset(0 * 4)]
  2351. public uint U0;
  2352. [FieldOffset(1 * 4)]
  2353. public uint U1;
  2354. [FieldOffset(2 * 4)]
  2355. public uint U2;
  2356. [FieldOffset(3 * 4)]
  2357. public uint U3;
  2358. [FieldOffset(0 * 8)]
  2359. private ulong ulo64LE;
  2360. [FieldOffset(1 * 8)]
  2361. private ulong uhigh64LE;
  2362. public ulong Low64
  2363. {
  2364. #if BIGENDIAN
  2365. get => ((ulong)U1 << 32) | U0;
  2366. set { U1 = (uint)(value >> 32); U0 = (uint)value; }
  2367. #else
  2368. get => ulo64LE;
  2369. set => ulo64LE = value;
  2370. #endif
  2371. }
  2372. public ulong High64
  2373. {
  2374. #if BIGENDIAN
  2375. get => ((ulong)U3 << 32) | U2;
  2376. set { U3 = (uint)(value >> 32); U2 = (uint)value; }
  2377. #else
  2378. get => uhigh64LE;
  2379. set => uhigh64LE = value;
  2380. #endif
  2381. }
  2382. }
  2383. [StructLayout(LayoutKind.Explicit)]
  2384. private struct Buf24
  2385. {
  2386. [FieldOffset(0 * 4)]
  2387. public uint U0;
  2388. [FieldOffset(1 * 4)]
  2389. public uint U1;
  2390. [FieldOffset(2 * 4)]
  2391. public uint U2;
  2392. [FieldOffset(3 * 4)]
  2393. public uint U3;
  2394. [FieldOffset(4 * 4)]
  2395. public uint U4;
  2396. [FieldOffset(5 * 4)]
  2397. public uint U5;
  2398. [FieldOffset(0 * 8)]
  2399. private ulong ulo64LE;
  2400. [FieldOffset(1 * 8)]
  2401. private ulong umid64LE;
  2402. [FieldOffset(2 * 8)]
  2403. private ulong uhigh64LE;
  2404. public ulong Low64
  2405. {
  2406. #if BIGENDIAN
  2407. get => ((ulong)U1 << 32) | U0;
  2408. set { U1 = (uint)(value >> 32); U0 = (uint)value; }
  2409. #else
  2410. get => ulo64LE;
  2411. set => ulo64LE = value;
  2412. #endif
  2413. }
  2414. public ulong Mid64
  2415. {
  2416. #if BIGENDIAN
  2417. get => ((ulong)U3 << 32) | U2;
  2418. set { U3 = (uint)(value >> 32); U2 = (uint)value; }
  2419. #else
  2420. get => umid64LE;
  2421. set => umid64LE = value;
  2422. #endif
  2423. }
  2424. public ulong High64
  2425. {
  2426. #if BIGENDIAN
  2427. get => ((ulong)U5 << 32) | U4;
  2428. set { U5 = (uint)(value >> 32); U4 = (uint)value; }
  2429. #else
  2430. get => uhigh64LE;
  2431. set => uhigh64LE = value;
  2432. #endif
  2433. }
  2434. public int Length => 6;
  2435. }
  2436. private struct Buf28
  2437. {
  2438. public Buf24 Buf24;
  2439. public uint U6;
  2440. public int Length => 7;
  2441. }
  2442. }
  2443. }
  2444. }