1111
1212 module json_string_utilities
1313
14+ use ,intrinsic :: ieee_arithmetic
1415 use json_kinds
1516 use json_parameters
1617
@@ -148,33 +149,61 @@ end subroutine string_to_integer
148149! Convert a real value to a string.
149150!
150151! ### Modified
151- ! * Izaak Beekman : 02/24/2015 : added the compact option.
152+ ! * Izaak Beekman : 02/24/2015 : added the compact option.
152153! * Jacob Williams : 10/27/2015 : added the star option.
154+ ! * Jacob Williams : 07/07/2019 : added null and ieee options.
153155
154- subroutine real_to_string (rval ,real_fmt ,compact_real ,str )
156+ subroutine real_to_string (rval ,real_fmt ,compact_real ,non_normals_to_null , str )
155157
156158 implicit none
157159
158160 real (RK),intent (in ) :: rval ! ! real value.
159161 character (kind= CDK,len=* ),intent (in ) :: real_fmt ! ! format for real numbers
160162 logical (LK),intent (in ) :: compact_real ! ! compact the string so that it is
161163 ! ! displayed with fewer characters
164+ logical (LK),intent (in ) :: non_normals_to_null ! ! If True, NaN, Infinity, or -Infinity are returned as `null`.
165+ ! ! If False, the string value will be returned in quotes
166+ ! ! (e.g., "NaN", "Infinity", or "-Infinity" )
162167 character (kind= CK,len=* ),intent (out ) :: str ! ! `rval` converted to a string.
163168
164- integer (IK) :: istat
169+ integer (IK) :: istat ! ! write `iostat` flag
165170
166- if (real_fmt== star) then
167- write (str,fmt=* ,iostat= istat) rval
168- else
169- write (str,fmt= real_fmt,iostat= istat) rval
170- end if
171+ if (ieee_is_finite(rval) .and. .not. ieee_is_nan(rval)) then
172+
173+ ! normal real numbers
174+
175+ if (real_fmt== star) then
176+ write (str,fmt=* ,iostat= istat) rval
177+ else
178+ write (str,fmt= real_fmt,iostat= istat) rval
179+ end if
180+
181+ if (istat== 0 ) then
182+ ! in this case, the default string will be compacted,
183+ ! so that the same value is displayed with fewer characters.
184+ if (compact_real) call compact_real_string(str)
185+ else
186+ str = repeat (star,len (str)) ! error
187+ end if
171188
172- if (istat== 0 ) then
173- ! in this case, the default string will be compacted,
174- ! so that the same value is displayed with fewer characters.
175- if (compact_real) call compact_real_string(str)
176189 else
177- str = repeat (star,len (str))
190+ ! special cases for NaN, Infinity, and -Infinity
191+
192+ if (non_normals_to_null) then
193+ ! return it as a JSON null value
194+ str = null_str
195+ else
196+ ! Let the compiler do the real to string conversion
197+ ! like before, but put the result in quotes so it
198+ ! gets printed as a string
199+ write (str,fmt=* ,iostat= istat) rval
200+ if (istat== 0 ) then
201+ str = quotation_mark// trim (adjustl (str))// quotation_mark
202+ else
203+ str = repeat (star,len (str)) ! error
204+ end if
205+ end if
206+
178207 end if
179208
180209 end subroutine real_to_string
@@ -192,19 +221,34 @@ end subroutine real_to_string
192221! (e.g., when `str='1E-5'`).
193222! * Jacob Williams : 2/6/2017 : moved core logic to this routine.
194223
195- subroutine string_to_real (str ,rval ,status_ok )
224+ subroutine string_to_real (str ,use_quiet_nan , rval ,status_ok )
196225
197226 implicit none
198227
199- character (kind= CK,len=* ),intent (in ) :: str ! ! the string to convert to a real
200- real (RK),intent (out ) :: rval ! ! `str` converted to a real value
201- logical (LK),intent (out ) :: status_ok ! ! true if there were no errors
228+ character (kind= CK,len=* ),intent (in ) :: str ! ! the string to convert to a real
229+ logical (LK),intent (in ) :: use_quiet_nan ! ! if true, return NaN's as `ieee_quiet_nan`.
230+ ! ! otherwise, use `ieee_signaling_nan`.
231+ real (RK),intent (out ) :: rval ! ! `str` converted to a real value
232+ logical (LK),intent (out ) :: status_ok ! ! true if there were no errors
202233
203234 integer (IK) :: ierr ! ! read iostat error code
204235
205236 read (str,fmt=* ,iostat= ierr) rval
206237 status_ok = (ierr== 0 )
207- if (.not. status_ok) rval = 0.0_RK
238+ if (.not. status_ok) then
239+ rval = 0.0_RK
240+ else
241+ if (ieee_support_nan(rval)) then
242+ if (ieee_is_nan(rval)) then
243+ ! make sure to return the correct NaN
244+ if (use_quiet_nan) then
245+ rval = ieee_value(rval,ieee_quiet_nan)
246+ else
247+ rval = ieee_value(rval,ieee_signaling_nan)
248+ end if
249+ end if
250+ end if
251+ end if
208252
209253 end subroutine string_to_real
210254! *****************************************************************************************
0 commit comments