www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ConvExt.d v0.2 please review, comment, suggest, and / or correct.

reply David L. Davis <SpottedTiger yahoo.com> writes:
Well per Walter advice in to below message,

D forum thread: "process improvement for phobos"
digitalmars.D/20328

I'd like to resubmit to my fellow D developers for comments and review, the
following code that's been submitted to Walter for including into Phobos.

Recently, D v0.120 has forced a number of correction to be made into this code
(a lot of additional cast()s had to put into place...which was kool, a better
compiler means better executing code), but in so doing I found some areas that
needed a bit more tighting up. 

Please free feel to give some suggests and / or correction to the following
code, that's designed to fill in the missing "string to floating-point" function
gap in std.conv. Note I'm in no way a floating-point expert, but just a guy
trying in improve and move D forward...one line or one function at a time if I
possibly can.

# /+
#  ' Module        : convext.d - "char[] to floating-point number" 
#  '               : wrapper functions.
#  ' Version       : v0.2 
#  '               :
#  ' Author(s)     : David L. 'SpottedTiger' Davis 
#  '               : for the wrapper functions / unittests,  
#  '               : Pavel "EvilOne" Minayev for writing the std.math2 code
#  '               : that does most of the work, and to Walter Bright for 
#  '               : the great D compiler, as well as the D's Phobos runtime 
#  '               : library filled with very useful modules and functions
#  '               : ...of which the std.math2 module is a part of.
#  '               :
#  ' Created Date  : 07.Nov.04 Complied and Tested with dmd v0.105
#  ' Modified Date : 09.Nov.04 Added unitconvext code, 
#  '               :           recompiled and tested with dmd v0.106.
#  '               : 20.Jan.05 Recompiled and tested with dmd v0.111.
#  '               : 20.Mar.05 Recomplied and Tested with dmd v0.119.
#  '               : 08.Apr.05 Recompiled and tested with dmd v0.120, 
#  '               :           well it looks like the fixes done in v0.120 
#  '               :           to tight up floating-point convertions has 
#  '               :           exposed some errors mainly in the toIfloat(), 
#  '               :           toIdouble(), and toIReal() functions, and  
#  '               :           some minor unittesting errors (many of which 
#  '               :           needed a cast() to correct things) that I've
#  '               :           fixed.
#  '               :
#  ' Requirements  : std.string for the ifind() and find() functions, 
#  '               : and std.math2 for both the atof() and feq() functions. 
#  '               : 
#  ' Licence       : DigitalMars (waiting for this to be included into 
#  '               : std.conv.d, at which time this code will be pulled
#  '               : totally from this site.)
#  ' --------------------------------------------------------------------------
#  ' Note: The main purpose of this code is to extend std.conv, with some
#  '       useful "char[] to floating-point number" wrapper functions...
#  '       which mainly uses the "real std.math2.atof( in char[] )" function 
#  '       for all the conversions.
#  '
#  '
#  ' To complie for a unittest:
#  ' C:\dmd>bin\dmd convext.d -debug=convext -unittest
#  '
#  ' To compile a D program that use convext.d:
#  ' C:\dmd>bin\dmd MySource.d convext.d
#  '
#  ' Public functions:
#  ' ------------------------------
#  ' 01) bit toBit( in char )
#  ' 02) bit toBit( in char[] ) 
#  ' 03) float toFloat( in char[] )
#  ' 04) double toDouble( in char[] )
#  ' 05) real toReal( in char[] )
#  ' 06) ifloat toIfloat( in char[] )
#  ' 07) idouble toIdouble( in char[] ) 
#  ' 08) ireal toIreal( in char[] )
#  ' 09) cfloat toCfloat( in char[] )
#  ' 10) cdouble toCdouble( in char[] )
#  ' 11) creal toCreal( in char[] )
#  '
#  ' Private functions:
#  ' ------------------------------
#  ' 01) void getComplexStrings( in char[], out char[], out char[] )
#  '
#  +/
# module convext;
# 
# private import std.math2;
# private import std.string;
# 
# debug( convext ) private import std.stdio;
# 
# bit toBit( in char c )
# {
#     if ( c == 't' || c == 'T' || c == '1' || 
#          c == 'Y' || c == 'y' ) 
#         c = '1';
#              
#     return ( c == '1' ? true : false ); 
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toBit( in char ).unittest" );
#     bit b;
# 
#     b = toBit( 'T' );
#     assert( b == true );
#     b = toBit( 'f' );
#     assert( b == false );
#     b = toBit( 'x' );
#     assert( b == false );
#     b = toBit( 'n' );
#     assert( b == false );
# }
# 
# bit toBit( in char[] s )
# {
#     char[] s1 = std.string.toupper( s );
#     
#     if ( s1 == "TRUE" || s1 == "T" || s1 == "1" || 
#          s1 == "Y" || s1 == "YES" || s1 == "ON" ) 
#         s1 = "1";
#              
#     return ( s1 == "1" ? true : false ); 
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toBit( in char[] ).unittest" );
#     bit b;
# 
#     b = toBit( "True" );
#     assert( b == true );
#     b = toBit( "Xta" );
#     assert( b == false );
#     b = toBit( "" );
#     assert( b == false );
#     b = toBit( "yeS" );
#     assert( b == true );
# }
# 
# float toFloat( in char[] s )
# {
#     return cast(float)std.math2.atof( s );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toFloat( in char[] ).unittest" );
#     float f;
# 
#     f = toFloat( "123" );
#     assert( f == 123f );
#     f = toFloat( "+123" );
#     assert( f == +123f );
#     f = toFloat( "-123" );
#     assert( f == -123f );
#     f = toFloat( "123e2" );
#     assert( f == 123e2f );
# 
#     f = toFloat( "123e-2" );
#     assert( f == 123e-2f );
#     f = toFloat( "123." );
#     assert( f == 123.f );
#     f = toFloat( ".456" );
#     assert( f == .456f );
#     f = toFloat( "1.23456E+2" );
#     assert( f == 1.23456E+2f );
# }
# 
# double toDouble( in char[] s )
# {
#     return cast(double)std.math2.atof( s );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toDouble( in char[] ).unittest" );
#     double d;
# 
#     d = toDouble( "123" );
#     assert( d == 123 );
#     d = toDouble( "+123" );
#     assert( d == +123 );
#     d = toDouble( "-123" );
#     assert( d == -123 );
#     d = toDouble( "123e2" );
#     assert( d == 123e2);
#     d = toDouble( "123e-2" );
#     assert( d == 123e-2 );
#     d = toDouble( "123." );
#     assert( d == 123. );
#     d = toDouble( ".456" );
#     assert( d == .456 );
#     d = toDouble( "1.23456E+2" );
#     assert( d == 1.23456E+2 );
# }
# 
# real toReal( in char[] s )
# {
#     return cast(real)std.math2.atof( s );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toReal( in char[] ).unittest" );
#     real r;
# 
#     r = toReal( "123" );
#     assert( r == 123L );
#     r = toReal( "+123" );
#     assert( r == 123L );
#     r = toReal( "-123" );
#     assert( r == -123L );
#     r = toReal( "123e2" );
#     assert( std.math2.feq( r, 123e2L ) );
#     r = toReal( "123e-2" );
#     assert( std.math2.feq( r, 1.23L ) );
#     r = toReal( "123." );
#     assert( r == 123L );
#     r = toReal( ".456" );
#     assert( r == .456L );
# 
#     r = toReal( "1.23456E+2" );
#     assert( std.math2.feq( r,  1.23456E+2L ) );
#     r = toReal( std.string.toString( real.max / 2L ) );
#     assert( std.string.toString( r ) == 
#             std.string.toString( real.max / 2L ) );
#     r = toReal( std.string.toString( real.max ) );
#     assert( std.string.toString( r ) == std.string.toString( real.max ) );
# }
# 
# ifloat toIfloat( in char[] s )
# {
#     float f;
#     ifloat ift;
#     
#     if ( ifind( s, "i" ) > 0f )
#         f = cast(float)std.math2.atof( s[ 0 .. s.length - 1 ] );
#     else
#         f = cast(float)std.math2.atof( s );    
#     
#     if ( f == 0f )
#        ift = cast(ifloat)( 0f );
#     else if ( f.nan == true )   
#         ift = cast(ifloat)f.nan;
#     else    
#         ift = cast(ifloat)( f * 1.0i );
#         
#     return ift;
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toIfloat( in char[] ).unittest" );
#     ifloat ift;
#     float  f;
#     
#     ift = toIfloat( std.string.toString( ifloat.min ) );
#     //writefln( "ift=\"%g\", s=\"%s\"", 
#                  ift, std.string.toString( ifloat.min ) );
# 
#     assert( std.string.toString( ift ) == 
#             std.string.toString( ifloat.min ) );
#     assert( ift.re == ifloat.min.re );
#     assert( std.math2.feq( cast(real)ift.im, cast(real)ifloat.min.im ) );
# 
#     ift = toIfloat( std.string.toString( ifloat.max ) );
#     assert( std.string.toString( ift ) == 
#             std.string.toString( ifloat.max ) );
#     assert( ift.re == ifloat.max.re );
#     assert( std.math2.feq( cast(real)ift, cast(real)ifloat.max ) );
# 
#     ift = toIfloat( std.string.toString( 123.45 ) );
#     assert( std.string.toString( ift ) == std.string.toString( 123.45i ) );
# 
#     ift = toIfloat( std.string.toString( 456.77i ) );
#     assert( std.string.toString( ift ) == std.string.toString( 456.77i ) );
#     
#     ift = toIfloat( std.string.toString( ifloat.nan ) );
#     // There's a isnan() for float, double, and real, 
#     // but no isnani() for ifloat, idouble, ireal, 
#     // cfloat, cdouble, and creal.
#     //
#     //writefln( "ift=%gi, ift.nan=%gi, isnan()=%d", 
#                  ift, ift.nan, std.math.isnan( cast(real)ift.nan ) );
#     assert( std.string.toString( ift.nan ) == 
#             std.string.toString( ifloat.nan ) );
# }
# 
# idouble toIdouble( in char[] s )
# {
#     double  d;
#     idouble id;
#     
#     if ( ifind( s, "i" ) > 0 )
#         d = cast(double)std.math2.atof( s[ 0 .. s.length - 1 ] );
#     else
#         d = cast(double)std.math2.atof( s );    
#     
#     if ( d == 0 )
#        id = cast(idouble)( 0 );
#     else if ( d.nan == true )   
#         id = cast(idouble)d.nan;
#     else    
#         id = cast(idouble)(d * 1.0i);
#     
#     return id;
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toIdouble( in char[] ).unittest" );
#     idouble id;
# 
#     id = toIdouble( std.string.toString( idouble.min ) );
#     assert( std.string.toString( id ) == 
#             std.string.toString( idouble.min ) );
#     assert( std.math2.feq( cast(real)id.re, cast(real)idouble.min.re ) );
#     assert( std.math2.feq( cast(real)id.im, cast(real)idouble.min.im ) );
#     
#     id = toIdouble( std.string.toString( idouble.max ) );
#     assert( std.string.toString( id ) == 
#             std.string.toString( idouble.max ) );
#     assert( std.math2.feq( cast(real)id.re, cast(real)idouble.max.re ) );
#     //assert( std.math2.feq( cast(real)id.im, cast(real)idouble.max.im ) );
# 
#     id = toIdouble( std.string.toString( "123.45" ) );
#     assert( id == 123.45i );
#     
#     id = toIdouble( std.string.toString( idouble.nan ) );
#     assert( std.string.toString( id.nan ) == 
#             std.string.toString( idouble.nan ) );
# }
# 
# ireal toIreal( in char[] s )
# {
#     real  r;
#     ireal ir;
#     
#     if ( ifind( s, "i" ) > 0 )
#         r = cast(real)std.math2.atof( s[ 0 .. s.length - 1 ] );
#     else
#         r = cast(real)std.math2.atof( s );    
#     
#     if ( r == 0L )
#        ir = cast(ireal)( 0L );
#     else if ( r.nan == true )   
#         ir = cast(ireal)r.nan;
#     else    
#         ir = cast(ireal)(r * 1.0i);
#         
#     return ir;
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toIreal( in char[] ).unittest" );
#     ireal ir;
# 
#     ir = toIreal( std.string.toString( ireal.min ) );
#     assert( std.string.toString( ir ) == std.string.toString( ireal.min ) );
#     assert( std.math2.feq( cast(real)ir.re, cast(real)ireal.min.re ) );
#     assert( std.math2.feq( cast(real)ir.im, cast(real)ireal.min.im ) );
# 
#     ir = toIreal( std.string.toString( ireal.max ) );
#     assert( std.string.toString( ir ) == std.string.toString( ireal.max ) );
#     assert( std.math2.feq( cast(real)ir.re, cast(real)ireal.max.re ) );
# 
#     ir = toIreal( std.string.toString( "123.45" ) );
#     assert( std.math2.feq( cast(real)ir.re, cast(real)123.45i ) ); 
#     
#     ir = toIreal( std.string.toString( ireal.nan ) );
#     assert( std.string.toString( ir.nan ) == 
#             std.string.toString( ireal.nan ) );
# }
# 
# cfloat toCfloat( in char[] s )
# {
#     char[] s1;
#     char[] s2;
#     
#     getComplexStrings( s, s1, s2 );
#     
#     return cast(cfloat)std.math2.atof( s1 ) + 
#            ( cast(cfloat)std.math2.atof( s2 ) * 1.0i );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toCfloat( in char[] ).unittest" );
#     cfloat cf;
# 
#     cf = toCfloat( std.string.toString( cfloat.min ) );
#     assert( std.string.toString( cf ) == std.string.toString( cfloat.min ) );
# 
#     cf = toCfloat( std.string.toString( cfloat.max ) );
#     assert( std.string.toString( cf ) == std.string.toString( cfloat.max ) );
# 
#     cf = toCfloat( std.string.toString( "1.2345e-5+0i" ) );
#     assert( std.string.toString( cf ) == 
#             std.string.toString( 1.2345e-5+0i ) );
#     //assert( cf == 1.2345e-5+0i );
# }
# 
# cdouble toCdouble( in char[] s )
# {
#     char[] s1;
#     char[] s2;
#     
#     getComplexStrings( s, s1, s2 );
#     
#     return cast(cdouble)std.math2.atof( s1 ) + 
#            ( cast(cdouble)std.math2.atof( s2 ) * 1.0i );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toCdouble( in char[] ).unittest" );
#     cdouble cd;
# 
#     cd = toCdouble( std.string.toString( cdouble.min ) );
#     assert( std.string.toString( cd ) == 
#             std.string.toString( cdouble.min ) );
# 
#     cd = toCdouble( std.string.toString( cdouble.max ) );
#     assert( std.string.toString( cd ) == 
#             std.string.toString( cdouble.max ) );
# 
#     cd = toCdouble( std.string.toString( "1.2345e-5+0i" ) );
#     assert( std.string.toString( cd ) == 
#             std.string.toString( 1.2345e-5+0i ) );
#     //assert( cd == 1.2345e-5+0i );
# }
# 
# creal toCreal( in char[] s )
# {
#     char[] s1;
#     char[] s2;
#     
#     getComplexStrings( s, s1, s2 );
#     
#     return cast(creal)std.math2.atof( s1 ) + 
#            ( cast(creal)std.math2.atof( s2 ) * 1.0i );
# }
# 
# unittest
# {
#     debug( convext ) writefln( "convext.toCreal( in char[] ).unittest" );
#     creal cr;
# 
#     cr = toCreal( std.string.toString( creal.min ) );
#     assert( std.string.toString( cr ) == std.string.toString( creal.min ) );
#     assert( std.math2.feq( cast(real)cr.re, cast(real)creal.min.re ) );
#     assert( std.math2.feq( cast(real)cr.im, cast(real)creal.min.im ) );
#     
#     cr = toCreal( std.string.toString( creal.max ) );
#     assert( std.string.toString( cr ) == std.string.toString( creal.max ) );
#     //assert( std.math2.feq( cast(real)cr.re, cast(real)creal.max.re ) );
#     //assert( std.math2.feq( cast(real)cr.im, cast(real)creal.max.im ) );
#  
#     cr = toCreal( std.string.toString( "1.2345e-5+0i" ) );
#     assert( std.string.toString( cr ) == 
#             std.string.toString( 1.2345e-5+0i ) );
#     assert( std.math2.feq( cast(real)cr.re, cast(real)1.2345e-5+0i.re ) );
#     //assert( std.math2.feq( cast(real)cr.im, cast(real)1.2345e-5+0i.im ) );
# 
#     cr = toCreal( std.string.toString( "0.0e-0+0i" ) );
#     assert( std.string.toString( cr ) == std.string.toString( 0.0e-0+0i ) );
#     assert( cr == 0.0e-0+0i );
# }
# 
# private void getComplexStrings( in char[] s, out char[] s1, out char[] s2 )
# {
#     int iPos1 = 0;
#     int iPos2 = 0;
#     
#     s1 = s.dup;
#     s2 = "";
#     
#     iPos1 = ifind( s1, "e+" );
#     if ( iPos1 != -1 )
#         iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
# 
#     if ( iPos1 == -1 )
#     {
#         iPos1 = ifind( s1, "e-" );
#         if ( iPos1 != -1 )
#             iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
#     }
# 
#     if ( iPos1 == -1 )
#         s1 = "0e+0";
#  
#     if ( iPos2 != -1 )   
#     { 
#         iPos2 += iPos1;
#         s2 = s1[ iPos2 + 4 .. s1.length - 1 ].dup;
#         s1 = s1[ 0 .. iPos2 + 3 ];
#     }
#              
#     //writefln( "getComplexStrings().s1=%s, s2=%s, iPos1=%d, iPos2=%d", 
#                  s1, s2, iPos1, iPos2 );
# 
#     if ( iPos2 == -1 )
#     {
#         s1 = s1[ 0 .. s1.length - 1 ];
#         s2 = "0";             
#     }
#     
# } // end void getComplexStrings( in char[], out char[], out char[] )
# 
# debug( convext )
# {
# int main()
# {
#     writefln( "convext.unittests done!" );
#     return 0;
# 
# } // end int main()
# }

