Unified · Split
| @@ -290,7 +290,28 @@ void · 289 unmodified lines | |||
| 290 | Math_export_int(vm_registers_t &r, vm_t &vm) | 290 | Math_export_int(vm_registers_t &r, vm_t &vm) |
| 291 | { | 291 | { |
| 292 | auto &fp = r.stack.peek_frame()->base<F_Math_export_int>(); | 292 | auto &fp = r.stack.peek_frame()->base<F_Math_export_int>(); |
| 293 | throw vm_system_exception{ "Function not implemented" }; | 293 | |
| 294 | auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b); | ||
| 295 | assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get())); | ||
| 296 | |||
| 297 | auto values = vm_alloc_t::from_allocation<vm_array_t>(fp.x); | ||
| 298 | assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<word_t>().get())); | ||
| 299 | const auto values_len = values->get_length(); | ||
| 300 | |||
| 301 | if (buffer->get_length() != (sizeof(word_t) * values_len)) | ||
| 302 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | ||
| 303 | |||
| 304 | // Insert as big endian | ||
| 305 | for (int i = 0; i < values_len; ++i) | ||
| 306 | { | ||
| 307 | auto x = values->at<word_t>(i); | ||
| 308 | |||
| 309 | auto base = reinterpret_cast<byte_t *>(buffer->at(i * sizeof(x))); | ||
| 310 | base[0] = static_cast<byte_t>(x >> 24); | ||
| 311 | base[1] = static_cast<byte_t>(x >> 16); | ||
| 312 | base[2] = static_cast<byte_t>(x >> 8); | ||
| 313 | base[3] = static_cast<byte_t>(x); | ||
| 314 | } | ||
| 294 | } | 315 | } |
| 295 | 316 | ||
| 296 | void | 317 | void |
| @@ -305,7 +326,7 @@ Math_export_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines | |||
| 305 | assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); | 326 | assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); |
| 306 | const auto values_len = values->get_length(); | 327 | const auto values_len = values->get_length(); |
| 307 | 328 | ||
| 308 | if (buffer->get_length() != (8 * values_len)) | 329 | if (buffer->get_length() != (sizeof(real_t) * values_len)) |
| 309 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | 330 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; |
| 310 | 331 | ||
| 311 | // Insert as big endian | 332 | // Insert as big endian |
| @@ -332,7 +353,32 @@ void · 20 unmodified lines | |||
| 332 | Math_export_real32(vm_registers_t &r, vm_t &vm) | 353 | Math_export_real32(vm_registers_t &r, vm_t &vm) |
| 333 | { | 354 | { |
| 334 | auto &fp = r.stack.peek_frame()->base<F_Math_export_real32>(); | 355 | auto &fp = r.stack.peek_frame()->base<F_Math_export_real32>(); |
| 335 | throw vm_system_exception{ "Function not implemented" }; | 356 | |
| 357 | auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b); | ||
| 358 | assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get())); | ||
| 359 | |||
| 360 | auto values = vm_alloc_t::from_allocation<vm_array_t>(fp.x); | ||
| 361 | assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); | ||
| 362 | const auto values_len = values->get_length(); | ||
| 363 | |||
| 364 | if (buffer->get_length() != (sizeof(float) * values_len)) | ||
| 365 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | ||
| 366 | |||
| 367 | // Insert as big endian | ||
| 368 | for (int i = 0; i < values_len; ++i) | ||
| 369 | { | ||
| 370 | auto x_r = values->at<real_t>(i); | ||
| 371 | auto x = static_cast<float>(x_r); | ||
| 372 | uint32_t t; | ||
| 373 | std::memcpy(&t, &x, sizeof(x)); | ||
| 374 | static_assert(sizeof(t) == sizeof(x), "Short-real should be 32-bits"); | ||
| 375 | |||
| 376 | auto base = reinterpret_cast<byte_t *>(buffer->at(i * sizeof(x))); | ||
| 377 | base[0] = static_cast<byte_t>(t >> 24); | ||
| 378 | base[1] = static_cast<byte_t>(t >> 16); | ||
| 379 | base[2] = static_cast<byte_t>(t >> 8); | ||
| 380 | base[3] = static_cast<byte_t>(t); | ||
| 381 | } | ||
| 336 | } | 382 | } |
| 337 | 383 | ||
| 338 | void | 384 | void |
| @@ -416,7 +462,34 @@ void · 77 unmodified lines | |||
| 416 | Math_iamax(vm_registers_t &r, vm_t &vm) | 462 | Math_iamax(vm_registers_t &r, vm_t &vm) |
| 417 | { | 463 | { |
| 418 | auto &fp = r.stack.peek_frame()->base<F_Math_iamax>(); | 464 | auto &fp = r.stack.peek_frame()->base<F_Math_iamax>(); |
| 419 | throw vm_system_exception{ "Function not implemented" }; | 465 | |
| 466 | // [SPEC] According to the Inferno implementation (libmath/blas.c), 0 is returned | ||
| 467 | // if the array is empty. This means there is no indication the supplied array was | ||
| 468 | // empty or the first index was max. The spec does not describe this condition, | ||
| 469 | // therefore this implementation will indicate with -1. | ||
| 470 | *fp.ret = -1; | ||
| 471 | |||
| 472 | auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x); | ||
| 473 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); | ||
| 474 | if (result->get_length() <= 0) | ||
| 475 | return; | ||
| 476 | |||
| 477 | auto r_raw = reinterpret_cast<real_t *>(result->at(0)); | ||
| 478 | |||
| 479 | auto max_idx = 0; | ||
| 480 | auto r_len = result->get_length(); | ||
| 481 | auto curr_max = std::fabs(r_raw[max_idx]); | ||
| 482 | for (auto i = word_t{ 1 }; i < r_len; ++i) | ||
| 483 | { | ||
| 484 | auto t = std::fabs(r_raw[i]); | ||
| 485 | if (curr_max < t) | ||
| 486 | { | ||
| 487 | max_idx = i; | ||
| 488 | curr_max = t; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | *fp.ret = max_idx; | ||
| 420 | } | 493 | } |
| 421 | 494 | ||
| 422 | void | 495 | void |
| @@ -430,7 +503,27 @@ void · 7 unmodified lines | |||
| 430 | Math_import_int(vm_registers_t &r, vm_t &vm) | 503 | Math_import_int(vm_registers_t &r, vm_t &vm) |
| 431 | { | 504 | { |
| 432 | auto &fp = r.stack.peek_frame()->base<F_Math_import_int>(); | 505 | auto &fp = r.stack.peek_frame()->base<F_Math_import_int>(); |
| 433 | throw vm_system_exception{ "Function not implemented" }; | 506 | |
| 507 | auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b); | ||
| 508 | assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get())); | ||
| 509 | |||
| 510 | auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x); | ||
| 511 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<word_t>().get())); | ||
| 512 | const auto result_len = result->get_length(); | ||
| 513 | |||
| 514 | if (buffer->get_length() != (sizeof(word_t) * result_len)) | ||
| 515 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | ||
| 516 | |||
| 517 | // Process as big endian | ||
| 518 | for (int i = 0; i < result_len; ++i) | ||
| 519 | { | ||
| 520 | uint32_t t = buffer->at<byte_t>(0); | ||
| 521 | for (int j = 1; j < sizeof(word_t); ++j) | ||
| 522 | t = (t << 8) | buffer->at<byte_t>(j); | ||
| 523 | |||
| 524 | auto x = static_cast<word_t>(t); | ||
| 525 | result->at<word_t>(i) = x; | ||
| 526 | } | ||
| 434 | } | 527 | } |
| 435 | 528 | ||
| 436 | void | 529 | void |
| @@ -445,14 +538,14 @@ Math_import_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines | |||
| 445 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); | 538 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); |
| 446 | const auto result_len = result->get_length(); | 539 | const auto result_len = result->get_length(); |
| 447 | 540 | ||
| 448 | if (buffer->get_length() != (8 * result_len)) | 541 | if (buffer->get_length() != (sizeof(real_t) * result_len)) |
| 449 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | 542 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; |
| 450 | 543 | ||
| 451 | // Process as big endian | 544 | // Process as big endian |
| 452 | for (int i = 0; i < result_len; ++i) | 545 | for (int i = 0; i < result_len; ++i) |
| 453 | { | 546 | { |
| 454 | uint64_t t = buffer->at<byte_t>(0); | 547 | uint64_t t = buffer->at<byte_t>(0); |
| 455 | for (int j = 1; j < 8; ++j) | 548 | for (int j = 1; j < sizeof(real_t); ++j) |
| 456 | t = (t << 8) | buffer->at<byte_t>(j); | 549 | t = (t << 8) | buffer->at<byte_t>(j); |
| 457 | 550 | ||
| 458 | real_t x; | 551 | real_t x; |
| @@ -467,7 +560,31 @@ void · 8 unmodified lines | |||
| 467 | Math_import_real32(vm_registers_t &r, vm_t &vm) | 560 | Math_import_real32(vm_registers_t &r, vm_t &vm) |
| 468 | { | 561 | { |
| 469 | auto &fp = r.stack.peek_frame()->base<F_Math_import_real32>(); | 562 | auto &fp = r.stack.peek_frame()->base<F_Math_import_real32>(); |
| 470 | throw vm_system_exception{ "Function not implemented" }; | 563 | |
| 564 | auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.b); | ||
| 565 | assert(buffer->get_element_type()->is_equal(intrinsic_type_desc::type<byte_t>().get())); | ||
| 566 | |||
| 567 | auto result = vm_alloc_t::from_allocation<vm_array_t>(fp.x); | ||
| 568 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); | ||
| 569 | const auto result_len = result->get_length(); | ||
| 570 | |||
| 571 | if (buffer->get_length() != (sizeof(float) * result_len)) | ||
| 572 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; | ||
| 573 | |||
| 574 | // Process as big endian | ||
| 575 | for (int i = 0; i < result_len; ++i) | ||
| 576 | { | ||
| 577 | uint32_t t = buffer->at<byte_t>(0); | ||
| 578 | for (int j = 1; j < sizeof(float); ++j) | ||
| 579 | t = (t << 8) | buffer->at<byte_t>(j); | ||
| 580 | |||
| 581 | float x_f; | ||
| 582 | std::memcpy(&x_f, &t, sizeof(t)); | ||
| 583 | static_assert(sizeof(t) == sizeof(x_f), "Short-real should be 32-bits"); | ||
| 584 | |||
| 585 | auto x = real_t{ x_f }; | ||
| 586 | result->at<real_t>(i) = x; | ||
| 587 | } | ||
| 471 | } | 588 | } |
| 472 | 589 | ||
| 473 | void | 590 | void |
| @@ -481,6 +598,8 @@ void · 7 unmodified lines | |||
| 481 | Math_j0(vm_registers_t &r, vm_t &vm) | 598 | Math_j0(vm_registers_t &r, vm_t &vm) |
| 482 | { | 599 | { |
| 483 | auto &fp = r.stack.peek_frame()->base<F_Math_j0>(); | 600 | auto &fp = r.stack.peek_frame()->base<F_Math_j0>(); |
| 601 | |||
| 602 | // [PAL] Consume platform API | ||
| 484 | throw vm_system_exception{ "Function not implemented" }; | 603 | throw vm_system_exception{ "Function not implemented" }; |
| 485 | } | 604 | } |
| 486 | 605 | ||
| @@ -488,6 +607,8 @@ void · 1 unmodified line | |||
| 488 | Math_j1(vm_registers_t &r, vm_t &vm) | 607 | Math_j1(vm_registers_t &r, vm_t &vm) |
| 489 | { | 608 | { |
| 490 | auto &fp = r.stack.peek_frame()->base<F_Math_j1>(); | 609 | auto &fp = r.stack.peek_frame()->base<F_Math_j1>(); |
| 610 | |||
| 611 | // [PAL] Consume platform API | ||
| 491 | throw vm_system_exception{ "Function not implemented" }; | 612 | throw vm_system_exception{ "Function not implemented" }; |
| 492 | } | 613 | } |
| 493 | 614 | ||
| @@ -495,6 +616,8 @@ void · 1 unmodified line | |||
| 495 | Math_jn(vm_registers_t &r, vm_t &vm) | 616 | Math_jn(vm_registers_t &r, vm_t &vm) |
| 496 | { | 617 | { |
| 497 | auto &fp = r.stack.peek_frame()->base<F_Math_jn>(); | 618 | auto &fp = r.stack.peek_frame()->base<F_Math_jn>(); |
| 619 | |||
| 620 | // [PAL] Consume platform API | ||
| 498 | throw vm_system_exception{ "Function not implemented" }; | 621 | throw vm_system_exception{ "Function not implemented" }; |
| 499 | } | 622 | } |
| 500 | 623 | ||
| @@ -530,7 +653,13 @@ void · 29 unmodified lines | |||
| 530 | Math_modf(vm_registers_t &r, vm_t &vm) | 653 | Math_modf(vm_registers_t &r, vm_t &vm) |
| 531 | { | 654 | { |
| 532 | auto &fp = r.stack.peek_frame()->base<F_Math_modf>(); | 655 | auto &fp = r.stack.peek_frame()->base<F_Math_modf>(); |
| 533 | throw vm_system_exception{ "Function not implemented" }; | 656 | |
| 657 | real_t integral_out; | ||
| 658 | const auto fractional_part = std::modf(fp.x, &integral_out); | ||
| 659 | const auto integral_part = static_cast<word_t>(integral_out); | ||
| 660 | |||
| 661 | fp.ret->t0 = integral_part; | ||
| 662 | fp.ret->t1 = fractional_part; | ||
| 534 | } | 663 | } |
| 535 | 664 | ||
| 536 | void | 665 | void |
| @@ -600,7 +729,7 @@ void · 63 unmodified lines | |||
| 600 | Math_pow10(vm_registers_t &r, vm_t &vm) | 729 | Math_pow10(vm_registers_t &r, vm_t &vm) |
| 601 | { | 730 | { |
| 602 | auto &fp = r.stack.peek_frame()->base<F_Math_pow10>(); | 731 | auto &fp = r.stack.peek_frame()->base<F_Math_pow10>(); |
| 603 | throw vm_system_exception{ "Function not implemented" }; | 732 | *fp.ret = std::pow(10., static_cast<real_t>(fp.p)); |
| 604 | } | 733 | } |
| 605 | 734 | ||
| 606 | void | 735 | void |
| @@ -646,7 +775,7 @@ void · 39 unmodified lines | |||
| 646 | Math_scalbn(vm_registers_t &r, vm_t &vm) | 775 | Math_scalbn(vm_registers_t &r, vm_t &vm) |
| 647 | { | 776 | { |
| 648 | auto &fp = r.stack.peek_frame()->base<F_Math_scalbn>(); | 777 | auto &fp = r.stack.peek_frame()->base<F_Math_scalbn>(); |
| 649 | throw vm_system_exception{ "Function not implemented" }; | 778 | *fp.ret = std::scalbln(fp.x, fp.n); |
| 650 | } | 779 | } |
| 651 | 780 | ||
| 652 | void | 781 | void |
| @@ -723,6 +852,8 @@ void · 70 unmodified lines | |||
| 723 | Math_y0(vm_registers_t &r, vm_t &vm) | 852 | Math_y0(vm_registers_t &r, vm_t &vm) |
| 724 | { | 853 | { |
| 725 | auto &fp = r.stack.peek_frame()->base<F_Math_y0>(); | 854 | auto &fp = r.stack.peek_frame()->base<F_Math_y0>(); |
| 855 | |||
| 856 | // [PAL] Consume platform API | ||
| 726 | throw vm_system_exception{ "Function not implemented" }; | 857 | throw vm_system_exception{ "Function not implemented" }; |
| 727 | } | 858 | } |
| 728 | 859 | ||
| @@ -730,6 +861,8 @@ void · 1 unmodified line | |||
| 730 | Math_y1(vm_registers_t &r, vm_t &vm) | 861 | Math_y1(vm_registers_t &r, vm_t &vm) |
| 731 | { | 862 | { |
| 732 | auto &fp = r.stack.peek_frame()->base<F_Math_y1>(); | 863 | auto &fp = r.stack.peek_frame()->base<F_Math_y1>(); |
| 864 | |||
| 865 | // [PAL] Consume platform API | ||
| 733 | throw vm_system_exception{ "Function not implemented" }; | 866 | throw vm_system_exception{ "Function not implemented" }; |
| 734 | } | 867 | } |
| 735 | 868 | ||
| @@ -737,5 +870,7 @@ void · 1 unmodified line | |||
| 737 | Math_yn(vm_registers_t &r, vm_t &vm) | 870 | Math_yn(vm_registers_t &r, vm_t &vm) |
| 738 | { | 871 | { |
| 739 | auto &fp = r.stack.peek_frame()->base<F_Math_yn>(); | 872 | auto &fp = r.stack.peek_frame()->base<F_Math_yn>(); |
| 873 | |||
| 874 | // [PAL] Consume platform API | ||
| 740 | throw vm_system_exception{ "Function not implemented" }; | 875 | throw vm_system_exception{ "Function not implemented" }; |
| 741 | } | 876 | } |