@@ -266,34 +266,42 @@ RT_API_ATTRS bool RealOutputEditingBase::EmitSuffix(const DataEdit &edit) {
266266 }
267267}
268268
269+ static RT_API_ATTRS char IsInfOrNaN (const char *p, std::size_t length) {
270+ if (!p || length < 1 ) {
271+ return ' \0 ' ;
272+ }
273+ if (*p == ' -' || *p == ' +' ) {
274+ if (length == 1 ) {
275+ return ' \0 ' ;
276+ }
277+ ++p;
278+ }
279+ return *p == ' I' || *p == ' N' ? *p : ' \0 ' ;
280+ }
281+
269282template <int KIND>
270283RT_API_ATTRS decimal::ConversionToDecimalResult
271- RealOutputEditing<KIND>::ConvertToDecimal(
272- int significantDigits, enum decimal::FortranRounding rounding, int flags) {
284+ RealOutputEditing<KIND>::ConvertToDecimal(int significantDigits,
285+ enum decimal::FortranRounding rounding, int width , int flags) {
273286 auto converted{decimal::ConvertToDecimal<binaryPrecision>(buffer_,
274287 sizeof buffer_, static_cast <enum decimal::DecimalConversionFlags>(flags),
275288 significantDigits, rounding, x_)};
276289 if (!converted.str ) { // overflow
277290 io_.GetIoErrorHandler ().Crash (
278291 " RealOutputEditing::ConvertToDecimal: buffer size %zd was insufficient" ,
279292 sizeof buffer_);
293+ } else if (IsInfOrNaN (converted.str , converted.length ) == ' I' &&
294+ converted.length <= 4 &&
295+ static_cast <int >(converted.length + 5 ) <= width) {
296+ // Emit "Infinity" rather than "Inf" (F'2023 13.7.2.3.2 p9), possibly signed
297+ std::memcpy (buffer_, converted.str , converted.length );
298+ std::memcpy (buffer_ + converted.length , " inity" , 5 );
299+ converted.str = buffer_;
300+ converted.length += 5 ;
280301 }
281302 return converted;
282303}
283304
284- static RT_API_ATTRS bool IsInfOrNaN (const char *p, int length) {
285- if (!p || length < 1 ) {
286- return false ;
287- }
288- if (*p == ' -' || *p == ' +' ) {
289- if (length == 1 ) {
290- return false ;
291- }
292- ++p;
293- }
294- return *p == ' I' || *p == ' N' ;
295- }
296-
297305// 13.7.2.3.3 in F'2018
298306template <int KIND>
299307RT_API_ATTRS bool RealOutputEditing<KIND>::EditEorDOutput(
@@ -353,9 +361,9 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditEorDOutput(
353361 }
354362 // In EN editing, multiple attempts may be necessary, so this is a loop.
355363 while (true ) {
356- decimal::ConversionToDecimalResult converted{
357- ConvertToDecimal ( significantDigits, edit.modes .round , flags)};
358- if (IsInfOrNaN (converted.str , static_cast < int >( converted.length ) )) {
364+ decimal::ConversionToDecimalResult converted{ConvertToDecimal (
365+ significantDigits, edit.modes .round , editWidth , flags)};
366+ if (IsInfOrNaN (converted.str , converted.length )) {
359367 return editWidth > 0 &&
360368 converted.length + trailingBlanks_ >
361369 static_cast <std::size_t >(editWidth)
@@ -454,9 +462,9 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
454462 bool canIncrease{true };
455463 for (int extraDigits{fracDigits == 0 ? 1 : 0 };;) {
456464 decimal::ConversionToDecimalResult converted{
457- ConvertToDecimal (extraDigits + fracDigits, rounding, flags)};
465+ ConvertToDecimal (extraDigits + fracDigits, rounding, editWidth, flags)};
458466 const char *convertedStr{converted.str };
459- if (IsInfOrNaN (convertedStr, static_cast < int >( converted.length ) )) {
467+ if (IsInfOrNaN (converted. str , converted.length )) {
460468 return editWidth > 0 &&
461469 converted.length > static_cast <std::size_t >(editWidth)
462470 ? EmitRepeated (io_, ' *' , editWidth)
@@ -585,8 +593,8 @@ RT_API_ATTRS DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) {
585593 flags |= decimal::AlwaysSign;
586594 }
587595 decimal::ConversionToDecimalResult converted{
588- ConvertToDecimal (significantDigits, edit.modes .round , flags)};
589- if (IsInfOrNaN (converted.str , static_cast < int >( converted.length ) )) {
596+ ConvertToDecimal (significantDigits, edit.modes .round , editWidth, flags)};
597+ if (IsInfOrNaN (converted.str , converted.length )) {
590598 return edit; // Inf/Nan -> Ew.d (same as Fw.d)
591599 }
592600 int expo{IsZero () ? 1 : converted.decimalExponent }; // 's'
@@ -619,7 +627,7 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditListDirectedOutput(
619627 const DataEdit &edit) {
620628 decimal::ConversionToDecimalResult converted{
621629 ConvertToDecimal (1 , edit.modes .round )};
622- if (IsInfOrNaN (converted.str , static_cast < int >( converted.length ) )) {
630+ if (IsInfOrNaN (converted.str , converted.length )) {
623631 DataEdit copy{edit};
624632 copy.variation = DataEdit::ListDirected;
625633 return EditEorDOutput (copy);
@@ -652,15 +660,17 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditListDirectedOutput(
652660template <int KIND>
653661RT_API_ATTRS auto RealOutputEditing<KIND>::ConvertToHexadecimal(
654662 int significantDigits, enum decimal::FortranRounding rounding,
655- int flags) -> ConvertToHexadecimalResult {
663+ int editWidth, int flags) -> ConvertToHexadecimalResult {
656664 if (x_.IsNaN () || x_.IsInfinite ()) {
657- auto converted{ConvertToDecimal (significantDigits, rounding, flags)};
658- return {converted.str , static_cast <int >(converted.length ), 0 };
665+ auto converted{
666+ ConvertToDecimal (significantDigits, rounding, editWidth, flags)};
667+ return {converted.str , static_cast <int >(converted.length ), /* exponent=*/ 0 };
659668 }
660669 x_.RoundToBits (4 * significantDigits, rounding);
661670 if (x_.IsInfinite ()) { // rounded away to +/-Inf
662- auto converted{ConvertToDecimal (significantDigits, rounding, flags)};
663- return {converted.str , static_cast <int >(converted.length ), 0 };
671+ auto converted{
672+ ConvertToDecimal (significantDigits, rounding, editWidth, flags)};
673+ return {converted.str , static_cast <int >(converted.length ), /* exponent=*/ 0 };
664674 }
665675 int len{0 };
666676 if (x_.IsNegative ()) {
@@ -724,8 +734,8 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) {
724734 (common::PrecisionOfRealKind (16 ) + 3 ) / 4 };
725735 significantDigits = maxSigHexDigits;
726736 }
727- auto converted{
728- ConvertToHexadecimal ( significantDigits, edit.modes .round , flags)};
737+ auto converted{ConvertToHexadecimal (
738+ significantDigits, edit.modes .round , editWidth , flags)};
729739 if (IsInfOrNaN (converted.str , converted.length )) {
730740 return editWidth > 0 && converted.length > editWidth
731741 ? EmitRepeated (io_, ' *' , editWidth)
0 commit comments