17684d5e0SkleinkThis directory contains source for a library of binary -> decimal 27684d5e0Skleinkand decimal -> binary conversion routines, for single-, double-, 37684d5e0Skleinkand extended-precision IEEE binary floating-point arithmetic, and 47684d5e0Skleinkother IEEE-like binary floating-point, including "double double", 57684d5e0Skleinkas in 67684d5e0Skleink 77684d5e0Skleink T. J. Dekker, "A Floating-Point Technique for Extending the 87684d5e0Skleink Available Precision", Numer. Math. 18 (1971), pp. 224-242 97684d5e0Skleink 107684d5e0Skleinkand 117684d5e0Skleink 127684d5e0Skleink "Inside Macintosh: PowerPC Numerics", Addison-Wesley, 1994 137684d5e0Skleink 147684d5e0SkleinkThe conversion routines use double-precision floating-point arithmetic 157684d5e0Skleinkand, where necessary, high precision integer arithmetic. The routines 167684d5e0Skleinkare generalizations of the strtod and dtoa routines described in 177684d5e0Skleink 187684d5e0Skleink David M. Gay, "Correctly Rounded Binary-Decimal and 197684d5e0Skleink Decimal-Binary Conversions", Numerical Analysis Manuscript 207684d5e0Skleink No. 90-10, Bell Labs, Murray Hill, 1990; 217684d5e0Skleink http://cm.bell-labs.com/cm/cs/what/ampl/REFS/rounding.ps.gz 227684d5e0Skleink 237684d5e0Skleink(based in part on papers by Clinger and Steele & White: see the 247684d5e0Skleinkreferences in the above paper). 257684d5e0Skleink 267684d5e0SkleinkThe present conversion routines should be able to use any of IEEE binary, 277684d5e0SkleinkVAX, or IBM-mainframe double-precision arithmetic internally, but I (dmg) 287684d5e0Skleinkhave so far only had a chance to test them with IEEE double precision 297684d5e0Skleinkarithmetic. 307684d5e0Skleink 317684d5e0SkleinkThe core conversion routines are strtodg for decimal -> binary conversions 327684d5e0Skleinkand gdtoa for binary -> decimal conversions. These routines operate 337684d5e0Skleinkon arrays of unsigned 32-bit integers of type ULong, a signed 32-bit 347684d5e0Skleinkexponent of type Long, and arithmetic characteristics described in 357684d5e0Skleinkstruct FPI; FPI, Long, and ULong are defined in gdtoa.h. File arith.h 367684d5e0Skleinkis supposed to provide #defines that cause gdtoa.h to define its 377684d5e0Skleinktypes correctly. File arithchk.c is source for a program that 387684d5e0Skleinkgenerates a suitable arith.h on all systems where I've been able to 397684d5e0Skleinktest it. 407684d5e0Skleink 417684d5e0SkleinkThe core conversion routines are meant to be called by helper routines 427684d5e0Skleinkthat know details of the particular binary arithmetic of interest and 437684d5e0Skleinkconvert. The present directory provides helper routines for 5 variants 447684d5e0Skleinkof IEEE binary floating-point arithmetic, each indicated by one or 457684d5e0Skleinktwo letters: 467684d5e0Skleink 477684d5e0Skleink f IEEE single precision 487684d5e0Skleink d IEEE double precision 497684d5e0Skleink x IEEE extended precision, as on Intel 80x87 507684d5e0Skleink and software emulations of Motorola 68xxx chips 517684d5e0Skleink that do not pad the way the 68xxx does, but 527684d5e0Skleink only store 80 bits 537684d5e0Skleink xL IEEE extended precision, as on Motorola 68xxx chips 547684d5e0Skleink Q quad precision, as on Sun Sparc chips 557684d5e0Skleink dd double double, pairs of IEEE double numbers 567684d5e0Skleink whose sum is the desired value 577684d5e0Skleink 587684d5e0SkleinkFor decimal -> binary conversions, there are three families of 59*185969ddSchristoshelper routines: one for round-nearest (or the current rounding 60*185969ddSchristosmode on IEEE-arithmetic systems that provide the C99 fegetround() 61*185969ddSchristosfunction, if compiled with -DHonor_FLT_ROUNDS): 627684d5e0Skleink 637684d5e0Skleink strtof 647684d5e0Skleink strtod 657684d5e0Skleink strtodd 667684d5e0Skleink strtopd 677684d5e0Skleink strtopf 687684d5e0Skleink strtopx 697684d5e0Skleink strtopxL 707684d5e0Skleink strtopQ 717684d5e0Skleink 727684d5e0Skleinkone with rounding direction specified: 737684d5e0Skleink 747684d5e0Skleink strtorf 757684d5e0Skleink strtord 767684d5e0Skleink strtordd 777684d5e0Skleink strtorx 787684d5e0Skleink strtorxL 797684d5e0Skleink strtorQ 807684d5e0Skleink 817684d5e0Skleinkand one for computing an interval (at most one bit wide) that contains 827684d5e0Skleinkthe decimal number: 837684d5e0Skleink 847684d5e0Skleink strtoIf 857684d5e0Skleink strtoId 867684d5e0Skleink strtoIdd 877684d5e0Skleink strtoIx 887684d5e0Skleink strtoIxL 897684d5e0Skleink strtoIQ 907684d5e0Skleink 917684d5e0SkleinkThe latter call strtoIg, which makes one call on strtodg and adjusts 927684d5e0Skleinkthe result to provide the desired interval. On systems where native 937684d5e0Skleinkarithmetic can easily make one-ulp adjustments on values in the 947684d5e0Skleinkdesired floating-point format, it might be more efficient to use the 957684d5e0Skleinknative arithmetic. Routine strtodI is a variant of strtoId that 967684d5e0Skleinkillustrates one way to do this for IEEE binary double-precision 977684d5e0Skleinkarithmetic -- but whether this is more efficient remains to be seen. 987684d5e0Skleink 997684d5e0SkleinkFunctions strtod and strtof have "natural" return types, float and 1007684d5e0Skleinkdouble -- strtod is specified by the C standard, and strtof appears 1017684d5e0Skleinkin the stdlib.h of some systems, such as (at least some) Linux systems. 1027684d5e0SkleinkThe other functions write their results to their final argument(s): 1037684d5e0Skleinkto the final two argument for the strtoI... (interval) functions, 1047684d5e0Skleinkand to the final argument for the others (strtop... and strtor...). 1057684d5e0SkleinkWhere possible, these arguments have "natural" return types (double* 1067684d5e0Skleinkor float*), to permit at least some type checking. In reality, they 1077684d5e0Skleinkare viewed as arrays of ULong (or, for the "x" functions, UShort) 1087684d5e0Skleinkvalues. On systems where long double is the appropriate type, one can 1097684d5e0Skleinkpass long double* final argument(s) to these routines. The int value 1107684d5e0Skleinkthat these routines return is the return value from the call they make 1117684d5e0Skleinkon strtodg; see the enum of possible return values in gdtoa.h. 1127684d5e0Skleink 1137684d5e0SkleinkSource files g_ddfmt.c, misc.c, smisc.c, strtod.c, strtodg.c, and ulp.c 1147684d5e0Skleinkshould use true IEEE double arithmetic (not, e.g., double extended), 1157684d5e0Skleinkat least for storing (and viewing the bits of) the variables declared 1167684d5e0Skleink"double" within them. 1177684d5e0Skleink 1187684d5e0SkleinkOne detail indicated in struct FPI is whether the target binary 1197684d5e0Skleinkarithmetic departs from the IEEE standard by flushing denormalized 1207684d5e0Skleinknumbers to 0. On systems that do this, the helper routines for 1217684d5e0Skleinkconversion to double-double format (when compiled with 1227684d5e0SkleinkSudden_Underflow #defined) penalize the bottom of the exponent 1237684d5e0Skleinkrange so that they return a nonzero result only when the least 1247684d5e0Skleinksignificant bit of the less significant member of the pair of 1257684d5e0Skleinkdouble values returned can be expressed as a normalized double 1267684d5e0Skleinkvalue. An alternative would be to drop to 53-bit precision near 1277684d5e0Skleinkthe bottom of the exponent range. To get correct rounding, this 1287684d5e0Skleinkwould (in general) require two calls on strtodg (one specifying 1297684d5e0Skleink126-bit arithmetic, then, if necessary, one specifying 53-bit 1307684d5e0Skleinkarithmetic). 1317684d5e0Skleink 1327684d5e0SkleinkBy default, the core routine strtodg and strtod set errno to ERANGE 1337684d5e0Skleinkif the result overflows to +Infinity or underflows to 0. Compile 1347684d5e0Skleinkthese routines with NO_ERRNO #defined to inhibit errno assignments. 1357684d5e0Skleink 1367684d5e0SkleinkRoutine strtod is based on netlib's "dtoa.c from fp", and 1377684d5e0Skleink(f = strtod(s,se)) is more efficient for some conversions than, say, 1387684d5e0Skleinkstrtord(s,se,1,&f). Parts of strtod require true IEEE double 1397684d5e0Skleinkarithmetic with the default rounding mode (round-to-nearest) and, on 1407684d5e0Skleinksystems with IEEE extended-precision registers, double-precision 1417684d5e0Skleink(53-bit) rounding precision. If the machine uses (the equivalent of) 1427684d5e0SkleinkIntel 80x87 arithmetic, the call 1437684d5e0Skleink _control87(PC_53, MCW_PC); 1447684d5e0Skleinkdoes this with many compilers. Whether this or another call is 1457684d5e0Skleinkappropriate depends on the compiler; for this to work, it may be 1467684d5e0Skleinknecessary to #include "float.h" or another system-dependent header 1477684d5e0Skleinkfile. 1487684d5e0Skleink 1497684d5e0SkleinkSource file strtodnrp.c gives a strtod that does not require 53-bit 1507684d5e0Skleinkrounding precision on systems (such as Intel IA32 systems) that may 1517684d5e0Skleinksuffer double rounding due to use of extended-precision registers. 1527684d5e0SkleinkFor some conversions this variant of strtod is less efficient than the 1537684d5e0Skleinkone in strtod.c when the latter is run with 53-bit rounding precision. 1547684d5e0Skleink 1557684d5e0SkleinkThe values that the strto* routines return for NaNs are determined by 1567684d5e0Skleinkgd_qnan.h, which the makefile generates by running the program whose 1577684d5e0Skleinksource is qnan.c. Note that the rules for distinguishing signaling 1587684d5e0Skleinkfrom quiet NaNs are system-dependent. For cross-compilation, you need 1597684d5e0Skleinkto determine arith.h and gd_qnan.h suitably, e.g., using the 1607684d5e0Skleinkarithmetic of the target machine. 1617684d5e0Skleink 1627684d5e0SkleinkC99's hexadecimal floating-point constants are recognized by the 1637684d5e0Skleinkstrto* routines (but this feature has not yet been heavily tested). 1647684d5e0SkleinkCompiling with NO_HEX_FP #defined disables this feature. 1657684d5e0Skleink 1667684d5e0SkleinkWhen compiled with -DINFNAN_CHECK, the strto* routines recognize C99's 1677684d5e0SkleinkNaN and Infinity syntax. Moreover, unless No_Hex_NaN is #defined, the 1687684d5e0Skleinkstrto* routines also recognize C99's NaN(...) syntax: they accept 1697684d5e0Skleink(case insensitively) strings of the form NaN(x), where x is a string 1707684d5e0Skleinkof hexadecimal digits and spaces; if there is only one string of 1717684d5e0Skleinkhexadecimal digits, it is taken for the fraction bits of the resulting 1727684d5e0SkleinkNaN; if there are two or more strings of hexadecimal digits, each 1737684d5e0Skleinkstring is assigned to the next available sequence of 32-bit words of 1747684d5e0Skleinkfractions bits (starting with the most significant), right-aligned in 1757684d5e0Skleinkeach sequence. 1767684d5e0Skleink 1777684d5e0SkleinkFor binary -> decimal conversions, I've provided just one family 1787684d5e0Skleinkof helper routines: 1797684d5e0Skleink 1807684d5e0Skleink g_ffmt 1817684d5e0Skleink g_dfmt 1827684d5e0Skleink g_ddfmt 1837684d5e0Skleink g_xfmt 1847684d5e0Skleink g_xLfmt 1857684d5e0Skleink g_Qfmt 1867684d5e0Skleink 1877684d5e0Skleinkwhich do a "%g" style conversion either to a specified number of decimal 1887684d5e0Skleinkplaces (if their ndig argument is positive), or to the shortest 1897684d5e0Skleinkdecimal string that rounds to the given binary floating-point value 1907684d5e0Skleink(if ndig <= 0). They write into a buffer supplied as an argument 1917684d5e0Skleinkand return either a pointer to the end of the string (a null character) 1927684d5e0Skleinkin the buffer, if the buffer was long enough, or 0. Other forms of 1937684d5e0Skleinkconversion are easily done with the help of gdtoa(), such as %e or %f 1947684d5e0Skleinkstyle and conversions with direction of rounding specified (so that, if 1957684d5e0Skleinkdesired, the decimal value is either >= or <= the binary value). 196*185969ddSchristosOn IEEE-arithmetic systems that provide the C99 fegetround() function, 197*185969ddSchristosif compiled with -DHonor_FLT_ROUNDS, these routines honor the current 198*185969ddSchristosrounding mode. 1997684d5e0Skleink 2007684d5e0SkleinkFor an example of more general conversions based on dtoa(), see 2017684d5e0Skleinknetlib's "printf.c from ampl/solvers". 2027684d5e0Skleink 2037684d5e0SkleinkFor double-double -> decimal, g_ddfmt() assumes IEEE-like arithmetic 2047684d5e0Skleinkof precision max(126, #bits(input)) bits, where #bits(input) is the 2057684d5e0Skleinknumber of mantissa bits needed to represent the sum of the two double 2067684d5e0Skleinkvalues in the input. 2077684d5e0Skleink 2087684d5e0SkleinkThe makefile creates a library, gdtoa.a. To use the helper 2097684d5e0Skleinkroutines, a program only needs to include gdtoa.h. All the 2107684d5e0Skleinksource files for gdtoa.a include a more extensive gdtoaimp.h; 2117684d5e0Skleinkamong other things, gdtoaimp.h has #defines that make "internal" 2127684d5e0Skleinknames end in _D2A. To make a "system" library, one could modify 2137684d5e0Skleinkthese #defines to make the names start with __. 2147684d5e0Skleink 2157684d5e0SkleinkVarious comments about possible #defines appear in gdtoaimp.h, 2167684d5e0Skleinkbut for most purposes, arith.h should set suitable #defines. 2177684d5e0Skleink 2187684d5e0SkleinkSystems with preemptive scheduling of multiple threads require some 2197684d5e0Skleinkmanual intervention. On such systems, it's necessary to compile 2207684d5e0Skleinkdmisc.c, dtoa.c gdota.c, and misc.c with MULTIPLE_THREADS #defined, 2217684d5e0Skleinkand to provide (or suitably #define) two locks, acquired by 2227684d5e0SkleinkACQUIRE_DTOA_LOCK(n) and freed by FREE_DTOA_LOCK(n) for n = 0 or 1. 2237684d5e0Skleink(The second lock, accessed in pow5mult, ensures lazy evaluation of 2247684d5e0Skleinkonly one copy of high powers of 5; omitting this lock would introduce 2257684d5e0Skleinka small probability of wasting memory, but would otherwise be harmless.) 2267684d5e0SkleinkRoutines that call dtoa or gdtoa directly must also invoke freedtoa(s) 2277684d5e0Skleinkto free the value s returned by dtoa or gdtoa. It's OK to do so whether 2287684d5e0Skleinkor not MULTIPLE_THREADS is #defined, and the helper g_*fmt routines 2297684d5e0Skleinklisted above all do this indirectly (in gfmt_D2A(), which they all call). 2307684d5e0Skleink 2317684d5e0SkleinkBy default, there is a private pool of memory of length 2000 bytes 2327684d5e0Skleinkfor intermediate quantities, and MALLOC (see gdtoaimp.h) is called only 2337684d5e0Skleinkif the private pool does not suffice. 2000 is large enough that MALLOC 2347684d5e0Skleinkis called only under very unusual circumstances (decimal -> binary 2357684d5e0Skleinkconversion of very long strings) for conversions to and from double 2367684d5e0Skleinkprecision. For systems with preemptively scheduled multiple threads 2377684d5e0Skleinkor for conversions to extended or quad, it may be appropriate to 2387684d5e0Skleink#define PRIVATE_MEM nnnn, where nnnn is a suitable value > 2000. 2397684d5e0SkleinkFor extended and quad precisions, -DPRIVATE_MEM=20000 is probably 2407684d5e0Skleinkplenty even for many digits at the ends of the exponent range. 2417684d5e0SkleinkUse of the private pool avoids some overhead. 2427684d5e0Skleink 2437684d5e0SkleinkDirectory test provides some test routines. See its README. 2447684d5e0SkleinkI've also tested this stuff (except double double conversions) 2457684d5e0Skleinkwith Vern Paxson's testbase program: see 2467684d5e0Skleink 2477684d5e0Skleink V. Paxson and W. Kahan, "A Program for Testing IEEE Binary-Decimal 2487684d5e0Skleink Conversion", manuscript, May 1991, 2497684d5e0Skleink ftp://ftp.ee.lbl.gov/testbase-report.ps.Z . 2507684d5e0Skleink 2517684d5e0Skleink(The same ftp directory has source for testbase.) 2527684d5e0Skleink 2537684d5e0SkleinkSome system-dependent additions to CFLAGS in the makefile: 2547684d5e0Skleink 2557684d5e0Skleink HU-UX: -Aa -Ae 2567684d5e0Skleink OSF (DEC Unix): -ieee_with_no_inexact 2577684d5e0Skleink SunOS 4.1x: -DKR_headers -DBad_float_h 2587684d5e0Skleink 2597684d5e0SkleinkIf you want to put this stuff into a shared library and your 2607684d5e0Skleinkoperating system requires export lists for shared libraries, 2617684d5e0Skleinkthe following would be an appropriate export list: 2627684d5e0Skleink 2637684d5e0Skleink dtoa 2647684d5e0Skleink freedtoa 2657684d5e0Skleink g_Qfmt 2667684d5e0Skleink g_ddfmt 2677684d5e0Skleink g_dfmt 2687684d5e0Skleink g_ffmt 2697684d5e0Skleink g_xLfmt 2707684d5e0Skleink g_xfmt 2717684d5e0Skleink gdtoa 2727684d5e0Skleink strtoIQ 2737684d5e0Skleink strtoId 2747684d5e0Skleink strtoIdd 2757684d5e0Skleink strtoIf 2767684d5e0Skleink strtoIx 2777684d5e0Skleink strtoIxL 2787684d5e0Skleink strtod 2797684d5e0Skleink strtodI 2807684d5e0Skleink strtodg 2817684d5e0Skleink strtof 2827684d5e0Skleink strtopQ 2837684d5e0Skleink strtopd 2847684d5e0Skleink strtopdd 2857684d5e0Skleink strtopf 2867684d5e0Skleink strtopx 2877684d5e0Skleink strtopxL 2887684d5e0Skleink strtorQ 2897684d5e0Skleink strtord 2907684d5e0Skleink strtordd 2917684d5e0Skleink strtorf 2927684d5e0Skleink strtorx 2937684d5e0Skleink strtorxL 2947684d5e0Skleink 2957684d5e0SkleinkWhen time permits, I (dmg) hope to write in more detail about the 2967684d5e0Skleinkpresent conversion routines; for now, this README file must suffice. 2977684d5e0SkleinkMeanwhile, if you wish to write helper functions for other kinds of 2987684d5e0SkleinkIEEE-like arithmetic, some explanation of struct FPI and the bits 2997684d5e0Skleinkarray may be helpful. Both gdtoa and strtodg operate on a bits array 3007684d5e0Skleinkdescribed by FPI *fpi. The bits array is of type ULong, a 32-bit 3017684d5e0Skleinkunsigned integer type. Floating-point numbers have fpi->nbits bits, 3027684d5e0Skleinkwith the least significant 32 bits in bits[0], the next 32 bits in 3037684d5e0Skleinkbits[1], etc. These numbers are regarded as integers multiplied by 3047684d5e0Skleink2^e (i.e., 2 to the power of the exponent e), where e is the second 3057684d5e0Skleinkargument (be) to gdtoa and is stored in *exp by strtodg. The minimum 3067684d5e0Skleinkand maximum exponent values fpi->emin and fpi->emax for normalized 3077684d5e0Skleinkfloating-point numbers reflect this arrangement. For example, the 3087684d5e0SkleinkP754 standard for binary IEEE arithmetic specifies doubles as having 3097684d5e0Skleink53 bits, with normalized values of the form 1.xxxxx... times 2^(b-1023), 3107684d5e0Skleinkwith 52 bits (the x's) and the biased exponent b represented explicitly; 3117684d5e0Skleinkb is an unsigned integer in the range 1 <= b <= 2046 for normalized 3127684d5e0Skleinkfinite doubles, b = 0 for denormals, and b = 2047 for Infinities and NaNs. 3137684d5e0SkleinkTo turn an IEEE double into the representation used by strtodg and gdtoa, 3147684d5e0Skleinkwe multiply 1.xxxx... by 2^52 (to make it an integer) and reduce the 3157684d5e0Skleinkexponent e = (b-1023) by 52: 3167684d5e0Skleink 3177684d5e0Skleink fpi->emin = 1 - 1023 - 52 3187684d5e0Skleink fpi->emax = 1046 - 1023 - 52 3197684d5e0Skleink 3207684d5e0SkleinkIn various wrappers for IEEE double, we actually write -53 + 1 rather 3217684d5e0Skleinkthan -52, to emphasize that there are 53 bits including one implicit bit. 3227684d5e0SkleinkField fpi->rounding indicates the desired rounding direction, with 3237684d5e0Skleinkpossible values 3247684d5e0Skleink FPI_Round_zero = toward 0, 3257684d5e0Skleink FPI_Round_near = unbiased rounding -- the IEEE default, 3267684d5e0Skleink FPI_Round_up = toward +Infinity, and 3277684d5e0Skleink FPI_Round_down = toward -Infinity 3287684d5e0Skleinkgiven in gdtoa.h. 3297684d5e0Skleink 3307684d5e0SkleinkField fpi->sudden_underflow indicates whether strtodg should return 3317684d5e0Skleinkdenormals or flush them to zero. Normal floating-point numbers have 3327684d5e0Skleinkbit fpi->nbits in the bits array on. Denormals have it off, with 3337684d5e0Skleinkexponent = fpi->emin. Strtodg provides distinct return values for normals 3347684d5e0Skleinkand denormals; see gdtoa.h. 3357684d5e0Skleink 3367684d5e0SkleinkCompiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes 3377684d5e0Skleinkthe decimal-point character to be taken from the current locale; otherwise 3387684d5e0Skleinkit is '.'. 3397684d5e0Skleink 340*185969ddSchristosSource files dtoa.c and strtod.c in this directory are derived from 341*185969ddSchristosnetlib's "dtoa.c from fp" and are meant to function equivalently. 342*185969ddSchristosWhen compiled with Honor_FLT_ROUNDS #defined (on systems that provide 343*185969ddSchristosFLT_ROUNDS and fegetround() as specified in the C99 standard), they 344*185969ddSchristoshonor the current rounding mode. Because FLT_ROUNDS is buggy on some 345*185969ddSchristos(Linux) systems -- not reflecting calls on fesetround(), as the C99 346*185969ddSchristosstandard says it should -- when Honor_FLT_ROUNDS is #defined, the 347*185969ddSchristoscurrent rounding mode is obtained from fegetround() rather than from 348*185969ddSchristosFLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined. 349*185969ddSchristos 350*185969ddSchristosCompile with -DUSE_LOCALE to use the current locale; otherwise 351*185969ddSchristosdecimal points are assumed to be '.'. With -DUSE_LOCALE, unless 352*185969ddSchristosyou also compile with -DNO_LOCALE_CACHE, the details about the 353*185969ddSchristoscurrent "decimal point" character string are cached and assumed not 354*185969ddSchristosto change during the program's execution. 355*185969ddSchristos 356*185969ddSchristosOn machines with a 64-bit long double and perhaps a 113-bit "quad" 357*185969ddSchristostype, you can invoke "make Printf" to add Printf (and variants, such 358*185969ddSchristosas Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of 359*185969ddSchristosprintf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long 360*185969ddSchristosdouble and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad 361*185969ddSchristosprecision printing. 362*185969ddSchristos 3637684d5e0SkleinkPlease send comments to David M. Gay (dmg at acm dot org, with " at " 3647684d5e0Skleinkchanged at "@" and " dot " changed to "."). 365