Decimal.DecCalc.cs 105 KB

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