michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/FloatingPoint.h" michael@0: michael@0: #include "txExpr.h" michael@0: #include michael@0: #include "txIXPathContext.h" michael@0: michael@0: nsresult michael@0: txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) michael@0: { michael@0: *aResult = nullptr; michael@0: michael@0: nsRefPtr exprRes; michael@0: nsresult rv = mRightExpr->evaluate(aContext, getter_AddRefs(exprRes)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: double rightDbl = exprRes->numberValue(); michael@0: michael@0: rv = mLeftExpr->evaluate(aContext, getter_AddRefs(exprRes)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: double leftDbl = exprRes->numberValue(); michael@0: double result = 0; michael@0: michael@0: switch (mOp) { michael@0: case ADD: michael@0: result = leftDbl + rightDbl; michael@0: break; michael@0: michael@0: case SUBTRACT: michael@0: result = leftDbl - rightDbl; michael@0: break; michael@0: michael@0: case DIVIDE: michael@0: if (rightDbl == 0) { michael@0: #if defined(XP_WIN) michael@0: /* XXX MSVC miscompiles such that (NaN == 0) */ michael@0: if (mozilla::IsNaN(rightDbl)) michael@0: result = mozilla::UnspecifiedNaN(); michael@0: else michael@0: #endif michael@0: if (leftDbl == 0 || mozilla::IsNaN(leftDbl)) michael@0: result = mozilla::UnspecifiedNaN(); michael@0: else if (mozilla::IsNegative(leftDbl) != mozilla::IsNegative(rightDbl)) michael@0: result = mozilla::NegativeInfinity(); michael@0: else michael@0: result = mozilla::PositiveInfinity(); michael@0: } michael@0: else michael@0: result = leftDbl / rightDbl; michael@0: break; michael@0: michael@0: case MODULUS: michael@0: if (rightDbl == 0) { michael@0: result = mozilla::UnspecifiedNaN(); michael@0: } michael@0: else { michael@0: #if defined(XP_WIN) michael@0: /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */ michael@0: if (!mozilla::IsInfinite(leftDbl) && mozilla::IsInfinite(rightDbl)) michael@0: result = leftDbl; michael@0: else michael@0: #endif michael@0: result = fmod(leftDbl, rightDbl); michael@0: } michael@0: break; michael@0: michael@0: case MULTIPLY: michael@0: result = leftDbl * rightDbl; michael@0: break; michael@0: } michael@0: michael@0: return aContext->recycler()->getNumberResult(result, aResult); michael@0: } //-- evaluate michael@0: michael@0: TX_IMPL_EXPR_STUBS_2(txNumberExpr, NUMBER_RESULT, mLeftExpr, mRightExpr) michael@0: michael@0: bool michael@0: txNumberExpr::isSensitiveTo(ContextSensitivity aContext) michael@0: { michael@0: return mLeftExpr->isSensitiveTo(aContext) || michael@0: mRightExpr->isSensitiveTo(aContext); michael@0: } michael@0: michael@0: #ifdef TX_TO_STRING michael@0: void michael@0: txNumberExpr::toString(nsAString& str) michael@0: { michael@0: mLeftExpr->toString(str); michael@0: michael@0: switch (mOp) { michael@0: case ADD: michael@0: str.AppendLiteral(" + "); michael@0: break; michael@0: case SUBTRACT: michael@0: str.AppendLiteral(" - "); michael@0: break; michael@0: case DIVIDE: michael@0: str.AppendLiteral(" div "); michael@0: break; michael@0: case MODULUS: michael@0: str.AppendLiteral(" mod "); michael@0: break; michael@0: case MULTIPLY: michael@0: str.AppendLiteral(" * "); michael@0: break; michael@0: } michael@0: michael@0: mRightExpr->toString(str); michael@0: michael@0: } michael@0: #endif