/*****
 NAME
	creal.m - source code for CReal class
 VERSION
	$Id$
 CHANGELOG
	$Log$
 */

#include <coconut/creal.h>
#include <coconut/cstring.h>
#include <coconut/csystem.h>
#include <coconut/cerror.h>
#include <coconut/ptext.h>
#include <stdlib.h>
#include <errno.h>

@implementation CReal

+ (id <PNumber>) newReal: (double) realval
{
	id <PNumber>	obj ;

	obj = [[CReal alloc] init] ;
	g_assert(obj != nil) ;
	[obj setReal: realval] ;
	return obj ;
}

+ (id <PError>) strToReal: (const char *) str to: (double *) result
{
	char *	endp ;
	if(str == NULL || result == NULL)
		return [CError illegal_parameter] ;
	*result = strtod(str, &endp) ;
	if(*endp == '\0' && errno == 0)
		return nil ;
	else
		return [CError illegal_parameter] ;
}

- initReal: (double) val
{
	real_value = val ;
	return [super init] ;
}

- init
{
	real_value = 0.0 ;
	return [super init] ;
}

- (void) dealloc
{
	return [super dealloc] ;
}

- (valtype_t) type
{
	return valtype_double ;
}

- setObject: (id <PNumber>) object
{
	real_value = [object realNum] ;
	return nil ;
}

- setBoolean: (boolean) val
{
	real_value = val ? 1.0 : 0.0 ;
	return nil ;
}

- setInt: (int) val
{
	real_value = (double) val ;
	return nil ;
}

- setReal: (double) val
{
	real_value = val ;
	return nil ;
}

- (boolean) booleanNum
{
	return real_value != 0.0 ? TRUE : FALSE ;
}

- (int) intNum
{
	return (double) real_value ;
}

- (double) realNum
{
	return real_value ;
}

- (id <PNumber>) addObject: (id <PNumber>) obj
{
	real_value += (double) [obj intNum] ;
	return self ;
}

- (id <PNumber>) addBoolean: (boolean) val
{
	real_value += val ? 1.0 : 0.0 ;
	return self ;
}

- (id <PNumber>) addInt: (int) val
{
	real_value += (double) val ;
	return self ;
}

- (id <PNumber>) addReal: (double) val
{
	real_value += val ;
	return self ;
}

- (id <PNumber>) duplicate
{
	return [CReal newReal: real_value] ;
}

- (id <PString>) toString
{
	id <PString>	newstr ;

	newstr = [[CString alloc] init] ;
	[CSystem checkPtr: newstr] ;
	[newstr setFormat: "((real) %lf)", real_value] ;
	return newstr ;
}

#define	INTDIFF(A, B)	(((int) A) - ((int) B))
- (int) compare: (id <PNumber>) src
{
	int	delta ;
	double	srcval, realdiff ;

	if((delta = INTDIFF(valtype_double, [src type])) != 0)
		return delta ;
	srcval = [src realNum] ;
	if(real_value == srcval)
		return 0 ;
	else {
		realdiff = real_value - srcval ;
		return realdiff > 0 ? 1 : -1 ;
	}
}

- (u_int) hashkey
{
	return (((int) VALTYPE_REAL) << 8) + real_value * 100 ;
}

#define	STREAM	((id <PIndentStream>) stream)
- print: (id) stream
{
	io_status_t	stat ;
	stat = [STREAM putFormat: "%.3f", real_value] ;
	return stat == io_status_normal ? nil : [CError can_not_happen] ;
}

@end

