Unified · Split
| @@ -290,7 +290,28 @@ void · 289 unmodified lines | ||
| 290 | 290 | Math_export_int(vm_registers_t &r, vm_t &vm) |
| 291 | 291 | { |
| 292 | 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 | 317 | void |
| @@ -305,7 +326,7 @@ Math_export_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines | ||
| 305 | 326 | assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); |
| 306 | 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 | 330 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; |
| 310 | 331 | |
| 311 | 332 | // Insert as big endian |
| @@ -332,7 +353,32 @@ void · 20 unmodified lines | ||
| 332 | 353 | Math_export_real32(vm_registers_t &r, vm_t &vm) |
| 333 | 354 | { |
| 334 | 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 | 384 | void |
| @@ -416,7 +462,34 @@ void · 77 unmodified lines | ||
| 416 | 462 | Math_iamax(vm_registers_t &r, vm_t &vm) |
| 417 | 463 | { |
| 418 | 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 | 495 | void |
| @@ -430,7 +503,27 @@ void · 7 unmodified lines | ||
| 430 | 503 | Math_import_int(vm_registers_t &r, vm_t &vm) |
| 431 | 504 | { |
| 432 | 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 | 529 | void |
| @@ -445,14 +538,14 @@ Math_import_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines | ||
| 445 | 538 | assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get())); |
| 446 | 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 | 542 | throw vm_user_exception{ "Invalid buffer size based on conversion" }; |
| 450 | 543 | |
| 451 | 544 | // Process as big endian |
| 452 | 545 | for (int i = 0; i < result_len; ++i) |
| 453 | 546 | { |
| 454 | 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 | 549 | t = (t << 8) | buffer->at<byte_t>(j); |
| 457 | 550 | |
| 458 | 551 | real_t x; |
| @@ -467,7 +560,31 @@ void · 8 unmodified lines | ||
| 467 | 560 | Math_import_real32(vm_registers_t &r, vm_t &vm) |
| 468 | 561 | { |
| 469 | 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 | 590 | void |
| @@ -481,6 +598,8 @@ void · 7 unmodified lines | ||
| 481 | 598 | Math_j0(vm_registers_t &r, vm_t &vm) |
| 482 | 599 | { |
| 483 | 600 | auto &fp = r.stack.peek_frame()->base<F_Math_j0>(); |
| 601 | + | |
| 602 | + // [PAL] Consume platform API | |
| 484 | 603 | throw vm_system_exception{ "Function not implemented" }; |
| 485 | 604 | } |
| 486 | 605 | |
| @@ -488,6 +607,8 @@ void · 1 unmodified line | ||
| 488 | 607 | Math_j1(vm_registers_t &r, vm_t &vm) |
| 489 | 608 | { |
| 490 | 609 | auto &fp = r.stack.peek_frame()->base<F_Math_j1>(); |
| 610 | + | |
| 611 | + // [PAL] Consume platform API | |
| 491 | 612 | throw vm_system_exception{ "Function not implemented" }; |
| 492 | 613 | } |
| 493 | 614 | |
| @@ -495,6 +616,8 @@ void · 1 unmodified line | ||
| 495 | 616 | Math_jn(vm_registers_t &r, vm_t &vm) |
| 496 | 617 | { |
| 497 | 618 | auto &fp = r.stack.peek_frame()->base<F_Math_jn>(); |
| 619 | + | |
| 620 | + // [PAL] Consume platform API | |
| 498 | 621 | throw vm_system_exception{ "Function not implemented" }; |
| 499 | 622 | } |
| 500 | 623 | |
| @@ -530,7 +653,13 @@ void · 29 unmodified lines | ||
| 530 | 653 | Math_modf(vm_registers_t &r, vm_t &vm) |
| 531 | 654 | { |
| 532 | 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 | 665 | void |
| @@ -600,7 +729,7 @@ void · 63 unmodified lines | ||
| 600 | 729 | Math_pow10(vm_registers_t &r, vm_t &vm) |
| 601 | 730 | { |
| 602 | 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 | 735 | void |
| @@ -646,7 +775,7 @@ void · 39 unmodified lines | ||
| 646 | 775 | Math_scalbn(vm_registers_t &r, vm_t &vm) |
| 647 | 776 | { |
| 648 | 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 | 781 | void |
| @@ -723,6 +852,8 @@ void · 70 unmodified lines | ||
| 723 | 852 | Math_y0(vm_registers_t &r, vm_t &vm) |
| 724 | 853 | { |
| 725 | 854 | auto &fp = r.stack.peek_frame()->base<F_Math_y0>(); |
| 855 | + | |
| 856 | + // [PAL] Consume platform API | |
| 726 | 857 | throw vm_system_exception{ "Function not implemented" }; |
| 727 | 858 | } |
| 728 | 859 | |
| @@ -730,6 +861,8 @@ void · 1 unmodified line | ||
| 730 | 861 | Math_y1(vm_registers_t &r, vm_t &vm) |
| 731 | 862 | { |
| 732 | 863 | auto &fp = r.stack.peek_frame()->base<F_Math_y1>(); |
| 864 | + | |
| 865 | + // [PAL] Consume platform API | |
| 733 | 866 | throw vm_system_exception{ "Function not implemented" }; |
| 734 | 867 | } |
| 735 | 868 | |
| @@ -737,5 +870,7 @@ void · 1 unmodified line | ||
| 737 | 870 | Math_yn(vm_registers_t &r, vm_t &vm) |
| 738 | 871 | { |
| 739 | 872 | auto &fp = r.stack.peek_frame()->base<F_Math_yn>(); |
| 873 | + | |
| 874 | + // [PAL] Consume platform API | |
| 740 | 875 | throw vm_system_exception{ "Function not implemented" }; |
| 741 | 876 | } |