Author: yegor
Date: Sun Jun 2 16:08:17 2013
New Revision: 1488734
URL: http://svn.apache.org/r1488734
Log:
Bugzilla 55043 and 55042: initial support for Complex and Quotient functions
Added:
poi/trunk/src/java/org/apache/poi/ss/formula/functions/Complex.java
poi/trunk/src/java/org/apache/poi/ss/formula/functions/Quotient.java
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java
Added: poi/trunk/src/java/org/apache/poi/ss/formula/functions/Complex.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/functions/Complex.java?rev=1488734&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/functions/Complex.java (added)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/functions/Complex.java Sun Jun
2 16:08:17 2013
@@ -0,0 +1,119 @@
+package org.apache.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.*;
+
+/**
+ * Implementation for Excel COMPLEX () function.<p/>
+ * <p/>
+ * <b>Syntax</b>:<br/> <b>COMPLEX
</b>(<b>real_num</b>,<b>i_num</b>,<b>suffix </b> )<br/>
+ * <p/>
+ * Converts real and imaginary coefficients into a complex number of the form
x + yi or x + yj.
+ * <p/>
+ * <p/>
+ * All complex number functions accept "i" and "j" for suffix, but neither "I"
nor "J".
+ * Using uppercase results in the #VALUE! error value. All functions that
accept two
+ * or more complex numbers require that all suffixes match.
+ * <p/>
+ * <b>real_num</b> The real coefficient of the complex number.
+ * If this argument is nonnumeric, this function returns the #VALUE! error
value.
+ * <p/>
+ * <p/>
+ * <b>i_num</b> The imaginary coefficient of the complex number.
+ * If this argument is nonnumeric, this function returns the #VALUE! error
value.
+ * <p/>
+ * <p/>
+ * <b>suffix</b> The suffix for the imaginary component of the complex number.
+ * <ul>
+ * <li>If omitted, suffix is assumed to be "i".</li>
+ * <li>If suffix is neither "i" nor "j", COMPLEX returns the #VALUE! error
value.</li>
+ * </ul>
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class Complex extends Var2or3ArgFunction {
+
+ public static final String DEFAULT_SUFFIX = "i";
+ public static final String SUPPORTED_SUFFIX = "j";
+
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval
real_num, ValueEval i_num) {
+ return this.evaluate(srcRowIndex, srcColumnIndex, real_num, i_num, new
StringEval(DEFAULT_SUFFIX));
+ }
+
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval
real_num, ValueEval i_num, ValueEval suffix) {
+ ValueEval veText1;
+ try {
+ veText1 = OperandResolver.getSingleValue(real_num, srcRowIndex,
srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ double realNum = 0;
+ try {
+ realNum = OperandResolver.coerceValueToDouble(veText1);
+ } catch (EvaluationException e) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ ValueEval veINum;
+ try {
+ veINum = OperandResolver.getSingleValue(i_num, srcRowIndex,
srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ double realINum = 0;
+ try {
+ realINum = OperandResolver.coerceValueToDouble(veINum);
+ } catch (EvaluationException e) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ String suffixValue = OperandResolver.coerceValueToString(suffix);
+ if (suffixValue.isEmpty()) {
+ suffixValue = DEFAULT_SUFFIX;
+ }
+ if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase()) ||
suffixValue.equals(SUPPORTED_SUFFIX.toUpperCase())) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ if (!(suffixValue.equals(DEFAULT_SUFFIX) ||
suffixValue.equals(SUPPORTED_SUFFIX))) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ StringBuffer strb = new StringBuffer("");
+ if (realNum != 0) {
+ if (isDoubleAnInt(realNum)) {
+ strb.append(new Double(realNum).intValue());
+ } else {
+ strb.append(realNum);
+ }
+ }
+ if (realINum != 0) {
+ if (strb.length() != 0) {
+ if (realINum > 0) {
+ strb.append("+");
+ }
+ }
+
+ if (realINum != 1 && realINum != -1) {
+ if (isDoubleAnInt(realINum)) {
+ strb.append(new Double(realINum).intValue());
+ } else {
+ strb.append(realINum);
+ }
+ }
+
+ strb.append(suffixValue);
+ }
+
+ return new StringEval(strb.toString());
+ }
+
+ /**
+ * @param number
+ * @return
+ */
+ private boolean isDoubleAnInt(double number) {
+ return (number == Math.floor(number)) && !Double.isInfinite(number);
+ }
+
+}
Added: poi/trunk/src/java/org/apache/poi/ss/formula/functions/Quotient.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/functions/Quotient.java?rev=1488734&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/functions/Quotient.java (added)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/functions/Quotient.java Sun
Jun 2 16:08:17 2013
@@ -0,0 +1,49 @@
+package org.apache.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+
+import org.apache.poi.ss.formula.eval.*;
+
+/**
+ * <p>Implementation for Excel QUOTIENT () function.<p/>
+ * <p>
+ * <b>Syntax</b>:<br/>
<b>QUOTIENT</b>(<b>Numerator</b>,<b>Denominator</b>)<br/>
+ * <p/>
+ * <p>
+ * Numerator is the dividend.
+ * Denominator is the divisor.
+ *
+ * Returns the integer portion of a division. Use this function when you want
to discard the remainder of a division.
+ * <p/>
+ *
+ * If either enumerator/denominator is non numeric, QUOTIENT returns the
#VALUE! error value.
+ * If denominator is equals to zero, QUOTIENT returns the #DIV/0! error value.
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class Quotient extends Fixed2ArgFunction {
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval
venumerator, ValueEval vedenominator) {
+
+ double enumerator = 0;
+ try {
+ enumerator = OperandResolver.coerceValueToDouble(venumerator);
+ } catch (EvaluationException e) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ double denominator = 0;
+ try {
+ denominator = OperandResolver.coerceValueToDouble(vedenominator);
+ } catch (EvaluationException e) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ if (denominator == 0) {
+ return ErrorEval.DIV_ZERO;
+ }
+
+ return new StringEval(String.valueOf((int)(enumerator / denominator)));
+ }
+}
Added:
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java?rev=1488734&view=auto
==============================================================================
---
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java
(added)
+++
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java
Sun Jun 2 16:08:17 2013
@@ -0,0 +1,69 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Tests for {@link Complex}
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class TestComplex extends TestCase
+{
+ private static ValueEval invokeValue(String real_num, String i_num, String
suffix) {
+ ValueEval[] args = new ValueEval[]{new StringEval(real_num), new
StringEval(i_num), new StringEval(suffix)};
+ return new Complex().evaluate(args, -1, -1);
+ }
+
+ private static void confirmValue(String msg, String real_num, String
i_num, String suffix, String expected) {
+ ValueEval result = invokeValue(real_num, i_num, suffix);
+ assertEquals(StringEval.class, result.getClass());
+ assertEquals(msg, expected, ((StringEval) result).getStringValue());
+ }
+
+ private static void confirmValueError(String msg, String real_num, String
i_num, String suffix, ErrorEval numError) {
+ ValueEval result = invokeValue(real_num, i_num, suffix);
+ assertEquals(ErrorEval.class, result.getClass());
+ assertEquals(msg, numError, result);
+ }
+
+ public void testBasic() {
+ confirmValue("Complex number with 3 and 4 as the real and imaginary
coefficients (3 + 4i)", "3","4", "", "3+4i");
+ confirmValue("Complex number with 3 and 4 as the real and imaginary
coefficients, and j as the suffix (3 + 4j)", "3","4", "j", "3+4j");
+
+ confirmValue("Complex number with 0 and 1 as the real and imaginary
coefficients (i)", "0","1", "", "i");
+ confirmValue("Complex number with 1 and 0 as the real and imaginary
coefficients (1)", "1","0", "", "1");
+
+ confirmValue("Complex number with 2 and 3 as the real and imaginary
coefficients (2 + 3i)", "2","3", "", "2+3i");
+ confirmValue("Complex number with -2 and -3 as the real and imaginary
coefficients (-2-3i)", "-2","-3", "", "-2-3i");
+
+ confirmValue("Complex number with -2 and -3 as the real and imaginary
coefficients (-0.5-3.2i)", "-0.5","-3.2", "", "-0.5-3.2i");
+ }
+
+ public void testErrors() {
+ confirmValueError("argument is nonnumeric", "ABCD", "","",
ErrorEval.VALUE_INVALID);
+ confirmValueError("argument is nonnumeric", "1", "ABCD","",
ErrorEval.VALUE_INVALID);
+ confirmValueError("f suffix is neither \"i\" nor \"j\"", "1", "1","k",
ErrorEval.VALUE_INVALID);
+
+ confirmValueError("never use \"I\" ", "1", "1","I",
ErrorEval.VALUE_INVALID);
+ confirmValueError("never use \"J\" ", "1", "1","J",
ErrorEval.VALUE_INVALID);
+ }
+}
\ No newline at end of file
Added:
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java?rev=1488734&view=auto
==============================================================================
---
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java
(added)
+++
poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java
Sun Jun 2 16:08:17 2013
@@ -0,0 +1,63 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Tests for {@link Quotient}
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class TestQuotient extends TestCase {
+ private static ValueEval invokeValue(String numerator, String denominator)
{
+ ValueEval[] args = new ValueEval[]{new StringEval(numerator), new
StringEval(denominator)};
+ return new Quotient().evaluate(args, -1, -1);
+ }
+
+ private static void confirmValue(String msg, String numerator, String
denominator, String expected) {
+ ValueEval result = invokeValue(numerator, denominator);
+ assertEquals(StringEval.class, result.getClass());
+ assertEquals(msg, expected, ((StringEval) result).getStringValue());
+ }
+
+ private static void confirmValueError(String msg, String numerator, String
denominator, ErrorEval numError) {
+ ValueEval result = invokeValue(numerator, denominator);
+ assertEquals(ErrorEval.class, result.getClass());
+ assertEquals(msg, numError, result);
+ }
+
+ public void testBasic() {
+ confirmValue("Integer portion of 5/2 (2)", "5", "2", "2");
+ confirmValue("Integer portion of 4.5/3.1 (1)", "4.5", "3.1", "1");
+
+ confirmValue("Integer portion of -10/3 (-3)", "-10", "3", "-3");
+ confirmValue("Integer portion of -5.5/2 (-2)", "-5.5", "2", "-2");
+
+ confirmValue("Integer portion of Pi/Avogadro (0)", "3.14159",
"6.02214179E+23", "0");
+ }
+
+ public void testErrors() {
+ confirmValueError("numerator is nonnumeric", "ABCD", "",
ErrorEval.VALUE_INVALID);
+ confirmValueError("denominator is nonnumeric", "", "ABCD",
ErrorEval.VALUE_INVALID);
+
+ confirmValueError("denominator is nonnumeric", "3.14159", "0",
ErrorEval.DIV_ZERO);
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]