Thanks in advance,
David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
Apr 09 2005
next sibling parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
Little bit out of scope but I would like to rise question about
string-to-value  function signatures again.

My proposal is to use

int valueOf( string s , out T v, in T defaultValue = 0 )

Where T is a numeric type int, uint, etc.
Functions return number of valid characters processed.

Such functions are flexible enough to allow blind and controllable
conversions.

Andrew.



"David L. Davis" <SpottedTiger yahoo.com> wrote in message 
news:d3903a$vr8$1 digitaldaemon.com...
 Well per Walter advice in to below message,

 D forum thread: "process improvement for phobos"
 digitalmars.D/20328

 I'd like to resubmit to my fellow D developers for comments and review, 
 the
 following code that's been submitted to Walter for including into Phobos.

 Recently, D v0.120 has forced a number of correction to be made into this 
 code
 (a lot of additional cast()s had to put into place...which was kool, a 
 better
 compiler means better executing code), but in so doing I found some areas 
 that
 needed a bit more tighting up.

 Please free feel to give some suggests and / or correction to the 
 following
 code, that's designed to fill in the missing "string to floating-point" 
 function
 gap in std.conv. Note I'm in no way a floating-point expert, but just a 
 guy
 trying in improve and move D forward...one line or one function at a time 
 if I
 possibly can.

 # /+
 #  ' Module        : convext.d - "char[] to floating-point number"
 #  '               : wrapper functions.
 #  ' Version       : v0.2
 #  '               :
 #  ' Author(s)     : David L. 'SpottedTiger' Davis
 #  '               : for the wrapper functions / unittests,
 #  '               : Pavel "EvilOne" Minayev for writing the std.math2 
 code
 #  '               : that does most of the work, and to Walter Bright for
 #  '               : the great D compiler, as well as the D's Phobos 
 runtime
 #  '               : library filled with very useful modules and functions
 #  '               : ...of which the std.math2 module is a part of.
 #  '               :
 #  ' Created Date  : 07.Nov.04 Complied and Tested with dmd v0.105
 #  ' Modified Date : 09.Nov.04 Added unitconvext code,
 #  '               :           recompiled and tested with dmd v0.106.
 #  '               : 20.Jan.05 Recompiled and tested with dmd v0.111.
 #  '               : 20.Mar.05 Recomplied and Tested with dmd v0.119.
 #  '               : 08.Apr.05 Recompiled and tested with dmd v0.120,
 #  '               :           well it looks like the fixes done in v0.120
 #  '               :           to tight up floating-point convertions has
 #  '               :           exposed some errors mainly in the 
 toIfloat(),
 #  '               :           toIdouble(), and toIReal() functions, and
 #  '               :           some minor unittesting errors (many of 
 which
 #  '               :           needed a cast() to correct things) that 
 I've
 #  '               :           fixed.
 #  '               :
 #  ' Requirements  : std.string for the ifind() and find() functions,
 #  '               : and std.math2 for both the atof() and feq() 
 functions.
 #  '               :
 #  ' Licence       : DigitalMars (waiting for this to be included into
 #  '               : std.conv.d, at which time this code will be pulled
 #  '               : totally from this site.)
 # 
  ' --------------------------------------------------------------------------
 #  ' Note: The main purpose of this code is to extend std.conv, with some
 #  '       useful "char[] to floating-point number" wrapper functions...
 #  '       which mainly uses the "real std.math2.atof( in char[] )" 
 function
 #  '       for all the conversions.
 #  '
 #  '
 #  ' To complie for a unittest:
 #  ' C:\dmd>bin\dmd convext.d -debug=convext -unittest
 #  '
 #  ' To compile a D program that use convext.d:
 #  ' C:\dmd>bin\dmd MySource.d convext.d
 #  '
 #  ' Public functions:
 #  ' ------------------------------
 #  ' 01) bit toBit( in char )
 #  ' 02) bit toBit( in char[] )
 #  ' 03) float toFloat( in char[] )
 #  ' 04) double toDouble( in char[] )
 #  ' 05) real toReal( in char[] )
 #  ' 06) ifloat toIfloat( in char[] )
 #  ' 07) idouble toIdouble( in char[] )
 #  ' 08) ireal toIreal( in char[] )
 #  ' 09) cfloat toCfloat( in char[] )
 #  ' 10) cdouble toCdouble( in char[] )
 #  ' 11) creal toCreal( in char[] )
 #  '
 #  ' Private functions:
 #  ' ------------------------------
 #  ' 01) void getComplexStrings( in char[], out char[], out char[] )
 #  '
 #  +/
 # module convext;
 #
 # private import std.math2;
 # private import std.string;
 #
 # debug( convext ) private import std.stdio;
 #
 # bit toBit( in char c )
 # {
 #     if ( c == 't' || c == 'T' || c == '1' ||
 #          c == 'Y' || c == 'y' )
 #         c = '1';
 #
 #     return ( c == '1' ? true : false );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toBit( in char ).unittest" );
 #     bit b;
 #
 #     b = toBit( 'T' );
 #     assert( b == true );
 #     b = toBit( 'f' );
 #     assert( b == false );
 #     b = toBit( 'x' );
 #     assert( b == false );
 #     b = toBit( 'n' );
 #     assert( b == false );
 # }
 #
 # bit toBit( in char[] s )
 # {
 #     char[] s1 = std.string.toupper( s );
 #
 #     if ( s1 == "TRUE" || s1 == "T" || s1 == "1" ||
 #          s1 == "Y" || s1 == "YES" || s1 == "ON" )
 #         s1 = "1";
 #
 #     return ( s1 == "1" ? true : false );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toBit( in char[] ).unittest" );
 #     bit b;
 #
 #     b = toBit( "True" );
 #     assert( b == true );
 #     b = toBit( "Xta" );
 #     assert( b == false );
 #     b = toBit( "" );
 #     assert( b == false );
 #     b = toBit( "yeS" );
 #     assert( b == true );
 # }
 #
 # float toFloat( in char[] s )
 # {
 #     return cast(float)std.math2.atof( s );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toFloat( in 
 char[] ).unittest" );
 #     float f;
 #
 #     f = toFloat( "123" );
 #     assert( f == 123f );
 #     f = toFloat( "+123" );
 #     assert( f == +123f );
 #     f = toFloat( "-123" );
 #     assert( f == -123f );
 #     f = toFloat( "123e2" );
 #     assert( f == 123e2f );
 #
 #     f = toFloat( "123e-2" );
 #     assert( f == 123e-2f );
 #     f = toFloat( "123." );
 #     assert( f == 123.f );
 #     f = toFloat( ".456" );
 #     assert( f == .456f );
 #     f = toFloat( "1.23456E+2" );
 #     assert( f == 1.23456E+2f );
 # }
 #
 # double toDouble( in char[] s )
 # {
 #     return cast(double)std.math2.atof( s );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toDouble( in 
 char[] ).unittest" );
 #     double d;
 #
 #     d = toDouble( "123" );
 #     assert( d == 123 );
 #     d = toDouble( "+123" );
 #     assert( d == +123 );
 #     d = toDouble( "-123" );
 #     assert( d == -123 );
 #     d = toDouble( "123e2" );
 #     assert( d == 123e2);
 #     d = toDouble( "123e-2" );
 #     assert( d == 123e-2 );
 #     d = toDouble( "123." );
 #     assert( d == 123. );
 #     d = toDouble( ".456" );
 #     assert( d == .456 );
 #     d = toDouble( "1.23456E+2" );
 #     assert( d == 1.23456E+2 );
 # }
 #
 # real toReal( in char[] s )
 # {
 #     return cast(real)std.math2.atof( s );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toReal( in char[] ).unittest" );
 #     real r;
 #
 #     r = toReal( "123" );
 #     assert( r == 123L );
 #     r = toReal( "+123" );
 #     assert( r == 123L );
 #     r = toReal( "-123" );
 #     assert( r == -123L );
 #     r = toReal( "123e2" );
 #     assert( std.math2.feq( r, 123e2L ) );
 #     r = toReal( "123e-2" );
 #     assert( std.math2.feq( r, 1.23L ) );
 #     r = toReal( "123." );
 #     assert( r == 123L );
 #     r = toReal( ".456" );
 #     assert( r == .456L );
 #
 #     r = toReal( "1.23456E+2" );
 #     assert( std.math2.feq( r,  1.23456E+2L ) );
 #     r = toReal( std.string.toString( real.max / 2L ) );
 #     assert( std.string.toString( r ) ==
 #             std.string.toString( real.max / 2L ) );
 #     r = toReal( std.string.toString( real.max ) );
 #     assert( std.string.toString( r ) == std.string.toString( 
 real.max ) );
 # }
 #
 # ifloat toIfloat( in char[] s )
 # {
 #     float f;
 #     ifloat ift;
 #
 #     if ( ifind( s, "i" ) > 0f )
 #         f = cast(float)std.math2.atof( s[ 0 .. s.length - 1 ] );
 #     else
 #         f = cast(float)std.math2.atof( s );
 #
 #     if ( f == 0f )
 #        ift = cast(ifloat)( 0f );
 #     else if ( f.nan == true )
 #         ift = cast(ifloat)f.nan;
 #     else
 #         ift = cast(ifloat)( f * 1.0i );
 #
 #     return ift;
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toIfloat( in 
 char[] ).unittest" );
 #     ifloat ift;
 #     float  f;
 #
 #     ift = toIfloat( std.string.toString( ifloat.min ) );
 #     //writefln( "ift=\"%g\", s=\"%s\"",
 #                  ift, std.string.toString( ifloat.min ) );
 #
 #     assert( std.string.toString( ift ) ==
 #             std.string.toString( ifloat.min ) );
 #     assert( ift.re == ifloat.min.re );
 #     assert( std.math2.feq( cast(real)ift.im, 
 cast(real)ifloat.min.im ) );
 #
 #     ift = toIfloat( std.string.toString( ifloat.max ) );
 #     assert( std.string.toString( ift ) ==
 #             std.string.toString( ifloat.max ) );
 #     assert( ift.re == ifloat.max.re );
 #     assert( std.math2.feq( cast(real)ift, cast(real)ifloat.max ) );
 #
 #     ift = toIfloat( std.string.toString( 123.45 ) );
 #     assert( std.string.toString( ift ) == std.string.toString( 
 123.45i ) );
 #
 #     ift = toIfloat( std.string.toString( 456.77i ) );
 #     assert( std.string.toString( ift ) == std.string.toString( 
 456.77i ) );
 #
 #     ift = toIfloat( std.string.toString( ifloat.nan ) );
 #     // There's a isnan() for float, double, and real,
 #     // but no isnani() for ifloat, idouble, ireal,
 #     // cfloat, cdouble, and creal.
 #     //
 #     //writefln( "ift=%gi, ift.nan=%gi, isnan()=%d",
 #                  ift, ift.nan, std.math.isnan( cast(real)ift.nan ) );
 #     assert( std.string.toString( ift.nan ) ==
 #             std.string.toString( ifloat.nan ) );
 # }
 #
 # idouble toIdouble( in char[] s )
 # {
 #     double  d;
 #     idouble id;
 #
 #     if ( ifind( s, "i" ) > 0 )
 #         d = cast(double)std.math2.atof( s[ 0 .. s.length - 1 ] );
 #     else
 #         d = cast(double)std.math2.atof( s );
 #
 #     if ( d == 0 )
 #        id = cast(idouble)( 0 );
 #     else if ( d.nan == true )
 #         id = cast(idouble)d.nan;
 #     else
 #         id = cast(idouble)(d * 1.0i);
 #
 #     return id;
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toIdouble( in 
 char[] ).unittest" );
 #     idouble id;
 #
 #     id = toIdouble( std.string.toString( idouble.min ) );
 #     assert( std.string.toString( id ) ==
 #             std.string.toString( idouble.min ) );
 #     assert( std.math2.feq( cast(real)id.re, 
 cast(real)idouble.min.re ) );
 #     assert( std.math2.feq( cast(real)id.im, 
 cast(real)idouble.min.im ) );
 #
 #     id = toIdouble( std.string.toString( idouble.max ) );
 #     assert( std.string.toString( id ) ==
 #             std.string.toString( idouble.max ) );
 #     assert( std.math2.feq( cast(real)id.re, 
 cast(real)idouble.max.re ) );
 #     //assert( std.math2.feq( cast(real)id.im, 
 cast(real)idouble.max.im ) );
 #
 #     id = toIdouble( std.string.toString( "123.45" ) );
 #     assert( id == 123.45i );
 #
 #     id = toIdouble( std.string.toString( idouble.nan ) );
 #     assert( std.string.toString( id.nan ) ==
 #             std.string.toString( idouble.nan ) );
 # }
 #
 # ireal toIreal( in char[] s )
 # {
 #     real  r;
 #     ireal ir;
 #
 #     if ( ifind( s, "i" ) > 0 )
 #         r = cast(real)std.math2.atof( s[ 0 .. s.length - 1 ] );
 #     else
 #         r = cast(real)std.math2.atof( s );
 #
 #     if ( r == 0L )
 #        ir = cast(ireal)( 0L );
 #     else if ( r.nan == true )
 #         ir = cast(ireal)r.nan;
 #     else
 #         ir = cast(ireal)(r * 1.0i);
 #
 #     return ir;
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toIreal( in 
 char[] ).unittest" );
 #     ireal ir;
 #
 #     ir = toIreal( std.string.toString( ireal.min ) );
 #     assert( std.string.toString( ir ) == std.string.toString( 
 ireal.min ) );
 #     assert( std.math2.feq( cast(real)ir.re, cast(real)ireal.min.re ) );
 #     assert( std.math2.feq( cast(real)ir.im, cast(real)ireal.min.im ) );
 #
 #     ir = toIreal( std.string.toString( ireal.max ) );
 #     assert( std.string.toString( ir ) == std.string.toString( 
 ireal.max ) );
 #     assert( std.math2.feq( cast(real)ir.re, cast(real)ireal.max.re ) );
 #
 #     ir = toIreal( std.string.toString( "123.45" ) );
 #     assert( std.math2.feq( cast(real)ir.re, cast(real)123.45i ) );
 #
 #     ir = toIreal( std.string.toString( ireal.nan ) );
 #     assert( std.string.toString( ir.nan ) ==
 #             std.string.toString( ireal.nan ) );
 # }
 #
 # cfloat toCfloat( in char[] s )
 # {
 #     char[] s1;
 #     char[] s2;
 #
 #     getComplexStrings( s, s1, s2 );
 #
 #     return cast(cfloat)std.math2.atof( s1 ) +
 #            ( cast(cfloat)std.math2.atof( s2 ) * 1.0i );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toCfloat( in 
 char[] ).unittest" );
 #     cfloat cf;
 #
 #     cf = toCfloat( std.string.toString( cfloat.min ) );
 #     assert( std.string.toString( cf ) == std.string.toString( 
 cfloat.min ) );
 #
 #     cf = toCfloat( std.string.toString( cfloat.max ) );
 #     assert( std.string.toString( cf ) == std.string.toString( 
 cfloat.max ) );
 #
 #     cf = toCfloat( std.string.toString( "1.2345e-5+0i" ) );
 #     assert( std.string.toString( cf ) ==
 #             std.string.toString( 1.2345e-5+0i ) );
 #     //assert( cf == 1.2345e-5+0i );
 # }
 #
 # cdouble toCdouble( in char[] s )
 # {
 #     char[] s1;
 #     char[] s2;
 #
 #     getComplexStrings( s, s1, s2 );
 #
 #     return cast(cdouble)std.math2.atof( s1 ) +
 #            ( cast(cdouble)std.math2.atof( s2 ) * 1.0i );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toCdouble( in 
 char[] ).unittest" );
 #     cdouble cd;
 #
 #     cd = toCdouble( std.string.toString( cdouble.min ) );
 #     assert( std.string.toString( cd ) ==
 #             std.string.toString( cdouble.min ) );
 #
 #     cd = toCdouble( std.string.toString( cdouble.max ) );
 #     assert( std.string.toString( cd ) ==
 #             std.string.toString( cdouble.max ) );
 #
 #     cd = toCdouble( std.string.toString( "1.2345e-5+0i" ) );
 #     assert( std.string.toString( cd ) ==
 #             std.string.toString( 1.2345e-5+0i ) );
 #     //assert( cd == 1.2345e-5+0i );
 # }
 #
 # creal toCreal( in char[] s )
 # {
 #     char[] s1;
 #     char[] s2;
 #
 #     getComplexStrings( s, s1, s2 );
 #
 #     return cast(creal)std.math2.atof( s1 ) +
 #            ( cast(creal)std.math2.atof( s2 ) * 1.0i );
 # }
 #
 # unittest
 # {
 #     debug( convext ) writefln( "convext.toCreal( in 
 char[] ).unittest" );
 #     creal cr;
 #
 #     cr = toCreal( std.string.toString( creal.min ) );
 #     assert( std.string.toString( cr ) == std.string.toString( 
 creal.min ) );
 #     assert( std.math2.feq( cast(real)cr.re, cast(real)creal.min.re ) );
 #     assert( std.math2.feq( cast(real)cr.im, cast(real)creal.min.im ) );
 #
 #     cr = toCreal( std.string.toString( creal.max ) );
 #     assert( std.string.toString( cr ) == std.string.toString( 
 creal.max ) );
 #     //assert( std.math2.feq( cast(real)cr.re, 
 cast(real)creal.max.re ) );
 #     //assert( std.math2.feq( cast(real)cr.im, 
 cast(real)creal.max.im ) );
 #
 #     cr = toCreal( std.string.toString( "1.2345e-5+0i" ) );
 #     assert( std.string.toString( cr ) ==
 #             std.string.toString( 1.2345e-5+0i ) );
 #     assert( std.math2.feq( cast(real)cr.re, 
 cast(real)1.2345e-5+0i.re ) );
 #     //assert( std.math2.feq( cast(real)cr.im, 
 cast(real)1.2345e-5+0i.im ) );
 #
 #     cr = toCreal( std.string.toString( "0.0e-0+0i" ) );
 #     assert( std.string.toString( cr ) == std.string.toString( 
 0.0e-0+0i ) );
 #     assert( cr == 0.0e-0+0i );
 # }
 #
 # private void getComplexStrings( in char[] s, out char[] s1, out char[] 
 s2 )
 # {
 #     int iPos1 = 0;
 #     int iPos2 = 0;
 #
 #     s1 = s.dup;
 #     s2 = "";
 #
 #     iPos1 = ifind( s1, "e+" );
 #     if ( iPos1 != -1 )
 #         iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #
 #     if ( iPos1 == -1 )
 #     {
 #         iPos1 = ifind( s1, "e-" );
 #         if ( iPos1 != -1 )
 #             iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #     }
 #
 #     if ( iPos1 == -1 )
 #         s1 = "0e+0";
 #
 #     if ( iPos2 != -1 )
 #     {
 #         iPos2 += iPos1;
 #         s2 = s1[ iPos2 + 4 .. s1.length - 1 ].dup;
 #         s1 = s1[ 0 .. iPos2 + 3 ];
 #     }
 #
 #     //writefln( "getComplexStrings().s1=%s, s2=%s, iPos1=%d, iPos2=%d",
 #                  s1, s2, iPos1, iPos2 );
 #
 #     if ( iPos2 == -1 )
 #     {
 #         s1 = s1[ 0 .. s1.length - 1 ];
 #         s2 = "0";
 #     }
 #
 # } // end void getComplexStrings( in char[], out char[], out char[] )
 #
 # debug( convext )
 # {
 # int main()
 # {
 #     writefln( "convext.unittests done!" );
 #     return 0;
 #
 # } // end int main()
 # }

 Thanks in advance,
 David L.

 -------------------------------------------------------------------
 "Dare to reach for the Stars...Dare to Dream, Build, and Achieve!" 

