} 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
} void Math_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" }; } void Math_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" }; } void Math_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); } void Math_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; } void Math_ilogb(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_ilogb>(); *fp.ret = std::ilogb(fp.x); } void Math_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; } } void Math_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; } } void Math_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; } } void Math_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; } void Math_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" }; } void Math_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" }; } void Math_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" }; } void Math_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" }; } void Math_log(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_log>(); *fp.ret = std::log(fp.x); } void Math_log10(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_log10>(); *fp.ret = std::log10(fp.x); } void Math_log1p(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_log1p>(); *fp.ret = std::log1p(fp.x); } void Math_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; } void Math_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); } void Math_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; } void Math_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); } void Math_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); } void Math_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)); } void Math_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; } void Math_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; } void Math_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); } void Math_rint(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_rint>(); *fp.ret = std::rint(fp.x); } void Math_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); } void Math_sin(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_sin>(); *fp.ret = std::sin(fp.x); } void Math_sinh(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_sinh>(); *fp.ret = std::sinh(fp.x); } void Math_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]; }); } void Math_sqrt(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_sqrt>(); *fp.ret = std::sqrt(fp.x); } void Math_tan(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_tan>(); *fp.ret = std::tan(fp.x); } void Math_tanh(vm_registers_t &r, vm_t &vm) { auto &fp = r.stack.peek_frame()->base<F_Math_tanh>(); *fp.ret = std::tanh(fp.x); } void Math_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" }; } void Math_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" }; } void Math_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" }; }