From f1cc78dfdc5bfb677e547c589e9d8204a8f87642 Mon Sep 17 00:00:00 2001 From: "zhengyang.zhu" Date: Wed, 21 May 2025 15:55:19 +0800 Subject: [PATCH 1/2] #2139 avoid lookupLinearSearch malloc slice --- calc.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/calc.go b/calc.go index c36e500942..1823c37065 100644 --- a/calc.go +++ b/calc.go @@ -14996,6 +14996,66 @@ func (fn *formulaFuncs) HYPERLINK(argsList *list.List) formulaArg { return newStringFormulaArg(argsList.Back().Value.(formulaArg).Value()) } +// calcMatch returns the position of the value by given match type, criteria +// and lookup array for the formula function MATCH. +func calcMatchMatrix(vertical bool, matchType int, criteria *formulaCriteria, lookupArray [][]formulaArg) formulaArg { + idx := -1 + var result *formulaArg + + var calc = func(i int, arg formulaArg) bool { + switch matchType { + case 0: + if ok, _ := formulaCriteriaEval(arg, criteria); ok { + out := newNumberFormulaArg(float64(i + 1)) + result = &out + return true + } + case -1: + if ok, _ := formulaCriteriaEval(arg, &formulaCriteria{ + Type: criteriaGe, Condition: criteria.Condition, + }); ok { + idx = i + return false + } + if criteria.Condition.Type == ArgNumber { + return true + } + case 1: + if ok, _ := formulaCriteriaEval(arg, &formulaCriteria{ + Type: criteriaLe, Condition: criteria.Condition, + }); ok { + idx = i + return false + } + if criteria.Condition.Type == ArgNumber { + return true + } + } + return false + } + + if vertical { + for i, row := range lookupArray { + if ok := calc(i, row[0]); ok { + break + } + } + } else { + for i, cell := range lookupArray[0] { + if ok := calc(i, cell); ok { + break + } + } + } + if result != nil { + return *result + } + if idx == -1 { + return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) + } + return newNumberFormulaArg(float64(idx + 1)) +} + // calcMatch returns the position of the value by given match type, criteria // and lookup array for the formula function MATCH. func calcMatch(matchType int, criteria *formulaCriteria, lookupArray []formulaArg) formulaArg { @@ -15110,18 +15170,8 @@ func (fn *formulaFuncs) TRANSPOSE(argsList *list.List) formulaArg { // lookupLinearSearch sequentially checks each look value of the lookup array until // a match is found or the whole list has been searched. func lookupLinearSearch(vertical bool, lookupValue, lookupArray, matchMode, searchMode formulaArg) (int, bool) { - var tableArray []formulaArg - if vertical { - for _, row := range lookupArray.Matrix { - tableArray = append(tableArray, row[0]) - } - } else { - tableArray = lookupArray.Matrix[0] - } matchIdx, wasExact := -1, false -start: - for i, cell := range tableArray { - lhs := cell + var linearSearch = func(i int, cell, lhs formulaArg) bool { if lookupValue.Type == ArgNumber { if lhs = cell.ToNumber(); lhs.Type == ArgError { lhs = cell @@ -15135,12 +15185,28 @@ start: matchIdx = i wasExact = true if searchMode.Number == searchModeLinear { - break start + return true } } if matchMode.Number == matchModeMinGreater || matchMode.Number == matchModeMaxLess { - matchIdx = int(calcMatch(int(matchMode.Number), formulaCriteriaParser(lookupValue), tableArray).Number) - continue + matchIdx = int(calcMatchMatrix(vertical, int(matchMode.Number), formulaCriteriaParser(lookupValue), lookupArray.Matrix).Number) + return false + } + return false + } + + if vertical { + for i, row := range lookupArray.Matrix { + lhs := row[0] + if linearSearch(i, lhs, lhs) { + break + } + } + } else { + for i, lhs := range lookupArray.Matrix[0] { + if linearSearch(i, lhs, lhs) { + break + } } } return matchIdx, wasExact From 999a96f2268e710b775d1b8aa709df825f6bcbc9 Mon Sep 17 00:00:00 2001 From: "zhengyang.zhu" Date: Thu, 22 May 2025 11:32:18 +0800 Subject: [PATCH 2/2] This related with #2140, alcMatchMatrix function, the parameter matchType is only passed values of 1 and -1 from above. --- calc.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/calc.go b/calc.go index 1823c37065..8127697457 100644 --- a/calc.go +++ b/calc.go @@ -14998,18 +14998,11 @@ func (fn *formulaFuncs) HYPERLINK(argsList *list.List) formulaArg { // calcMatch returns the position of the value by given match type, criteria // and lookup array for the formula function MATCH. +// matchType only contains -1, and 1. func calcMatchMatrix(vertical bool, matchType int, criteria *formulaCriteria, lookupArray [][]formulaArg) formulaArg { idx := -1 - var result *formulaArg - var calc = func(i int, arg formulaArg) bool { switch matchType { - case 0: - if ok, _ := formulaCriteriaEval(arg, criteria); ok { - out := newNumberFormulaArg(float64(i + 1)) - result = &out - return true - } case -1: if ok, _ := formulaCriteriaEval(arg, &formulaCriteria{ Type: criteriaGe, Condition: criteria.Condition, @@ -15047,9 +15040,6 @@ func calcMatchMatrix(vertical bool, matchType int, criteria *formulaCriteria, lo } } } - if result != nil { - return *result - } if idx == -1 { return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) }