ソースを参照

#65 fn: IMLOG2, IMPOWER, IMPRODUCT, IMREAL, IMSEC, and IMSECH

xuri 4 年 前
コミット
99963f89c7
2 ファイル変更197 行追加0 行削除
  1. 140 0
      calc.go
  2. 57 0
      calc_test.go

+ 140 - 0
calc.go

@@ -302,6 +302,12 @@ var tokenPriority = map[string]int{
 //    IMEXP
 //    IMLN
 //    IMLOG10
+//    IMLOG2
+//    IMPOWER
+//    IMPRODUCT
+//    IMREAL
+//    IMSEC
+//    IMSECH
 //    IMSIN
 //    IMSINH
 //    IMSQRT
@@ -1857,6 +1863,140 @@ func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
 	return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
 }
 
+// IMLOG2 function calculates the base 2 logarithm of a supplied complex
+// number. The syntax of the function is:
+//
+//    IMLOG2(inumber)
+//
+func (fn *formulaFuncs) IMLOG2(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMLOG2 requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	num := cmplx.Log(inumber)
+	if cmplx.IsInf(num) {
+		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(num/cmplx.Log(2)), "i"))
+}
+
+// IMPOWER function returns a supplied complex number, raised to a given
+// power. The syntax of the function is:
+//
+//    IMPOWER(inumber,number)
+//
+func (fn *formulaFuncs) IMPOWER(argsList *list.List) formulaArg {
+	if argsList.Len() != 2 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMPOWER requires 2 arguments")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	number, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	if inumber == 0 && number == 0 {
+		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+	}
+	num := cmplx.Pow(inumber, number)
+	if cmplx.IsInf(num) {
+		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+}
+
+// IMPRODUCT function calculates the product of two or more complex numbers.
+// The syntax of the function is:
+//
+//    IMPRODUCT(number1,[number2],...)
+//
+func (fn *formulaFuncs) IMPRODUCT(argsList *list.List) formulaArg {
+	product := complex128(1)
+	for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+		token := arg.Value.(formulaArg)
+		switch token.Type {
+		case ArgString:
+			if token.Value() == "" {
+				continue
+			}
+			val, err := strconv.ParseComplex(str2cmplx(token.Value()), 128)
+			if err != nil {
+				return newErrorFormulaArg(formulaErrorNUM, err.Error())
+			}
+			product = product * val
+		case ArgNumber:
+			product = product * complex(token.Number, 0)
+		case ArgMatrix:
+			for _, row := range token.Matrix {
+				for _, value := range row {
+					if value.Value() == "" {
+						continue
+					}
+					val, err := strconv.ParseComplex(str2cmplx(value.Value()), 128)
+					if err != nil {
+						return newErrorFormulaArg(formulaErrorNUM, err.Error())
+					}
+					product = product * val
+				}
+			}
+		}
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(product), "i"))
+}
+
+// IMREAL function returns the real coefficient of a supplied complex number.
+// The syntax of the function is:
+//
+//    IMREAL(inumber)
+//
+func (fn *formulaFuncs) IMREAL(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMREAL requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(real(inumber)), "i"))
+}
+
+// IMSEC function returns the secant of a supplied complex number. The syntax
+// of the function is:
+//
+//    IMSEC(inumber)
+//
+func (fn *formulaFuncs) IMSEC(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSEC requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(1/cmplx.Cos(inumber)), "i"))
+}
+
+// IMSECH function returns the hyperbolic secant of a supplied complex number.
+// The syntax of the function is:
+//
+//    IMSECH(inumber)
+//
+func (fn *formulaFuncs) IMSECH(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSECH requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(1/cmplx.Cosh(inumber)), "i"))
+}
+
 // IMSIN function returns the Sine of a supplied complex number. The syntax of
 // the function is:
 //

+ 57 - 0
calc_test.go

