History

Implement all import/export functions Implement all forwardable to std functions

arr committed 9 years ago

Commit 83d4a881 parent 98ad0161 file · +146 −11Browse files

Unified · Split

src/vm/math/Mathmod.cpp+146−11
@@ -290,7 +290,28 @@ void · 289 unmodified lines
290290 Math_export_int(vm_registers_t &r, vm_t &vm)
291291 {
292292 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+ }
294315 }
295316
296317 void
@@ -305,7 +326,7 @@ Math_export_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines
305326 assert(values->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));
306327 const auto values_len = values->get_length();
307328
308− if (buffer->get_length() != (8 * values_len))
329+ if (buffer->get_length() != (sizeof(real_t) * values_len))
309330 throw vm_user_exception{ "Invalid buffer size based on conversion" };
310331
311332 // Insert as big endian
@@ -332,7 +353,32 @@ void · 20 unmodified lines
332353 Math_export_real32(vm_registers_t &r, vm_t &vm)
333354 {
334355 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+ }
336382 }
337383
338384 void
@@ -416,7 +462,34 @@ void · 77 unmodified lines
416462 Math_iamax(vm_registers_t &r, vm_t &vm)
417463 {
418464 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;
420493 }
421494
422495 void
@@ -430,7 +503,27 @@ void · 7 unmodified lines
430503 Math_import_int(vm_registers_t &r, vm_t &vm)
431504 {
432505 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+ }
434527 }
435528
436529 void
@@ -445,14 +538,14 @@ Math_import_real(vm_registers_t &r, vm_t &vm) · 8 unmodified lines
445538 assert(result->get_element_type()->is_equal(intrinsic_type_desc::type<real_t>().get()));
446539 const auto result_len = result->get_length();
447540
448− if (buffer->get_length() != (8 * result_len))
541+ if (buffer->get_length() != (sizeof(real_t) * result_len))
449542 throw vm_user_exception{ "Invalid buffer size based on conversion" };
450543
451544 // Process as big endian
452545 for (int i = 0; i < result_len; ++i)
453546 {
454547 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)
456549 t = (t << 8) | buffer->at<byte_t>(j);
457550
458551 real_t x;
@@ -467,7 +560,31 @@ void · 8 unmodified lines
467560 Math_import_real32(vm_registers_t &r, vm_t &vm)
468561 {
469562 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+ }
471588 }
472589
473590 void
@@ -481,6 +598,8 @@ void · 7 unmodified lines
481598 Math_j0(vm_registers_t &r, vm_t &vm)
482599 {
483600 auto &fp = r.stack.peek_frame()->base<F_Math_j0>();
601+
602+ // [PAL] Consume platform API
484603 throw vm_system_exception{ "Function not implemented" };
485604 }
486605
@@ -488,6 +607,8 @@ void · 1 unmodified line
488607 Math_j1(vm_registers_t &r, vm_t &vm)
489608 {
490609 auto &fp = r.stack.peek_frame()->base<F_Math_j1>();
610+
611+ // [PAL] Consume platform API
491612 throw vm_system_exception{ "Function not implemented" };
492613 }
493614
@@ -495,6 +616,8 @@ void · 1 unmodified line
495616 Math_jn(vm_registers_t &r, vm_t &vm)
496617 {
497618 auto &fp = r.stack.peek_frame()->base<F_Math_jn>();
619+
620+ // [PAL] Consume platform API
498621 throw vm_system_exception{ "Function not implemented" };
499622 }
500623
@@ -530,7 +653,13 @@ void · 29 unmodified lines
530653 Math_modf(vm_registers_t &r, vm_t &vm)
531654 {
532655 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;
534663 }
535664
536665 void
@@ -600,7 +729,7 @@ void · 63 unmodified lines
600729 Math_pow10(vm_registers_t &r, vm_t &vm)
601730 {
602731 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));
604733 }
605734
606735 void
@@ -646,7 +775,7 @@ void · 39 unmodified lines
646775 Math_scalbn(vm_registers_t &r, vm_t &vm)
647776 {
648777 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);
650779 }
651780
652781 void
@@ -723,6 +852,8 @@ void · 70 unmodified lines
723852 Math_y0(vm_registers_t &r, vm_t &vm)
724853 {
725854 auto &fp = r.stack.peek_frame()->base<F_Math_y0>();
855+
856+ // [PAL] Consume platform API
726857 throw vm_system_exception{ "Function not implemented" };
727858 }
728859
@@ -730,6 +861,8 @@ void · 1 unmodified line
730861 Math_y1(vm_registers_t &r, vm_t &vm)
731862 {
732863 auto &fp = r.stack.peek_frame()->base<F_Math_y1>();
864+
865+ // [PAL] Consume platform API
733866 throw vm_system_exception{ "Function not implemented" };
734867 }
735868
@@ -737,5 +870,7 @@ void · 1 unmodified line
737870 Math_yn(vm_registers_t &r, vm_t &vm)
738871 {
739872 auto &fp = r.stack.peek_frame()->base<F_Math_yn>();
873+
874+ // [PAL] Consume platform API
740875 throw vm_system_exception{ "Function not implemented" };
741876 }