Parcourir la source

#65 fn: IMSIN, IMSINH, IMSQRT, IMSUB, IMSUM, IMTAN

xuri il y a 4 ans
Parent
commit
3345e89b96
2 fichiers modifiés avec 163 ajouts et 2 suppressions
  1. 114 2
      calc.go
  2. 49 0
      calc_test.go

+ 114 - 2
calc.go

@@ -302,6 +302,12 @@ var tokenPriority = map[string]int{
 //    IMEXP
 //    IMLN
 //    IMLOG10
+//    IMSIN
+//    IMSINH
+//    IMSQRT
+//    IMSUB
+//    IMSUM
+//    IMTAN
 //    INT
 //    ISBLANK
 //    ISERR
@@ -1490,7 +1496,7 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
 
 // cmplx2str replace complex number string characters.
 func cmplx2str(c, suffix string) string {
-	if c == "(0+0i)" || c == "(0-0i)" {
+	if c == "(0+0i)" || c == "(-0+0i)" || c == "(0-0i)" || c == "(-0-0i)" {
 		return "0"
 	}
 	c = strings.TrimPrefix(c, "(")
@@ -1504,7 +1510,7 @@ func cmplx2str(c, suffix string) string {
 	c = strings.TrimPrefix(c, "0+")
 	c = strings.TrimSuffix(c, "+0i")
 	c = strings.TrimSuffix(c, "-0i")
-	c = strings.NewReplacer("+1i", "i", "-1i", "-i").Replace(c)
+	c = strings.NewReplacer("+1i", "+i", "-1i", "-i").Replace(c)
 	c = strings.Replace(c, "i", suffix, -1)
 	return c
 }
@@ -1851,6 +1857,112 @@ func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
 	return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
 }
 
+// IMSIN function returns the Sine of a supplied complex number. The syntax of
+// the function is:
+//
+//    IMSIN(inumber)
+//
+func (fn *formulaFuncs) IMSIN(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSIN 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(cmplx.Sin(inumber)), "i"))
+}
+
+// IMSINH function returns the hyperbolic sine of a supplied complex number.
+// The syntax of the function is:
+//
+//    IMSINH(inumber)
+//
+func (fn *formulaFuncs) IMSINH(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSINH 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(cmplx.Sinh(inumber)), "i"))
+}
+
+// IMSQRT function returns the square root of a supplied complex number. The
+// syntax of the function is:
+//
+//    IMSQRT(inumber)
+//
+func (fn *formulaFuncs) IMSQRT(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSQRT 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(cmplx.Sqrt(inumber)), "i"))
+}
+
+// IMSUB function calculates the difference between two complex numbers
+// (i.e. subtracts one complex number from another). The syntax of the
+// function is:
+//
+//    IMSUB(inumber1,inumber2)
+//
+func (fn *formulaFuncs) IMSUB(argsList *list.List) formulaArg {
+	if argsList.Len() != 2 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSUB requires 2 arguments")
+	}
+	i1, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	i2, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(i1-i2), "i"))
+}
+
+// IMSUM function calculates the sum of two or more complex numbers. The
+// syntax of the function is:
+//
+//    IMSUM(inumber1,inumber2,...)
+//
+func (fn *formulaFuncs) IMSUM(argsList *list.List) formulaArg {
+	if argsList.Len() < 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMSUM requires at least 1 argument")
+	}
+	var result complex128
+	for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+		token := arg.Value.(formulaArg)
+		num, err := strconv.ParseComplex(str2cmplx(token.Value()), 128)
+		if err != nil {
+			return newErrorFormulaArg(formulaErrorNUM, err.Error())
+		}
+		result += num
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(result), "i"))
+}
+
+// IMTAN function returns the tangent of a supplied complex number. The syntax
+// of the function is:
+//
+//    IMTAN(inumber)
+//
+func (fn *formulaFuncs) IMTAN(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMTAN 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(cmplx.Tan(inumber)), "i"))
+}
+
 // OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2)
 // number. The syntax of the function is:
 //

+ 49 - 0
calc_test.go

@@ -167,6 +167,36 @@ 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",
+		// IMSIN
+		"=IMSIN(0.5)":           "0.479425538604203",
+		"=IMSIN(\"3+0.5i\")":    "0.15913058529843999-0.5158804424525267i",
+		"=IMSIN(\"2-i\")":       "1.4031192506220405+0.4890562590412937i",
+		"=IMSIN(COMPLEX(1,-1))": "1.2984575814159773-0.6349639147847361i",
+		// IMSINH
+		"=IMSINH(-0)":            "0",
+		"=IMSINH(0.5)":           "0.521095305493747",
+		"=IMSINH(\"3+0.5i\")":    "8.791512343493714+4.82669427481082i",
+		"=IMSINH(\"2-i\")":       "1.9596010414216063-3.165778513216168i",
+		"=IMSINH(COMPLEX(1,-1))": "0.6349639147847361-1.2984575814159773i",
+		// IMSQRT
+		"=IMSQRT(\"i\")":     "0.7071067811865476+0.7071067811865476i",
+		"=IMSQRT(\"2-i\")":   "1.455346690225355-0.34356074972251244i",
+		"=IMSQRT(\"5+2i\")":  "2.27872385417085+0.4388421169022545i",
+		"=IMSQRT(6)":         "2.449489742783178",
+		"=IMSQRT(\"-2-4i\")": "1.1117859405028423-1.7989074399478673i",
+		// IMSUB
+		"=IMSUB(\"5+i\",\"1+4i\")":          "4-3i",
+		"=IMSUB(\"9+2i\",6)":                "3+2i",
+		"=IMSUB(COMPLEX(5,2),COMPLEX(0,1))": "5+i",
+		// IMSUM
+		"=IMSUM(\"1-i\",\"5+10i\",2)":       "8+9i",
+		"=IMSUM(COMPLEX(5,2),COMPLEX(0,1))": "5+3i",
+		// IMTAN
+		"=IMTAN(-0)":            "0",
+		"=IMTAN(0.5)":           "0.546302489843791",
+		"=IMTAN(\"3+0.5i\")":    "-0.11162105077158344+0.46946999342588536i",
+		"=IMTAN(\"2-i\")":       "-0.24345820118572523-1.16673625724092i",
+		"=IMTAN(COMPLEX(1,-1))": "0.2717525853195117-1.0839233273386948i",
 		// OCT2BIN
 		"=OCT2BIN(\"5\")":          "101",
 		"=OCT2BIN(\"0000000001\")": "1",
@@ -1206,6 +1236,25 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMLOG10()":     "IMLOG10 requires 1 argument",
 		"=IMLOG10(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		"=IMLOG10(0)":    "#NUM!",
+		// IMSIN
+		"=IMSIN()":     "IMSIN requires 1 argument",
+		"=IMSIN(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSINH
+		"=IMSINH()":     "IMSINH requires 1 argument",
+		"=IMSINH(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSQRT
+		"=IMSQRT()":     "IMSQRT requires 1 argument",
+		"=IMSQRT(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSUB
+		"=IMSUB()":       "IMSUB requires 2 arguments",
+		"=IMSUB(0,\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMSUB(\"\",0)": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMSUM
+		"=IMSUM()":     "IMSUM requires at least 1 argument",
+		"=IMSUM(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMTAN
+		"=IMTAN()":     "IMTAN requires 1 argument",
+		"=IMTAN(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		// OCT2BIN
 		"=OCT2BIN()":               "OCT2BIN requires at least 1 argument",
 		"=OCT2BIN(1,1,1)":          "OCT2BIN allows at most 2 arguments",