Browse Source

Fixed #819, read empty after streaming data writing
#65 fn: IMAGINARY, IMARGUMENT, IMCONJUGATE and IMDIV

xuri 4 năm trước cách đây
mục cha
commit
737b7839a2
3 tập tin đã thay đổi với 115 bổ sung2 xóa
  1. 78 2
      calc.go
  2. 34 0
      calc_test.go
  3. 3 0
      lib.go

+ 78 - 2
calc.go

@@ -294,11 +294,15 @@ var tokenPriority = map[string]int{
 //    IF
 //    IFERROR
 //    IMABS
+//    IMAGINARY
+//    IMARGUMENT
+//    IMCONJUGATE
 //    IMCOS
 //    IMCOSH
 //    IMCOT
 //    IMCSC
 //    IMCSCH
+//    IMDIV
 //    IMEXP
 //    IMLN
 //    IMLOG10
@@ -1712,13 +1716,61 @@ func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
 	if argsList.Len() != 1 {
 		return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument")
 	}
-	inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
 	if err != nil {
 		return newErrorFormulaArg(formulaErrorNUM, err.Error())
 	}
 	return newNumberFormulaArg(cmplx.Abs(inumber))
 }
 
+// IMAGINARY function returns the imaginary coefficient of a supplied complex
+// number. The syntax of the function is:
+//
+//    IMAGINARY(inumber)
+//
+func (fn *formulaFuncs) IMAGINARY(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMAGINARY requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newNumberFormulaArg(imag(inumber))
+}
+
+// IMARGUMENT function returns the phase (also called the argument) of a
+// supplied complex number. The syntax of the function is:
+//
+//    IMARGUMENT(inumber)
+//
+func (fn *formulaFuncs) IMARGUMENT(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMARGUMENT requires 1 argument")
+	}
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	return newNumberFormulaArg(cmplx.Phase(inumber))
+}
+
+// IMCONJUGATE function returns the complex conjugate of a supplied complex
+// number. The syntax of the function is:
+//
+//    IMCONJUGATE(inumber)
+//
+func (fn *formulaFuncs) IMCONJUGATE(argsList *list.List) formulaArg {
+	if argsList.Len() != 1 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMCONJUGATE 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.Conj(inumber)), "i"))
+}
+
 // IMCOS function returns the cosine of a supplied complex number. The syntax
 // of the function is:
 //
@@ -1728,7 +1780,7 @@ func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
 	if argsList.Len() != 1 {
 		return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument")
 	}
-	inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
+	inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
 	if err != nil {
 		return newErrorFormulaArg(formulaErrorNUM, err.Error())
 	}
@@ -1807,6 +1859,30 @@ func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
 	return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
 }
 
+// IMDIV function calculates the quotient of two complex numbers (i.e. divides
+// one complex number by another). The syntax of the function is:
+//
+//    IMDIV(inumber1,inumber2)
+//
+func (fn *formulaFuncs) IMDIV(argsList *list.List) formulaArg {
+	if argsList.Len() != 2 {
+		return newErrorFormulaArg(formulaErrorVALUE, "IMDIV requires 2 arguments")
+	}
+	inumber1, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	inumber2, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
+	if err != nil {
+		return newErrorFormulaArg(formulaErrorNUM, err.Error())
+	}
+	num := inumber1 / inumber2
+	if cmplx.IsInf(num) {
+		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+	}
+	return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+}
+
 // IMEXP function returns the exponential of a supplied complex number. The
 // syntax of the function is:
 //

+ 34 - 0
calc_test.go

@@ -134,6 +134,22 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMABS(\"2j\")":              "2",
 		"=IMABS(\"-1+2i\")":           "2.23606797749979",
 		"=IMABS(COMPLEX(-1,2,\"j\"))": "2.23606797749979",
+		// IMAGINARY
+		"=IMAGINARY(\"5+2i\")": "2",
+		"=IMAGINARY(\"2-i\")":  "-1",
+		"=IMAGINARY(6)":        "0",
+		"=IMAGINARY(\"3i\")":   "3",
+		"=IMAGINARY(\"4+i\")":  "1",
+		// IMARGUMENT
+		"=IMARGUMENT(\"5+2i\")": "0.380506377112365",
+		"=IMARGUMENT(\"2-i\")":  "-0.463647609000806",
+		"=IMARGUMENT(6)":        "0",
+		// IMCONJUGATE
+		"=IMCONJUGATE(\"5+2i\")": "5-2i",
+		"=IMCONJUGATE(\"2-i\")":  "2+i",
+		"=IMCONJUGATE(6)":        "6",
+		"=IMCONJUGATE(\"3i\")":   "-3i",
+		"=IMCONJUGATE(\"4+i\")":  "4-i",
 		// IMCOS
 		"=IMCOS(0)":          "1",
 		"=IMCOS(0.5)":        "0.877582561890373",
@@ -152,6 +168,10 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMCSC(\"j\")": "-0.8509181282393216i",
 		// IMCSCH
 		"=IMCSCH(COMPLEX(1,-1))": "0.30393100162842646+0.6215180171704284i",
+		// IMDIV
+		"=IMDIV(\"5+2i\",\"1+i\")":          "3.5-1.5i",
+		"=IMDIV(\"2+2i\",\"2+i\")":          "1.2+0.4i",
+		"=IMDIV(COMPLEX(5,2),COMPLEX(0,1))": "2-5i",
 		// IMEXP
 		"=IMEXP(0)":             "1",
 		"=IMEXP(0.5)":           "1.648721270700128",
@@ -1241,6 +1261,15 @@ func TestCalcCellValue(t *testing.T) {
 		// IMABS
 		"=IMABS()":     "IMABS requires 1 argument",
 		"=IMABS(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMAGINARY
+		"=IMAGINARY()":     "IMAGINARY requires 1 argument",
+		"=IMAGINARY(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMARGUMENT
+		"=IMARGUMENT()":     "IMARGUMENT requires 1 argument",
+		"=IMARGUMENT(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		// IMCONJUGATE
+		"=IMCONJUGATE()":     "IMCONJUGATE requires 1 argument",
+		"=IMCONJUGATE(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		// IMCOS
 		"=IMCOS()":     "IMCOS requires 1 argument",
 		"=IMCOS(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
@@ -1258,6 +1287,11 @@ func TestCalcCellValue(t *testing.T) {
 		"=IMCSCH()":     "IMCSCH requires 1 argument",
 		"=IMCSCH(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
 		"=IMCSCH(0)":    "#NUM!",
+		// IMDIV
+		"=IMDIV()":       "IMDIV requires 2 arguments",
+		"=IMDIV(0,\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMDIV(\"\",0)": "strconv.ParseComplex: parsing \"\": invalid syntax",
+		"=IMDIV(1,0)":    "#NUM!",
 		// IMEXP
 		"=IMEXP()":     "IMEXP requires 1 argument",
 		"=IMEXP(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",

+ 3 - 0
lib.go

@@ -52,6 +52,9 @@ func (f *File) readXML(name string) []byte {
 	if content, ok := f.XLSX[name]; ok {
 		return content
 	}
+	if content, ok := f.streams[name]; ok {
+		return content.rawData.buf.Bytes()
+	}
 	return []byte{}
 }