Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: src/runtime.cc

Issue 163563003: Harmony: implement Math.cbrt, Math.expm1 and Math.log1p. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 7629 matching lines...) Expand 10 before | Expand all | Expand 10 after
7640 } 7640 }
7641 { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y); 7641 { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7642 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7642 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7643 } 7643 }
7644 7644
7645 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) 7645 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7646 : StringCharacterStreamCompare(isolate->runtime_state(), x, y); 7646 : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7647 } 7647 }
7648 7648
7649 7649
7650 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) { 7650 #define RUNTIME_UNARY_MATH(NAME) \
7651 SealHandleScope shs(isolate); 7651 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_##NAME) { \
7652 ASSERT(args.length() == 1); 7652 SealHandleScope shs(isolate); \
7653 isolate->counters()->math_acos()->Increment(); 7653 ASSERT(args.length() == 1); \
7654 isolate->counters()->math_##NAME()->Increment(); \
7655 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \
7656 return isolate->heap()->AllocateHeapNumber(std::NAME(x)); \
7657 }
7654 7658
7655 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7659 RUNTIME_UNARY_MATH(acos)
7656 return isolate->heap()->AllocateHeapNumber(std::acos(x)); 7660 RUNTIME_UNARY_MATH(asin)
7661 RUNTIME_UNARY_MATH(atan)
7662 RUNTIME_UNARY_MATH(log)
7663 #undef RUNTIME_UNARY_MATH
7664
7665
7666 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm
7667 // Using initial approximation adapted from Kahan's cbrt and 4 iterations
7668 // of Newton's method.
7669 inline double CubeRootNewtonIteration(double approx, double x) {
7670 return (1.0 / 3.0) * (x / (approx * approx) + 2 * approx);
7657 } 7671 }
7658 7672
7659 7673
7660 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) { 7674 inline double CubeRoot(double x) {
7661 SealHandleScope shs(isolate); 7675 double approx = 0.0;
7662 ASSERT(args.length() == 1); 7676 unsigned int* p_approx = (unsigned int*) ≈
7663 isolate->counters()->math_asin()->Increment(); 7677 unsigned int* p_x = (unsigned int*) &x;
7678 p_approx[1] = p_x[1] / 3 + 715094163; // magic number.
Jarin 2014/02/18 14:08:53 Nit: could you make this more friendly to big endi
7664 7679
7665 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7680 approx = CubeRootNewtonIteration(approx, x);
7666 return isolate->heap()->AllocateHeapNumber(std::asin(x)); 7681 approx = CubeRootNewtonIteration(approx, x);
7682 approx = CubeRootNewtonIteration(approx, x);
7683 return CubeRootNewtonIteration(approx, x);
7667 } 7684 }
7668 7685
7669 7686
7670 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) { 7687 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cbrt) {
7671 SealHandleScope shs(isolate); 7688 SealHandleScope shs(isolate);
7672 ASSERT(args.length() == 1); 7689 ASSERT(args.length() == 1);
7673 isolate->counters()->math_atan()->Increment();
7674
7675 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7690 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7676 return isolate->heap()->AllocateHeapNumber(std::atan(x)); 7691 if (x == 0 || std::isinf(x)) return args[0];
7692 double result = (x > 0) ? CubeRoot(x) : -CubeRoot(-x);
7693 return isolate->heap()->AllocateHeapNumber(result);
7677 } 7694 }
7678 7695
7679 7696
7697 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log1p) {
7698 SealHandleScope shs(isolate);
7699 ASSERT(args.length() == 1);
7700 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7701
7702 double x_abs = std::fabs(x);
7703 // Use Taylor series to approximate. With y = x + 1;
7704 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
7705 // == 0 + x - x^2/2 + x^3/3 ...
7706 // The closer x is to 0, the fewer terms are required.
7707 static const double threshold_2 = 1.0 / 0x00800000;
7708 static const double threshold_3 = 1.0 / 0x00008000;
7709 static const double threshold_7 = 1.0 / 0x00000080;
7710
7711 double result;
7712 if (x_abs < threshold_2) {
7713 result = x * (1.0/1.0 - x * 1.0/2.0);
7714 } else if (x_abs < threshold_3) {
7715 result = x * (1.0/1.0 - x * (1.0/2.0 - x * (1.0/3.0)));
7716 } else if (x_abs < threshold_7) {
7717 result = x * (1.0/1.0 - x * (1.0/2.0 - x * (
7718 1.0/3.0 - x * (1.0/4.0 - x * (
7719 1.0/5.0 - x * (1.0/6.0 - x * (
7720 1.0/7.0)))))));
7721 } else { // Use regular log if not close enough to 0.
7722 result = std::log(1.0 + x);
7723 }
7724 return isolate->heap()->AllocateHeapNumber(result);
7725 }
7726
7727
7728 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_expm1) {
7729 SealHandleScope shs(isolate);
7730 ASSERT(args.length() == 1);
7731 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7732
7733 double x_abs = std::fabs(x);
7734 // Use Taylor series to approximate.
7735 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ...
7736 // == x/1! + x^2/2! + x^3/3! + ...
7737 // The closer x is to 0, the fewer terms are required.
7738 static const double threshold_2 = 1.0 / 0x00400000;
7739 static const double threshold_3 = 1.0 / 0x00004000;
7740 static const double threshold_6 = 1.0 / 0x00000040;
7741
7742 double result;
7743 if (x_abs < threshold_2) {
7744 result = x * (1.0/1.0 + x * (1.0/2.0));
7745 } else if (x_abs < threshold_3) {
7746 result = x * (1.0/1.0 + x * (1.0/2.0 + x * (1.0/6.0)));
7747 } else if (x_abs < threshold_6) {
7748 result = x * (1.0/1.0 + x * (1.0/2.0 + x * (
7749 1.0/6.0 + x * (1.0/24.0 + x * (
7750 1.0/120.0 + x * (1.0/720.0))))));
7751 } else { // Use regular exp if not close enough to 0.
7752 result = std::exp(x) - 1.0;
7753 }
7754 return isolate->heap()->AllocateHeapNumber(result);
7755 }
7756
7757
7680 static const double kPiDividedBy4 = 0.78539816339744830962; 7758 static const double kPiDividedBy4 = 0.78539816339744830962;
7681 7759
7682 7760
7683 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) { 7761 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7684 SealHandleScope shs(isolate); 7762 SealHandleScope shs(isolate);
7685 ASSERT(args.length() == 2); 7763 ASSERT(args.length() == 2);
7686 isolate->counters()->math_atan2()->Increment(); 7764 isolate->counters()->math_atan2()->Increment();
7687 7765
7688 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7766 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7689 CONVERT_DOUBLE_ARG_CHECKED(y, 1); 7767 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
(...skipping 27 matching lines...) Expand all
7717 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) { 7795 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7718 SealHandleScope shs(isolate); 7796 SealHandleScope shs(isolate);
7719 ASSERT(args.length() == 1); 7797 ASSERT(args.length() == 1);
7720 isolate->counters()->math_floor()->Increment(); 7798 isolate->counters()->math_floor()->Increment();
7721 7799
7722 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7800 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7723 return isolate->heap()->NumberFromDouble(std::floor(x)); 7801 return isolate->heap()->NumberFromDouble(std::floor(x));
7724 } 7802 }
7725 7803
7726 7804
7727 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7728 SealHandleScope shs(isolate);
7729 ASSERT(args.length() == 1);
7730 isolate->counters()->math_log()->Increment();
7731
7732 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7733 return isolate->heap()->AllocateHeapNumber(std::log(x));
7734 }
7735
7736
7737 // Slow version of Math.pow. We check for fast paths for special cases. 7805 // Slow version of Math.pow. We check for fast paths for special cases.
7738 // Used if SSE2/VFP3 is not available. 7806 // Used if SSE2/VFP3 is not available.
7739 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) { 7807 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7740 SealHandleScope shs(isolate); 7808 SealHandleScope shs(isolate);
7741 ASSERT(args.length() == 2); 7809 ASSERT(args.length() == 2);
7742 isolate->counters()->math_pow()->Increment(); 7810 isolate->counters()->math_pow()->Increment();
7743 7811
7744 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7812 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7745 7813
7746 // If the second argument is a smi, it is much faster to call the 7814 // If the second argument is a smi, it is much faster to call the
(...skipping 7132 matching lines...) Expand 10 before | Expand all | Expand 10 after
14879 // Handle last resort GC and make sure to allow future allocations 14947 // Handle last resort GC and make sure to allow future allocations
14880 // to grow the heap without causing GCs (if possible). 14948 // to grow the heap without causing GCs (if possible).
14881 isolate->counters()->gc_last_resort_from_js()->Increment(); 14949 isolate->counters()->gc_last_resort_from_js()->Increment();
14882 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 14950 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14883 "Runtime::PerformGC"); 14951 "Runtime::PerformGC");
14884 } 14952 }
14885 } 14953 }
14886 14954
14887 14955
14888 } } // namespace v8::internal 14956 } } // namespace v8::internal
OLDNEW
« src/harmony-math.js ('K') | « src/runtime.h ('k') | test/mjsunit/harmony/math-cbrt.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698