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

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: uploaded new 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
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/harmony/math-cbrt.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 static const uint64_t magic = V8_2PART_UINT64_C(0x2A9F7893, 00000000);
7662 ASSERT(args.length() == 1); 7676 uint64_t xhigh = double_to_uint64(x);
7663 isolate->counters()->math_asin()->Increment(); 7677 double approx = uint64_to_double(xhigh / 3 + magic);
7664 7678
7665 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7679 approx = CubeRootNewtonIteration(approx, x);
7666 return isolate->heap()->AllocateHeapNumber(std::asin(x)); 7680 approx = CubeRootNewtonIteration(approx, x);
7681 approx = CubeRootNewtonIteration(approx, x);
7682 return CubeRootNewtonIteration(approx, x);
7667 } 7683 }
7668 7684
7669 7685
7670 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) { 7686 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cbrt) {
7671 SealHandleScope shs(isolate); 7687 SealHandleScope shs(isolate);
7672 ASSERT(args.length() == 1); 7688 ASSERT(args.length() == 1);
7673 isolate->counters()->math_atan()->Increment();
7674
7675 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7689 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7676 return isolate->heap()->AllocateHeapNumber(std::atan(x)); 7690 if (x == 0 || std::isinf(x)) return args[0];
7691 double result = (x > 0) ? CubeRoot(x) : -CubeRoot(-x);
7692 return isolate->heap()->AllocateHeapNumber(result);
7677 } 7693 }
7678 7694
7679 7695
7696 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log1p) {
7697 SealHandleScope shs(isolate);
7698 ASSERT(args.length() == 1);
7699 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7700
7701 double x_abs = std::fabs(x);
7702 // Use Taylor series to approximate. With y = x + 1;
7703 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
7704 // == 0 + x - x^2/2 + x^3/3 ...
7705 // The closer x is to 0, the fewer terms are required.
7706 static const double threshold_2 = 1.0 / 0x00800000;
7707 static const double threshold_3 = 1.0 / 0x00008000;
7708 static const double threshold_7 = 1.0 / 0x00000080;
7709
7710 double result;
7711 if (x_abs < threshold_2) {
7712 result = x * (1.0/1.0 - x * 1.0/2.0);
7713 } else if (x_abs < threshold_3) {
7714 result = x * (1.0/1.0 - x * (1.0/2.0 - x * (1.0/3.0)));
7715 } else if (x_abs < threshold_7) {
7716 result = x * (1.0/1.0 - x * (1.0/2.0 - x * (
7717 1.0/3.0 - x * (1.0/4.0 - x * (
7718 1.0/5.0 - x * (1.0/6.0 - x * (
7719 1.0/7.0)))))));
7720 } else { // Use regular log if not close enough to 0.
7721 result = std::log(1.0 + x);
7722 }
7723 return isolate->heap()->AllocateHeapNumber(result);
7724 }
7725
7726
7727 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_expm1) {
7728 SealHandleScope shs(isolate);
7729 ASSERT(args.length() == 1);
7730 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7731
7732 double x_abs = std::fabs(x);
7733 // Use Taylor series to approximate.
7734 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ...
7735 // == x/1! + x^2/2! + x^3/3! + ...
7736 // The closer x is to 0, the fewer terms are required.
7737 static const double threshold_2 = 1.0 / 0x00400000;
7738 static const double threshold_3 = 1.0 / 0x00004000;
7739 static const double threshold_6 = 1.0 / 0x00000040;
7740
7741 double result;
7742 if (x_abs < threshold_2) {
7743 result = x * (1.0/1.0 + x * (1.0/2.0));
7744 } else if (x_abs < threshold_3) {
7745 result = x * (1.0/1.0 + x * (1.0/2.0 + x * (1.0/6.0)));
7746 } else if (x_abs < threshold_6) {
7747 result = x * (1.0/1.0 + x * (1.0/2.0 + x * (
7748 1.0/6.0 + x * (1.0/24.0 + x * (
7749 1.0/120.0 + x * (1.0/720.0))))));
7750 } else { // Use regular exp if not close enough to 0.
7751 result = std::exp(x) - 1.0;
7752 }
7753 return isolate->heap()->AllocateHeapNumber(result);
7754 }
7755
7756
7680 static const double kPiDividedBy4 = 0.78539816339744830962; 7757 static const double kPiDividedBy4 = 0.78539816339744830962;
7681 7758
7682 7759
7683 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) { 7760 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7684 SealHandleScope shs(isolate); 7761 SealHandleScope shs(isolate);
7685 ASSERT(args.length() == 2); 7762 ASSERT(args.length() == 2);
7686 isolate->counters()->math_atan2()->Increment(); 7763 isolate->counters()->math_atan2()->Increment();
7687 7764
7688 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7765 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7689 CONVERT_DOUBLE_ARG_CHECKED(y, 1); 7766 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
(...skipping 27 matching lines...) Expand all
7717 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) { 7794 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7718 SealHandleScope shs(isolate); 7795 SealHandleScope shs(isolate);
7719 ASSERT(args.length() == 1); 7796 ASSERT(args.length() == 1);
7720 isolate->counters()->math_floor()->Increment(); 7797 isolate->counters()->math_floor()->Increment();
7721 7798
7722 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7799 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7723 return isolate->heap()->NumberFromDouble(std::floor(x)); 7800 return isolate->heap()->NumberFromDouble(std::floor(x));
7724 } 7801 }
7725 7802
7726 7803
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. 7804 // Slow version of Math.pow. We check for fast paths for special cases.
7738 // Used if SSE2/VFP3 is not available. 7805 // Used if SSE2/VFP3 is not available.
7739 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) { 7806 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7740 SealHandleScope shs(isolate); 7807 SealHandleScope shs(isolate);
7741 ASSERT(args.length() == 2); 7808 ASSERT(args.length() == 2);
7742 isolate->counters()->math_pow()->Increment(); 7809 isolate->counters()->math_pow()->Increment();
7743 7810
7744 CONVERT_DOUBLE_ARG_CHECKED(x, 0); 7811 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7745 7812
7746 // If the second argument is a smi, it is much faster to call the 7813 // If the second argument is a smi, it is much faster to call the
(...skipping 7145 matching lines...) Expand 10 before | Expand all | Expand 10 after
14892 // Handle last resort GC and make sure to allow future allocations 14959 // Handle last resort GC and make sure to allow future allocations
14893 // to grow the heap without causing GCs (if possible). 14960 // to grow the heap without causing GCs (if possible).
14894 isolate->counters()->gc_last_resort_from_js()->Increment(); 14961 isolate->counters()->gc_last_resort_from_js()->Increment();
14895 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 14962 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14896 "Runtime::PerformGC"); 14963 "Runtime::PerformGC");
14897 } 14964 }
14898 } 14965 }
14899 14966
14900 14967
14901 } } // namespace v8::internal 14968 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « 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