Hello, This is similar crude approach short of using GMP directly in that method. It basically adds handling for scalar types yet still relies on a temporary string an parsing for double an float.
It does attempt to do some handling of nan and +/-inf. I propose this patch for the trunk. The release branch should probably only add the GSPrivateDefaultLocale. The patch also add NAN handling for NSDecimalDouble. >From Working on this patch, I think that the _public_ API, which only includes ... /** Give back the value of a NSDecimal as a double in (preallocated) result. */ GS_EXPORT double NSDecimalDouble(NSDecimal *number); ..., is missing the following conversion functions: void GSFloatDecimal(NSDecimal *result, float value); void GSDoubleDecimal(NSDecimal *result, double value); void GSLongDoubleDecimal(NSDecimal *result, long double value); These functions would be implemented via GMP where available or via format string processing otherwise. Possibly the API should allow for explicit precision: void GSFloatDecimal(NSDecimal *result, float value, unsigned prec); void GSDoubleDecimal(NSDecimal *result, double value, unsigned prec); void GSLongDoubleDecimal(NSDecimal *result, long double value, unsigned prec); Cheers, David
Index: Source/NSDecimalNumber.m =================================================================== --- Source/NSDecimalNumber.m (Revision 24312) +++ Source/NSDecimalNumber.m (Arbeitskopie) @@ -26,6 +26,9 @@ $Date$ $Revision$ */ +#define _GNU_SOURCE +#include <math.h> + #include "Foundation/NSCoder.h" #include "Foundation/NSDecimal.h" #include "Foundation/NSDecimalNumber.h" @@ -235,14 +238,146 @@ */ - (id) initWithBytes: (const void*)value objCType: (const char*)type { - double tmp; - NSString *s; + unsigned long long val; + long long llval; + NSDecimal decimal; + BOOL negative, llvalSet; - memcpy(&tmp, value, sizeof(tmp)); - s = [[NSString alloc] initWithFormat: @"%g", tmp]; - self = [self initWithString: s]; - RELEASE(s); - return self; + if (strlen(type) != 1) + { + DESTROY(self); + return nil; + } + + llvalSet = YES; + negative = NO; + + switch (*type) + { + case _C_CHR: + { + signed char v = *(signed char *)value; + llval = (long long)v; + break; + } + case _C_UCHR: + { + unsigned char v = *(unsigned char *)value; + llval = (long long)v; + break; + } + case _C_SHT: + { + short v = *(short *)value; + llval = (long long)v; + break; + } + case _C_USHT: + { + unsigned short v = *(unsigned short *)value; + llval = (long long)v; + break; + } + case _C_INT: + { + int v = *(int *)value; + llval = (long long)v; + break; + } + case _C_UINT: + { + unsigned int v = *(unsigned int *)value; + llval = (long long)v; + break; + } + case _C_LNG: + { + long v = *(long *)value; + llval = (long long)v; + break; + } + case _C_ULNG: + { + unsigned long v = *(unsigned long *)value; + llval = (long long)v; + break; + } +#ifdef _C_LNGLNG + case _C_LNGLNG: +#else + case 'q': +#endif + { + long long v = *(long long *)value; + llval = (long long)v; + break; + } +#ifdef _C_ULNGLNG + case _C_ULNGLNG: +#else + case 'Q': +#endif + default: + { + llvalSet = NO; + break; + + } + } + if (llvalSet) + { + if (llval<0) + { + negative = YES; + llval *= -1; + } + val = llval; + } + else + { + switch (*type) + { + case _C_FLT: + { + NSString *s; + float v = *(float *)value; + if (isnanf(v)) return notANumber; + if (isinff(v)) return (v < 0.0) ? minNumber : maxNumber; + s = [[NSString alloc] initWithFormat: @"%g" + locale: GSPrivateDefaultLocale(), (double)v]; + self = [self initWithString: s]; + RELEASE(s); + return self; + break; + } + case _C_DBL: + { + NSString *s; + double v = *(double *)value; + if (isnan(v)) return notANumber; + if (isinf(v)) return (v < 0.0) ? minNumber : maxNumber; + s = [[NSString alloc] initWithFormat: @"%g" + locale: GSPrivateDefaultLocale(), v]; + self = [self initWithString: s]; + RELEASE(s); + return self; + break; + } +#ifdef _C_ULNGLNG + case _C_ULNGLNG: +#else + case 'Q': +#endif + { + val = *(unsigned long long *)value; + break; + } + } + } + + NSDecimalFromComponents(&decimal, val, + 0, negative); + return [self initWithDecimal: decimal]; } - (id) initWithDecimal: (NSDecimal)decimal Index: Source/NSDecimal.m =================================================================== --- Source/NSDecimal.m (Revision 24312) +++ Source/NSDecimal.m (Arbeitskopie) @@ -26,6 +26,7 @@ $Date$ $Revision$ */ +#define _GNU_SOURCE #include <math.h> #if !defined(__APPLE__) || !defined(GNU_RUNTIME) #include <ctype.h> @@ -35,6 +36,10 @@ #include "Foundation/NSDictionary.h" #include "Foundation/NSUserDefaults.h" +#ifndef NAN +#define NAN 0.0 +#endif + /* This file provides two implementations of the NSDecimal functions. One is based on pure simple decimal mathematics, as we all learned it @@ -910,8 +915,7 @@ int i; if (!number->validNumber) - // Somehow I dont have NAN defined on my machine - return 0.0; + return NAN; // Sum up the digits for (i = 0; i < number->length; i++)
Index: base/NSDecimal/functions.m =================================================================== --- base/NSDecimal/functions.m (Revision 0) +++ base/NSDecimal/functions.m (Revision 0) @@ -0,0 +1,38 @@ +#import "ObjectTesting.h" +#import <Foundation/NSAutoreleasePool.h> +#import <Foundation/NSString.h> +#import <Foundation/NSDecimal.h> + +int +main(int argc, char *argv[]) +{ + CREATE_AUTORELEASE_POOL(arp); + NSDecimal dec1, dec2; + NSDictionary *noLocale; + NSString *string; + + noLocale = [NSDictionary dictionary]; + + NSDecimalFromComponents(&dec1,0LL,0,0); + string = NSDecimalString(&dec1, noLocale); + pass([@"0.0" isEqual:string],"NSDecimalFromComponents(&dec,0,0,0)"); + + NSDecimalFromComponents(&dec1,0LL,0,1); + string = NSDecimalString(&dec1, noLocale); + pass([@"0.0" isEqual:string],"NSDecimalFromComponents(&dec,0,0,1)"); + + NSDecimalFromComponents(&dec1,10LL,0,0); + string = NSDecimalString(&dec1, noLocale); + pass([@"10" isEqual:string],"NSDecimalFromComponents(&dec,10,0,0)"); + + NSDecimalFromComponents(&dec1,100LL,0,0); + string = NSDecimalString(&dec1, noLocale); + pass([@"100" isEqual:string],"NSDecimalFromComponents(&dec,100,0,0)"); + + NSDecimalFromComponents(&dec1,10LL,1,0); + string = NSDecimalString(&dec1, noLocale); + pass([@"100" isEqual:string],"NSDecimalFromComponents(&dec,10,1,0)"); + + DESTROY(arp); + return 0; +} Index: base/NSDecimalNumber/creation.m =================================================================== --- base/NSDecimalNumber/creation.m (Revision 0) +++ base/NSDecimalNumber/creation.m (Revision 0) @@ -0,0 +1,81 @@ +#import "ObjectTesting.h" +#import <Foundation/NSAutoreleasePool.h> +#import <Foundation/NSString.h> +#import <Foundation/NSDecimalNumber.h> + +/* We avoid limits.h to remain portable. + The string constants in these tests may not be reliable. */ + +signed char scm = -127; +unsigned char ucm = 255; +short ssm = -32767; +unsigned short usm = 65535; +int sim = 2147483647; +unsigned int uim = 4294967295U; +long slm = 2147483647; +unsigned long ulm = 4294967295LU; +float fm = 4294.967294; +double dm = 4294.967294; + +int +main(int argc, char *argv[]) +{ + CREATE_AUTORELEASE_POOL(arp); + NSDecimalNumber *dec1, *dec2; + NSString *string1, *string2; + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&scm objCType: "c"]; + string1 = [dec1 description]; + string2 = @"-127"; + pass([string1 isEqual:string2],"initWithBytes: _C_CHR"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&ucm objCType: "C"]; + string1 = [dec1 description]; + string2 = @"255"; + pass([string1 isEqual:string2],"initWithBytes: _C_UCHR"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&ssm objCType: "s"]; + string1 = [dec1 description]; + string2 = @"-32767"; + pass([string1 isEqual:string2],"initWithBytes: _C_SHRT"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&usm objCType: "S"]; + string1 = [dec1 description]; + string2 = @"65535"; + pass([string1 isEqual:string2],"initWithBytes: _C_USHRT"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&sim objCType: "i"]; + string1 = [dec1 description]; + string2 = [NSString stringWithFormat:@"%i",sim]; + string2 = @"2.147483647E9"; + pass([string1 isEqual:string2],"initWithBytes: _C_INT"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&uim objCType: "I"]; + string1 = [dec1 description]; + string2 = @"4.294967295E9"; + pass([string1 isEqual:string2],"initWithBytes: _C_UINT"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&slm objCType: "l"]; + string1 = [dec1 description]; + string2 = @"2.147483647E9"; + pass([string1 isEqual:string2],"initWithBytes: _C_LONG"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&ulm objCType: "L"]; + string1 = [dec1 description]; + string2 = @"4.294967295E9"; + pass([string1 isEqual:string2],"initWithBytes: _C_ULONG"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&fm objCType: "f"]; + string1 = [dec1 description]; + string2 = @"4294.97"; + pass([string1 isEqual:string2],"initWithBytes: _C_FLT"); + + dec1 = [[NSDecimalNumber alloc] initWithBytes:&dm objCType: "d"]; + string1 = [dec1 description]; + string2 = @"4294.97"; + pass([string1 isEqual:string2],"initWithBytes: _C_DBL"); + + + DESTROY(arp); + return 0; +}
_______________________________________________ Gnustep-dev mailing list Gnustep-dev@gnu.org http://lists.gnu.org/mailman/listinfo/gnustep-dev