Apr 09 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"David L. Davis" <SpottedTiger yahoo.com> wrote in message 
news:d3903a$vr8$1 digitaldaemon.com...
 Well per Walter advice in to below message,

 D forum thread: "process improvement for phobos"
 digitalmars.D/20328

 I'd like to resubmit to my fellow D developers for comments and review, 
 the
 following code that's been submitted to Walter for including into Phobos.

 Recently, D v0.120 has forced a number of correction to be made into this 
 code
 (a lot of additional cast()s had to put into place...which was kool, a 
 better
 compiler means better executing code), but in so doing I found some areas 
 that
 needed a bit more tighting up.

 Please free feel to give some suggests and / or correction to the 
 following
 code, that's designed to fill in the missing "string to floating-point" 
 function
 gap in std.conv. Note I'm in no way a floating-point expert, but just a 
 guy
 trying in improve and move D forward...one line or one function at a time 
 if I
 possibly can.

cool. comments inline
 # /+
 #  ' Module        : convext.d - "char[] to floating-point number"

My first comment is the comment style. Does anything else in phobos use this comment style? Looking in std.conv I see comments like /************************* * Convert blah to foo. * Gammar: digit(digit) */ The use of /+ and ' seems non-standard. I'm not sure exactly what you intend to send Walter but if this stuff is to go in std.convext (though I don't see why it can't go into std.conv if you ask me) I would get it into the exact format that you want to appear in phobos. It looks like none of the functions have comments preceding them in the style of std.conv - those comments should be in there to explain just what is allowed and what isn't.
 #  '               : wrapper functions.
 #  ' Version       : v0.2
 #  '               :
 #  ' Author(s)     : David L. 'SpottedTiger' Davis
 #  '               : for the wrapper functions / unittests,
 #  '               : Pavel "EvilOne" Minayev for writing the std.math2 
 code
 #  '               : that does most of the work, and to Walter Bright for
 #  '               : the great D compiler, as well as the D's Phobos 
 runtime
 #  '               : library filled with very useful modules and functions
 #  '               : ...of which the std.math2 module is a part of.
 #  '               :
 #  ' Created Date  : 07.Nov.04 Complied and Tested with dmd v0.105
 #  ' Modified Date : 09.Nov.04 Added unitconvext code,
 #  '               :           recompiled and tested with dmd v0.106.
 #  '               : 20.Jan.05 Recompiled and tested with dmd v0.111.
 #  '               : 20.Mar.05 Recomplied and Tested with dmd v0.119.
 #  '               : 08.Apr.05 Recompiled and tested with dmd v0.120,
 #  '               :           well it looks like the fixes done in v0.120
 #  '               :           to tight up floating-point convertions has
 #  '               :           exposed some errors mainly in the 
 toIfloat(),
 #  '               :           toIdouble(), and toIReal() functions, and
 #  '               :           some minor unittesting errors (many of 
 which
 #  '               :           needed a cast() to correct things) that 
 I've
 #  '               :           fixed.
 #  '               :
 #  ' Requirements  : std.string for the ifind() and find() functions,
 #  '               : and std.math2 for both the atof() and feq() 
 functions.
 #  '               :
 #  ' Licence       : DigitalMars (waiting for this to be included into
 #  '               : std.conv.d, at which time this code will be pulled
 #  '               : totally from this site.)
 # 
  ' --------------------------------------------------------------------------
 #  ' Note: The main purpose of this code is to extend std.conv, with some
 #  '       useful "char[] to floating-point number" wrapper functions...
 #  '       which mainly uses the "real std.math2.atof( in char[] )" 
 function
 #  '       for all the conversions.
 #  '
 #  '
 #  ' To complie for a unittest:
 #  ' C:\dmd>bin\dmd convext.d -debug=convext -unittest
 #  '
 #  ' To compile a D program that use convext.d:
 #  ' C:\dmd>bin\dmd MySource.d convext.d
 #  '
 #  ' Public functions:
 #  ' ------------------------------
 #  ' 01) bit toBit( in char )
 #  ' 02) bit toBit( in char[] )
 #  ' 03) float toFloat( in char[] )
 #  ' 04) double toDouble( in char[] )
 #  ' 05) real toReal( in char[] )
 #  ' 06) ifloat toIfloat( in char[] )
 #  ' 07) idouble toIdouble( in char[] )
 #  ' 08) ireal toIreal( in char[] )
 #  ' 09) cfloat toCfloat( in char[] )
 #  ' 10) cdouble toCdouble( in char[] )
 #  ' 11) creal toCreal( in char[] )
 #  '
 #  ' Private functions:
 #  ' ------------------------------
 #  ' 01) void getComplexStrings( in char[], out char[], out char[] )
 #  '
 #  +/
 # module convext;
 #
 # private import std.math2;
 # private import std.string;
 #
 # debug( convext ) private import std.stdio;
 #
 # bit toBit( in char c )
 # {
 #     if ( c == 't' || c == 'T' || c == '1' ||
 #          c == 'Y' || c == 'y' )
 #         c = '1';
 #
 #     return ( c == '1' ? true : false );
 # }
 # bit toBit( in char[] s )
 # {
 #     char[] s1 = std.string.toupper( s );
 #
 #     if ( s1 == "TRUE" || s1 == "T" || s1 == "1" ||
 #          s1 == "Y" || s1 == "YES" || s1 == "ON" )
 #         s1 = "1";
 #
 #     return ( s1 == "1" ? true : false );
 # }

