941 lines · 25.7 KB · C++
RawDownload
} voidMath_getFPcontrol(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_getFPcontrol>();     // [PAL] Properly implement floating point control    throw vm_system_exception{ "Function not implemented" };} voidMath_getFPstatus(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_getFPstatus>();     // [PAL] Properly implement floating point control    throw vm_system_exception{ "Function not implemented" };} voidMath_hypot(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_hypot>();    *fp.ret = std::hypot(fp.x, fp.y);} voidMath_iamax(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_iamax>();     // [SPEC] According to the Inferno implementation (libmath/blas.c), 0 is returned    // if the array is empty. This means there is no indication the supplied array was    // empty or the first index was max. The spec does not describe this condition,    // therefore this implementation will indicate with -1.    *fp.ret = -1;     auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));    if (result->get_length() <= 0)        return;     auto r_raw = reinterpret_cast<real_t *>(result->at(0));     auto max_idx = 0;    auto r_len = result->get_length();    auto curr_max = std::fabs(r_raw[max_idx]);    for (auto i = word_t{ 1 }; i < r_len; ++i)    {        auto t = std::fabs(r_raw[i]);        if (curr_max < t)        {            max_idx = i;            curr_max = t;        }    }     *fp.ret = max_idx;} voidMath_ilogb(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_ilogb>();    *fp.ret = std::ilogb(fp.x);} voidMath_import_int(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_import_int>();     auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b);    assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get()));     auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<word_t>().get()));    const auto result_len = result->get_length();     if (buffer->get_length() != (sizeof(word_t) * result_len))        throw vm_user_exception{ "Invalid buffer size based on conversion" };     // Process as big endian    for (int i = 0; i < result_len; ++i)    {        uint32_t t = buffer->at<byte_t>(0);        for (int j = 1; j < sizeof(word_t); ++j)            t = (t << 8) | buffer->at<byte_t>(j);         auto x = static_cast<word_t>(t);        result->at<word_t>(i) = x;    }} voidMath_import_real(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_import_real>();     auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b);    assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get()));     auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));    const auto result_len = result->get_length();     if (buffer->get_length() != (sizeof(real_t) * result_len))        throw vm_user_exception{ "Invalid buffer size based on conversion" };     // Process as big endian    for (int i = 0; i < result_len; ++i)    {        uint64_t t = buffer->at<byte_t>(0);        for (int j = 1; j < sizeof(real_t); ++j)            t = (t << 8) | buffer->at<byte_t>(j);         real_t x;        std::memcpy(&x, &t, sizeof(t));        static_assert(sizeof(t) == sizeof(x), "Real should be 64-bits");         result->at<real_t>(i) = x;    }} voidMath_import_real32(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_import_real32>();     auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b);    assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get()));     auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));    const auto result_len = result->get_length();     if (buffer->get_length() != (sizeof(float) * result_len))        throw vm_user_exception{ "Invalid buffer size based on conversion" };     // Process as big endian    for (int i = 0; i < result_len; ++i)    {        uint32_t t = buffer->at<byte_t>(0);        for (int j = 1; j < sizeof(float); ++j)            t = (t << 8) | buffer->at<byte_t>(j);         float x_f;        std::memcpy(&x_f, &t, sizeof(t));        static_assert(sizeof(t) == sizeof(x_f), "Short-real should be 32-bits");         auto x = real_t{ x_f };        result->at<real_t>(i) = x;    }} voidMath_isnan(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_isnan>();    *fp.ret = std::isnan(fp.x) ? 1 : 0;} voidMath_j0(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_j0>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };} voidMath_j1(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_j1>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };} voidMath_jn(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_jn>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };} voidMath_lgamma(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_lgamma>();    throw vm_system_exception{ "Function not implemented" };} voidMath_log(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_log>();    *fp.ret = std::log(fp.x);} voidMath_log10(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_log10>();    *fp.ret = std::log10(fp.x);} voidMath_log1p(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_log1p>();    *fp.ret = std::log1p(fp.x);} voidMath_modf(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_modf>();     real_t integral_out;    const auto fractional_part = std::modf(fp.x, &integral_out);    const auto integral_part = static_cast<word_t>(integral_out);     fp.ret->t0 = integral_part;    fp.ret->t1 = fractional_part;} voidMath_nextafter(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_nextafter>();    *fp.ret = std::nextafter(fp.x, fp.y);} voidMath_norm1(vm_registers_t &r, vm_t &vm){    // Defined as: norm1(x) = sum(fabs(x[i]))    auto &fp = r.stack.peek_frame()->base<F_Math_norm1>();     auto xs = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    if (xs == nullptr)        throw dereference_nil{ "norm1" };     assert(xs->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));     const auto x_len = xs->get_length();    auto x_raw = reinterpret_cast<real_t *>(xs->at(0));     auto result = real_t{ 0 };    for (auto i = 0; i < x_len; ++i)        result += std::fabs(x_raw[i]);     *fp.ret = result;} voidMath_norm2(vm_registers_t &r, vm_t &vm){    // Defined as: norm2(x) = sqrt(dot(x, x))    auto &fp = r.stack.peek_frame()->base<F_Math_norm2>();     auto xs = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    if (xs == nullptr)        throw dereference_nil{ "norm2" };     assert(xs->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));     const auto x_len = xs->get_length();    auto x_raw = reinterpret_cast<real_t *>(xs->at(0));     auto result = real_t{ 0 };    for (auto i = 0; i < x_len; ++i)    {        const auto x_l = x_raw[i];        result += (x_l * x_l);    }     *fp.ret = std::sqrt(result);} voidMath_pow(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_pow>();    *fp.ret = std::pow(fp.x, fp.y);} voidMath_pow10(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_pow10>();    *fp.ret = std::pow(10., static_cast<real_t>(fp.p));} voidMath_realbits32(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_realbits32>();     auto x = static_cast<float>(fp.x);    word_t t;    std::memcpy(&t, &x, sizeof(x));     *fp.ret = t;} voidMath_realbits64(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_realbits64>();     auto x = fp.x;    big_t t;    std::memcpy(&t, &x, sizeof(x));    static_assert(sizeof(t) == sizeof(x), "Real should be 64-bits");     *fp.ret = t;} voidMath_remainder(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_remainder>();    *fp.ret = std::remainder(fp.x, fp.p);} voidMath_rint(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_rint>();    *fp.ret = std::rint(fp.x);} voidMath_scalbn(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_scalbn>();    *fp.ret = std::scalbln(fp.x, fp.n);} voidMath_sin(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_sin>();    *fp.ret = std::sin(fp.x);} voidMath_sinh(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_sinh>();    *fp.ret = std::sinh(fp.x);} voidMath_sort(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_sort>();     auto reals = vm_alloc_t::from_allocation<vm_array_t>(fp.x);    auto words = vm_alloc_t::from_allocation<vm_array_t>(fp.pi);    if (reals == nullptr || words == nullptr)        throw dereference_nil{ "Sort reals" };     assert(reals->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));    assert(words->get_element_type()->is_equal(intrinsic_type_desc::type<word_t>().get()));     const auto words_len = words->get_length();    if (reals->get_length() != words_len)        throw vm_user_exception{ "Array lengths must be equal" };     // Handle trivial sort cases    if (words_len <= 1)        return;     auto begin_words = reinterpret_cast<word_t *>(words->at(0));    auto end_words = begin_words + words_len;     // Validate array of indices    for (auto iter = begin_words; iter != end_words; ++iter)    {        if (*iter < 0 || words_len <= *iter)            throw vm_user_exception{ "Invalid sort index values" };    }     const auto reals_raw = reinterpret_cast<real_t *>(reals->at(0));    std::sort(begin_words, end_words, [reals_raw](word_t l, word_t r) { return reals_raw[l] < reals_raw[r]; });} voidMath_sqrt(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_sqrt>();    *fp.ret = std::sqrt(fp.x);} voidMath_tan(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_tan>();    *fp.ret = std::tan(fp.x);} voidMath_tanh(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_tanh>();    *fp.ret = std::tanh(fp.x);} voidMath_y0(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_y0>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };} voidMath_y1(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_y1>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };} voidMath_yn(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Math_yn>();     // [PAL] Consume platform API    throw vm_system_exception{ "Function not implemented" };}

Lines 501–941 of 941. Previous lines