281 lines
6.0 KiB
C
281 lines
6.0 KiB
C
#include <fx/double.h>
|
|
#include <fx/stream.h>
|
|
#include <inttypes.h>
|
|
#include <stdint.h>
|
|
|
|
/*** PRIVATE DATA *************************************************************/
|
|
|
|
enum double_type {
|
|
DOUBLE_REGULAR = 0,
|
|
DOUBLE_INF_POSITIVE,
|
|
DOUBLE_INF_NEGATIVE,
|
|
DOUBLE_NAN_POSITIVE,
|
|
DOUBLE_NAN_NEGATIVE,
|
|
};
|
|
|
|
struct fx_double_p {
|
|
enum double_type i_type;
|
|
double i_value;
|
|
};
|
|
|
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
|
|
|
static bool double_get_value(const struct fx_double_p *i)
|
|
{
|
|
return i->i_value;
|
|
}
|
|
|
|
static void double_set_value(struct fx_double_p *i, double v)
|
|
{
|
|
i->i_type = DOUBLE_REGULAR;
|
|
i->i_value = v;
|
|
}
|
|
|
|
static void double_set_value_nan(struct fx_double_p *i)
|
|
{
|
|
i->i_type = DOUBLE_NAN_POSITIVE;
|
|
i->i_value = 0;
|
|
}
|
|
|
|
static void double_set_value_nan_negative(struct fx_double_p *i)
|
|
{
|
|
i->i_type = DOUBLE_NAN_NEGATIVE;
|
|
i->i_value = 0;
|
|
}
|
|
|
|
static void double_set_value_inf(struct fx_double_p *i)
|
|
{
|
|
i->i_type = DOUBLE_INF_POSITIVE;
|
|
i->i_value = 0;
|
|
}
|
|
|
|
static void double_set_value_inf_negative(struct fx_double_p *i)
|
|
{
|
|
i->i_type = DOUBLE_INF_NEGATIVE;
|
|
i->i_value = 0;
|
|
}
|
|
|
|
static bool double_is_nan(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_NAN_POSITIVE
|
|
|| i->i_type == DOUBLE_NAN_NEGATIVE;
|
|
}
|
|
|
|
static bool double_is_nan_positive(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_NAN_POSITIVE;
|
|
}
|
|
|
|
static bool double_is_nan_negative(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_NAN_NEGATIVE;
|
|
}
|
|
|
|
static bool double_is_inf(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_INF_POSITIVE
|
|
|| i->i_type == DOUBLE_INF_NEGATIVE;
|
|
}
|
|
|
|
static bool double_is_inf_positive(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_INF_POSITIVE;
|
|
}
|
|
|
|
static bool double_is_inf_negative(struct fx_double_p *i)
|
|
{
|
|
return i->i_type == DOUBLE_INF_NEGATIVE;
|
|
}
|
|
|
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
|
|
|
fx_double *fx_double_create(double value)
|
|
{
|
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
|
p->i_type = DOUBLE_REGULAR;
|
|
p->i_value = value;
|
|
|
|
return i;
|
|
}
|
|
|
|
fx_double *fx_double_create_nan(void)
|
|
{
|
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
|
p->i_type = DOUBLE_NAN_POSITIVE;
|
|
p->i_value = 0;
|
|
|
|
return i;
|
|
}
|
|
|
|
fx_double *fx_double_create_nan_negative(void)
|
|
{
|
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
|
p->i_type = DOUBLE_NAN_NEGATIVE;
|
|
p->i_value = 0;
|
|
|
|
return i;
|
|
}
|
|
|
|
fx_double *fx_double_create_inf(void)
|
|
{
|
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
|
p->i_type = DOUBLE_INF_POSITIVE;
|
|
p->i_value = 0;
|
|
|
|
return i;
|
|
}
|
|
|
|
fx_double *fx_double_create_inf_negative(void)
|
|
{
|
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
|
p->i_type = DOUBLE_INF_NEGATIVE;
|
|
p->i_value = 0;
|
|
|
|
return i;
|
|
}
|
|
|
|
double fx_double_get_value(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_get_value, i);
|
|
}
|
|
|
|
void fx_double_set_value(fx_double *i, double v)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_V(FX_TYPE_DOUBLE, double_set_value, i, v);
|
|
}
|
|
|
|
void fx_double_set_value_nan(fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_DOUBLE, double_set_value_nan, i);
|
|
}
|
|
|
|
void fx_double_set_value_nan_negative(fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_V0(
|
|
FX_TYPE_DOUBLE,
|
|
double_set_value_nan_negative,
|
|
i);
|
|
}
|
|
|
|
void fx_double_set_value_inf(fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_DOUBLE, double_set_value_inf, i);
|
|
}
|
|
|
|
void fx_double_set_value_inf_negative(fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_V0(
|
|
FX_TYPE_DOUBLE,
|
|
double_set_value_inf_negative,
|
|
i);
|
|
}
|
|
|
|
bool fx_double_is_nan(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan, i);
|
|
}
|
|
|
|
bool fx_double_is_nan_positive(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan_positive, i);
|
|
}
|
|
|
|
bool fx_double_is_nan_negative(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan_negative, i);
|
|
}
|
|
|
|
bool fx_double_is_inf(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf, i);
|
|
}
|
|
|
|
bool fx_double_is_inf_positive(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf_positive, i);
|
|
}
|
|
|
|
bool fx_double_is_inf_negative(const fx_double *i)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf_negative, i);
|
|
}
|
|
|
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
|
|
|
static void double_init(fx_object *obj, void *priv)
|
|
{
|
|
struct fx_double_p *i = priv;
|
|
|
|
i->i_type = DOUBLE_REGULAR;
|
|
i->i_value = 0;
|
|
}
|
|
|
|
static void double_fini(fx_object *obj, void *priv)
|
|
{
|
|
}
|
|
|
|
static void double_to_string(const fx_object *obj, fx_stream *out)
|
|
{
|
|
struct fx_double_p *i = fx_object_get_private(obj, FX_TYPE_DOUBLE);
|
|
switch (i->i_type) {
|
|
case DOUBLE_REGULAR:
|
|
fx_stream_write_fmt(out, NULL, "%" PRIdPTR, i->i_value);
|
|
break;
|
|
case DOUBLE_INF_POSITIVE:
|
|
fx_stream_write_cstr(out, "inf", NULL);
|
|
break;
|
|
case DOUBLE_INF_NEGATIVE:
|
|
fx_stream_write_cstr(out, "-inf", NULL);
|
|
break;
|
|
case DOUBLE_NAN_POSITIVE:
|
|
fx_stream_write_cstr(out, "NaN", NULL);
|
|
break;
|
|
case DOUBLE_NAN_NEGATIVE:
|
|
fx_stream_write_cstr(out, "-NaN", NULL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*** CLASS DEFINITION *********************************************************/
|
|
|
|
FX_TYPE_CLASS_BEGIN(fx_double)
|
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
|
FX_INTERFACE_ENTRY(to_string) = double_to_string;
|
|
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
|
FX_TYPE_CLASS_END(fx_double)
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_double)
|
|
FX_TYPE_ID(0x3b20f57a, 0x2ddf, 0x4682, 0x81c4, 0x4fe404a6524e);
|
|
FX_TYPE_CLASS(fx_double_class);
|
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_double_p);
|
|
FX_TYPE_INSTANCE_INIT(double_init);
|
|
FX_TYPE_INSTANCE_FINI(double_fini);
|
|
FX_TYPE_DEFINITION_END(fx_double)
|