Personally I'd remove these toBit conversions. The strings it recognizes seem somewhat arbitrary. Why "yes" but not "oui"? If anything I would just have toBit recognize what std.format does with a bit, which is print "true" or "false". And given that restriction it would be simpler to just have a comparison with "true" or "false". One trouble with toBit(char c) for example is the numeric nature char might lead people to guess that c!=0 is the test for toBit instead of comparing with some ascii codes.
 # float toFloat( in char[] s )
 # {
 #     return cast(float)std.math2.atof( s );
 # }

All these floating point functions seem to be very small wrappers around std.math2.atof. Why not put these in math2? I can see the desire to mimic the std.conv module but IMO that isn't a strong enough reason to make another module. Also if the idea is to follow std.conv then I would have the ones that cast check for overflow etc just like toShort checks for overflow after getting the result of toInt. [snip]
 # ifloat toIfloat( in char[] s )
 # {
 #     float f;
 #     ifloat ift;
 #
 #     if ( ifind( s, "i" ) > 0f )

why 0f?
 #         f = cast(float)std.math2.atof( s[ 0 .. s.length - 1 ] );

I don't see where the index of the "i" shows up. If you only parse "<float>i" then you can just check the last char instead of doing an ifind.
 #     else
 #         f = cast(float)std.math2.atof( s );
 #
 #     if ( f == 0f )
 #        ift = cast(ifloat)( 0f );
 #     else if ( f.nan == true )
 #         ift = cast(ifloat)f.nan;

