|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "mozilla/FloatingPoint.h" |
|
7 |
|
8 #include "txExpr.h" |
|
9 #include <math.h> |
|
10 #include "txIXPathContext.h" |
|
11 |
|
12 nsresult |
|
13 txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) |
|
14 { |
|
15 *aResult = nullptr; |
|
16 |
|
17 nsRefPtr<txAExprResult> exprRes; |
|
18 nsresult rv = mRightExpr->evaluate(aContext, getter_AddRefs(exprRes)); |
|
19 NS_ENSURE_SUCCESS(rv, rv); |
|
20 |
|
21 double rightDbl = exprRes->numberValue(); |
|
22 |
|
23 rv = mLeftExpr->evaluate(aContext, getter_AddRefs(exprRes)); |
|
24 NS_ENSURE_SUCCESS(rv, rv); |
|
25 |
|
26 double leftDbl = exprRes->numberValue(); |
|
27 double result = 0; |
|
28 |
|
29 switch (mOp) { |
|
30 case ADD: |
|
31 result = leftDbl + rightDbl; |
|
32 break; |
|
33 |
|
34 case SUBTRACT: |
|
35 result = leftDbl - rightDbl; |
|
36 break; |
|
37 |
|
38 case DIVIDE: |
|
39 if (rightDbl == 0) { |
|
40 #if defined(XP_WIN) |
|
41 /* XXX MSVC miscompiles such that (NaN == 0) */ |
|
42 if (mozilla::IsNaN(rightDbl)) |
|
43 result = mozilla::UnspecifiedNaN<double>(); |
|
44 else |
|
45 #endif |
|
46 if (leftDbl == 0 || mozilla::IsNaN(leftDbl)) |
|
47 result = mozilla::UnspecifiedNaN<double>(); |
|
48 else if (mozilla::IsNegative(leftDbl) != mozilla::IsNegative(rightDbl)) |
|
49 result = mozilla::NegativeInfinity<double>(); |
|
50 else |
|
51 result = mozilla::PositiveInfinity<double>(); |
|
52 } |
|
53 else |
|
54 result = leftDbl / rightDbl; |
|
55 break; |
|
56 |
|
57 case MODULUS: |
|
58 if (rightDbl == 0) { |
|
59 result = mozilla::UnspecifiedNaN<double>(); |
|
60 } |
|
61 else { |
|
62 #if defined(XP_WIN) |
|
63 /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */ |
|
64 if (!mozilla::IsInfinite(leftDbl) && mozilla::IsInfinite(rightDbl)) |
|
65 result = leftDbl; |
|
66 else |
|
67 #endif |
|
68 result = fmod(leftDbl, rightDbl); |
|
69 } |
|
70 break; |
|
71 |
|
72 case MULTIPLY: |
|
73 result = leftDbl * rightDbl; |
|
74 break; |
|
75 } |
|
76 |
|
77 return aContext->recycler()->getNumberResult(result, aResult); |
|
78 } //-- evaluate |
|
79 |
|
80 TX_IMPL_EXPR_STUBS_2(txNumberExpr, NUMBER_RESULT, mLeftExpr, mRightExpr) |
|
81 |
|
82 bool |
|
83 txNumberExpr::isSensitiveTo(ContextSensitivity aContext) |
|
84 { |
|
85 return mLeftExpr->isSensitiveTo(aContext) || |
|
86 mRightExpr->isSensitiveTo(aContext); |
|
87 } |
|
88 |
|
89 #ifdef TX_TO_STRING |
|
90 void |
|
91 txNumberExpr::toString(nsAString& str) |
|
92 { |
|
93 mLeftExpr->toString(str); |
|
94 |
|
95 switch (mOp) { |
|
96 case ADD: |
|
97 str.AppendLiteral(" + "); |
|
98 break; |
|
99 case SUBTRACT: |
|
100 str.AppendLiteral(" - "); |
|
101 break; |
|
102 case DIVIDE: |
|
103 str.AppendLiteral(" div "); |
|
104 break; |
|
105 case MODULUS: |
|
106 str.AppendLiteral(" mod "); |
|
107 break; |
|
108 case MULTIPLY: |
|
109 str.AppendLiteral(" * "); |
|
110 break; |
|
111 } |
|
112 |
|
113 mRightExpr->toString(str); |
|
114 |
|
115 } |
|
116 #endif |