@@ -167,6 +167,22 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMLOG10(\"3+0.5i\")":    "0.48307086636951624+0.07172315929479262i",
 		"=IMLOG10(\"2-i\")":       "0.34948500216800943-0.20135959813668655i",
 		"=IMLOG10(COMPLEX(1,-1))": "0.1505149978319906-0.3410940884604603i",
+		// IMREAL
+		"=IMREAL(\"5+2i\")":     "5",
+		"=IMREAL(\"2+2i\")":     "2",
+		"=IMREAL(6)":            "6",
+		"=IMREAL(\"3i\")":       "0",
+		"=IMREAL(COMPLEX(4,1))": "4",
+		// IMSEC
+		"=IMSEC(0.5)":           "1.139493927324549",
+		"=IMSEC(\"3+0.5i\")":    "-0.8919131797403304+0.05875317818173977i",
+		"=IMSEC(\"2-i\")":       "-0.4131493442669401-0.687527438655479i",
+		"=IMSEC(COMPLEX(1,-1))": "0.49833703055518686-0.5910838417210451i",
+		// IMSECH
+		"=IMSECH(0.5)":           "0.886818883970074",
+		"=IMSECH(\"3+0.5i\")":    "0.08736657796213027-0.047492549490160664i",
+		"=IMSECH(\"2-i\")":       "0.1511762982655772+0.22697367539372157i",
+		"=IMSECH(COMPLEX(1,-1))": "0.49833703055518686+0.5910838417210451i",
 		// IMSIN
 		"=IMSIN(0.5)":           "0.479425538604203",
 		"=IMSIN(\"3+0.5i\")":    "0.15913058529843999-0.5158804424525267i",
@@ -465,6 +481,23 @@ func TestCalcCellValue(t *testing.T) {
 		"=LOG10(0.001)":      "-3",
 		"=LOG10(25)":         "1.397940008672038",
 		"=LOG10(LOG10(100))": "0.301029995663981",
+		// IMLOG2
+		"=IMLOG2(\"5+2i\")": "2.4289904975637864+0.5489546632866347i",
+		"=IMLOG2(\"2-i\")":  "1.1609640474436813-0.6689021062254881i",
+		"=IMLOG2(6)":        "2.584962500721156",
+		"=IMLOG2(\"3i\")":   "1.584962500721156+2.266180070913597i",
+		"=IMLOG2(\"4+i\")":  "2.04373142062517+0.3534295024167349i",
+		// IMPOWER
+		"=IMPOWER(\"2-i\",2)":   "3.000000000000001-4i",
+		"=IMPOWER(\"2-i\",3)":   "2.0000000000000018-11.000000000000002i",
+		"=IMPOWER(9,0.5)":       "3",
+		"=IMPOWER(\"2+4i\",-2)": "-0.029999999999999985-0.039999999999999994i",
+		// IMPRODUCT
+		"=IMPRODUCT(3,6)":                       "18",
+		`=IMPRODUCT("",3,SUM(6))`:               "18",
+		"=IMPRODUCT(\"1-i\",\"5+10i\",2)":       "30+10i",
+		"=IMPRODUCT(COMPLEX(5,2),COMPLEX(0,1))": "-2+5i",
+		"=IMPRODUCT(A1:C1)":                     "4",
 		// MOD
 		"=MOD(6,4)":        "2",
 		"=MOD(6,3)":        "0",
@@ -1236,6 +1269,28 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMLOG10()":     "IMLOG10 requires 1 argument",
 		"=IMLOG10(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		"=IMLOG10(0)":    "#NUM!",
+		// IMLOG2
+		"=IMLOG2()":     "IMLOG2 requires 1 argument",
+		"=IMLOG2(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMLOG2(0)":    "#NUM!",
+		// IMPOWER
+		"=IMPOWER()":       "IMPOWER requires 2 arguments",
+		"=IMPOWER(0,\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMPOWER(\"\",0)": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMPOWER(0,0)":    "#NUM!",
+		"=IMPOWER(0,-1)":   "#NUM!",
+		// IMPRODUCT
+		"=IMPRODUCT(\"x\")": "strconv.ParseComplex: parsing \"x\": invalid syntax",
+		"=IMPRODUCT(A1:D1)": "strconv.ParseComplex: parsing \"Month\": invalid syntax",
+		// IMREAL
+		"=IMREAL()":     "IMREAL requires 1 argument",
+		"=IMREAL(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSEC
+		"=IMSEC()":     "IMSEC requires 1 argument",
+		"=IMSEC(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSECH
+		"=IMSECH()":     "IMSECH requires 1 argument",
+		"=IMSECH(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		// IMSIN
 		"=IMSIN()":     "IMSIN requires 1 argument",
 		"=IMSIN(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
@@ -1944,6 +1999,8 @@ func TestCalcCellValue(t *testing.T) {
 		"=MDETERM(A1:B2)": "-3",
 		// PRODUCT
 		"=PRODUCT(Sheet1!A1:Sheet1!A1:A2,A2)": "4",
+		// IMPRODUCT
+		"=IMPRODUCT(Sheet1!A1:Sheet1!A1:A2,A2)": "4",
 		// SUM
 		"=A1/A3":                          "0.333333333333333",
 		"=SUM(A1:A2)":                     "3",