I'm not sure what f.nan == true is supposed to test. Do you want to see if f is a nan? The isnan function in std.math is for that.
 #     else
 #         ift = cast(ifloat)( f * 1.0i );
 #
 #     return ift;
 # }

[snip]
 # private void getComplexStrings( in char[] s, out char[] s1, out char[] 
 s2 )
 # {
 #     int iPos1 = 0;
 #     int iPos2 = 0;
 #
 #     s1 = s.dup;

why the dup? You shouldn't need to change s so there is no need to make a copy. Also I can't tell exactly what string parse into complex numbers. For example will the string "1-2i" parse correctly? I think it should. In any case documenting what works and what doesn't is important.
 #     s2 = "";
 #
 #     iPos1 = ifind( s1, "e+" );
 #     if ( iPos1 != -1 )
 #         iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #
 #     if ( iPos1 == -1 )
 #     {
 #         iPos1 = ifind( s1, "e-" );
 #         if ( iPos1 != -1 )
 #             iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #     }
 #
 #     if ( iPos1 == -1 )
 #         s1 = "0e+0";
 #
 #     if ( iPos2 != -1 )
 #     {
 #         iPos2 += iPos1;
 #         s2 = s1[ iPos2 + 4 .. s1.length - 1 ].dup;
 #         s1 = s1[ 0 .. iPos2 + 3 ];
 #     }
 #
 #     //writefln( "getComplexStrings().s1=%s, s2=%s, iPos1=%d, iPos2=%d",
 #                  s1, s2, iPos1, iPos2 );
 #
 #     if ( iPos2 == -1 )
 #     {
 #         s1 = s1[ 0 .. s1.length - 1 ];
 #         s2 = "0";
 #     }
 #
 # } // end void getComplexStrings( in char[], out char[], out char[] )

