diff --git a/object/include/blue/object/number.h b/object/include/blue/object/number.h index b8eaa0c..0051846 100644 --- a/object/include/blue/object/number.h +++ b/object/include/blue/object/number.h @@ -237,6 +237,17 @@ static inline size_t b_number_get_size_t(const b_number *number) BLUE_API bool b_number_is_integer(const b_number *number); BLUE_API bool b_number_is_float(const b_number *number); +BLUE_API bool b_number_is_inf(const b_number *number); +BLUE_API bool b_number_is_inf_positive(const b_number *number); +BLUE_API bool b_number_is_inf_negative(const b_number *number); +BLUE_API bool b_number_is_nan(const b_number *number); +BLUE_API bool b_number_is_nan_positive(const b_number *number); +BLUE_API bool b_number_is_nan_negative(const b_number *number); + +BLUE_API void b_number_set_inf_positive(b_number *number, bool v); +BLUE_API void b_number_set_inf_negative(b_number *number, bool v); +BLUE_API void b_number_set_nan_positive(b_number *number, bool v); +BLUE_API void b_number_set_nan_negative(b_number *number, bool v); BLUE_API size_t b_number_data_size(const b_number *number); diff --git a/object/number.c b/object/number.c index a031cfe..075520f 100644 --- a/object/number.c +++ b/object/number.c @@ -139,6 +139,408 @@ bool b_number_is_float(const struct b_number *number) } } +bool b_number_is_inf(const b_number *number) +{ + return (number->n_flags & NUMBER_F_INF) != 0; +} + +bool b_number_is_inf_positive(const b_number *number) +{ + if (!(number->n_flags & NUMBER_F_INF)) { + return false; + } + + switch (number->n_type) { + case B_NUMBER_INT8: + return number->n_value.v_int8 >= 0; + case B_NUMBER_INT16: + return number->n_value.v_int16 >= 0; + case B_NUMBER_INT32: + return number->n_value.v_int32 >= 0; + case B_NUMBER_INT64: + return number->n_value.v_int64 >= 0; + case B_NUMBER_FLOAT32: + return number->n_value.v_float32 >= 0; + case B_NUMBER_FLOAT64: + return number->n_value.v_float64 >= 0; + case B_NUMBER_CHAR: + return number->n_value.v_char >= 0; + case B_NUMBER_SHORT: + return number->n_value.v_short >= 0; + case B_NUMBER_INT: + return number->n_value.v_int >= 0; + case B_NUMBER_LONG: + return number->n_value.v_long >= 0; + case B_NUMBER_LONGLONG: + return number->n_value.v_longlong >= 0; + case B_NUMBER_FLOAT: + return number->n_value.v_float >= 0; + case B_NUMBER_DOUBLE: + return number->n_value.v_double >= 0; + case B_NUMBER_SIZE_T: + return number->n_value.v_size_t >= 0; + default: + return true; + } +} + +bool b_number_is_inf_negative(const b_number *number) +{ + if (!(number->n_flags & NUMBER_F_INF)) { + return false; + } + + switch (number->n_type) { + case B_NUMBER_INT8: + return number->n_value.v_int8 < 0; + case B_NUMBER_INT16: + return number->n_value.v_int16 < 0; + case B_NUMBER_INT32: + return number->n_value.v_int32 < 0; + case B_NUMBER_INT64: + return number->n_value.v_int64 < 0; + case B_NUMBER_FLOAT32: + return number->n_value.v_float32 < 0; + case B_NUMBER_FLOAT64: + return number->n_value.v_float64 < 0; + case B_NUMBER_CHAR: + return number->n_value.v_char < 0; + case B_NUMBER_SHORT: + return number->n_value.v_short < 0; + case B_NUMBER_INT: + return number->n_value.v_int < 0; + case B_NUMBER_LONG: + return number->n_value.v_long < 0; + case B_NUMBER_LONGLONG: + return number->n_value.v_longlong < 0; + case B_NUMBER_FLOAT: + return number->n_value.v_float < 0; + case B_NUMBER_DOUBLE: + return number->n_value.v_double < 0; + case B_NUMBER_SIZE_T: + return number->n_value.v_size_t < 0; + default: + return false; + } +} + +bool b_number_is_nan(const b_number *number) +{ + return (number->n_flags & NUMBER_F_NAN) != 0; +} + +bool b_number_is_nan_positive(const b_number *number) +{ + if (!(number->n_flags & NUMBER_F_NAN)) { + return false; + } + + switch (number->n_type) { + case B_NUMBER_INT8: + return number->n_value.v_int8 >= 0; + case B_NUMBER_INT16: + return number->n_value.v_int16 >= 0; + case B_NUMBER_INT32: + return number->n_value.v_int32 >= 0; + case B_NUMBER_INT64: + return number->n_value.v_int64 >= 0; + case B_NUMBER_FLOAT32: + return number->n_value.v_float32 >= 0; + case B_NUMBER_FLOAT64: + return number->n_value.v_float64 >= 0; + case B_NUMBER_CHAR: + return number->n_value.v_char >= 0; + case B_NUMBER_SHORT: + return number->n_value.v_short >= 0; + case B_NUMBER_INT: + return number->n_value.v_int >= 0; + case B_NUMBER_LONG: + return number->n_value.v_long >= 0; + case B_NUMBER_LONGLONG: + return number->n_value.v_longlong >= 0; + case B_NUMBER_FLOAT: + return number->n_value.v_float >= 0; + case B_NUMBER_DOUBLE: + return number->n_value.v_double >= 0; + case B_NUMBER_SIZE_T: + return number->n_value.v_size_t >= 0; + default: + return true; + } +} + +bool b_number_is_nan_negative(const b_number *number) +{ + if (!(number->n_flags & NUMBER_F_NAN)) { + return false; + } + + switch (number->n_type) { + case B_NUMBER_INT8: + return number->n_value.v_int8 < 0; + case B_NUMBER_INT16: + return number->n_value.v_int16 < 0; + case B_NUMBER_INT32: + return number->n_value.v_int32 < 0; + case B_NUMBER_INT64: + return number->n_value.v_int64 < 0; + case B_NUMBER_FLOAT32: + return number->n_value.v_float32 < 0; + case B_NUMBER_FLOAT64: + return number->n_value.v_float64 < 0; + case B_NUMBER_CHAR: + return number->n_value.v_char < 0; + case B_NUMBER_SHORT: + return number->n_value.v_short < 0; + case B_NUMBER_INT: + return number->n_value.v_int < 0; + case B_NUMBER_LONG: + return number->n_value.v_long < 0; + case B_NUMBER_LONGLONG: + return number->n_value.v_longlong < 0; + case B_NUMBER_FLOAT: + return number->n_value.v_float < 0; + case B_NUMBER_DOUBLE: + return number->n_value.v_double < 0; + case B_NUMBER_SIZE_T: + return number->n_value.v_size_t < 0; + default: + return false; + } +} + +void b_number_set_inf_positive(b_number *number, bool v) +{ + if (!v) { + number->n_flags &= ~NUMBER_F_INF; + return; + } + + number->n_flags &= ~NUMBER_F_NAN; + number->n_flags |= NUMBER_F_INF; + + switch (number->n_type) { + case B_NUMBER_INT8: + number->n_value.v_int8 = 0; + break; + case B_NUMBER_INT16: + number->n_value.v_int16 = 0; + break; + case B_NUMBER_INT32: + number->n_value.v_int32 = 0; + break; + case B_NUMBER_INT64: + number->n_value.v_int64 = 0; + break; + case B_NUMBER_FLOAT32: + number->n_value.v_float32 = 0; + break; + case B_NUMBER_FLOAT64: + number->n_value.v_float64 = 0; + break; + case B_NUMBER_CHAR: + number->n_value.v_char = 0; + break; + case B_NUMBER_SHORT: + number->n_value.v_short = 0; + break; + case B_NUMBER_INT: + number->n_value.v_int = 0; + break; + case B_NUMBER_LONG: + number->n_value.v_long = 0; + break; + case B_NUMBER_LONGLONG: + number->n_value.v_longlong = 0; + break; + case B_NUMBER_FLOAT: + number->n_value.v_float = 0; + break; + case B_NUMBER_DOUBLE: + number->n_value.v_double = 0; + break; + case B_NUMBER_SIZE_T: + number->n_value.v_size_t = 0; + break; + default: + break; + } +} + +void b_number_set_inf_negative(b_number *number, bool v) +{ + if (!v) { + number->n_flags &= ~NUMBER_F_INF; + return; + } + + number->n_flags &= ~NUMBER_F_NAN; + number->n_flags |= NUMBER_F_INF; + + switch (number->n_type) { + case B_NUMBER_INT8: + number->n_value.v_int8 = -1; + break; + case B_NUMBER_INT16: + number->n_value.v_int16 = -1; + break; + case B_NUMBER_INT32: + number->n_value.v_int32 = -1; + break; + case B_NUMBER_INT64: + number->n_value.v_int64 = -1; + break; + case B_NUMBER_FLOAT32: + number->n_value.v_float32 = -1; + break; + case B_NUMBER_FLOAT64: + number->n_value.v_float64 = -1; + break; + case B_NUMBER_CHAR: + number->n_value.v_char = -1; + break; + case B_NUMBER_SHORT: + number->n_value.v_short = -1; + break; + case B_NUMBER_INT: + number->n_value.v_int = -1; + break; + case B_NUMBER_LONG: + number->n_value.v_long = -1; + break; + case B_NUMBER_LONGLONG: + number->n_value.v_longlong = -1; + break; + case B_NUMBER_FLOAT: + number->n_value.v_float = -1; + break; + case B_NUMBER_DOUBLE: + number->n_value.v_double = -1; + break; + case B_NUMBER_SIZE_T: + number->n_value.v_size_t = -1; + break; + default: + break; + } +} + +void b_number_set_nan_positive(b_number *number, bool v) +{ + if (!v) { + number->n_flags &= ~NUMBER_F_NAN; + return; + } + + number->n_flags &= ~NUMBER_F_INF; + number->n_flags |= NUMBER_F_NAN; + + switch (number->n_type) { + case B_NUMBER_INT8: + number->n_value.v_int8 = 0; + break; + case B_NUMBER_INT16: + number->n_value.v_int16 = 0; + break; + case B_NUMBER_INT32: + number->n_value.v_int32 = 0; + break; + case B_NUMBER_INT64: + number->n_value.v_int64 = 0; + break; + case B_NUMBER_FLOAT32: + number->n_value.v_float32 = 0; + break; + case B_NUMBER_FLOAT64: + number->n_value.v_float64 = 0; + break; + case B_NUMBER_CHAR: + number->n_value.v_char = 0; + break; + case B_NUMBER_SHORT: + number->n_value.v_short = 0; + break; + case B_NUMBER_INT: + number->n_value.v_int = 0; + break; + case B_NUMBER_LONG: + number->n_value.v_long = 0; + break; + case B_NUMBER_LONGLONG: + number->n_value.v_longlong = 0; + break; + case B_NUMBER_FLOAT: + number->n_value.v_float = 0; + break; + case B_NUMBER_DOUBLE: + number->n_value.v_double = 0; + break; + case B_NUMBER_SIZE_T: + number->n_value.v_size_t = 0; + break; + default: + break; + } +} + +void b_number_set_nan_negative(b_number *number, bool v) +{ + if (!v) { + number->n_flags &= ~NUMBER_F_NAN; + return; + } + + number->n_flags &= ~NUMBER_F_INF; + number->n_flags |= NUMBER_F_NAN; + + switch (number->n_type) { + case B_NUMBER_INT8: + number->n_value.v_int8 = -1; + break; + case B_NUMBER_INT16: + number->n_value.v_int16 = -1; + break; + case B_NUMBER_INT32: + number->n_value.v_int32 = -1; + break; + case B_NUMBER_INT64: + number->n_value.v_int64 = -1; + break; + case B_NUMBER_FLOAT32: + number->n_value.v_float32 = -1; + break; + case B_NUMBER_FLOAT64: + number->n_value.v_float64 = -1; + break; + case B_NUMBER_CHAR: + number->n_value.v_char = -1; + break; + case B_NUMBER_SHORT: + number->n_value.v_short = -1; + break; + case B_NUMBER_INT: + number->n_value.v_int = -1; + break; + case B_NUMBER_LONG: + number->n_value.v_long = -1; + break; + case B_NUMBER_LONGLONG: + number->n_value.v_longlong = -1; + break; + case B_NUMBER_FLOAT: + number->n_value.v_float = -1; + break; + case B_NUMBER_DOUBLE: + number->n_value.v_double = -1; + break; + case B_NUMBER_SIZE_T: + number->n_value.v_size_t = -1; + break; + default: + break; + } +} + size_t b_number_data_size(const struct b_number *number) { switch (number->n_type) { @@ -175,9 +577,130 @@ size_t b_number_data_size(const struct b_number *number) } } +static void print_inf(const struct b_number *n, struct b_stream *out) +{ + switch (n->n_type) { + case B_NUMBER_INT8: + b_stream_write_string(out, n->n_value.v_int8 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT16: + b_stream_write_string(out, n->n_value.v_int16 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT32: + b_stream_write_string(out, n->n_value.v_int32 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT64: + b_stream_write_string(out, n->n_value.v_int64 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT32: + b_stream_write_string( + out, n->n_value.v_float32 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT64: + b_stream_write_string( + out, n->n_value.v_float64 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_CHAR: + b_stream_write_string(out, n->n_value.v_char < 0 ? "-" : "", NULL); + break; + case B_NUMBER_SHORT: + b_stream_write_string(out, n->n_value.v_short < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT: + b_stream_write_string(out, n->n_value.v_int < 0 ? "-" : "", NULL); + break; + case B_NUMBER_LONG: + b_stream_write_string(out, n->n_value.v_long < 0 ? "-" : "", NULL); + break; + case B_NUMBER_LONGLONG: + b_stream_write_string( + out, n->n_value.v_longlong < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT: + b_stream_write_string(out, n->n_value.v_float < 0 ? "-" : "", NULL); + break; + case B_NUMBER_DOUBLE: + b_stream_write_string(out, n->n_value.v_double < 0 ? "-" : "", NULL); + break; + case B_NUMBER_SIZE_T: + b_stream_write_string(out, n->n_value.v_size_t < 0 ? "-" : "", NULL); + break; + default: + break; + } + + b_stream_write_string(out, "INF", NULL); +} + +static void print_nan(const struct b_number *n, struct b_stream *out) +{ + switch (n->n_type) { + case B_NUMBER_INT8: + b_stream_write_string(out, n->n_value.v_int8 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT16: + b_stream_write_string(out, n->n_value.v_int16 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT32: + b_stream_write_string(out, n->n_value.v_int32 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT64: + b_stream_write_string(out, n->n_value.v_int64 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT32: + b_stream_write_string( + out, n->n_value.v_float32 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT64: + b_stream_write_string( + out, n->n_value.v_float64 < 0 ? "-" : "", NULL); + break; + case B_NUMBER_CHAR: + b_stream_write_string(out, n->n_value.v_char < 0 ? "-" : "", NULL); + break; + case B_NUMBER_SHORT: + b_stream_write_string(out, n->n_value.v_short < 0 ? "-" : "", NULL); + break; + case B_NUMBER_INT: + b_stream_write_string(out, n->n_value.v_int < 0 ? "-" : "", NULL); + break; + case B_NUMBER_LONG: + b_stream_write_string(out, n->n_value.v_long < 0 ? "-" : "", NULL); + break; + case B_NUMBER_LONGLONG: + b_stream_write_string( + out, n->n_value.v_longlong < 0 ? "-" : "", NULL); + break; + case B_NUMBER_FLOAT: + b_stream_write_string(out, n->n_value.v_float < 0 ? "-" : "", NULL); + break; + case B_NUMBER_DOUBLE: + b_stream_write_string(out, n->n_value.v_double < 0 ? "-" : "", NULL); + break; + case B_NUMBER_SIZE_T: + b_stream_write_string(out, n->n_value.v_size_t < 0 ? "-" : "", NULL); + break; + default: + break; + } + + b_stream_write_string(out, "NaN", NULL); +} + static void number_to_string(const struct b_object *obj, struct b_stream *out) { struct b_number *number = B_NUMBER(obj); + + if (number->n_flags & NUMBER_F_INF) { + print_inf(number, out); + return; + } + + if (number->n_flags & NUMBER_F_NAN) { + print_nan(number, out); + return; + } + switch (number->n_type) { case B_NUMBER_INT8: b_stream_write_fmt(out, NULL, "%" PRIu8, number->n_value.v_int8); diff --git a/object/number.h b/object/number.h index fe29158..2aa7048 100644 --- a/object/number.h +++ b/object/number.h @@ -5,9 +5,15 @@ #include +enum b_number_flags { + NUMBER_F_INF = 0x01u, + NUMBER_F_NAN = 0x02u, +}; + struct b_number { struct b_object n_base; b_number_type n_type; + enum b_number_flags n_flags; union { int8_t v_int8; int16_t v_int16;