-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathcharconv
2615 lines (2102 loc) · 120 KB
/
charconv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// charconv standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef _CHARCONV_
#define _CHARCONV_
#include <yvals.h>
#if _STL_COMPILER_PREPROCESSOR
#if !_HAS_CXX17
_EMIT_STL_WARNING(STL4038, "The contents of <charconv> are available only with C++17 or later.");
#else // ^^^ !_HAS_CXX17 / _HAS_CXX17 vvv
#include <cstring>
#include <xbit_ops.h>
#include <xcharconv.h>
#include <xcharconv_ryu.h>
#include <xcharconv_tables.h>
#include <xutility>
#include _STL_INTRIN_HEADER
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
// This implementation is dedicated to the memory of Mary and Thavatchai.
_STD_BEGIN
inline constexpr char _Charconv_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
_STL_INTERNAL_STATIC_ASSERT(_STD size(_Charconv_digits) == 36);
template <class _RawTy>
_NODISCARD _CONSTEXPR23 to_chars_result _Integer_to_chars(
char* _First, char* const _Last, const _RawTy _Raw_value, const int _Base) noexcept {
_Adl_verify_range(_First, _Last);
_STL_ASSERT(_Base >= 2 && _Base <= 36, "invalid base in to_chars()");
using _Unsigned = make_unsigned_t<_RawTy>;
_Unsigned _Value = static_cast<_Unsigned>(_Raw_value);
if constexpr (is_signed_v<_RawTy>) {
if (_Raw_value < 0) {
if (_First == _Last) {
return {_Last, errc::value_too_large};
}
*_First++ = '-';
_Value = static_cast<_Unsigned>(0 - _Value);
}
}
constexpr size_t _Buff_size = sizeof(_Unsigned) * CHAR_BIT; // enough for base 2
char _Buff[_Buff_size];
char* const _Buff_end = _Buff + _Buff_size;
char* _RNext = _Buff_end;
switch (_Base) {
case 10:
{ // Derived from _UIntegral_to_buff()
// Performance note: Ryu's digit table should be faster here.
constexpr bool _Use_chunks = sizeof(_Unsigned) > sizeof(size_t);
if constexpr (_Use_chunks) { // For 64-bit numbers on 32-bit platforms, work in chunks to avoid 64-bit
// divisions.
while (_Value > 0xFFFF'FFFFU) {
// Performance note: Ryu's division workaround would be faster here.
unsigned long _Chunk = static_cast<unsigned long>(_Value % 1'000'000'000);
_Value = static_cast<_Unsigned>(_Value / 1'000'000'000);
for (int _Idx = 0; _Idx != 9; ++_Idx) {
*--_RNext = static_cast<char>('0' + _Chunk % 10);
_Chunk /= 10;
}
}
}
using _Truncated = conditional_t<_Use_chunks, unsigned long, _Unsigned>;
_Truncated _Trunc = static_cast<_Truncated>(_Value);
do {
*--_RNext = static_cast<char>('0' + _Trunc % 10);
_Trunc /= 10;
} while (_Trunc != 0);
break;
}
case 2:
do {
*--_RNext = static_cast<char>('0' + (_Value & 0b1));
_Value >>= 1;
} while (_Value != 0);
break;
case 4:
do {
*--_RNext = static_cast<char>('0' + (_Value & 0b11));
_Value >>= 2;
} while (_Value != 0);
break;
case 8:
do {
*--_RNext = static_cast<char>('0' + (_Value & 0b111));
_Value >>= 3;
} while (_Value != 0);
break;
case 16:
do {
*--_RNext = _Charconv_digits[_Value & 0b1111];
_Value >>= 4;
} while (_Value != 0);
break;
case 32:
do {
*--_RNext = _Charconv_digits[_Value & 0b11111];
_Value >>= 5;
} while (_Value != 0);
break;
case 3:
case 5:
case 6:
case 7:
case 9:
do {
*--_RNext = static_cast<char>('0' + _Value % _Base);
_Value = static_cast<_Unsigned>(_Value / _Base);
} while (_Value != 0);
break;
default:
do {
*--_RNext = _Charconv_digits[_Value % _Base];
_Value = static_cast<_Unsigned>(_Value / _Base);
} while (_Value != 0);
break;
}
const ptrdiff_t _Digits_written = _Buff_end - _RNext;
if (_Last - _First < _Digits_written) {
return {_Last, errc::value_too_large};
}
_Copy_n_unchecked4(_RNext, _Digits_written, _First);
return {_First + _Digits_written, errc{}};
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const char _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const signed char _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(char* const _First, char* const _Last, const unsigned char _Value,
const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const short _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(char* const _First, char* const _Last, const unsigned short _Value,
const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const int _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(char* const _First, char* const _Last, const unsigned int _Value,
const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const long _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(char* const _First, char* const _Last, const unsigned long _Value,
const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(
char* const _First, char* const _Last, const long long _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 to_chars_result to_chars(char* const _First, char* const _Last,
const unsigned long long _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_to_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD to_chars_result to_chars(char* _First, char* _Last, bool _Value, int _Base = 10) = delete;
_EXPORT_STD struct from_chars_result {
const char* ptr;
errc ec;
#if _HAS_CXX20
_NODISCARD friend bool operator==(const from_chars_result&, const from_chars_result&) = default;
#endif // _HAS_CXX20
};
// convert ['0', '9'] ['A', 'Z'] ['a', 'z'] to [0, 35], everything else to 255
inline constexpr unsigned char _Digit_from_byte[] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255,
255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
_STL_INTERNAL_STATIC_ASSERT(_STD size(_Digit_from_byte) == 256);
_NODISCARD _CONSTEXPR23 unsigned char _Digit_from_char(const char _Ch) noexcept {
// convert ['0', '9'] ['A', 'Z'] ['a', 'z'] to [0, 35], everything else to 255
// CodeQL [SM01954] This index is valid: we cast to unsigned char and the array has 256 elements.
return _Digit_from_byte[static_cast<unsigned char>(_Ch)];
}
template <class _RawTy>
_NODISCARD _CONSTEXPR23 from_chars_result _Integer_from_chars(
const char* const _First, const char* const _Last, _RawTy& _Raw_value, const int _Base) noexcept {
_Adl_verify_range(_First, _Last);
_STL_ASSERT(_Base >= 2 && _Base <= 36, "invalid base in from_chars()");
bool _Minus_sign = false;
const char* _Next = _First;
if constexpr (is_signed_v<_RawTy>) {
if (_Next != _Last && *_Next == '-') {
_Minus_sign = true;
++_Next;
}
}
using _Unsigned = make_unsigned_t<_RawTy>;
constexpr _Unsigned _Uint_max = static_cast<_Unsigned>(-1);
constexpr _Unsigned _Int_max = static_cast<_Unsigned>(_Uint_max >> 1);
#pragma warning(push)
#pragma warning(disable : 26450) // TRANSITION, VSO-1828677
constexpr _Unsigned _Abs_int_min = static_cast<_Unsigned>(_Int_max + 1);
#pragma warning(pop)
_Unsigned _Risky_val;
_Unsigned _Max_digit;
if constexpr (is_signed_v<_RawTy>) {
if (_Minus_sign) {
_Risky_val = static_cast<_Unsigned>(_Abs_int_min / _Base);
_Max_digit = static_cast<_Unsigned>(_Abs_int_min % _Base);
} else {
_Risky_val = static_cast<_Unsigned>(_Int_max / _Base);
_Max_digit = static_cast<_Unsigned>(_Int_max % _Base);
}
} else {
_Risky_val = static_cast<_Unsigned>(_Uint_max / _Base);
_Max_digit = static_cast<_Unsigned>(_Uint_max % _Base);
}
_Unsigned _Value = 0;
bool _Overflowed = false;
for (; _Next != _Last; ++_Next) {
const unsigned char _Digit = _Digit_from_char(*_Next);
if (_Digit >= _Base) {
break;
}
if (_Value < _Risky_val // never overflows
|| (_Value == _Risky_val && _Digit <= _Max_digit)) { // overflows for certain digits
_Value = static_cast<_Unsigned>(_Value * _Base + _Digit);
} else { // _Value > _Risky_val always overflows
_Overflowed = true; // keep going, _Next still needs to be updated, _Value is now irrelevant
}
}
if (_Next - _First == static_cast<ptrdiff_t>(_Minus_sign)) {
return {_First, errc::invalid_argument};
}
if (_Overflowed) {
return {_Next, errc::result_out_of_range};
}
if constexpr (is_signed_v<_RawTy>) {
if (_Minus_sign) {
_Value = static_cast<_Unsigned>(0 - _Value);
}
}
_Raw_value = static_cast<_RawTy>(_Value); // congruent to _Value modulo 2^N for negative, N4950 [conv.integral]/3
return {_Next, errc{}};
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(
const char* const _First, const char* const _Last, char& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
signed char& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
unsigned char& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last, short& _Value,
const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
unsigned short& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(
const char* const _First, const char* const _Last, int& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
unsigned int& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(
const char* const _First, const char* const _Last, long& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
unsigned long& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
long long& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
_EXPORT_STD _CONSTEXPR23 from_chars_result from_chars(const char* const _First, const char* const _Last,
unsigned long long& _Value, const int _Base = 10) noexcept /* strengthened */ {
return _Integer_from_chars(_First, _Last, _Value, _Base);
}
// vvvvvvvvvv DERIVED FROM corecrt_internal_big_integer.h vvvvvvvvvv
// A lightweight, sufficiently functional high-precision integer type for use in the binary floating-point <=> decimal
// string conversions. We define only the operations (and in some cases, parts of operations) that are actually used.
// We require sufficient precision to represent the reciprocal of the smallest representable value (the smallest
// denormal, 2^-1074). During parsing, we may also consider up to 768 decimal digits. For this, we require an
// additional log2(10^768) bits of precision. Finally, we require 54 bits of space for pre-division numerator shifting,
// because double explicitly stores 52 bits, implicitly stores 1 bit, and we need 1 more bit for rounding.
// PERFORMANCE NOTE: We intentionally do not initialize the _Mydata array when a _Big_integer_flt object is constructed.
// Profiling showed that zero-initialization caused a substantial performance hit. Initialization of the _Mydata
// array is not necessary: all operations on the _Big_integer_flt type are carefully written to only access elements at
// indices [0, _Myused), and all operations correctly update _Myused as the utilized size increases.
// _Big_integer_flt _Xval{}; is direct-list-initialization (N4950 [dcl.init.list]/1).
// N4950 [dcl.init.list]/3.5:
// "Otherwise, if the initializer list has no elements and T is a class type with a default constructor,
// the object is value-initialized."
// N4950 [dcl.init.general]/9, /9.1, /9.1.1:
// "To value-initialize an object of type T means:
// - if T is a (possibly cv-qualified) class type ([class]), then
// - if T has either no default constructor ([class.default.ctor]) or a default constructor
// that is user-provided or deleted, then the object is default-initialized;"
// N4950 [dcl.init.general]/7, /7.1:
// "To default-initialize an object of type T means:
// - If T is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors
// are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution
// ([over.match]).
// The constructor thus selected is called, with an empty argument list, to initialize the object."
// N4950 [class.base.init]/9, /9.3:
// "In a non-delegating constructor other than an implicitly-defined copy/move constructor ([class.copy.ctor]),
// if a given potentially constructed subobject is not designated by a mem-initializer-id (including the case
// where there is no mem-initializer-list because the constructor has no ctor-initializer), then [...]
// - otherwise, the entity is default-initialized ([dcl.init])."
// N4950 [dcl.init.general]/7, /7.2, /7.3:
// "To default-initialize an object of type T means: [...]
// - If T is an array type, each element is default-initialized.
// - Otherwise, no initialization is performed."
// Therefore, _Mydata's elements are not initialized.
struct _Big_integer_flt {
#pragma warning(push)
#pragma warning(disable : 26495) // Variable 'std::_Big_integer_flt::_Mydata' is uninitialized.
// Always initialize a member variable (type.6).
_Big_integer_flt() noexcept : _Myused(0) {}
#pragma warning(pop)
_Big_integer_flt(const _Big_integer_flt& _Other) noexcept : _Myused(_Other._Myused) {
_CSTD memcpy(_Mydata, _Other._Mydata, _Other._Myused * sizeof(uint32_t));
}
_Big_integer_flt& operator=(const _Big_integer_flt& _Other) noexcept {
_Myused = _Other._Myused;
_CSTD memmove(_Mydata, _Other._Mydata, _Other._Myused * sizeof(uint32_t));
return *this;
}
_NODISCARD bool operator<(const _Big_integer_flt& _Rhs) const noexcept {
if (_Myused != _Rhs._Myused) {
return _Myused < _Rhs._Myused;
}
for (uint32_t _Ix = _Myused - 1; _Ix != static_cast<uint32_t>(-1); --_Ix) {
if (_Mydata[_Ix] != _Rhs._Mydata[_Ix]) {
return _Mydata[_Ix] < _Rhs._Mydata[_Ix];
}
}
return false;
}
static constexpr uint32_t _Maximum_bits = 1074 // 1074 bits required to represent 2^1074
+ 2552 // ceil(log2(10^768))
+ 54; // shift space
static constexpr uint32_t _Element_bits = 32;
static constexpr uint32_t _Element_count = (_Maximum_bits + _Element_bits - 1) / _Element_bits;
uint32_t _Myused; // The number of elements currently in use
uint32_t _Mydata[_Element_count]; // The number, stored in little-endian form
};
_NODISCARD inline _Big_integer_flt _Make_big_integer_flt_one() noexcept {
_Big_integer_flt _Xval{};
_Xval._Mydata[0] = 1;
_Xval._Myused = 1;
return _Xval;
}
_NODISCARD inline uint32_t _Bit_scan_reverse(const _Big_integer_flt& _Xval) noexcept {
if (_Xval._Myused == 0) {
return 0;
}
const uint32_t _Bx = _Xval._Myused - 1;
unsigned long _Index; // Intentionally uninitialized for better codegen
_STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed
// CodeQL [SM02313] _Index is always initialized: we've guaranteed that _Xval._Mydata[_Bx] is non-zero.
_BitScanReverse(&_Index, _Xval._Mydata[_Bx]);
return _Index + 1 + _Bx * _Big_integer_flt::_Element_bits;
}
// Shifts the high-precision integer _Xval by _Nx bits to the left. Returns true if the left shift was successful;
// false if it overflowed. When overflow occurs, the high-precision integer is reset to zero.
_NODISCARD inline bool _Shift_left(_Big_integer_flt& _Xval, const uint32_t _Nx) noexcept {
if (_Xval._Myused == 0) {
return true;
}
const uint32_t _Unit_shift = _Nx / _Big_integer_flt::_Element_bits;
const uint32_t _Bit_shift = _Nx % _Big_integer_flt::_Element_bits;
if (_Xval._Myused + _Unit_shift > _Big_integer_flt::_Element_count) {
// Unit shift will overflow.
_Xval._Myused = 0;
return false;
}
if (_Bit_shift == 0) {
_CSTD memmove(_Xval._Mydata + _Unit_shift, _Xval._Mydata, _Xval._Myused * sizeof(uint32_t));
_Xval._Myused += _Unit_shift;
} else {
const bool _Bit_shifts_into_next_unit =
_Bit_shift > (_Big_integer_flt::_Element_bits - _Bit_scan_reverse(_Xval._Mydata[_Xval._Myused - 1]));
const uint32_t _New_used = _Xval._Myused + _Unit_shift + static_cast<uint32_t>(_Bit_shifts_into_next_unit);
if (_New_used > _Big_integer_flt::_Element_count) {
// Bit shift will overflow.
_Xval._Myused = 0;
return false;
}
const uint32_t _Msb_bits = _Bit_shift;
const uint32_t _Lsb_bits = _Big_integer_flt::_Element_bits - _Msb_bits;
const uint32_t _Lsb_mask = (1UL << _Lsb_bits) - 1UL;
const uint32_t _Msb_mask = ~_Lsb_mask;
// If _Unit_shift == 0, this will wraparound, which is okay.
for (uint32_t _Dest_index = _New_used - 1; _Dest_index != _Unit_shift - 1; --_Dest_index) {
// performance note: PSLLDQ and PALIGNR instructions could be more efficient here
// If _Bit_shifts_into_next_unit, the first iteration will trigger the bounds check below, which is okay.
const uint32_t _Upper_source_index = _Dest_index - _Unit_shift;
// When _Dest_index == _Unit_shift, this will wraparound, which is okay (see bounds check below).
const uint32_t _Lower_source_index = _Dest_index - _Unit_shift - 1;
const uint32_t _Upper_source = _Upper_source_index < _Xval._Myused ? _Xval._Mydata[_Upper_source_index] : 0;
const uint32_t _Lower_source = _Lower_source_index < _Xval._Myused ? _Xval._Mydata[_Lower_source_index] : 0;
const uint32_t _Shifted_upper_source = (_Upper_source & _Lsb_mask) << _Msb_bits;
const uint32_t _Shifted_lower_source = (_Lower_source & _Msb_mask) >> _Lsb_bits;
const uint32_t _Combined_shifted_source = _Shifted_upper_source | _Shifted_lower_source;
_Xval._Mydata[_Dest_index] = _Combined_shifted_source;
}
_Xval._Myused = _New_used;
}
_CSTD memset(_Xval._Mydata, 0, _Unit_shift * sizeof(uint32_t));
return true;
}
// Adds a 32-bit _Value to the high-precision integer _Xval. Returns true if the addition was successful;
// false if it overflowed. When overflow occurs, the high-precision integer is reset to zero.
_NODISCARD inline bool _Add(_Big_integer_flt& _Xval, const uint32_t _Value) noexcept {
if (_Value == 0) {
return true;
}
uint32_t _Carry = _Value;
for (uint32_t _Ix = 0; _Ix != _Xval._Myused; ++_Ix) {
const uint64_t _Result = static_cast<uint64_t>(_Xval._Mydata[_Ix]) + _Carry;
_Xval._Mydata[_Ix] = static_cast<uint32_t>(_Result);
_Carry = static_cast<uint32_t>(_Result >> 32);
}
if (_Carry != 0) {
if (_Xval._Myused < _Big_integer_flt::_Element_count) {
_Xval._Mydata[_Xval._Myused] = _Carry;
++_Xval._Myused;
} else {
_Xval._Myused = 0;
return false;
}
}
return true;
}
_NODISCARD inline uint32_t _Add_carry(uint32_t& _Ux1, const uint32_t _Ux2, const uint32_t _U_carry) noexcept {
const uint64_t _Uu = static_cast<uint64_t>(_Ux1) + _Ux2 + _U_carry;
_Ux1 = static_cast<uint32_t>(_Uu);
return static_cast<uint32_t>(_Uu >> 32);
}
_NODISCARD inline uint32_t _Add_multiply_carry(
uint32_t& _U_add, const uint32_t _U_mul_1, const uint32_t _U_mul_2, const uint32_t _U_carry) noexcept {
const uint64_t _Uu_res = static_cast<uint64_t>(_U_mul_1) * _U_mul_2 + _U_add + _U_carry;
_U_add = static_cast<uint32_t>(_Uu_res);
return static_cast<uint32_t>(_Uu_res >> 32);
}
_NODISCARD inline uint32_t _Multiply_core(
uint32_t* const _Multiplicand, const uint32_t _Multiplicand_count, const uint32_t _Multiplier) noexcept {
uint32_t _Carry = 0;
for (uint32_t _Ix = 0; _Ix != _Multiplicand_count; ++_Ix) {
const uint64_t _Result = static_cast<uint64_t>(_Multiplicand[_Ix]) * _Multiplier + _Carry;
_Multiplicand[_Ix] = static_cast<uint32_t>(_Result);
_Carry = static_cast<uint32_t>(_Result >> 32);
}
return _Carry;
}
// Multiplies the high-precision _Multiplicand by a 32-bit _Multiplier. Returns true if the multiplication
// was successful; false if it overflowed. When overflow occurs, the _Multiplicand is reset to zero.
_NODISCARD inline bool _Multiply(_Big_integer_flt& _Multiplicand, const uint32_t _Multiplier) noexcept {
if (_Multiplier == 0) {
_Multiplicand._Myused = 0;
return true;
}
if (_Multiplier == 1) {
return true;
}
if (_Multiplicand._Myused == 0) {
return true;
}
const uint32_t _Carry = _Multiply_core(_Multiplicand._Mydata, _Multiplicand._Myused, _Multiplier);
if (_Carry != 0) {
if (_Multiplicand._Myused < _Big_integer_flt::_Element_count) {
_Multiplicand._Mydata[_Multiplicand._Myused] = _Carry;
++_Multiplicand._Myused;
} else {
_Multiplicand._Myused = 0;
return false;
}
}
return true;
}
// This high-precision integer multiplication implementation was translated from the implementation of
// System.Numerics.BigIntegerBuilder.Mul in the .NET Framework sources. It multiplies the _Multiplicand
// by the _Multiplier and returns true if the multiplication was successful; false if it overflowed.
// When overflow occurs, the _Multiplicand is reset to zero.
_NODISCARD inline bool _Multiply(_Big_integer_flt& _Multiplicand, const _Big_integer_flt& _Multiplier) noexcept {
if (_Multiplicand._Myused == 0) {
return true;
}
if (_Multiplier._Myused == 0) {
_Multiplicand._Myused = 0;
return true;
}
if (_Multiplier._Myused == 1) {
return _Multiply(_Multiplicand, _Multiplier._Mydata[0]); // when overflow occurs, resets to zero
}
if (_Multiplicand._Myused == 1) {
const uint32_t _Small_multiplier = _Multiplicand._Mydata[0];
_Multiplicand = _Multiplier;
return _Multiply(_Multiplicand, _Small_multiplier); // when overflow occurs, resets to zero
}
// We prefer more iterations on the inner loop and fewer on the outer:
const bool _Multiplier_is_shorter = _Multiplier._Myused < _Multiplicand._Myused;
const uint32_t* const _Rgu1 = _Multiplier_is_shorter ? _Multiplier._Mydata : _Multiplicand._Mydata;
const uint32_t* const _Rgu2 = _Multiplier_is_shorter ? _Multiplicand._Mydata : _Multiplier._Mydata;
const uint32_t _Cu1 = _Multiplier_is_shorter ? _Multiplier._Myused : _Multiplicand._Myused;
const uint32_t _Cu2 = _Multiplier_is_shorter ? _Multiplicand._Myused : _Multiplier._Myused;
_Big_integer_flt _Result{};
for (uint32_t _Iu1 = 0; _Iu1 != _Cu1; ++_Iu1) {
const uint32_t _U_cur = _Rgu1[_Iu1];
if (_U_cur == 0) {
if (_Iu1 == _Result._Myused) {
_Result._Mydata[_Iu1] = 0;
_Result._Myused = _Iu1 + 1;
}
continue;
}
uint32_t _U_carry = 0;
uint32_t _Iu_res = _Iu1;
for (uint32_t _Iu2 = 0; _Iu2 != _Cu2 && _Iu_res != _Big_integer_flt::_Element_count; ++_Iu2, ++_Iu_res) {
if (_Iu_res == _Result._Myused) {
_Result._Mydata[_Iu_res] = 0;
_Result._Myused = _Iu_res + 1;
}
_U_carry = _Add_multiply_carry(_Result._Mydata[_Iu_res], _U_cur, _Rgu2[_Iu2], _U_carry);
}
while (_U_carry != 0 && _Iu_res != _Big_integer_flt::_Element_count) {
if (_Iu_res == _Result._Myused) {
_Result._Mydata[_Iu_res] = 0;
_Result._Myused = _Iu_res + 1;
}
_U_carry = _Add_carry(_Result._Mydata[_Iu_res++], 0, _U_carry);
}
if (_Iu_res == _Big_integer_flt::_Element_count) {
_Multiplicand._Myused = 0;
return false;
}
}
// Store the _Result in the _Multiplicand and compute the actual number of elements used:
_Multiplicand = _Result;
return true;
}
extern const uint32_t _Large_power_data[578];
// Multiplies the high-precision integer _Xval by 10^_Power. Returns true if the multiplication was successful;
// false if it overflowed. When overflow occurs, the high-precision integer is reset to zero.
_NODISCARD inline bool _Multiply_by_power_of_ten(_Big_integer_flt& _Xval, const uint32_t _Power) noexcept {
// To improve performance, we use a table of precomputed powers of ten, from 10^10 through 10^380, in increments
// of ten. In its unpacked form, as an array of _Big_integer_flt objects, this table consists mostly of zero
// elements. Thus, we store the table in a packed form, trimming leading and trailing zero elements. We provide an
// index that is used to unpack powers from the table, using the function that appears after this function in this
// file.
// The minimum value representable with double-precision is 5E-324.
// With the _Large_power_data table we can thus compute most multiplications with a single multiply.
struct _Unpack_index {
uint16_t _Offset; // The offset of this power's initial element in the array
uint8_t _Zeroes; // The number of omitted leading zero elements
uint8_t _Size; // The number of elements present for this power
};
static constexpr _Unpack_index _Large_power_indices[] = {{0, 0, 2}, {2, 0, 3}, {5, 0, 4}, {9, 1, 4}, {13, 1, 5},
{18, 1, 6}, {24, 2, 6}, {30, 2, 7}, {37, 2, 8}, {45, 3, 8}, {53, 3, 9}, {62, 3, 10}, {72, 4, 10}, {82, 4, 11},
{93, 4, 12}, {105, 5, 12}, {117, 5, 13}, {130, 5, 14}, {144, 5, 15}, {159, 6, 15}, {174, 6, 16}, {190, 6, 17},
{207, 7, 17}, {224, 7, 18}, {242, 7, 19}, {261, 8, 19}, {280, 8, 21}, {301, 8, 22}, {323, 9, 22}, {345, 9, 23},
{368, 9, 24}, {392, 10, 24}, {416, 10, 25}, {441, 10, 26}, {467, 10, 27}, {494, 11, 27}, {521, 11, 28},
{549, 11, 29}};
for (uint32_t _Large_power = _Power / 10; _Large_power != 0;) {
const uint32_t _Current_power =
(_STD min)(_Large_power, static_cast<uint32_t>(_STD size(_Large_power_indices)));
const _Unpack_index& _Index = _Large_power_indices[_Current_power - 1];
_Big_integer_flt _Multiplier{};
_Multiplier._Myused = static_cast<uint32_t>(_Index._Size + _Index._Zeroes);
const uint32_t* const _Source = _Large_power_data + _Index._Offset;
_CSTD memset(_Multiplier._Mydata, 0, _Index._Zeroes * sizeof(uint32_t));
_CSTD memcpy(_Multiplier._Mydata + _Index._Zeroes, _Source, _Index._Size * sizeof(uint32_t));
if (!_Multiply(_Xval, _Multiplier)) { // when overflow occurs, resets to zero
return false;
}
_Large_power -= _Current_power;
}
static constexpr uint32_t _Small_powers_of_ten[9] = {
10, 100, 1'000, 10'000, 100'000, 1'000'000, 10'000'000, 100'000'000, 1'000'000'000};
const uint32_t _Small_power = _Power % 10;
if (_Small_power == 0) {
return true;
}
return _Multiply(_Xval, _Small_powers_of_ten[_Small_power - 1]); // when overflow occurs, resets to zero
}
// Computes the number of zeroes higher than the most significant set bit in _Ux
_NODISCARD inline uint32_t _Count_sequential_high_zeroes(const uint32_t _Ux) noexcept {
unsigned long _Index; // Intentionally uninitialized for better codegen
return _BitScanReverse(&_Index, _Ux) ? 31 - _Index : 32;
}
// This high-precision integer division implementation was translated from the implementation of
// System.Numerics.BigIntegerBuilder.ModDivCore in the .NET Framework sources.
// It computes both quotient and remainder: the remainder is stored in the _Numerator argument,
// and the least significant 64 bits of the quotient are returned from the function.
_NODISCARD inline uint64_t _Divide(_Big_integer_flt& _Numerator, const _Big_integer_flt& _Denominator) noexcept {
// If the _Numerator is zero, then both the quotient and remainder are zero:
if (_Numerator._Myused == 0) {
return 0;
}
// If the _Denominator is zero, then uh oh. We can't divide by zero:
_STL_INTERNAL_CHECK(_Denominator._Myused != 0); // Division by zero
uint32_t _Max_numerator_element_index = _Numerator._Myused - 1;
const uint32_t _Max_denominator_element_index = _Denominator._Myused - 1;
// The _Numerator and _Denominator are both nonzero.
// If the _Denominator is only one element wide, we can take the fast route:
if (_Max_denominator_element_index == 0) {
const uint32_t _Small_denominator = _Denominator._Mydata[0];
if (_Max_numerator_element_index == 0) {
const uint32_t _Small_numerator = _Numerator._Mydata[0];
if (_Small_denominator == 1) {
_Numerator._Myused = 0;
return _Small_numerator;
}
_Numerator._Mydata[0] = _Small_numerator % _Small_denominator;
_Numerator._Myused = _Numerator._Mydata[0] > 0 ? 1u : 0u;
return _Small_numerator / _Small_denominator;
}
if (_Small_denominator == 1) {
uint64_t _Quotient = _Numerator._Mydata[1];
_Quotient <<= 32;
_Quotient |= _Numerator._Mydata[0];
_Numerator._Myused = 0;
return _Quotient;
}
// We count down in the next loop, so the last assignment to _Quotient will be the correct one.
uint64_t _Quotient = 0;
uint64_t _Uu = 0;
for (uint32_t _Iv = _Max_numerator_element_index; _Iv != static_cast<uint32_t>(-1); --_Iv) {
_Uu = (_Uu << 32) | _Numerator._Mydata[_Iv];
_Quotient = (_Quotient << 32) + static_cast<uint32_t>(_Uu / _Small_denominator);
_Uu %= _Small_denominator;
}
_Numerator._Mydata[1] = static_cast<uint32_t>(_Uu >> 32);
_Numerator._Mydata[0] = static_cast<uint32_t>(_Uu);
if (_Numerator._Mydata[1] > 0) {
_Numerator._Myused = 2u;
} else if (_Numerator._Mydata[0] > 0) {
_Numerator._Myused = 1u;
} else {
_Numerator._Myused = 0u;
}
return _Quotient;
}
if (_Max_denominator_element_index > _Max_numerator_element_index) {
return 0;
}
const uint32_t _Cu_den = _Max_denominator_element_index + 1;
const int32_t _Cu_diff = static_cast<int32_t>(_Max_numerator_element_index - _Max_denominator_element_index);
// Determine whether the result will have _Cu_diff or _Cu_diff + 1 digits:
int32_t _Cu_quo = _Cu_diff;
for (int32_t _Iu = static_cast<int32_t>(_Max_numerator_element_index);; --_Iu) {
if (_Iu < _Cu_diff) {
++_Cu_quo;
break;
}
if (_Denominator._Mydata[_Iu - _Cu_diff] != _Numerator._Mydata[_Iu]) {
if (_Denominator._Mydata[_Iu - _Cu_diff] < _Numerator._Mydata[_Iu]) {
++_Cu_quo;
}
break;
}
}
if (_Cu_quo == 0) {
return 0;
}
// Get the uint to use for the trial divisions. We normalize so the high bit is set:
uint32_t _U_den = _Denominator._Mydata[_Cu_den - 1];
uint32_t _U_den_next = _Denominator._Mydata[_Cu_den - 2];
const uint32_t _Cbit_shift_left = _Count_sequential_high_zeroes(_U_den);
const uint32_t _Cbit_shift_right = 32 - _Cbit_shift_left;
if (_Cbit_shift_left > 0) {
_U_den = (_U_den << _Cbit_shift_left) | (_U_den_next >> _Cbit_shift_right);
_U_den_next <<= _Cbit_shift_left;
if (_Cu_den > 2) {
_U_den_next |= _Denominator._Mydata[_Cu_den - 3] >> _Cbit_shift_right;
}
}
uint64_t _Quotient = 0;
for (int32_t _Iu = _Cu_quo; --_Iu >= 0;) {
// Get the high (normalized) bits of the _Numerator:
const uint32_t _U_num_hi =
(_Iu + _Cu_den <= _Max_numerator_element_index) ? _Numerator._Mydata[_Iu + _Cu_den] : 0;
uint64_t _Uu_num =
(static_cast<uint64_t>(_U_num_hi) << 32) | static_cast<uint64_t>(_Numerator._Mydata[_Iu + _Cu_den - 1]);
uint32_t _U_num_next = _Numerator._Mydata[_Iu + _Cu_den - 2];
if (_Cbit_shift_left > 0) {
_Uu_num = (_Uu_num << _Cbit_shift_left) | (_U_num_next >> _Cbit_shift_right);
_U_num_next <<= _Cbit_shift_left;
if (_Iu + _Cu_den >= 3) {
_U_num_next |= _Numerator._Mydata[_Iu + _Cu_den - 3] >> _Cbit_shift_right;
}
}
// Divide to get the quotient digit:
uint64_t _Uu_quo = _Uu_num / _U_den;
uint64_t _Uu_rem = static_cast<uint32_t>(_Uu_num % _U_den);
if (_Uu_quo > UINT32_MAX) {
_Uu_rem += _U_den * (_Uu_quo - UINT32_MAX);
_Uu_quo = UINT32_MAX;
}
while (_Uu_rem <= UINT32_MAX && _Uu_quo * _U_den_next > ((_Uu_rem << 32) | _U_num_next)) {
--_Uu_quo;
_Uu_rem += _U_den;
}
// Multiply and subtract. Note that _Uu_quo may be one too large.
// If we have a borrow at the end, we'll add the _Denominator back on and decrement _Uu_quo.
if (_Uu_quo > 0) {
uint64_t _Uu_borrow = 0;
for (uint32_t _Iu2 = 0; _Iu2 < _Cu_den; ++_Iu2) {
_Uu_borrow += _Uu_quo * _Denominator._Mydata[_Iu2];
const uint32_t _U_sub = static_cast<uint32_t>(_Uu_borrow);
_Uu_borrow >>= 32;
if (_Numerator._Mydata[_Iu + _Iu2] < _U_sub) {
++_Uu_borrow;
}
_Numerator._Mydata[_Iu + _Iu2] -= _U_sub;
}
if (_U_num_hi < _Uu_borrow) {
// Add, tracking carry:
uint32_t _U_carry = 0;
for (uint32_t _Iu2 = 0; _Iu2 < _Cu_den; ++_Iu2) {
const uint64_t _Sum = static_cast<uint64_t>(_Numerator._Mydata[_Iu + _Iu2])
+ static_cast<uint64_t>(_Denominator._Mydata[_Iu2]) + _U_carry;
_Numerator._Mydata[_Iu + _Iu2] = static_cast<uint32_t>(_Sum);
_U_carry = static_cast<uint32_t>(_Sum >> 32);
}
--_Uu_quo;
}
_Max_numerator_element_index = _Iu + _Cu_den - 1;
}
_Quotient = (_Quotient << 32) + static_cast<uint32_t>(_Uu_quo);
}
// Trim the remainder:
uint32_t _Used = _Max_numerator_element_index + 1;
while (_Used != 0 && _Numerator._Mydata[_Used - 1] == 0) {
--_Used;
}
_Numerator._Myused = _Used;
return _Quotient;
}
// ^^^^^^^^^^ DERIVED FROM corecrt_internal_big_integer.h ^^^^^^^^^^
// vvvvvvvvvv DERIVED FROM corecrt_internal_strtox.h vvvvvvvvvv
// This type is used to hold a partially-parsed string representation of a floating-point number.
// The number is stored in the following form:
// [sign] 0._Mymantissa * B^_Myexponent
// The _Mymantissa buffer stores the mantissa digits in big-endian, binary-coded decimal form. The _Mymantissa_count
// stores the number of digits present in the _Mymantissa buffer. The base B is not stored; it must be tracked
// separately. Note that the base of the mantissa digits may not be the same as B (e.g., for hexadecimal
// floating-point, the mantissa digits are in base 16 but the exponent is a base 2 exponent).
// We consider up to 768 decimal digits during conversion. In most cases, we require nowhere near this many digits
// of precision to compute the correctly rounded binary floating-point value for the input string. The worst case is
// (2 - 3 * 2^-53) * 2^-1022, which has an exact decimal representation of 768 decimal digits after trimming zeroes.
// This value is exactly between 0x1.ffffffffffffep-1022 and 0x1.fffffffffffffp-1022. For round-to-nearest,
// ties-to-even behavior, we also need to consider whether there are any nonzero trailing decimal digits.
// NOTE: The mantissa buffer count here must be kept in sync with the precision of the _Big_integer_flt type.
struct _Floating_point_string {
bool _Myis_negative;
int32_t _Myexponent;
uint32_t _Mymantissa_count;
uint8_t _Mymantissa[768];
};
// Stores a positive or negative zero into the _Result object
template <class _FloatingType>
void _Assemble_floating_point_zero(const bool _Is_negative, _FloatingType& _Result) noexcept {
using _Floating_traits = _Floating_type_traits<_FloatingType>;
using _Uint_type = typename _Floating_traits::_Uint_type;
_Uint_type _Sign_component = _Is_negative;
_Sign_component <<= _Floating_traits::_Sign_shift;
_Result = _Bit_cast<_FloatingType>(_Sign_component);
}
// Stores a positive or negative infinity into the _Result object
template <class _FloatingType>
void _Assemble_floating_point_infinity(const bool _Is_negative, _FloatingType& _Result) noexcept {
using _Floating_traits = _Floating_type_traits<_FloatingType>;
using _Uint_type = typename _Floating_traits::_Uint_type;
_Uint_type _Sign_component = _Is_negative;
_Sign_component <<= _Floating_traits::_Sign_shift;
constexpr _Uint_type _Exponent_component = _Floating_traits::_Shifted_exponent_mask;
_Result = _Bit_cast<_FloatingType>(_Sign_component | _Exponent_component);
}