Apr 10 2005
parent reply David L. Davis <SpottedTiger yahoo.com> writes:
In article <d3cq53$19hh$1 digitaldaemon.com>, Ben Hinkle says...
"David L. Davis" <SpottedTiger yahoo.com> wrote in message 
news:d3903a$vr8$1 digitaldaemon.com...
 # /+
 #  ' Module        : convext.d - "char[] to floating-point number"

My first comment is the comment style. Does anything else in phobos use this comment style? Looking in std.conv I see comments like /************************* * Convert blah to foo. * Gammar: digit(digit) */

Yeah, the comment style is what I started to use on code on my web-site (something I remembere picking up from my programming classes back in my college days), but I don't really expect Walter to keep them. :) And since I've passed all rights of the code to him, he can make the changes he needs to make.
The use of /+ and ' seems non-standard. I'm not sure exactly what you intend 
to send Walter but if this stuff is to go in std.convext (though I don't see 
why it can't go into std.conv if you ask me) I would get it into the exact 
format that you want to appear in phobos. It looks like none of the 
functions have comments preceding them in the style of std.conv - those 
comments should be in there to explain just what is allowed and what isn't.

One of the nice things about D is that it gives you choices...in this case two multi-commenting blocks like "/* */" and "/+ +/". But it's hard to find a color-code syntax within the text editor to support more than one multi-comment block set of symbols. So, I picked to setup the "/+ +/" within the editor. And personally I like it a lot more than the "/* */".
 #
 # debug( convext ) private import std.stdio;
 #
 # bit toBit( in char c )
 # {
 #     if ( c == 't' || c == 'T' || c == '1' ||
 #          c == 'Y' || c == 'y' )
 #         c = '1';
 #
 #     return ( c == '1' ? true : false );
 # }
 # bit toBit( in char[] s )
 # {
 #     char[] s1 = std.string.toupper( s );
 #
 #     if ( s1 == "TRUE" || s1 == "T" || s1 == "1" ||
 #          s1 == "Y" || s1 == "YES" || s1 == "ON" )
 #         s1 = "1";
 #
 #     return ( s1 == "1" ? true : false );
 # }

Personally I'd remove these toBit conversions. The strings it recognizes seem somewhat arbitrary. Why "yes" but not "oui"? If anything I would just have toBit recognize what std.format does with a bit, which is print "true" or "false". And given that restriction it would be simpler to just have a comparison with "true" or "false". One trouble with toBit(char c) for example is the numeric nature char might lead people to guess that c!=0 is the test for toBit instead of comparing with some ascii codes.

The toBit() functions were a bit of me thinking out loud I guess, cause I really think that the std.conv module should cover all the datatypes. But here again, Walter will pick what he wants to add...and even then he will rewrite it if neccessary.
 # float toFloat( in char[] s )
 # {
 #     return cast(float)std.math2.atof( s );
 # }

All these floating point functions seem to be very small wrappers around std.math2.atof. Why not put these in math2? I can see the desire to mimic the std.conv module but IMO that isn't a strong enough reason to make another module. Also if the idea is to follow std.conv then I would have the ones that cast check for overflow etc just like toShort checks for overflow after getting the result of toInt.

It true that these are mainly wrapper functions that rely heavily upon std.math2 module, but it just makes more sense to me that std.conv is the module that converts strings (char[]s) back to numbers (both whole numbers and floating-point). But I'm beginning understand more as to why you were suggesting in the fromString() functions within some comments a few weeks ago in a different thread. It would be a nice way to have the toString() mirrored with the fromString() functions which could be overloaded with whatever numercial datatype that were passed into them. I'll have to take another look at the toShort() and toInt() functions in regards to the overflow checking. Thanks for the heads up on that.
[snip]
 # ifloat toIfloat( in char[] s )
 # {
 #     float f;
 #     ifloat ift;
 #
 #     if ( ifind( s, "i" ) > 0f )

why 0f?

I thought it better to cast the numercial literal with a suffix ("f" for float). Is that the wrong way to do it? I could have used cast(float)0 instead, would this had been better?
 #         f = cast(float)std.math2.atof( s[ 0 .. s.length - 1 ] );

I don't see where the index of the "i" shows up. If you only parse "<float>i" then you can just check the last char instead of doing an ifind.

You're right, the "i" would be at the end, if it were passed in. Of course the could "i" be missing from string all together, so instead of writing an if statement I used the ifind() function. Which on second thought, maybe I should've used the "if" statement. Thanks for pointing it out.
 #     else
 #         f = cast(float)std.math2.atof( s );
 #
 #     if ( f == 0f )
 #        ift = cast(ifloat)( 0f );
 #     else if ( f.nan == true )
 #         ift = cast(ifloat)f.nan;

I'm not sure what f.nan == true is supposed to test. Do you want to see if f is a nan? The isnan function in std.math is for that.

I wanted to put in code to check for a nan value, but to tell the truth I may not totally understand the use behind them. I thinking that a NaN is much like a null, but only for floating-point. Also, I looked at using the isnan() function, but it can't handle the <float>i (the "i" part of the floating-point). Seems like there should be a isnani() function. I did play around with the f.nan == 1 (true) and f.nan == 0 (false) in testing, and it seemed to be correct at the time, but I guess I should double-check that logic again.
 #     else
 #         ift = cast(ifloat)( f * 1.0i );
 #
 #     return ift;
 # }

[snip]
 # private void getComplexStrings( in char[] s, out char[] s1, out char[] 
 s2 )
 # {
 #     int iPos1 = 0;
 #     int iPos2 = 0;
 #
 #     s1 = s.dup;

