diff options
Diffstat (limited to 'calc.go')
-rw-r--r-- | calc.go | 101 |
1 files changed, 99 insertions, 2 deletions
@@ -26,6 +26,7 @@ import ( "strings" "time" "unicode" + "unsafe" "github.com/xuri/efp" ) @@ -240,6 +241,9 @@ var tokenPriority = map[string]int{ // CSC // CSCH // DATE +// DEC2BIN +// DEC2HEX +// DEC2OCT // DECIMAL // DEGREES // ENCODEURL @@ -1140,7 +1144,100 @@ func formulaCriteriaEval(val string, criteria *formulaCriteria) (result bool, er return } -// Math and Trigonometric functions +// Engineering Functions + +// DEC2BIN function converts a decimal number into a Binary (Base 2) number. +// The syntax of the function is: +// +// DEC2BIN(number,[places]) +// +func (fn *formulaFuncs) DEC2BIN(argsList *list.List) formulaArg { + if argsList.Len() < 1 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2BIN requires at least 1 argument") + } + if argsList.Len() > 2 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2BIN allows at most 2 arguments") + } + return fn.dec2x("DEC2BIN", argsList) +} + +// DEC2HEX function converts a decimal number into a Hexadecimal (Base 16) +// number. The syntax of the function is: +// +// DEC2HEX(number,[places]) +// +func (fn *formulaFuncs) DEC2HEX(argsList *list.List) formulaArg { + if argsList.Len() < 1 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2HEX requires at least 1 argument") + } + if argsList.Len() > 2 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2HEX allows at most 2 arguments") + } + return fn.dec2x("DEC2HEX", argsList) +} + +// DEC2OCT function converts a decimal number into an Octal (Base 8) number. +// The syntax of the function is: +// +// DEC2OCT(number,[places]) +// +func (fn *formulaFuncs) DEC2OCT(argsList *list.List) formulaArg { + if argsList.Len() < 1 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2OCT requires at least 1 argument") + } + if argsList.Len() > 2 { + return newErrorFormulaArg(formulaErrorVALUE, "DEC2OCT allows at most 2 arguments") + } + return fn.dec2x("DEC2OCT", argsList) +} + +// dec2x is an implementation of the formula function DEC2BIN, DEC2HEX and DEC2OCT. +func (fn *formulaFuncs) dec2x(name string, argsList *list.List) formulaArg { + decimal := argsList.Front().Value.(formulaArg).ToNumber() + if decimal.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, decimal.Error) + } + maxLimitMap := map[string]float64{ + "DEC2BIN": 511, + "DEC2HEX": 549755813887, + "DEC2OCT": 536870911, + } + minLimitMap := map[string]float64{ + "DEC2BIN": -512, + "DEC2HEX": -549755813888, + "DEC2OCT": -536870912, + } + baseMap := map[string]int{ + "DEC2BIN": 2, + "DEC2HEX": 16, + "DEC2OCT": 8, + } + maxLimit := maxLimitMap[name] + minLimit := minLimitMap[name] + base := baseMap[name] + if decimal.Number < minLimit || decimal.Number > maxLimit { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + n := int64(decimal.Number) + binary := strconv.FormatUint(*(*uint64)(unsafe.Pointer(&n)), base) + if argsList.Len() == 2 { + places := argsList.Back().Value.(formulaArg).ToNumber() + if places.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, places.Error) + } + binaryPlaces := len(binary) + if places.Number < 0 || places.Number > 10 || binaryPlaces > int(places.Number) { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%s%s", strings.Repeat("0", int(places.Number)-binaryPlaces), binary))) + } + if decimal.Number < 0 && len(binary) > 10 { + return newStringFormulaArg(strings.ToUpper(binary[len(binary)-10:])) + } + return newStringFormulaArg(strings.ToUpper(binary)) +} + +// Math and Trigonometric Functions // ABS function returns the absolute value of any supplied number. The syntax // of the function is: @@ -4357,7 +4454,7 @@ func (fn *formulaFuncs) IF(argsList *list.List) formulaArg { return newStringFormulaArg(result) } -// Excel Lookup and Reference Functions +// Lookup and Reference Functions // CHOOSE function returns a value from an array, that corresponds to a // supplied index number (position). The syntax of the function is: |