signed long long vanilla::int_object_to_signed_longlong(object::ptr const& obj) { #if LLONG_MAX == LONG_MAX return int_object_to_signed_long(obj); #endif if(obj->type_id() != OBJECT_ID_INT) { BOOST_THROW_EXCEPTION(error::bad_cast_error() << error::first_operand(obj) << error::cast_target_name("int")); } mpz_t& mpz = static_cast<int_object const*>(obj.get())->value().mpz(); if(mpz_sizeinbase(mpz, 2) + 1 > sizeof(long long) * CHAR_BIT) { BOOST_THROW_EXCEPTION(error::integer_conversion_overflow_error() << error::first_operand(obj) << error::integer_conversion_target_type("signed long long")); } size_t count = 0; long long result = 0; mpz_export(&result, &count, -1, sizeof(result), 0, 0, mpz); assert(count == 1); return result; }
vanilla::object::ptr vanilla::int_object::neq(object::ptr const& other) { switch(other->type_id()) { case OBJECT_ID_INT: { int_object const* rhs = static_cast<int_object const*>(other.get()); int result = mpz_cmp(_v.mpz(), rhs->value().mpz()); return allocate_object<bool_object>(result != 0); } case OBJECT_ID_FLOAT: { float_object const* rhs = static_cast<float_object const*>(other.get()); if(!mpf_integer_p(rhs->value().mpf())) return allocate_object<bool_object>(true); float_object::float_type lhs( (_v.mpz()) ); return allocate_object<bool_object>(mpf_cmp(lhs.mpf(), rhs->value().mpf()) != 0); } default: { return object::ge(other); } } }
vanilla::object::ptr vanilla::int_object::div(object::ptr const& other) { switch(other->type_id()) { case OBJECT_ID_INT: { float_object::float_type lhs( (_v.mpz()) ); float_object::float_type rhs( (static_cast<int_object const*>(other.get())->value().mpz()) ); float_object::float_type result; mpf_div(result.mpf(), lhs.mpf(), rhs.mpf()); return allocate_object<float_object>(std::move(result)); } case OBJECT_ID_FLOAT: { float_object::float_type lhs( (_v.mpz()) ); float_object const* rhs = static_cast<float_object const*>(other.get()); float_object::float_type result; mpf_div(result.mpf(), lhs.mpf(), rhs->value().mpf()); return allocate_object<float_object>(std::move(result)); } default: { return object::div(other); } } }
signed long vanilla::int_object_to_signed_long(object::ptr const& obj) { if(obj->type_id() != OBJECT_ID_INT) { BOOST_THROW_EXCEPTION(error::bad_cast_error() << error::first_operand(obj) << error::cast_target_name("int")); } mpz_t& mpz = static_cast<int_object const*>(obj.get())->value().mpz(); if(!mpz_fits_slong_p(mpz)) { BOOST_THROW_EXCEPTION(error::integer_conversion_overflow_error() << error::first_operand(obj) << error::integer_conversion_target_type("signed long")); } return mpz_get_si(mpz); }
double vanilla::float_object_to_double(object::ptr const& obj) { if(obj->type_id() != OBJECT_ID_FLOAT) { BOOST_THROW_EXCEPTION(error::bad_cast_error() << error::first_operand(obj) << error::cast_target_name("float")); } mpf_t& mpf = static_cast<float_object const*>(obj.get())->value().mpf(); double result = mpf_get_d(mpf); if(std::numeric_limits<double>::has_infinity && result == std::numeric_limits<double>::infinity()) { BOOST_THROW_EXCEPTION(error::float_conversion_overflow_error() << error::first_operand(obj) << error::float_conversion_target_type("double")); } return result; }