why the dup? You shouldn't need to change s so there is no need to make a copy. Also I can't tell exactly what string parse into complex numbers. For example will the string "1-2i" parse correctly? I think it should. In any case documenting what works and what doesn't is important.

I'm afraid it's a bad habit I've seemed to have picked up, "When in doubt...dup it!" Since Basic is my primary language and my D my secondary, I see the "out" in D as ByRef in Basic...and the fact that "s" is a local variable adds to the confusion (I have this great fear of a pointer referencing a memory location that disappears without warning...which has happen to me a few times in C).
 #     s2 = "";
 #
 #     iPos1 = ifind( s1, "e+" );
 #     if ( iPos1 != -1 )
 #         iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #
 #     if ( iPos1 == -1 )
 #     {
 #         iPos1 = ifind( s1, "e-" );
 #         if ( iPos1 != -1 )
 #             iPos2 = find( s1[ iPos1 + 3 .. s1.length ], "+" );
 #     }
 #
 #     if ( iPos1 == -1 )
 #         s1 = "0e+0";
 #
 #     if ( iPos2 != -1 )
 #     {
 #         iPos2 += iPos1;
 #         s2 = s1[ iPos2 + 4 .. s1.length - 1 ].dup;
 #         s1 = s1[ 0 .. iPos2 + 3 ];
 #     }
 #
 #     //writefln( "getComplexStrings().s1=%s, s2=%s, iPos1=%d, iPos2=%d",
 #                  s1, s2, iPos1, iPos2 );
 #
 #     if ( iPos2 == -1 )
 #     {
 #         s1 = s1[ 0 .. s1.length - 1 ];
 #         s2 = "0";
 #     }
 #
 # } // end void getComplexStrings( in char[], out char[], out char[] )


Well, Ben I'd like to thanks you for the time you spent looking things over! Did you have any time to test it in any of your D code? Thanks again. David L. ------------------------------------------------------------------- "Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
Apr 10 2005
parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
"David L. Davis" <SpottedTiger yahoo.com> wrote in message 
news:d3d1bp$1gle$1 digitaldaemon.com...
 In article <d3cq53$19hh$1 digitaldaemon.com>, Ben Hinkle says...
"David L. Davis" <SpottedTiger yahoo.com> wrote in message
news:d3903a$vr8$1 digitaldaemon.com...
 # /+
 #  ' Module        : convext.d - "char[] to floating-point number"

My first comment is the comment style. Does anything else in phobos use this comment style? Looking in std.conv I see comments like /************************* * Convert blah to foo. * Gammar: digit(digit) */

Yeah, the comment style is what I started to use on code on my web-site (something I remembere picking up from my programming classes back in my college days), but I don't really expect Walter to keep them. :) And since I've passed all rights of the code to him, he can make the changes he needs to make.

Your chances of getting something done to phobos goes up if you make it easy for him. It also makes it easier for us readers to have an idea what actually is intended to be in the final shipping library. I just assumed what you posted was what you expected to be accepted.
[snip]
 # ifloat toIfloat( in char[] s )
 # {
 #     float f;
 #     ifloat ift;
 #
 #     if ( ifind( s, "i" ) > 0f )

why 0f?

I thought it better to cast the numercial literal with a suffix ("f" for float). Is that the wrong way to do it? I could have used cast(float)0 instead, would this had been better?

ifind returns the int index of the first occurance of the requested char. No need to compare with a float.
 Well, Ben I'd like to thanks you for the time you spent looking things 
 over! Did
 you have any time to test it in any of your D code?

no problem. I want to see phobos improve, too. Thanks for posting your change request. I didn't try running the code.
Apr 11 2005