diff --git a/go.mod b/go.mod
index f6edc51c..23e50edb 100644
--- a/go.mod
+++ b/go.mod
@@ -18,8 +18,8 @@ require (
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.1
github.com/vbauerster/mpb/v7 v7.4.1
- github.com/xuri/excelize/v2 v2.5.0
- golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
+ github.com/xuri/excelize/v2 v2.6.0
+ golang.org/x/crypto v0.0.0-20220408190544-5352b0902921
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
@@ -49,13 +49,14 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/richardlehane/mscfb v1.0.3 // indirect
+ github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect
- github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
- golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
+ github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8 // indirect
+ github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
+ golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
diff --git a/go.sum b/go.sum
index 972256e8..61a3523b 100644
--- a/go.sum
+++ b/go.sum
@@ -560,8 +560,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
-github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI=
-github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
+github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
+github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
@@ -645,10 +645,12 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o=
-github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
-github.com/xuri/excelize/v2 v2.5.0 h1:nDDVfX0qaDuGjAvb+5zTd0Bxxoqa1Ffv9B4kiE23PTM=
-github.com/xuri/excelize/v2 v2.5.0/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A=
+github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8 h1:3X7aE0iLKJ5j+tz58BpvIZkXNV7Yq4jC93Z/rbN2Fxk=
+github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
+github.com/xuri/excelize/v2 v2.6.0 h1:m/aXAzSAqxgt74Nfd+sNzpzVKhTGl7+S9nbG4A57mF4=
+github.com/xuri/excelize/v2 v2.6.0/go.mod h1:Q1YetlHesXEKwGFfeJn7PfEZz2IvHb6wdOeYjBxVcVs=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -684,9 +686,8 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
+golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -699,8 +700,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
-golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
+golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -757,9 +758,9 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 h1:EN5+DfgmRMvRUrMGERW2gQl3Vc+Z7ZMnI/xdEpPSf0c=
+golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -843,6 +844,7 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
diff --git a/vendor/github.com/richardlehane/mscfb/.travis.yml b/vendor/github.com/richardlehane/mscfb/.travis.yml
index d09d42da..e0c814a8 100644
--- a/vendor/github.com/richardlehane/mscfb/.travis.yml
+++ b/vendor/github.com/richardlehane/mscfb/.travis.yml
@@ -1,5 +1,4 @@
language: go
go:
- - 1.2
- stable
- tip
\ No newline at end of file
diff --git a/vendor/github.com/richardlehane/mscfb/mscfb.go b/vendor/github.com/richardlehane/mscfb/mscfb.go
index b0ad1281..a054e7ce 100644
--- a/vendor/github.com/richardlehane/mscfb/mscfb.go
+++ b/vendor/github.com/richardlehane/mscfb/mscfb.go
@@ -195,14 +195,21 @@ func (r *Reader) setMiniStream() error {
// build a slice of ministream sectors
c = int(r.sectorSize / 4 * r.header.numMiniFatSectors)
r.header.miniStreamLocs = make([]uint32, 0, c)
+ cycles := make(map[uint32]bool)
sn := r.direntries[0].startingSectorLoc
- var err error
for sn != endOfChain {
r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn)
- sn, err = r.findNext(sn, false)
+ nsn, err := r.findNext(sn, false)
if err != nil {
return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(sn)}
}
+ if nsn <= sn {
+ if nsn == sn || cycles[nsn] {
+ return Error{ErrRead, "cycle detected in mini stream", int64(nsn)}
+ }
+ cycles[nsn] = true
+ }
+ sn = nsn
}
return nil
}
diff --git a/vendor/github.com/xuri/efp/LICENSE b/vendor/github.com/xuri/efp/LICENSE
index f38aebe2..b01e42ce 100644
--- a/vendor/github.com/xuri/efp/LICENSE
+++ b/vendor/github.com/xuri/efp/LICENSE
@@ -1,6 +1,6 @@
BSD 3-Clause License
-Copyright (c) 2017 - 2021 Ri Xu All rights reserved.
+Copyright (c) 2017 - 2022 Ri Xu All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
diff --git a/vendor/github.com/xuri/efp/efp.go b/vendor/github.com/xuri/efp/efp.go
index 6f420d06..559858a0 100644
--- a/vendor/github.com/xuri/efp/efp.go
+++ b/vendor/github.com/xuri/efp/efp.go
@@ -1,4 +1,4 @@
-// Package efp (Excel Formula Parser) tokenise an Excel formula using an
+// Package efp (Excel Formula Parser) tokenize an Excel formula using an
// implementation of E. W. Bachtal's algorithm, found here:
// https://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
//
@@ -44,7 +44,6 @@ const (
TokenTypeUnknown = "Unknown"
// Token subtypes
- TokenSubTypeNothing = "Nothing"
TokenSubTypeStart = "Start"
TokenSubTypeStop = "Stop"
TokenSubTypeText = "Text"
@@ -123,12 +122,12 @@ func (tk *Tokens) reset() {
tk.Index = -1
}
-// BOF provides function to check whether or not beginning of list.
+// BOF provides function to check whether beginning of list.
func (tk *Tokens) BOF() bool {
return tk.Index <= 0
}
-// EOF provides function to check whether or not end of list.
+// EOF provides function to check whether end of list.
func (tk *Tokens) EOF() bool {
return tk.Index >= (len(tk.Items) - 1)
}
@@ -224,7 +223,7 @@ func ExcelParser() Parser {
}
// getTokens return a token stream (list).
-func (ps *Parser) getTokens(formula string) Tokens {
+func (ps *Parser) getTokens() Tokens {
ps.Formula = strings.TrimSpace(ps.Formula)
f := []rune(ps.Formula)
if len(f) > 0 {
@@ -240,9 +239,9 @@ func (ps *Parser) getTokens(formula string) Tokens {
// embeds are doubled
// end marks token
if ps.InString {
- if ps.currentChar() == "\"" {
- if ps.nextChar() == "\"" {
- ps.Token += "\""
+ if ps.currentChar() == QuoteDouble {
+ if ps.nextChar() == QuoteDouble {
+ ps.Token += QuoteDouble
ps.Offset++
} else {
ps.InString = false
@@ -260,9 +259,9 @@ func (ps *Parser) getTokens(formula string) Tokens {
// embeds are double
// end does not mark a token
if ps.InPath {
- if ps.currentChar() == "'" {
- if ps.nextChar() == "'" {
- ps.Token += "'"
+ if ps.currentChar() == QuoteSingle {
+ if ps.nextChar() == QuoteSingle {
+ ps.Token += QuoteSingle
ps.Offset++
} else {
ps.InPath = false
@@ -278,7 +277,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
// no embeds (changed to "()" by Excel)
// end does not mark a token
if ps.InRange {
- if ps.currentChar() == "]" {
+ if ps.currentChar() == BracketClose {
ps.InRange = false
}
ps.Token += ps.currentChar()
@@ -291,9 +290,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
if ps.InError {
ps.Token += ps.currentChar()
ps.Offset++
- errors := map[string]string{",#NULL!,": "", ",#DIV/0!,": "", ",#VALUE!,": "", ",#REF!,": "", ",#NAME?,": "", ",#NUM!,": "", ",#N/A,": ""}
- _, ok := errors[","+ps.Token+","]
- if ok {
+ if inStrSlice([]string{",#NULL!,", ",#DIV/0!,", ",#VALUE!,", ",#REF!,", ",#NAME?,", ",#NUM!,", ",#N/A,"}, Comma+ps.Token+Comma) != -1 {
ps.InError = false
ps.Tokens.add(ps.Token, TokenTypeOperand, TokenSubTypeError)
ps.Token = ""
@@ -302,9 +299,9 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// scientific notation check
- if strings.ContainsAny(ps.currentChar(), "+-") && len(ps.Token) > 1 {
- match, _ := regexp.MatchString(`^[1-9]{1}(\.[0-9]+)?E{1}$`, ps.Token)
- if match {
+ if strings.ContainsAny(ps.currentChar(), OperatorsSN) && len(ps.Token) > 1 {
+ r, _ := regexp.Compile(`^[1-9]{1}(\.[0-9]+)?E{1}$`)
+ if r.MatchString(ps.Token) {
ps.Token += ps.currentChar()
ps.Offset++
continue
@@ -313,7 +310,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
// independent character evaluation (order not important)
// establish state-dependent character evaluations
- if ps.currentChar() == "\"" {
+ if ps.currentChar() == QuoteDouble {
if len(ps.Token) > 0 {
// not expected
ps.Tokens.add(ps.Token, TokenTypeUnknown, "")
@@ -324,7 +321,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
continue
}
- if ps.currentChar() == "'" {
+ if ps.currentChar() == QuoteSingle {
if len(ps.Token) > 0 {
// not expected
ps.Tokens.add(ps.Token, TokenTypeUnknown, "")
@@ -335,14 +332,14 @@ func (ps *Parser) getTokens(formula string) Tokens {
continue
}
- if ps.currentChar() == "[" {
+ if ps.currentChar() == BracketOpen {
ps.InRange = true
ps.Token += ps.currentChar()
ps.Offset++
continue
}
- if ps.currentChar() == "#" {
+ if ps.currentChar() == ErrorStart {
if len(ps.Token) > 0 {
// not expected
ps.Tokens.add(ps.Token, TokenTypeUnknown, "")
@@ -355,7 +352,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// mark start and end of arrays and array rows
- if ps.currentChar() == "{" {
+ if ps.currentChar() == BraceOpen {
if len(ps.Token) > 0 {
// not expected
ps.Tokens.add(ps.Token, TokenTypeUnknown, "")
@@ -367,19 +364,19 @@ func (ps *Parser) getTokens(formula string) Tokens {
continue
}
- if ps.currentChar() == ";" {
+ if ps.currentChar() == Semicolon {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
}
ps.Tokens.addRef(ps.TokenStack.pop())
- ps.Tokens.add(",", TokenTypeArgument, "")
+ ps.Tokens.add(Comma, TokenTypeArgument, "")
ps.TokenStack.push(ps.Tokens.add("ARRAYROW", TokenTypeFunction, TokenSubTypeStart))
ps.Offset++
continue
}
- if ps.currentChar() == "}" {
+ if ps.currentChar() == BraceClose {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -391,23 +388,21 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// trim white-space
- if ps.currentChar() == " " {
+ if ps.currentChar() == Whitespace {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
}
ps.Tokens.add("", TokenTypeWhitespace, "")
ps.Offset++
- for (ps.currentChar() == " ") && (!ps.EOF()) {
+ for (ps.currentChar() == Whitespace) && (!ps.EOF()) {
ps.Offset++
}
continue
}
// multi-character comparators
- comparators := map[string]string{",>=,": "", ",<=,": "", ",<>,": ""}
- _, ok := comparators[","+ps.doubleChar()+","]
- if ok {
+ if inStrSlice([]string{",>=,", ",<=,", ",<>,"}, Comma+ps.doubleChar()+Comma) != -1 {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -418,9 +413,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// standard infix operators
- operators := map[string]string{"+": "", "-": "", "*": "", "/": "", "^": "", "&": "", "=": "", ">": "", "<": ""}
- _, ok = operators[ps.currentChar()]
- if ok {
+ if strings.ContainsAny(OperatorsInfix, ps.currentChar()) {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -431,7 +424,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// standard postfix operators
- if ps.currentChar() == "%" {
+ if ps.currentChar() == OperatorsPostfix {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -442,7 +435,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// start subexpression or function
- if ps.currentChar() == "(" {
+ if ps.currentChar() == ParenOpen {
if len(ps.Token) > 0 {
ps.TokenStack.push(ps.Tokens.add(ps.Token, TokenTypeFunction, TokenSubTypeStart))
ps.Token = ""
@@ -454,7 +447,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// function, subexpression, array parameters
- if ps.currentChar() == "," {
+ if ps.currentChar() == Comma {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -469,7 +462,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
// stop subexpression
- if ps.currentChar() == ")" {
+ if ps.currentChar() == ParenClose {
if len(ps.Token) > 0 {
ps.Tokens.add(ps.Token, TokenTypeOperand, "")
ps.Token = ""
@@ -540,9 +533,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
}
if (token.TType == TokenTypeOperatorInfix) && (len(token.TSubType) == 0) {
- op := map[string]string{"<": "", ">": "", "=": ""}
- _, ok := op[token.TValue[0:1]]
- if ok {
+ if strings.ContainsAny(token.TValue[0:1], "<>=") {
token.TSubType = TokenSubTypeLogical
} else if token.TValue == "&" {
token.TSubType = TokenSubTypeConcatenation
@@ -575,7 +566,7 @@ func (ps *Parser) getTokens(formula string) Tokens {
tokens2.reset()
- // move all tokens to a new collection, excluding all noops
+ // move all tokens to a new collection, excluding all no-ops
tokens := fTokens()
for tokens2.moveNext() {
if tokens2.current().TType != TokenTypeNoop {
@@ -613,7 +604,7 @@ func (ps *Parser) nextChar() string {
return ""
}
-// EOF provides function to check whether or not end of tokens stack.
+// EOF provides function to check whether end of tokens stack.
func (ps *Parser) EOF() bool {
return ps.Offset >= len([]rune(ps.Formula))
}
@@ -621,7 +612,7 @@ func (ps *Parser) EOF() bool {
// Parse provides function to parse formula as a token stream (list).
func (ps *Parser) Parse(formula string) []Token {
ps.Formula = formula
- ps.Tokens = ps.getTokens(formula)
+ ps.Tokens = ps.getTokens()
return ps.Tokens.Items
}
@@ -650,20 +641,31 @@ func (ps *Parser) Render() string {
output := ""
for _, t := range ps.Tokens.Items {
if t.TType == TokenTypeFunction && t.TSubType == TokenSubTypeStart {
- output += t.TValue + "("
+ output += t.TValue + ParenOpen
} else if t.TType == TokenTypeFunction && t.TSubType == TokenSubTypeStop {
- output += ")"
+ output += ParenClose
} else if t.TType == TokenTypeSubexpression && t.TSubType == TokenSubTypeStart {
- output += "("
+ output += ParenOpen
} else if t.TType == TokenTypeSubexpression && t.TSubType == TokenSubTypeStop {
- output += ")"
+ output += ParenClose
} else if t.TType == TokenTypeOperand && t.TSubType == TokenSubTypeText {
- output += "\"" + t.TValue + "\""
+ output += QuoteDouble + t.TValue + QuoteDouble
} else if t.TType == TokenTypeOperatorInfix && t.TSubType == TokenSubTypeIntersection {
- output += " "
+ output += Whitespace
} else {
output += t.TValue
}
}
return output
}
+
+// inStrSlice provides a method to check if an element is present in an array,
+// and return the index of its location, otherwise return -1.
+func inStrSlice(a []string, x string) int {
+ for idx, n := range a {
+ if x == n {
+ return idx
+ }
+ }
+ return -1
+}
diff --git a/vendor/github.com/xuri/excelize/v2/.gitignore b/vendor/github.com/xuri/excelize/v2/.gitignore
index 68532a7f..4dce7680 100644
--- a/vendor/github.com/xuri/excelize/v2/.gitignore
+++ b/vendor/github.com/xuri/excelize/v2/.gitignore
@@ -1,6 +1,9 @@
~$*.xlsx
-test/Test*.xlsx
+test/Test*.xlam
test/Test*.xlsm
+test/Test*.xlsx
+test/Test*.xltm
+test/Test*.xltx
# generated files
test/BadEncrypt.xlsx
test/BadWorkbook.SaveAsEmptyStruct.xlsx
diff --git a/vendor/github.com/xuri/excelize/v2/LICENSE b/vendor/github.com/xuri/excelize/v2/LICENSE
index 17591f25..10897e7d 100644
--- a/vendor/github.com/xuri/excelize/v2/LICENSE
+++ b/vendor/github.com/xuri/excelize/v2/LICENSE
@@ -1,6 +1,6 @@
BSD 3-Clause License
-Copyright (c) 2016-2021 The excelize Authors.
+Copyright (c) 2016-2022 The excelize Authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/vendor/github.com/xuri/excelize/v2/README.md b/vendor/github.com/xuri/excelize/v2/README.md
index a0d2d3dd..8e16a88b 100644
--- a/vendor/github.com/xuri/excelize/v2/README.md
+++ b/vendor/github.com/xuri/excelize/v2/README.md
@@ -13,7 +13,7 @@
## Introduction
-Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLSX / XLSM / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.15 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
+Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.15 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
## Basic Usage
diff --git a/vendor/github.com/xuri/excelize/v2/README_zh.md b/vendor/github.com/xuri/excelize/v2/README_zh.md
index 919e954b..dafdd93f 100644
--- a/vendor/github.com/xuri/excelize/v2/README_zh.md
+++ b/vendor/github.com/xuri/excelize/v2/README_zh.md
@@ -13,7 +13,7 @@
## 简介
-Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
+Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
## 快速上手
diff --git a/vendor/github.com/xuri/excelize/v2/adjust.go b/vendor/github.com/xuri/excelize/v2/adjust.go
index 243c7745..e1c0e15e 100644
--- a/vendor/github.com/xuri/excelize/v2/adjust.go
+++ b/vendor/github.com/xuri/excelize/v2/adjust.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -81,13 +81,13 @@ func (f *File) adjustRowDimensions(ws *xlsxWorksheet, row, offset int) {
for i := range ws.SheetData.Row {
r := &ws.SheetData.Row[i]
if newRow := r.R + offset; r.R >= row && newRow > 0 {
- f.ajustSingleRowDimensions(r, newRow)
+ f.adjustSingleRowDimensions(r, newRow)
}
}
}
-// ajustSingleRowDimensions provides a function to ajust single row dimensions.
-func (f *File) ajustSingleRowDimensions(r *xlsxRow, num int) {
+// adjustSingleRowDimensions provides a function to adjust single row dimensions.
+func (f *File) adjustSingleRowDimensions(r *xlsxRow, num int) {
r.R = num
for i, col := range r.C {
colName, _, _ := SplitCellName(col.R)
@@ -226,6 +226,7 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off
i--
continue
}
+ areaData.rect = []int{x1, y1, x2, y2}
if areaData.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
return err
}
diff --git a/vendor/github.com/xuri/excelize/v2/calc.go b/vendor/github.com/xuri/excelize/v2/calc.go
index b096af94..57b2cda8 100644
--- a/vendor/github.com/xuri/excelize/v2/calc.go
+++ b/vendor/github.com/xuri/excelize/v2/calc.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -69,7 +69,7 @@ const (
searchModeDescBinary = -2
maxFinancialIterations = 128
- financialPercision = 1.0e-08
+ financialPrecision = 1.0e-08
// Date and time format regular expressions
monthRe = `((jan|january)|(feb|february)|(mar|march)|(apr|april)|(may)|(jun|june)|(jul|july)|(aug|august)|(sep|september)|(oct|october)|(nov|november)|(dec|december))`
df1 = `(([0-9])+)/(([0-9])+)/(([0-9])+)`
@@ -282,11 +282,11 @@ func (fa formulaArg) ToBool() formulaArg {
func (fa formulaArg) ToList() []formulaArg {
switch fa.Type {
case ArgMatrix:
- list := []formulaArg{}
+ var args []formulaArg
for _, row := range fa.Matrix {
- list = append(list, row...)
+ args = append(args, row...)
}
- return list
+ return args
case ArgList:
return fa.List
case ArgNumber, ArgString, ArgError, ArgUnknown:
@@ -328,14 +328,23 @@ type formulaFuncs struct {
// AVERAGE
// AVERAGEA
// AVERAGEIF
+// AVERAGEIFS
// BASE
// BESSELI
// BESSELJ
// BESSELK
// BESSELY
+// BETADIST
+// BETA.DIST
+// BETAINV
+// BETA.INV
// BIN2DEC
// BIN2HEX
// BIN2OCT
+// BINOMDIST
+// BINOM.DIST
+// BINOM.DIST.RANGE
+// BINOM.INV
// BITAND
// BITLSHIFT
// BITOR
@@ -346,6 +355,13 @@ type formulaFuncs struct {
// CEILING.PRECISE
// CHAR
// CHIDIST
+// CHIINV
+// CHITEST
+// CHISQ.DIST
+// CHISQ.DIST.RT
+// CHISQ.INV
+// CHISQ.INV.RT
+// CHISQ.TEST
// CHOOSE
// CLEAN
// CODE
@@ -358,6 +374,8 @@ type formulaFuncs struct {
// CONCATENATE
// CONFIDENCE
// CONFIDENCE.NORM
+// CONFIDENCE.T
+// CORREL
// COS
// COSH
// COT
@@ -373,6 +391,9 @@ type formulaFuncs struct {
// COUPNCD
// COUPNUM
// COUPPCD
+// COVAR
+// COVARIANCE.P
+// CRITBINOM
// CSC
// CSCH
// CUMIPMT
@@ -401,24 +422,42 @@ type formulaFuncs struct {
// ERF.PRECISE
// ERFC
// ERFC.PRECISE
+// ERROR.TYPE
// EVEN
// EXACT
// EXP
+// EXPON.DIST
+// EXPONDIST
// FACT
// FACTDOUBLE
// FALSE
+// F.DIST
+// F.DIST.RT
+// FDIST
// FIND
// FINDB
+// F.INV
+// F.INV.RT
+// FINV
// FISHER
// FISHERINV
// FIXED
// FLOOR
// FLOOR.MATH
// FLOOR.PRECISE
+// FORMULATEXT
+// F.TEST
+// FTEST
// FV
// FVSCHEDULE
// GAMMA
+// GAMMA.DIST
+// GAMMADIST
+// GAMMA.INV
+// GAMMAINV
// GAMMALN
+// GAMMALN.PRECISE
+// GAUSS
// GCD
// GEOMEAN
// GESTEP
@@ -427,6 +466,9 @@ type formulaFuncs struct {
// HEX2DEC
// HEX2OCT
// HLOOKUP
+// HOUR
+// HYPGEOM.DIST
+// HYPGEOMDIST
// IF
// IFERROR
// IFNA
@@ -457,6 +499,7 @@ type formulaFuncs struct {
// IMSUM
// IMTAN
// INDEX
+// INDIRECT
// INT
// INTRATE
// IPMT
@@ -486,6 +529,10 @@ type formulaFuncs struct {
// LN
// LOG
// LOG10
+// LOGINV
+// LOGNORM.DIST
+// LOGNORMDIST
+// LOGNORM.INV
// LOOKUP
// LOWER
// MATCH
@@ -503,12 +550,17 @@ type formulaFuncs struct {
// MINUTE
// MIRR
// MOD
+// MODE
+// MODE.MULT
+// MODE.SNGL
// MONTH
// MROUND
// MULTINOMIAL
// MUNIT
// N
// NA
+// NEGBINOM.DIST
+// NEGBINOMDIST
// NOMINAL
// NORM.DIST
// NORMDIST
@@ -537,6 +589,7 @@ type formulaFuncs struct {
// PERCENTRANK
// PERMUT
// PERMUTATIONA
+// PHI
// PI
// PMT
// POISSON.DIST
@@ -574,6 +627,8 @@ type formulaFuncs struct {
// RRI
// SEC
// SECH
+// SECOND
+// SERIESSUM
// SHEET
// SHEETS
// SIGN
@@ -593,7 +648,12 @@ type formulaFuncs struct {
// SUBSTITUTE
// SUM
// SUMIF
+// SUMIFS
+// SUMPRODUCT
// SUMSQ
+// SUMX2MY2
+// SUMX2PY2
+// SUMXMY2
// SWITCH
// SYD
// T
@@ -602,14 +662,25 @@ type formulaFuncs struct {
// TBILLEQ
// TBILLPRICE
// TBILLYIELD
+// T.DIST
+// T.DIST.2T
+// T.DIST.RT
+// TDIST
// TEXTJOIN
// TIME
+// TIMEVALUE
+// T.INV
+// T.INV.2T
+// TINV
// TODAY
// TRANSPOSE
// TRIM
// TRIMMEAN
// TRUE
// TRUNC
+// T.TEST
+// TTEST
+// TYPE
// UNICHAR
// UNICODE
// UPPER
@@ -655,7 +726,7 @@ func (f *File) CalcCellValue(sheet, cell string) (result string, err error) {
}
result = token.TValue
isNum, precision := isNumeric(result)
- if isNum && precision > 15 {
+ if isNum && (precision > 15 || precision == 0) {
num := roundPrecision(result, -1)
result = strings.ToUpper(num)
}
@@ -798,6 +869,17 @@ func (f *File) evalInfixExp(sheet, cell string, tokens []efp.Token) (efp.Token,
}
}
+ if isEndParenthesesToken(token) && isBeginParenthesesToken(opftStack.Peek().(efp.Token)) {
+ if arg := argsStack.Peek().(*list.List).Back(); arg != nil {
+ opfdStack.Push(efp.Token{
+ TType: efp.TokenTypeOperand,
+ TSubType: efp.TokenSubTypeNumber,
+ TValue: arg.Value.(formulaArg).Value(),
+ })
+ argsStack.Peek().(*list.List).Remove(arg)
+ }
+ }
+
// check current token is opft
if err = f.parseToken(sheet, token, opfdStack, opftStack); err != nil {
return efp.Token{}, err
@@ -847,20 +929,7 @@ func (f *File) evalInfixExpFunc(sheet, cell string, token, nextToken efp.Token,
if !isFunctionStopToken(token) {
return nil
}
- // current token is function stop
- for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
- // calculate trigger
- topOpt := opftStack.Peek().(efp.Token)
- if err := calculate(opfdStack, topOpt); err != nil {
- return err
- }
- opftStack.Pop()
- }
-
- // push opfd to args
- if opfdStack.Len() > 0 {
- argsStack.Peek().(*list.List).PushBack(newStringFormulaArg(opfdStack.Pop().(efp.Token).TValue))
- }
+ prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack)
// call formula function to evaluate
arg := callFuncByName(&formulaFuncs{f: f, sheet: sheet, cell: cell}, strings.NewReplacer(
"_xlfn.", "", ".", "dot").Replace(opfStack.Peek().(efp.Token).TValue),
@@ -874,7 +943,11 @@ func (f *File) evalInfixExpFunc(sheet, cell string, token, nextToken efp.Token,
if opfStack.Len() > 0 { // still in function stack
if nextToken.TType == efp.TokenTypeOperatorInfix || (opftStack.Len() > 1 && opfdStack.Len() > 0) {
// mathematics calculate in formula function
- opfdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber})
+ if arg.Type == ArgError {
+ opfdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeError})
+ } else {
+ opfdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber})
+ }
} else {
argsStack.Peek().(*list.List).PushBack(arg)
}
@@ -884,6 +957,34 @@ func (f *File) evalInfixExpFunc(sheet, cell string, token, nextToken efp.Token,
return nil
}
+// prepareEvalInfixExp check the token and stack state for formula function
+// evaluate.
+func prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack *Stack) {
+ // current token is function stop
+ for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
+ // calculate trigger
+ topOpt := opftStack.Peek().(efp.Token)
+ if err := calculate(opfdStack, topOpt); err != nil {
+ argsStack.Peek().(*list.List).PushBack(newErrorFormulaArg(err.Error(), err.Error()))
+ opftStack.Pop()
+ continue
+ }
+ opftStack.Pop()
+ }
+ argument := true
+ if opftStack.Len() > 2 && opfdStack.Len() == 1 {
+ topOpt := opftStack.Pop()
+ if opftStack.Peek().(efp.Token).TType == efp.TokenTypeOperatorInfix {
+ argument = false
+ }
+ opftStack.Push(topOpt)
+ }
+ // push opfd to args
+ if argument && opfdStack.Len() > 0 {
+ argsStack.Peek().(*list.List).PushBack(newStringFormulaArg(opfdStack.Pop().(efp.Token).TValue))
+ }
+}
+
// calcPow evaluate exponentiation arithmetic operations.
func calcPow(rOpd, lOpd efp.Token, opdStack *Stack) error {
lOpdVal, err := strconv.ParseFloat(lOpd.TValue, 64)
@@ -1070,6 +1171,16 @@ func calculate(opdStack *Stack, opt efp.Token) error {
result := 0 - opdVal
opdStack.Push(efp.Token{TValue: fmt.Sprintf("%g", result), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber})
}
+ if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorInfix {
+ if opdStack.Len() < 2 {
+ return ErrInvalidFormula
+ }
+ rOpd := opdStack.Pop().(efp.Token)
+ lOpd := opdStack.Pop().(efp.Token)
+ if err := calcSubtract(rOpd, lOpd, opdStack); err != nil {
+ return err
+ }
+ }
tokenCalcFunc := map[string]func(rOpd, lOpd efp.Token, opdStack *Stack) error{
"^": calcPow,
"*": calcMultiply,
@@ -1083,16 +1194,6 @@ func calculate(opdStack *Stack, opt efp.Token) error {
">=": calcGe,
"&": calcSplice,
}
- if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorInfix {
- if opdStack.Len() < 2 {
- return ErrInvalidFormula
- }
- rOpd := opdStack.Pop().(efp.Token)
- lOpd := opdStack.Pop().(efp.Token)
- if err := calcSubtract(rOpd, lOpd, opdStack); err != nil {
- return err
- }
- }
fn, ok := tokenCalcFunc[opt.TValue]
if ok {
if opdStack.Len() < 2 {
@@ -1100,7 +1201,12 @@ func calculate(opdStack *Stack, opt efp.Token) error {
}
rOpd := opdStack.Pop().(efp.Token)
lOpd := opdStack.Pop().(efp.Token)
-
+ if rOpd.TSubType == efp.TokenSubTypeError {
+ return errors.New(rOpd.TValue)
+ }
+ if lOpd.TSubType == efp.TokenSubTypeError {
+ return errors.New(lOpd.TValue)
+ }
if err := fn(rOpd, lOpd, opdStack); err != nil {
return err
}
@@ -1164,32 +1270,11 @@ func isOperatorPrefixToken(token efp.Token) bool {
return (token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix) || (ok && token.TType == efp.TokenTypeOperatorInfix)
}
-// isOperand determine if the token is parse operand perand.
+// isOperand determine if the token is parse operand.
func isOperand(token efp.Token) bool {
return token.TType == efp.TokenTypeOperand && (token.TSubType == efp.TokenSubTypeNumber || token.TSubType == efp.TokenSubTypeText)
}
-// getDefinedNameRefTo convert defined name to reference range.
-func (f *File) getDefinedNameRefTo(definedNameName string, currentSheet string) (refTo string) {
- var workbookRefTo, worksheetRefTo string
- for _, definedName := range f.GetDefinedName() {
- if definedName.Name == definedNameName {
- // worksheet scope takes precedence over scope workbook when both definedNames exist
- if definedName.Scope == "Workbook" {
- workbookRefTo = definedName.RefersTo
- }
- if definedName.Scope == currentSheet {
- worksheetRefTo = definedName.RefersTo
- }
- }
- }
- refTo = workbookRefTo
- if worksheetRefTo != "" {
- refTo = worksheetRefTo
- }
- return
-}
-
// parseToken parse basic arithmetic operator priority and evaluate based on
// operators and operands.
func (f *File) parseToken(sheet string, token efp.Token, opdStack, optStack *Stack) error {
@@ -1377,7 +1462,7 @@ func (f *File) rangeResolver(cellRefs, cellRanges *list.List) (arg formulaArg, e
if cellRanges.Len() > 0 {
arg.Type = ArgMatrix
for row := valueRange[0]; row <= valueRange[1]; row++ {
- var matrixRow = []formulaArg{}
+ var matrixRow []formulaArg
for col := valueRange[2]; col <= valueRange[3]; col++ {
var cell, value string
if cell, err = CoordinatesToCellName(col, row); err != nil {
@@ -1473,7 +1558,7 @@ func formulaCriteriaParser(exp string) (fc *formulaCriteria) {
func formulaCriteriaEval(val string, criteria *formulaCriteria) (result bool, err error) {
var value, expected float64
var e error
- var prepareValue = func(val, cond string) (value float64, expected float64, err error) {
+ prepareValue := func(val, cond string) (value float64, expected float64, err error) {
if value, err = strconv.ParseFloat(val, 64); err != nil {
return
}
@@ -1554,10 +1639,11 @@ func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
n4++
n2 *= n4
t = result
+ r := x1 / n1 / n2
if modfied || add {
- result += (x1 / n1 / n2)
+ result += r
} else {
- result -= (x1 / n1 / n2)
+ result -= r
}
max--
add = !add
@@ -1904,9 +1990,9 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
if argsList.Len() > 3 {
return newErrorFormulaArg(formulaErrorVALUE, "COMPLEX allows at most 3 arguments")
}
- real, i, suffix := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber(), "i"
- if real.Type != ArgNumber {
- return real
+ realNum, i, suffix := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber(), "i"
+ if realNum.Type != ArgNumber {
+ return realNum
}
if i.Type != ArgNumber {
return i
@@ -1916,13 +2002,27 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(complex(real.Number, i.Number)), suffix))
+ return newStringFormulaArg(cmplx2str(complex(realNum.Number, i.Number), suffix))
}
// cmplx2str replace complex number string characters.
-func cmplx2str(c, suffix string) string {
- if c == "(0+0i)" || c == "(-0+0i)" || c == "(0-0i)" || c == "(-0-0i)" {
- return "0"
+func cmplx2str(num complex128, suffix string) string {
+ c := fmt.Sprint(num)
+ realPart, imagPart := fmt.Sprint(real(num)), fmt.Sprint(imag(num))
+ isNum, i := isNumeric(realPart)
+ if isNum && i > 15 {
+ realPart = roundPrecision(realPart, -1)
+ }
+ isNum, i = isNumeric(imagPart)
+ if isNum && i > 15 {
+ imagPart = roundPrecision(imagPart, -1)
+ }
+ c = realPart
+ if imag(num) > 0 {
+ c += "+"
+ }
+ if imag(num) != 0 {
+ c += imagPart + "i"
}
c = strings.TrimPrefix(c, "(")
c = strings.TrimPrefix(c, "+0+")
@@ -2137,7 +2237,7 @@ func (fn *formulaFuncs) ERFC(argsList *list.List) formulaArg {
return fn.erfc("ERFC", argsList)
}
-// ERFC.PRECISE function calculates the Complementary Error Function,
+// ERFCdotPRECISE function calculates the Complementary Error Function,
// integrated between a supplied lower limit and infinity. The syntax of the
// function is:
//
@@ -2256,7 +2356,8 @@ func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2272,7 +2373,8 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2288,7 +2390,8 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2304,11 +2407,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Conj(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Conj(inumber), value[len(value)-1:]))
}
// IMCOS function returns the cosine of a supplied complex number. The syntax
@@ -2320,11 +2424,12 @@ func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cos(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Cos(inumber), value[len(value)-1:]))
}
// IMCOSH function returns the hyperbolic cosine of a supplied complex number. The syntax
@@ -2336,11 +2441,12 @@ func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMCOSH requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cosh(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Cosh(inumber), value[len(value)-1:]))
}
// IMCOT function returns the cotangent of a supplied complex number. The syntax
@@ -2352,11 +2458,12 @@ func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMCOT requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cot(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Cot(inumber), value[len(value)-1:]))
}
// IMCSC function returns the cosecant of a supplied complex number. The syntax
@@ -2368,7 +2475,8 @@ func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMCSC requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2376,7 +2484,7 @@ func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMCSCH function returns the hyperbolic cosecant of a supplied complex
@@ -2388,7 +2496,8 @@ func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMCSCH requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2396,7 +2505,7 @@ func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMDIV function calculates the quotient of two complex numbers (i.e. divides
@@ -2408,7 +2517,8 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber1, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2420,7 +2530,7 @@ func (fn *formulaFuncs) IMDIV(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMEXP function returns the exponential of a supplied complex number. The
@@ -2432,11 +2542,12 @@ func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMEXP requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Exp(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Exp(inumber), value[len(value)-1:]))
}
// IMLN function returns the natural logarithm of a supplied complex number.
@@ -2448,7 +2559,8 @@ func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMLN requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2456,7 +2568,7 @@ func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMLOG10 function returns the common (base 10) logarithm of a supplied
@@ -2468,7 +2580,8 @@ func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "IMLOG10 requires 1 argument")
}
- inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2476,7 +2589,7 @@ func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMLOG2 function calculates the base 2 logarithm of a supplied complex
@@ -2488,7 +2601,8 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2496,7 +2610,7 @@ func (fn *formulaFuncs) IMLOG2(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num/cmplx.Log(2)), "i"))
+ return newStringFormulaArg(cmplx2str(num/cmplx.Log(2), value[len(value)-1:]))
}
// IMPOWER function returns a supplied complex number, raised to a given
@@ -2508,7 +2622,8 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
@@ -2523,7 +2638,7 @@ func (fn *formulaFuncs) IMPOWER(argsList *list.List) formulaArg {
if cmplx.IsInf(num) {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
+ return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
}
// IMPRODUCT function calculates the product of two or more complex numbers.
@@ -2562,7 +2677,7 @@ func (fn *formulaFuncs) IMPRODUCT(argsList *list.List) formulaArg {
}
}
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(product), "i"))
+ return newStringFormulaArg(cmplx2str(product, "i"))
}
// IMREAL function returns the real coefficient of a supplied complex number.
@@ -2574,11 +2689,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(real(inumber)), "i"))
+ return newStringFormulaArg(fmt.Sprint(real(inumber)))
}
// IMSEC function returns the secant of a supplied complex number. The syntax
@@ -2590,11 +2706,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(1/cmplx.Cos(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(1/cmplx.Cos(inumber), value[len(value)-1:]))
}
// IMSECH function returns the hyperbolic secant of a supplied complex number.
@@ -2606,11 +2723,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(1/cmplx.Cosh(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(1/cmplx.Cosh(inumber), value[len(value)-1:]))
}
// IMSIN function returns the Sine of a supplied complex number. The syntax of
@@ -2622,11 +2740,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Sin(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Sin(inumber), value[len(value)-1:]))
}
// IMSINH function returns the hyperbolic sine of a supplied complex number.
@@ -2638,11 +2757,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Sinh(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Sinh(inumber), value[len(value)-1:]))
}
// IMSQRT function returns the square root of a supplied complex number. The
@@ -2654,11 +2774,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Sqrt(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Sqrt(inumber), value[len(value)-1:]))
}
// IMSUB function calculates the difference between two complex numbers
@@ -2679,7 +2800,7 @@ func (fn *formulaFuncs) IMSUB(argsList *list.List) formulaArg {
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(i1-i2), "i"))
+ return newStringFormulaArg(cmplx2str(i1-i2, "i"))
}
// IMSUM function calculates the sum of two or more complex numbers. The
@@ -2700,7 +2821,7 @@ func (fn *formulaFuncs) IMSUM(argsList *list.List) formulaArg {
}
result += num
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(result), "i"))
+ return newStringFormulaArg(cmplx2str(result, "i"))
}
// IMTAN function returns the tangent of a supplied complex number. The syntax
@@ -2712,11 +2833,12 @@ 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)
+ value := argsList.Front().Value.(formulaArg).Value()
+ inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
if err != nil {
return newErrorFormulaArg(formulaErrorNUM, err.Error())
}
- return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Tan(inumber)), "i"))
+ return newStringFormulaArg(cmplx2str(cmplx.Tan(inumber), value[len(value)-1:]))
}
// OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2)
@@ -3385,7 +3507,7 @@ func (fn *formulaFuncs) DECIMAL(argsList *list.List) formulaArg {
if argsList.Len() != 2 {
return newErrorFormulaArg(formulaErrorVALUE, "DECIMAL requires 2 numeric arguments")
}
- var text = argsList.Front().Value.(formulaArg).String
+ text := argsList.Front().Value.(formulaArg).String
var radix int
var err error
radix, err = strconv.Atoi(argsList.Back().Value.(formulaArg).String)
@@ -3662,7 +3784,7 @@ func (fn *formulaFuncs) GCD(argsList *list.List) formulaArg {
}
var (
val float64
- nums = []float64{}
+ nums []float64
)
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
token := arg.Value.(formulaArg)
@@ -3779,7 +3901,7 @@ func (fn *formulaFuncs) LCM(argsList *list.List) formulaArg {
}
var (
val float64
- nums = []float64{}
+ nums []float64
err error
)
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
@@ -3884,12 +4006,12 @@ func (fn *formulaFuncs) LOG10(argsList *list.List) formulaArg {
// minor function implement a minor of a matrix A is the determinant of some
// smaller square matrix.
func minor(sqMtx [][]float64, idx int) [][]float64 {
- ret := [][]float64{}
+ var ret [][]float64
for i := range sqMtx {
if i == 0 {
continue
}
- row := []float64{}
+ var row []float64
for j := range sqMtx {
if j == idx {
continue
@@ -3926,7 +4048,7 @@ func det(sqMtx [][]float64) float64 {
func (fn *formulaFuncs) MDETERM(argsList *list.List) (result formulaArg) {
var (
num float64
- numMtx = [][]float64{}
+ numMtx [][]float64
err error
strMtx [][]formulaArg
)
@@ -3934,12 +4056,12 @@ func (fn *formulaFuncs) MDETERM(argsList *list.List) (result formulaArg) {
return newErrorFormulaArg(formulaErrorVALUE, "MDETERM requires at least 1 argument")
}
strMtx = argsList.Front().Value.(formulaArg).Matrix
- var rows = len(strMtx)
+ rows := len(strMtx)
for _, row := range argsList.Front().Value.(formulaArg).Matrix {
if len(row) != rows {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
- numRow := []float64{}
+ var numRow []float64
for _, ele := range row {
if num, err = strconv.ParseFloat(ele.String, 64); err != nil {
return newErrorFormulaArg(formulaErrorVALUE, err.Error())
@@ -4257,30 +4379,107 @@ type romanNumerals struct {
var romanTable = [][]romanNumerals{
{
- {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"},
- {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"},
+ {1000, "M"},
+ {900, "CM"},
+ {500, "D"},
+ {400, "CD"},
+ {100, "C"},
+ {90, "XC"},
+ {50, "L"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"},
},
{
- {1000, "M"}, {950, "LM"}, {900, "CM"}, {500, "D"}, {450, "LD"}, {400, "CD"},
- {100, "C"}, {95, "VC"}, {90, "XC"}, {50, "L"}, {45, "VL"}, {40, "XL"},
- {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"},
+ {1000, "M"},
+ {950, "LM"},
+ {900, "CM"},
+ {500, "D"},
+ {450, "LD"},
+ {400, "CD"},
+ {100, "C"},
+ {95, "VC"},
+ {90, "XC"},
+ {50, "L"},
+ {45, "VL"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"},
},
{
- {1000, "M"}, {990, "XM"}, {950, "LM"}, {900, "CM"}, {500, "D"}, {490, "XD"},
- {450, "LD"}, {400, "CD"}, {100, "C"}, {99, "IC"}, {90, "XC"}, {50, "L"},
- {45, "VL"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"},
+ {1000, "M"},
+ {990, "XM"},
+ {950, "LM"},
+ {900, "CM"},
+ {500, "D"},
+ {490, "XD"},
+ {450, "LD"},
+ {400, "CD"},
+ {100, "C"},
+ {99, "IC"},
+ {90, "XC"},
+ {50, "L"},
+ {45, "VL"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"},
},
{
- {1000, "M"}, {995, "VM"}, {990, "XM"}, {950, "LM"}, {900, "CM"}, {500, "D"},
- {495, "VD"}, {490, "XD"}, {450, "LD"}, {400, "CD"}, {100, "C"}, {99, "IC"},
- {90, "XC"}, {50, "L"}, {45, "VL"}, {40, "XL"}, {10, "X"}, {9, "IX"},
- {5, "V"}, {4, "IV"}, {1, "I"},
+ {1000, "M"},
+ {995, "VM"},
+ {990, "XM"},
+ {950, "LM"},
+ {900, "CM"},
+ {500, "D"},
+ {495, "VD"},
+ {490, "XD"},
+ {450, "LD"},
+ {400, "CD"},
+ {100, "C"},
+ {99, "IC"},
+ {90, "XC"},
+ {50, "L"},
+ {45, "VL"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"},
},
{
- {1000, "M"}, {999, "IM"}, {995, "VM"}, {990, "XM"}, {950, "LM"}, {900, "CM"},
- {500, "D"}, {499, "ID"}, {495, "VD"}, {490, "XD"}, {450, "LD"}, {400, "CD"},
- {100, "C"}, {99, "IC"}, {90, "XC"}, {50, "L"}, {45, "VL"}, {40, "XL"},
- {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"},
+ {1000, "M"},
+ {999, "IM"},
+ {995, "VM"},
+ {990, "XM"},
+ {950, "LM"},
+ {900, "CM"},
+ {500, "D"},
+ {499, "ID"},
+ {495, "VD"},
+ {490, "XD"},
+ {450, "LD"},
+ {400, "CD"},
+ {100, "C"},
+ {99, "IC"},
+ {90, "XC"},
+ {50, "L"},
+ {45, "VL"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"},
},
}
@@ -4464,6 +4663,40 @@ func (fn *formulaFuncs) SECH(argsList *list.List) formulaArg {
return newNumberFormulaArg(1 / math.Cosh(number.Number))
}
+// SERIESSUM function returns the sum of a power series. The syntax of the
+// function is:
+//
+// SERIESSUM(x,n,m,coefficients)
+//
+func (fn *formulaFuncs) SERIESSUM(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "SERIESSUM requires 4 arguments")
+ }
+ var x, n, m formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if n = argsList.Front().Next().Value.(formulaArg).ToNumber(); n.Type != ArgNumber {
+ return n
+ }
+ if m = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); m.Type != ArgNumber {
+ return m
+ }
+ var result, i float64
+ for _, coefficient := range argsList.Back().Value.(formulaArg).ToList() {
+ if coefficient.Value() == "" {
+ continue
+ }
+ num := coefficient.ToNumber()
+ if num.Type != ArgNumber {
+ return num
+ }
+ result += num.Number * math.Pow(x.Number, n.Number+(m.Number*i))
+ i++
+ }
+ return newNumberFormulaArg(result)
+}
+
// SIGN function returns the arithmetic sign (+1, -1 or 0) of a supplied
// number. I.e. if the number is positive, the Sign function returns +1, if
// the number is negative, the function returns -1 and if the number is 0
@@ -4595,9 +4828,9 @@ func (fn *formulaFuncs) STDEVA(argsList *list.List) formulaArg {
// calcStdevPow is part of the implementation stdev.
func calcStdevPow(result, count float64, n, m formulaArg) (float64, float64) {
if result == -1 {
- result = math.Pow((n.Number - m.Number), 2)
+ result = math.Pow(n.Number-m.Number, 2)
} else {
- result += math.Pow((n.Number - m.Number), 2)
+ result += math.Pow(n.Number-m.Number, 2)
}
count++
return result, count
@@ -4720,8 +4953,8 @@ func (fn *formulaFuncs) SUM(argsList *list.List) formulaArg {
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
token := arg.Value.(formulaArg)
switch token.Type {
- case ArgUnknown:
- continue
+ case ArgError:
+ return token
case ArgString:
if num := token.ToNumber(); num.Type == ArgNumber {
sum += num.Number
@@ -4751,8 +4984,8 @@ func (fn *formulaFuncs) SUMIF(argsList *list.List) formulaArg {
if argsList.Len() < 2 {
return newErrorFormulaArg(formulaErrorVALUE, "SUMIF requires at least 2 arguments")
}
- var criteria = formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg).String)
- var rangeMtx = argsList.Front().Value.(formulaArg).Matrix
+ criteria := formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg).String)
+ rangeMtx := argsList.Front().Value.(formulaArg).Matrix
var sumRange [][]formulaArg
if argsList.Len() == 3 {
sumRange = argsList.Back().Value.(formulaArg).Matrix
@@ -4784,6 +5017,99 @@ func (fn *formulaFuncs) SUMIF(argsList *list.List) formulaArg {
return newNumberFormulaArg(sum)
}
+// SUMIFS function finds values in one or more supplied arrays, that satisfy a
+// set of criteria, and returns the sum of the corresponding values in a
+// further supplied array. The syntax of the function is:
+//
+// SUMIFS(sum_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
+//
+func (fn *formulaFuncs) SUMIFS(argsList *list.List) formulaArg {
+ if argsList.Len() < 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "SUMIFS requires at least 3 arguments")
+ }
+ if argsList.Len()%2 != 1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ var args []formulaArg
+ sum, sumRange := 0.0, argsList.Front().Value.(formulaArg).Matrix
+ for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
+ args = append(args, arg.Value.(formulaArg))
+ }
+ for _, ref := range formulaIfsMatch(args) {
+ if num := sumRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber {
+ sum += num.Number
+ }
+ }
+ return newNumberFormulaArg(sum)
+}
+
+// sumproduct is an implementation of the formula function SUMPRODUCT.
+func (fn *formulaFuncs) sumproduct(argsList *list.List) formulaArg {
+ var (
+ argType ArgType
+ n int
+ res []float64
+ sum float64
+ )
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ token := arg.Value.(formulaArg)
+ if argType == ArgUnknown {
+ argType = token.Type
+ }
+ if token.Type != argType {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ switch token.Type {
+ case ArgString, ArgNumber:
+ if num := token.ToNumber(); num.Type == ArgNumber {
+ sum = fn.PRODUCT(argsList).Number
+ continue
+ }
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ case ArgMatrix:
+ args := token.ToList()
+ if res == nil {
+ n = len(args)
+ res = make([]float64, n)
+ for i := range res {
+ res[i] = 1.0
+ }
+ }
+ if len(args) != n {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ for i, value := range args {
+ num := value.ToNumber()
+ if num.Type != ArgNumber && value.Value() != "" {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ res[i] = res[i] * num.Number
+ }
+ }
+ }
+ for _, r := range res {
+ sum += r
+ }
+ return newNumberFormulaArg(sum)
+}
+
+// SUMPRODUCT function returns the sum of the products of the corresponding
+// values in a set of supplied arrays. The syntax of the function is:
+//
+// SUMPRODUCT(array1,[array2],[array3],...)
+//
+func (fn *formulaFuncs) SUMPRODUCT(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "SUMPRODUCT requires at least 1 argument")
+ }
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ if token := arg.Value.(formulaArg); token.Type == ArgError {
+ return token
+ }
+ }
+ return fn.sumproduct(argsList)
+}
+
// SUMSQ function returns the sum of squares of a supplied set of values. The
// syntax of the function is:
//
@@ -4822,6 +5148,63 @@ func (fn *formulaFuncs) SUMSQ(argsList *list.List) formulaArg {
return newNumberFormulaArg(sq)
}
+// sumx is an implementation of the formula functions SUMX2MY2, SUMX2PY2 and
+// SUMXMY2.
+func (fn *formulaFuncs) sumx(name string, argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 arguments", name))
+ }
+ array1 := argsList.Front().Value.(formulaArg)
+ array2 := argsList.Back().Value.(formulaArg)
+ left, right := array1.ToList(), array2.ToList()
+ n := len(left)
+ if n != len(right) {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ result := 0.0
+ for i := 0; i < n; i++ {
+ if lhs, rhs := left[i].ToNumber(), right[i].ToNumber(); lhs.Number != 0 && rhs.Number != 0 {
+ switch name {
+ case "SUMX2MY2":
+ result += lhs.Number*lhs.Number - rhs.Number*rhs.Number
+ case "SUMX2PY2":
+ result += lhs.Number*lhs.Number + rhs.Number*rhs.Number
+ default:
+ result += (lhs.Number - rhs.Number) * (lhs.Number - rhs.Number)
+ }
+ }
+ }
+ return newNumberFormulaArg(result)
+}
+
+// SUMX2MY2 function returns the sum of the differences of squares of two
+// supplied sets of values. The syntax of the function is:
+//
+// SUMX2MY2(array_x,array_y)
+//
+func (fn *formulaFuncs) SUMX2MY2(argsList *list.List) formulaArg {
+ return fn.sumx("SUMX2MY2", argsList)
+}
+
+// SUMX2PY2 function returns the sum of the sum of squares of two supplied sets
+// of values. The syntax of the function is:
+//
+// SUMX2PY2(array_x,array_y)
+//
+func (fn *formulaFuncs) SUMX2PY2(argsList *list.List) formulaArg {
+ return fn.sumx("SUMX2PY2", argsList)
+}
+
+// SUMXMY2 function returns the sum of the squares of differences between
+// corresponding values in two supplied arrays. The syntax of the function
+// is:
+//
+// SUMXMY2(array_x,array_y)
+//
+func (fn *formulaFuncs) SUMXMY2(argsList *list.List) formulaArg {
+ return fn.sumx("SUMXMY2", argsList)
+}
+
// TAN function calculates the tangent of a given angle. The syntax of the
// function is:
//
@@ -4923,7 +5306,7 @@ func (fn *formulaFuncs) AVEDEV(argsList *list.List) formulaArg {
// AVERAGE(number1,[number2],...)
//
func (fn *formulaFuncs) AVERAGE(argsList *list.List) formulaArg {
- args := []formulaArg{}
+ var args []formulaArg
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
@@ -4940,7 +5323,7 @@ func (fn *formulaFuncs) AVERAGE(argsList *list.List) formulaArg {
// AVERAGEA(number1,[number2],...)
//
func (fn *formulaFuncs) AVERAGEA(argsList *list.List) formulaArg {
- args := []formulaArg{}
+ var args []formulaArg
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
@@ -5002,522 +5385,2802 @@ func (fn *formulaFuncs) AVERAGEIF(argsList *list.List) formulaArg {
return newNumberFormulaArg(sum / count)
}
-// incompleteGamma is an implementation of the incomplete gamma function.
-func incompleteGamma(a, x float64) float64 {
- max := 32
- summer := 0.0
- for n := 0; n <= max; n++ {
- divisor := a
- for i := 1; i <= n; i++ {
- divisor *= (a + float64(i))
- }
- summer += math.Pow(x, float64(n)) / divisor
- }
- return math.Pow(x, a) * math.Exp(0-x) * summer
-}
-
-// CHIDIST function calculates the right-tailed probability of the chi-square
-// distribution. The syntax of the function is:
+// AVERAGEIFS function finds entries in one or more arrays, that satisfy a set
+// of supplied criteria, and returns the average (i.e. the statistical mean)
+// of the corresponding values in a further supplied array. The syntax of the
+// function is:
//
-// CHIDIST(x,degrees_freedom)
+// AVERAGEIFS(average_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
//
-func (fn *formulaFuncs) CHIDIST(argsList *list.List) formulaArg {
- if argsList.Len() != 2 {
- return newErrorFormulaArg(formulaErrorVALUE, "CHIDIST requires 2 numeric arguments")
+func (fn *formulaFuncs) AVERAGEIFS(argsList *list.List) formulaArg {
+ if argsList.Len() < 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "AVERAGEIFS requires at least 3 arguments")
}
- x := argsList.Front().Value.(formulaArg).ToNumber()
- if x.Type != ArgNumber {
- return x
+ if argsList.Len()%2 != 1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ var args []formulaArg
+ sum, sumRange := 0.0, argsList.Front().Value.(formulaArg).Matrix
+ for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
+ args = append(args, arg.Value.(formulaArg))
+ }
+ count := 0.0
+ for _, ref := range formulaIfsMatch(args) {
+ if num := sumRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber {
+ sum += num.Number
+ count++
+ }
}
- degress := argsList.Back().Value.(formulaArg).ToNumber()
- if degress.Type != ArgNumber {
- return degress
+ if count == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, "AVERAGEIF divide by zero")
}
- return newNumberFormulaArg(1 - (incompleteGamma(degress.Number/2, x.Number/2) / math.Gamma(degress.Number/2)))
+ return newNumberFormulaArg(sum / count)
}
-// confidence is an implementation of the formula functions CONFIDENCE and
-// CONFIDENCE.NORM.
-func (fn *formulaFuncs) confidence(name string, argsList *list.List) formulaArg {
- if argsList.Len() != 3 {
- return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 numeric arguments", name))
+// getBetaHelperContFrac continued fractions for the beta function.
+func getBetaHelperContFrac(fX, fA, fB float64) float64 {
+ var a1, b1, a2, b2, fnorm, cfnew, cf, rm float64
+ a1, b1, b2 = 1, 1, 1-(fA+fB)/(fA+1)*fX
+ if b2 == 0 {
+ a2, fnorm, cf = 0, 1, 1
+ } else {
+ a2, fnorm = 1, 1/b2
+ cf = a2 * fnorm
+ }
+ cfnew, rm = 1, 1
+ fMaxIter, fMachEps := 50000.0, 2.22045e-016
+ bfinished := false
+ for rm < fMaxIter && !bfinished {
+ apl2m := fA + 2*rm
+ d2m := rm * (fB - rm) * fX / ((apl2m - 1) * apl2m)
+ d2m1 := -(fA + rm) * (fA + fB + rm) * fX / (apl2m * (apl2m + 1))
+ a1 = (a2 + d2m*a1) * fnorm
+ b1 = (b2 + d2m*b1) * fnorm
+ a2 = a1 + d2m1*a2*fnorm
+ b2 = b1 + d2m1*b2*fnorm
+ if b2 != 0 {
+ fnorm = 1 / b2
+ cfnew = a2 * fnorm
+ bfinished = math.Abs(cf-cfnew) < math.Abs(cf)*fMachEps
+ }
+ cf = cfnew
+ rm += 1
+ }
+ return cf
+}
+
+// getLanczosSum uses a variant of the Lanczos sum with a rational function.
+func getLanczosSum(fZ float64) float64 {
+ num := []float64{
+ 23531376880.41075968857200767445163675473,
+ 42919803642.64909876895789904700198885093,
+ 35711959237.35566804944018545154716670596,
+ 17921034426.03720969991975575445893111267,
+ 6039542586.35202800506429164430729792107,
+ 1439720407.311721673663223072794912393972,
+ 248874557.8620541565114603864132294232163,
+ 31426415.58540019438061423162831820536287,
+ 2876370.628935372441225409051620849613599,
+ 186056.2653952234950402949897160456992822,
+ 8071.672002365816210638002902272250613822,
+ 210.8242777515793458725097339207133627117,
+ 2.506628274631000270164908177133837338626,
+ }
+ denom := []float64{
+ 0,
+ 39916800,
+ 120543840,
+ 150917976,
+ 105258076,
+ 45995730,
+ 13339535,
+ 2637558,
+ 357423,
+ 32670,
+ 1925,
+ 66,
+ 1,
+ }
+ var sumNum, sumDenom, zInv float64
+ if fZ <= 1 {
+ sumNum = num[12]
+ sumDenom = denom[12]
+ for i := 11; i >= 0; i-- {
+ sumNum *= fZ
+ sumNum += num[i]
+ sumDenom *= fZ
+ sumDenom += denom[i]
+ }
+ } else {
+ zInv = 1 / fZ
+ sumNum = num[0]
+ sumDenom = denom[0]
+ for i := 1; i <= 12; i++ {
+ sumNum *= zInv
+ sumNum += num[i]
+ sumDenom *= zInv
+ sumDenom += denom[i]
+ }
}
- alpha := argsList.Front().Value.(formulaArg).ToNumber()
- if alpha.Type != ArgNumber {
- return alpha
+ return sumNum / sumDenom
+}
+
+// getBeta return beta distribution.
+func getBeta(fAlpha, fBeta float64) float64 {
+ var fA, fB float64
+ if fAlpha > fBeta {
+ fA = fAlpha
+ fB = fBeta
+ } else {
+ fA = fBeta
+ fB = fAlpha
+ }
+ const maxGammaArgument = 171.624376956302
+ if fA+fB < maxGammaArgument {
+ return math.Gamma(fA) / math.Gamma(fA+fB) * math.Gamma(fB)
+ }
+ fg := 6.024680040776729583740234375
+ fgm := fg - 0.5
+ fLanczos := getLanczosSum(fA)
+ fLanczos /= getLanczosSum(fA + fB)
+ fLanczos *= getLanczosSum(fB)
+ fABgm := fA + fB + fgm
+ fLanczos *= math.Sqrt((fABgm / (fA + fgm)) / (fB + fgm))
+ fTempA := fB / (fA + fgm)
+ fTempB := fA / (fB + fgm)
+ fResult := math.Exp(-fA*math.Log1p(fTempA) - fB*math.Log1p(fTempB) - fgm)
+ fResult *= fLanczos
+ return fResult
+}
+
+// getBetaDistPDF is an implementation for the Beta probability density
+// function.
+func getBetaDistPDF(fX, fA, fB float64) float64 {
+ if fX <= 0 || fX >= 1 {
+ return 0
}
- if alpha.Number <= 0 || alpha.Number >= 1 {
- return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ fLogDblMax, fLogDblMin := math.Log(1.79769e+308), math.Log(2.22507e-308)
+ fLogY := math.Log(0.5 - fX + 0.5)
+ if fX < 0.1 {
+ fLogY = math.Log1p(-fX)
}
- stdDev := argsList.Front().Next().Value.(formulaArg).ToNumber()
- if stdDev.Type != ArgNumber {
- return stdDev
+ fLogX := math.Log(fX)
+ fAm1LogX := (fA - 1) * fLogX
+ fBm1LogY := (fB - 1) * fLogY
+ fLogBeta := getLogBeta(fA, fB)
+ if fAm1LogX < fLogDblMax && fAm1LogX > fLogDblMin && fBm1LogY < fLogDblMax &&
+ fBm1LogY > fLogDblMin && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin &&
+ fAm1LogX+fBm1LogY < fLogDblMax && fAm1LogX+fBm1LogY > fLogDblMin {
+ return math.Pow(fX, fA-1) * math.Pow(0.5-fX+0.5, fB-1) / getBeta(fA, fB)
}
- if stdDev.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ return math.Exp(fAm1LogX + fBm1LogY - fLogBeta)
+}
+
+// getLogBeta return beta with logarithm.
+func getLogBeta(fAlpha, fBeta float64) float64 {
+ var fA, fB float64
+ if fAlpha > fBeta {
+ fA, fB = fAlpha, fBeta
+ } else {
+ fA, fB = fBeta, fAlpha
+ }
+ fg := 6.024680040776729583740234375
+ fgm := fg - 0.5
+ fLanczos := getLanczosSum(fA)
+ fLanczos /= getLanczosSum(fA + fB)
+ fLanczos *= getLanczosSum(fB)
+ fLogLanczos := math.Log(fLanczos)
+ fABgm := fA + fB + fgm
+ fLogLanczos += 0.5 * (math.Log(fABgm) - math.Log(fA+fgm) - math.Log(fB+fgm))
+ fTempA := fB / (fA + fgm)
+ fTempB := fA / (fB + fgm)
+ fResult := -fA*math.Log1p(fTempA) - fB*math.Log1p(fTempB) - fgm
+ fResult += fLogLanczos
+ return fResult
+}
+
+// getBetaDist is an implementation for the beta distribution function.
+func getBetaDist(fXin, fAlpha, fBeta float64) float64 {
+ if fXin <= 0 {
+ return 0
}
- size := argsList.Back().Value.(formulaArg).ToNumber()
- if size.Type != ArgNumber {
- return size
+ if fXin >= 1 {
+ return 1
}
- if size.Number < 1 {
- return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ if fBeta == 1 {
+ return math.Pow(fXin, fAlpha)
+ }
+ if fAlpha == 1 {
+ return -math.Expm1(fBeta * math.Log1p(-fXin))
+ }
+ var fResult float64
+ fY, flnY := (0.5-fXin)+0.5, math.Log1p(-fXin)
+ fX, flnX := fXin, math.Log(fXin)
+ fA, fB := fAlpha, fBeta
+ bReflect := fXin > fAlpha/(fAlpha+fBeta)
+ if bReflect {
+ fA = fBeta
+ fB = fAlpha
+ fX = fY
+ fY = fXin
+ flnX = flnY
+ flnY = math.Log(fXin)
+ }
+ fResult = getBetaHelperContFrac(fX, fA, fB) / fA
+ fP, fQ := fA/(fA+fB), fB/(fA+fB)
+ var fTemp float64
+ if fA > 1 && fB > 1 && fP < 0.97 && fQ < 0.97 {
+ fTemp = getBetaDistPDF(fX, fA, fB) * fX * fY
+ } else {
+ fTemp = math.Exp(fA*flnX + fB*flnY - getLogBeta(fA, fB))
}
- args := list.New()
- args.Init()
- args.PushBack(newNumberFormulaArg(alpha.Number / 2))
- args.PushBack(newNumberFormulaArg(0))
- args.PushBack(newNumberFormulaArg(1))
- return newNumberFormulaArg(-fn.NORMINV(args).Number * (stdDev.Number / math.Sqrt(size.Number)))
+ fResult *= fTemp
+ if bReflect {
+ fResult = 0.5 - fResult + 0.5
+ }
+ return fResult
}
-// CONFIDENCE function uses a Normal Distribution to calculate a confidence
+// prepareBETAdotDISTArgs checking and prepare arguments for the formula
+// function BETA.DIST.
+func (fn *formulaFuncs) prepareBETAdotDISTArgs(argsList *list.List) formulaArg {
+ if argsList.Len() < 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BETA.DIST requires at least 4 arguments")
+ }
+ if argsList.Len() > 6 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BETA.DIST requires at most 6 arguments")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if alpha.Type != ArgNumber {
+ return alpha
+ }
+ beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
+ if beta.Type != ArgNumber {
+ return beta
+ }
+ if alpha.Number <= 0 || beta.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ cumulative := argsList.Front().Next().Next().Next().Value.(formulaArg).ToBool()
+ if cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
+ if argsList.Len() > 4 {
+ if a = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
+ return a
+ }
+ }
+ if argsList.Len() == 6 {
+ if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
+ return b
+ }
+ }
+ return newListFormulaArg([]formulaArg{x, alpha, beta, cumulative, a, b})
+}
+
+// BETAdotDIST function calculates the cumulative beta distribution function
+// or the probability density function of the Beta distribution, for a
+// supplied set of parameters. The syntax of the function is:
+//
+// BETA.DIST(x,alpha,beta,cumulative,[A],[B])
+//
+func (fn *formulaFuncs) BETAdotDIST(argsList *list.List) formulaArg {
+ args := fn.prepareBETAdotDISTArgs(argsList)
+ if args.Type != ArgList {
+ return args
+ }
+ x, alpha, beta, cumulative, a, b := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5]
+ if x.Number < a.Number || x.Number > b.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if a.Number == b.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ fScale := b.Number - a.Number
+ x.Number = (x.Number - a.Number) / fScale
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(getBetaDist(x.Number, alpha.Number, beta.Number))
+ }
+ return newNumberFormulaArg(getBetaDistPDF(x.Number, alpha.Number, beta.Number) / fScale)
+}
+
+// BETADIST function calculates the cumulative beta probability density
+// function for a supplied set of parameters. The syntax of the function is:
+//
+// BETADIST(x,alpha,beta,[A],[B])
+//
+func (fn *formulaFuncs) BETADIST(argsList *list.List) formulaArg {
+ if argsList.Len() < 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BETADIST requires at least 3 arguments")
+ }
+ if argsList.Len() > 5 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BETADIST requires at most 5 arguments")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if alpha.Type != ArgNumber {
+ return alpha
+ }
+ beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
+ if beta.Type != ArgNumber {
+ return beta
+ }
+ if alpha.Number <= 0 || beta.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
+ if argsList.Len() > 3 {
+ if a = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
+ return a
+ }
+ }
+ if argsList.Len() == 5 {
+ if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
+ return b
+ }
+ }
+ if x.Number < a.Number || x.Number > b.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if a.Number == b.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(getBetaDist((x.Number-a.Number)/(b.Number-a.Number), alpha.Number, beta.Number))
+}
+
+// d1mach returns double precision real machine constants.
+func d1mach(i int) float64 {
+ arr := []float64{
+ 2.2250738585072014e-308,
+ 1.7976931348623158e+308,
+ 1.1102230246251565e-16,
+ 2.2204460492503131e-16,
+ 0.301029995663981195,
+ }
+ if i > len(arr) {
+ return 0
+ }
+ return arr[i-1]
+}
+
+// chebyshevInit determines the number of terms for the double precision
+// orthogonal series "dos" needed to insure the error is no larger
+// than "eta". Ordinarily eta will be chosen to be one-tenth machine
+// precision.
+func chebyshevInit(nos int, eta float64, dos []float64) int {
+ i, e := 0, 0.0
+ if nos < 1 {
+ return 0
+ }
+ for ii := 1; ii <= nos; ii++ {
+ i = nos - ii
+ e += math.Abs(dos[i])
+ if e > eta {
+ return i
+ }
+ }
+ return i
+}
+
+// chebyshevEval evaluates the n-term Chebyshev series "a" at "x".
+func chebyshevEval(n int, x float64, a []float64) float64 {
+ if n < 1 || n > 1000 || x < -1.1 || x > 1.1 {
+ return math.NaN()
+ }
+ twox, b0, b1, b2 := x*2, 0.0, 0.0, 0.0
+ for i := 1; i <= n; i++ {
+ b2 = b1
+ b1 = b0
+ b0 = twox*b1 - b2 + a[n-i]
+ }
+ return (b0 - b2) * 0.5
+}
+
+// lgammacor is an implementation for the log(gamma) correction.
+func lgammacor(x float64) float64 {
+ algmcs := []float64{
+ 0.1666389480451863247205729650822, -0.1384948176067563840732986059135e-4,
+ 0.9810825646924729426157171547487e-8, -0.1809129475572494194263306266719e-10,
+ 0.6221098041892605227126015543416e-13, -0.3399615005417721944303330599666e-15,
+ 0.2683181998482698748957538846666e-17, -0.2868042435334643284144622399999e-19,
+ 0.3962837061046434803679306666666e-21, -0.6831888753985766870111999999999e-23,
+ 0.1429227355942498147573333333333e-24, -0.3547598158101070547199999999999e-26,
+ 0.1025680058010470912000000000000e-27, -0.3401102254316748799999999999999e-29,
+ 0.1276642195630062933333333333333e-30,
+ }
+ nalgm := chebyshevInit(15, d1mach(3), algmcs)
+ xbig := 1.0 / math.Sqrt(d1mach(3))
+ xmax := math.Exp(math.Min(math.Log(d1mach(2)/12.0), -math.Log(12.0*d1mach(1))))
+ if x < 10.0 {
+ return math.NaN()
+ } else if x >= xmax {
+ return 4.930380657631324e-32
+ } else if x < xbig {
+ tmp := 10.0 / x
+ return chebyshevEval(nalgm, tmp*tmp*2.0-1.0, algmcs) / x
+ }
+ return 1.0 / (x * 12.0)
+}
+
+// logrelerr compute the relative error logarithm.
+func logrelerr(x float64) float64 {
+ alnrcs := []float64{
+ 0.10378693562743769800686267719098e+1, -0.13364301504908918098766041553133,
+ 0.19408249135520563357926199374750e-1, -0.30107551127535777690376537776592e-2,
+ 0.48694614797154850090456366509137e-3, -0.81054881893175356066809943008622e-4,
+ 0.13778847799559524782938251496059e-4, -0.23802210894358970251369992914935e-5,
+ 0.41640416213865183476391859901989e-6, -0.73595828378075994984266837031998e-7,
+ 0.13117611876241674949152294345011e-7, -0.23546709317742425136696092330175e-8,
+ 0.42522773276034997775638052962567e-9, -0.77190894134840796826108107493300e-10,
+ 0.14075746481359069909215356472191e-10, -0.25769072058024680627537078627584e-11,
+ 0.47342406666294421849154395005938e-12, -0.87249012674742641745301263292675e-13,
+ 0.16124614902740551465739833119115e-13, -0.29875652015665773006710792416815e-14,
+ 0.55480701209082887983041321697279e-15, -0.10324619158271569595141333961932e-15,
+ 0.19250239203049851177878503244868e-16, -0.35955073465265150011189707844266e-17,
+ 0.67264542537876857892194574226773e-18, -0.12602624168735219252082425637546e-18,
+ 0.23644884408606210044916158955519e-19, -0.44419377050807936898878389179733e-20,
+ 0.83546594464034259016241293994666e-21, -0.15731559416479562574899253521066e-21,
+ 0.29653128740247422686154369706666e-22, -0.55949583481815947292156013226666e-23,
+ 0.10566354268835681048187284138666e-23, -0.19972483680670204548314999466666e-24,
+ 0.37782977818839361421049855999999e-25, -0.71531586889081740345038165333333e-26,
+ 0.13552488463674213646502024533333e-26, -0.25694673048487567430079829333333e-27,
+ 0.48747756066216949076459519999999e-28, -0.92542112530849715321132373333333e-29,
+ 0.17578597841760239233269760000000e-29, -0.33410026677731010351377066666666e-30,
+ 0.63533936180236187354180266666666e-31,
+ }
+ nlnrel := chebyshevInit(43, 0.1*d1mach(3), alnrcs)
+ if x <= -1 {
+ return math.NaN()
+ }
+ if math.Abs(x) <= 0.375 {
+ return x * (1.0 - x*chebyshevEval(nlnrel, x/0.375, alnrcs))
+ }
+ return math.Log(x + 1.0)
+}
+
+// logBeta is an implementation for the log of the beta distribution
+// function.
+func logBeta(a, b float64) float64 {
+ corr, p, q := 0.0, a, a
+ if b < p {
+ p = b
+ }
+ if b > q {
+ q = b
+ }
+ if p < 0 {
+ return math.NaN()
+ }
+ if p == 0 {
+ return math.MaxFloat64
+ }
+ if p >= 10.0 {
+ corr = lgammacor(p) + lgammacor(q) - lgammacor(p+q)
+ f1 := q * logrelerr(-p/(p+q))
+ return math.Log(q)*-0.5 + 0.918938533204672741780329736406 + corr + (p-0.5)*math.Log(p/(p+q)) + math.Nextafter(f1, f1)
+ }
+ if q >= 10 {
+ corr = lgammacor(q) - lgammacor(p+q)
+ val, _ := math.Lgamma(p)
+ return val + corr + p - p*math.Log(p+q) + (q-0.5)*logrelerr(-p/(p+q))
+ }
+ return math.Log(math.Gamma(p) * (math.Gamma(q) / math.Gamma(p+q)))
+}
+
+// pbetaRaw is a part of pbeta for the beta distribution.
+func pbetaRaw(alnsml, ans, eps, p, pin, q, sml, x, y float64) float64 {
+ if q > 1.0 {
+ xb := p*math.Log(y) + q*math.Log(1.0-y) - logBeta(p, q) - math.Log(q)
+ ib := int(math.Max(xb/alnsml, 0.0))
+ term := math.Exp(xb - float64(ib)*alnsml)
+ c := 1.0 / (1.0 - y)
+ p1 := q * c / (p + q - 1.0)
+ finsum := 0.0
+ n := int(q)
+ if q == float64(n) {
+ n = n - 1
+ }
+ for i := 1; i <= n; i++ {
+ if p1 <= 1 && term/eps <= finsum {
+ break
+ }
+ xi := float64(i)
+ term = (q - xi + 1.0) * c * term / (p + q - xi)
+ if term > 1.0 {
+ ib = ib - 1
+ term = term * sml
+ }
+ if ib == 0 {
+ finsum = finsum + term
+ }
+ }
+ ans = ans + finsum
+ }
+ if y != x || p != pin {
+ ans = 1.0 - ans
+ }
+ ans = math.Max(math.Min(ans, 1.0), 0.0)
+ return ans
+}
+
+// pbeta returns distribution function of the beta distribution.
+func pbeta(x, pin, qin float64) (ans float64) {
+ eps := d1mach(3)
+ alneps := math.Log(eps)
+ sml := d1mach(1)
+ alnsml := math.Log(sml)
+ y := x
+ p := pin
+ q := qin
+ if p/(p+q) < x {
+ y = 1.0 - y
+ p = qin
+ q = pin
+ }
+ if (p+q)*y/(p+1.0) < eps {
+ xb := p*math.Log(math.Max(y, sml)) - math.Log(p) - logBeta(p, q)
+ if xb > alnsml && y != 0.0 {
+ ans = math.Exp(xb)
+ }
+ if y != x || p != pin {
+ ans = 1.0 - ans
+ }
+ } else {
+ ps := q - math.Floor(q)
+ if ps == 0.0 {
+ ps = 1.0
+ }
+ xb := p*math.Log(y) - logBeta(ps, p) - math.Log(p)
+ if xb >= alnsml {
+ ans = math.Exp(xb)
+ term := ans * p
+ if ps != 1.0 {
+ n := int(math.Max(alneps/math.Log(y), 4.0))
+ for i := 1; i <= n; i++ {
+ xi := float64(i)
+ term = term * (xi - ps) * y / xi
+ ans = ans + term/(p+xi)
+ }
+ }
+ }
+ ans = pbetaRaw(alnsml, ans, eps, p, pin, q, sml, x, y)
+ }
+ return ans
+}
+
+// betainvProbIterator is a part of betainv for the inverse of the beta
+// function.
+func betainvProbIterator(alpha1, alpha3, beta1, beta2, beta3, logBeta, maxCumulative, prob1, prob2 float64) float64 {
+ var i, j, prev, prop4 float64
+ j = 1
+ for prob := 0; prob < 1000; prob++ {
+ prop3 := pbeta(beta3, alpha1, beta1)
+ prop3 = (prop3 - prob1) * math.Exp(logBeta+prob2*math.Log(beta3)+beta2*math.Log(1.0-beta3))
+ if prop3*prop4 <= 0 {
+ prev = math.Max(math.Abs(j), maxCumulative)
+ }
+ h := 1.0
+ for iteratorCount := 0; iteratorCount < 1000; iteratorCount++ {
+ j = h * prop3
+ if math.Abs(j) < prev {
+ i = beta3 - j
+ if i >= 0 && i <= 1.0 {
+ if prev <= alpha3 {
+ return beta3
+ }
+ if math.Abs(prop3) <= alpha3 {
+ return beta3
+ }
+ if i != 0 && i != 1.0 {
+ break
+ }
+ }
+ }
+ h /= 3.0
+ }
+ if i == beta3 {
+ return beta3
+ }
+ beta3, prop4 = i, prop3
+ }
+ return beta3
+}
+
+// calcBetainv is an implementation for the quantile of the beta
+// distribution.
+func calcBetainv(probability, alpha, beta, lower, upper float64) float64 {
+ minCumulative, maxCumulative := 1.0e-300, 3.0e-308
+ lowerBound, upperBound := maxCumulative, 1.0-2.22e-16
+ needSwap := false
+ var alpha1, alpha2, beta1, beta2, beta3, prob1, x, y float64
+ if probability <= 0.5 {
+ prob1, alpha1, beta1 = probability, alpha, beta
+ } else {
+ prob1, alpha1, beta1, needSwap = 1.0-probability, beta, alpha, true
+ }
+ logBetaNum := logBeta(alpha, beta)
+ prob2 := math.Sqrt(-math.Log(prob1 * prob1))
+ prob3 := prob2 - (prob2*0.27061+2.3075)/(prob2*(prob2*0.04481+0.99229)+1)
+ if alpha1 > 1 && beta1 > 1 {
+ alpha2, beta2, prob2 = 1/(alpha1+alpha1-1), 1/(beta1+beta1-1), (prob3*prob3-3)/6
+ x = 2 / (alpha2 + beta2)
+ y = prob3*math.Sqrt(x+prob2)/x - (beta2-alpha2)*(prob2+5/6.0-2/(x*3))
+ beta3 = alpha1 / (alpha1 + beta1*math.Exp(y+y))
+ } else {
+ beta2, prob2 = 1/(beta1*9), beta1+beta1
+ beta2 = prob2 * math.Pow(1-beta2+prob3*math.Sqrt(beta2), 3)
+ if beta2 <= 0 {
+ beta3 = 1 - math.Exp((math.Log((1-prob1)*beta1)+logBetaNum)/beta1)
+ } else {
+ beta2 = (prob2 + alpha1*4 - 2) / beta2
+ if beta2 <= 1 {
+ beta3 = math.Exp((logBetaNum + math.Log(alpha1*prob1)) / alpha1)
+ } else {
+ beta3 = 1 - 2/(beta2+1)
+ }
+ }
+ }
+ beta2, prob2 = 1-beta1, 1-alpha1
+ if beta3 < lowerBound {
+ beta3 = lowerBound
+ } else if beta3 > upperBound {
+ beta3 = upperBound
+ }
+ alpha3 := math.Max(minCumulative, math.Pow(10.0, -13.0-2.5/(alpha1*alpha1)-0.5/(prob1*prob1)))
+ beta3 = betainvProbIterator(alpha1, alpha3, beta1, beta2, beta3, logBetaNum, maxCumulative, prob1, prob2)
+ if needSwap {
+ beta3 = 1.0 - beta3
+ }
+ return (upper-lower)*beta3 + lower
+}
+
+// betainv is an implementation of the formula functions BETAINV and
+// BETA.INV.
+func (fn *formulaFuncs) betainv(name string, argsList *list.List) formulaArg {
+ if argsList.Len() < 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 3 arguments", name))
+ }
+ if argsList.Len() > 5 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at most 5 arguments", name))
+ }
+ probability := argsList.Front().Value.(formulaArg).ToNumber()
+ if probability.Type != ArgNumber {
+ return probability
+ }
+ if probability.Number <= 0 || probability.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if alpha.Type != ArgNumber {
+ return alpha
+ }
+ beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
+ if beta.Type != ArgNumber {
+ return beta
+ }
+ if alpha.Number <= 0 || beta.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
+ if argsList.Len() > 3 {
+ if a = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
+ return a
+ }
+ }
+ if argsList.Len() == 5 {
+ if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
+ return b
+ }
+ }
+ if a.Number == b.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(calcBetainv(probability.Number, alpha.Number, beta.Number, a.Number, b.Number))
+}
+
+// BETAINV function uses an iterative procedure to calculate the inverse of
+// the cumulative beta probability density function for a supplied
+// probability. The syntax of the function is:
+//
+// BETAINV(probability,alpha,beta,[A],[B])
+//
+func (fn *formulaFuncs) BETAINV(argsList *list.List) formulaArg {
+ return fn.betainv("BETAINV", argsList)
+}
+
+// BETAdotINV function uses an iterative procedure to calculate the inverse of
+// the cumulative beta probability density function for a supplied
+// probability. The syntax of the function is:
+//
+// BETA.INV(probability,alpha,beta,[A],[B])
+//
+func (fn *formulaFuncs) BETAdotINV(argsList *list.List) formulaArg {
+ return fn.betainv("BETA.INV", argsList)
+}
+
+// incompleteGamma is an implementation of the incomplete gamma function.
+func incompleteGamma(a, x float64) float64 {
+ max := 32
+ summer := 0.0
+ for n := 0; n <= max; n++ {
+ divisor := a
+ for i := 1; i <= n; i++ {
+ divisor *= a + float64(i)
+ }
+ summer += math.Pow(x, float64(n)) / divisor
+ }
+ return math.Pow(x, a) * math.Exp(0-x) * summer
+}
+
+// binomCoeff implement binomial coefficient calculation.
+func binomCoeff(n, k float64) float64 {
+ return fact(n) / (fact(k) * fact(n-k))
+}
+
+// binomdist implement binomial distribution calculation.
+func binomdist(x, n, p float64) float64 {
+ return binomCoeff(n, x) * math.Pow(p, x) * math.Pow(1-p, n-x)
+}
+
+// BINOMdotDIST function returns the Binomial Distribution probability for a
+// given number of successes from a specified number of trials. The syntax of
+// the function is:
+//
+// BINOM.DIST(number_s,trials,probability_s,cumulative)
+//
+func (fn *formulaFuncs) BINOMdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST requires 4 arguments")
+ }
+ return fn.BINOMDIST(argsList)
+}
+
+// BINOMDIST function returns the Binomial Distribution probability of a
+// specified number of successes out of a specified number of trials. The
+// syntax of the function is:
+//
+// BINOMDIST(number_s,trials,probability_s,cumulative)
+//
+func (fn *formulaFuncs) BINOMDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BINOMDIST requires 4 arguments")
+ }
+ var s, trials, probability, cumulative formulaArg
+ if s = argsList.Front().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
+ return s
+ }
+ if trials = argsList.Front().Next().Value.(formulaArg).ToNumber(); trials.Type != ArgNumber {
+ return trials
+ }
+ if s.Number < 0 || s.Number > trials.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if probability = argsList.Back().Prev().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+
+ if probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if cumulative.Number == 1 {
+ bm := 0.0
+ for i := 0; i <= int(s.Number); i++ {
+ bm += binomdist(float64(i), trials.Number, probability.Number)
+ }
+ return newNumberFormulaArg(bm)
+ }
+ return newNumberFormulaArg(binomdist(s.Number, trials.Number, probability.Number))
+}
+
+// BINOMdotDISTdotRANGE function returns the Binomial Distribution probability
+// for the number of successes from a specified number of trials falling into
+// a specified range.
+//
+// BINOM.DIST.RANGE(trials,probability_s,number_s,[number_s2])
+//
+func (fn *formulaFuncs) BINOMdotDISTdotRANGE(argsList *list.List) formulaArg {
+ if argsList.Len() < 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST.RANGE requires at least 3 arguments")
+ }
+ if argsList.Len() > 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST.RANGE requires at most 4 arguments")
+ }
+ trials := argsList.Front().Value.(formulaArg).ToNumber()
+ if trials.Type != ArgNumber {
+ return trials
+ }
+ probability := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if probability.Type != ArgNumber {
+ return probability
+ }
+ if probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ num1 := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
+ if num1.Type != ArgNumber {
+ return num1
+ }
+ if num1.Number < 0 || num1.Number > trials.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ num2 := num1
+ if argsList.Len() > 3 {
+ if num2 = argsList.Back().Value.(formulaArg).ToNumber(); num2.Type != ArgNumber {
+ return num2
+ }
+ }
+ if num2.Number < 0 || num2.Number > trials.Number {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ sum := 0.0
+ for i := num1.Number; i <= num2.Number; i++ {
+ sum += binomdist(i, trials.Number, probability.Number)
+ }
+ return newNumberFormulaArg(sum)
+}
+
+// binominv implement inverse of the binomial distribution calculation.
+func binominv(n, p, alpha float64) float64 {
+ q, i, sum, max := 1-p, 0.0, 0.0, 0.0
+ n = math.Floor(n)
+ if q > p {
+ factor := math.Pow(q, n)
+ sum = factor
+ for i = 0; i < n && sum < alpha; i++ {
+ factor *= (n - i) / (i + 1) * p / q
+ sum += factor
+ }
+ return i
+ }
+ factor := math.Pow(p, n)
+ sum, max = 1-factor, n
+ for i = 0; i < max && sum >= alpha; i++ {
+ factor *= (n - i) / (i + 1) * q / p
+ sum -= factor
+ }
+ return n - i
+}
+
+// BINOMdotINV function returns the inverse of the Cumulative Binomial
+// Distribution. The syntax of the function is:
+//
+// BINOM.INV(trials,probability_s,alpha)
+//
+func (fn *formulaFuncs) BINOMdotINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "BINOM.INV requires 3 numeric arguments")
+ }
+ trials := argsList.Front().Value.(formulaArg).ToNumber()
+ if trials.Type != ArgNumber {
+ return trials
+ }
+ if trials.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ probability := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if probability.Type != ArgNumber {
+ return probability
+ }
+ if probability.Number <= 0 || probability.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ alpha := argsList.Back().Value.(formulaArg).ToNumber()
+ if alpha.Type != ArgNumber {
+ return alpha
+ }
+ if alpha.Number <= 0 || alpha.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(binominv(trials.Number, probability.Number, alpha.Number))
+}
+
+// CHIDIST function calculates the right-tailed probability of the chi-square
+// distribution. The syntax of the function is:
+//
+// CHIDIST(x,degrees_freedom)
+//
+func (fn *formulaFuncs) CHIDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHIDIST requires 2 numeric arguments")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ degrees := argsList.Back().Value.(formulaArg).ToNumber()
+ if degrees.Type != ArgNumber {
+ return degrees
+ }
+ logSqrtPi, sqrtPi := math.Log(math.Sqrt(math.Pi)), 1/math.Sqrt(math.Pi)
+ var e, s, z, c, y float64
+ a, x1, even := x.Number/2, x.Number, int(degrees.Number)%2 == 0
+ if degrees.Number > 1 {
+ y = math.Exp(-a)
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg(-math.Sqrt(x1)))
+ o := fn.NORMSDIST(args)
+ s = 2 * o.Number
+ if even {
+ s = y
+ }
+ if degrees.Number > 2 {
+ x1 = (degrees.Number - 1) / 2
+ z = 0.5
+ if even {
+ z = 1
+ }
+ if a > 20 {
+ e = logSqrtPi
+ if even {
+ e = 0
+ }
+ c = math.Log(a)
+ for z <= x1 {
+ e = math.Log(z) + e
+ s += math.Exp(c*z - a - e)
+ z += 1
+ }
+ return newNumberFormulaArg(s)
+ }
+ e = sqrtPi / math.Sqrt(a)
+ if even {
+ e = 1
+ }
+ c = 0
+ for z <= x1 {
+ e = e * (a / z)
+ c = c + e
+ z += 1
+ }
+ return newNumberFormulaArg(c*y + s)
+ }
+ return newNumberFormulaArg(s)
+}
+
+// CHIINV function calculates the inverse of the right-tailed probability of
+// the Chi-Square Distribution. The syntax of the function is:
+//
+// CHIINV(probability,deg_freedom)
+//
+func (fn *formulaFuncs) CHIINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHIINV requires 2 numeric arguments")
+ }
+ probability := argsList.Front().Value.(formulaArg).ToNumber()
+ if probability.Type != ArgNumber {
+ return probability
+ }
+ if probability.Number <= 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ deg := argsList.Back().Value.(formulaArg).ToNumber()
+ if deg.Type != ArgNumber {
+ return deg
+ }
+ if deg.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(gammainv(1-probability.Number, 0.5*deg.Number, 2.0))
+}
+
+// CHITEST function uses the chi-square test to calculate the probability that
+// the differences between two supplied data sets (of observed and expected
+// frequencies), are likely to be simply due to sampling error, or if they are
+// likely to be real. The syntax of the function is:
+//
+// CHITEST(actual_range,expected_range)
+//
+func (fn *formulaFuncs) CHITEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHITEST requires 2 arguments")
+ }
+ actual, expected := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
+ actualList, expectedList := actual.ToList(), expected.ToList()
+ rows := len(actual.Matrix)
+ columns := len(actualList) / rows
+ if len(actualList) != len(expectedList) || len(actualList) == 1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ var result float64
+ var degrees int
+ for i := 0; i < len(actualList); i++ {
+ a, e := actualList[i].ToNumber(), expectedList[i].ToNumber()
+ if a.Type == ArgNumber && e.Type == ArgNumber {
+ if e.Number == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ if e.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ result += (a.Number - e.Number) * (a.Number - e.Number) / e.Number
+ }
+ }
+ if rows == 1 {
+ degrees = columns - 1
+ } else if columns == 1 {
+ degrees = rows - 1
+ } else {
+ degrees = (columns - 1) * (rows - 1)
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg(result))
+ args.PushBack(newNumberFormulaArg(float64(degrees)))
+ return fn.CHIDIST(args)
+}
+
+// getGammaSeries calculates a power-series of the gamma function.
+func getGammaSeries(fA, fX float64) float64 {
+ var (
+ fHalfMachEps = 2.22045e-016 / 2
+ fDenomfactor = fA
+ fSummand = 1 / fA
+ fSum = fSummand
+ nCount = 1
+ )
+ for fSummand/fSum > fHalfMachEps && nCount <= 10000 {
+ fDenomfactor = fDenomfactor + 1
+ fSummand = fSummand * fX / fDenomfactor
+ fSum = fSum + fSummand
+ nCount = nCount + 1
+ }
+ return fSum
+}
+
+// getGammaContFraction returns continued fraction with odd items of the gamma
+// function.
+func getGammaContFraction(fA, fX float64) float64 {
+ var (
+ fBigInv = 2.22045e-016
+ fHalfMachEps = fBigInv / 2
+ fBig = 1 / fBigInv
+ fCount = 0.0
+ fY = 1 - fA
+ fDenom = fX + 2 - fA
+ fPkm1 = fX + 1
+ fPkm2 = 1.0
+ fQkm1 = fDenom * fX
+ fQkm2 = fX
+ fApprox = fPkm1 / fQkm1
+ bFinished = false
+ )
+ for !bFinished && fCount < 10000 {
+ fCount = fCount + 1
+ fY = fY + 1
+ fDenom = fDenom + 2
+ var (
+ fNum = fY * fCount
+ f1 = fPkm1 * fDenom
+ f2 = fPkm2 * fNum
+ fPk = math.Nextafter(f1, f1) - math.Nextafter(f2, f2)
+ f3 = fQkm1 * fDenom
+ f4 = fQkm2 * fNum
+ fQk = math.Nextafter(f3, f3) - math.Nextafter(f4, f4)
+ )
+ if fQk != 0 {
+ fR := fPk / fQk
+ bFinished = math.Abs((fApprox-fR)/fR) <= fHalfMachEps
+ fApprox = fR
+ }
+ fPkm2, fPkm1, fQkm2, fQkm1 = fPkm1, fPk, fQkm1, fQk
+ if math.Abs(fPk) > fBig {
+ // reduce a fraction does not change the value
+ fPkm2 = fPkm2 * fBigInv
+ fPkm1 = fPkm1 * fBigInv
+ fQkm2 = fQkm2 * fBigInv
+ fQkm1 = fQkm1 * fBigInv
+ }
+ }
+ return fApprox
+}
+
+// getLogGammaHelper is a part of implementation of the function getLogGamma.
+func getLogGammaHelper(fZ float64) float64 {
+ _fg := 6.024680040776729583740234375
+ zgHelp := fZ + _fg - 0.5
+ return math.Log(getLanczosSum(fZ)) + (fZ-0.5)*math.Log(zgHelp) - zgHelp
+}
+
+// getGammaHelper is a part of implementation of the function getLogGamma.
+func getGammaHelper(fZ float64) float64 {
+ var (
+ gamma = getLanczosSum(fZ)
+ fg = 6.024680040776729583740234375
+ zgHelp = fZ + fg - 0.5
+ // avoid intermediate overflow
+ halfpower = math.Pow(zgHelp, fZ/2-0.25)
+ )
+ gamma *= halfpower
+ gamma /= math.Exp(zgHelp)
+ gamma *= halfpower
+ if fZ <= 20 && fZ == math.Floor(fZ) {
+ gamma = math.Round(gamma)
+ }
+ return gamma
+}
+
+// getLogGamma calculates the natural logarithm of the gamma function.
+func getLogGamma(fZ float64) float64 {
+ fMaxGammaArgument := 171.624376956302
+ if fZ >= fMaxGammaArgument {
+ return getLogGammaHelper(fZ)
+ }
+ if fZ >= 1.0 {
+ return math.Log(getGammaHelper(fZ))
+ }
+ if fZ >= 0.5 {
+ return math.Log(getGammaHelper(fZ+1) / fZ)
+ }
+ return getLogGammaHelper(fZ+2) - math.Log(fZ+1) - math.Log(fZ)
+}
+
+// getLowRegIGamma returns lower regularized incomplete gamma function.
+func getLowRegIGamma(fA, fX float64) float64 {
+ fLnFactor := fA*math.Log(fX) - fX - getLogGamma(fA)
+ fFactor := math.Exp(fLnFactor)
+ if fX > fA+1 {
+ return 1 - fFactor*getGammaContFraction(fA, fX)
+ }
+ return fFactor * getGammaSeries(fA, fX)
+}
+
+// getChiSqDistCDF returns left tail for the Chi-Square distribution.
+func getChiSqDistCDF(fX, fDF float64) float64 {
+ if fX <= 0 {
+ return 0
+ }
+ return getLowRegIGamma(fDF/2, fX/2)
+}
+
+// getChiSqDistPDF calculates the probability density function for the
+// Chi-Square distribution.
+func getChiSqDistPDF(fX, fDF float64) float64 {
+ if fDF*fX > 1391000 {
+ return math.Exp((0.5*fDF-1)*math.Log(fX*0.5) - 0.5*fX - math.Log(2) - getLogGamma(0.5*fDF))
+ }
+ var fCount, fValue float64
+ if math.Mod(fDF, 2) < 0.5 {
+ fValue = 0.5
+ fCount = 2
+ } else {
+ fValue = 1 / math.Sqrt(fX*2*math.Pi)
+ fCount = 1
+ }
+ for fCount < fDF {
+ fValue *= fX / fCount
+ fCount += 2
+ }
+ if fX >= 1425 {
+ fValue = math.Exp(math.Log(fValue) - fX/2)
+ } else {
+ fValue *= math.Exp(-fX / 2)
+ }
+ return fValue
+}
+
+// CHISQdotDIST function calculates the Probability Density Function or the
+// Cumulative Distribution Function for the Chi-Square Distribution. The
+// syntax of the function is:
+//
+// CHISQ.DIST(x,degrees_freedom,cumulative)
+//
+func (fn *formulaFuncs) CHISQdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.DIST requires 3 arguments")
+ }
+ var x, degrees, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if x.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ maxDeg := math.Pow10(10)
+ if degrees.Number < 1 || degrees.Number >= maxDeg {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(getChiSqDistCDF(x.Number, degrees.Number))
+ }
+ return newNumberFormulaArg(getChiSqDistPDF(x.Number, degrees.Number))
+}
+
+// CHISQdotDISTdotRT function calculates the right-tailed probability of the
+// Chi-Square Distribution. The syntax of the function is:
+//
+// CHISQ.DIST.RT(x,degrees_freedom)
+//
+func (fn *formulaFuncs) CHISQdotDISTdotRT(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.DIST.RT requires 2 numeric arguments")
+ }
+ return fn.CHIDIST(argsList)
+}
+
+// CHISQdotTEST function performs the chi-square test on two supplied data sets
+// (of observed and expected frequencies), and returns the probability that
+// the differences between the sets are simply due to sampling error. The
+// syntax of the function is:
+//
+// CHISQ.TEST(actual_range,expected_range)
+//
+func (fn *formulaFuncs) CHISQdotTEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.TEST requires 2 arguments")
+ }
+ return fn.CHITEST(argsList)
+}
+
+// hasChangeOfSign check if the sign has been changed.
+func hasChangeOfSign(u, w float64) bool {
+ return (u < 0 && w > 0) || (u > 0 && w < 0)
+}
+
+// calcInverseIterator directly maps the required parameters for inverse
+// distribution functions.
+type calcInverseIterator struct {
+ name string
+ fp, fDF, nT float64
+}
+
+// callBack implements the callback function for the inverse iterator.
+func (iterator *calcInverseIterator) callBack(x float64) float64 {
+ if iterator.name == "CHISQ.INV" {
+ return iterator.fp - getChiSqDistCDF(x, iterator.fDF)
+ }
+ return iterator.fp - getTDist(x, iterator.fDF, iterator.nT)
+}
+
+// inverseQuadraticInterpolation inverse quadratic interpolation with
+// additional brackets.
+func inverseQuadraticInterpolation(iterator calcInverseIterator, fAx, fAy, fBx, fBy float64) float64 {
+ fYEps := 1.0e-307
+ fXEps := 2.22045e-016
+ fPx, fPy, fQx, fQy, fRx, fRy := fAx, fAy, fBx, fBy, fAx, fAy
+ fSx := 0.5 * (fAx + fBx)
+ bHasToInterpolate := true
+ nCount := 0
+ for nCount < 500 && math.Abs(fRy) > fYEps && (fBx-fAx) > math.Max(math.Abs(fAx), math.Abs(fBx))*fXEps {
+ if bHasToInterpolate {
+ if fPy != fQy && fQy != fRy && fRy != fPy {
+ fSx = fPx*fRy*fQy/(fRy-fPy)/(fQy-fPy) + fRx*fQy*fPy/(fQy-fRy)/(fPy-fRy) +
+ fQx*fPy*fRy/(fPy-fQy)/(fRy-fQy)
+ bHasToInterpolate = (fAx < fSx) && (fSx < fBx)
+ } else {
+ bHasToInterpolate = false
+ }
+ }
+ if !bHasToInterpolate {
+ fSx = 0.5 * (fAx + fBx)
+ fQx, fQy = fBx, fBy
+ bHasToInterpolate = true
+ }
+ fPx, fQx, fRx, fPy, fQy = fQx, fRx, fSx, fQy, fRy
+ fRy = iterator.callBack(fSx)
+ if hasChangeOfSign(fAy, fRy) {
+ fBx, fBy = fRx, fRy
+ } else {
+ fAx, fAy = fRx, fRy
+ }
+ bHasToInterpolate = bHasToInterpolate && (math.Abs(fRy)*2 <= math.Abs(fQy))
+ nCount++
+ }
+ return fRx
+}
+
+// calcIterateInverse function calculates the iteration for inverse
+// distributions.
+func calcIterateInverse(iterator calcInverseIterator, fAx, fBx float64) float64 {
+ fAy, fBy := iterator.callBack(fAx), iterator.callBack(fBx)
+ var fTemp float64
+ var nCount int
+ for nCount = 0; nCount < 1000 && !hasChangeOfSign(fAy, fBy); nCount++ {
+ if math.Abs(fAy) <= math.Abs(fBy) {
+ fTemp = fAx
+ fAx += 2 * (fAx - fBx)
+ if fAx < 0 {
+ fAx = 0
+ }
+ fBx = fTemp
+ fBy = fAy
+ fAy = iterator.callBack(fAx)
+ } else {
+ fTemp = fBx
+ fBx += 2 * (fBx - fAx)
+ fAx = fTemp
+ fAy = fBy
+ fBy = iterator.callBack(fBx)
+ }
+ }
+ if fAy == 0 || fBy == 0 {
+ return 0
+ }
+ return inverseQuadraticInterpolation(iterator, fAx, fAy, fBx, fBy)
+}
+
+// CHISQdotINV function calculates the inverse of the left-tailed probability
+// of the Chi-Square Distribution. The syntax of the function is:
+//
+// CHISQ.INV(probability,degrees_freedom)
+//
+func (fn *formulaFuncs) CHISQdotINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.INV requires 2 numeric arguments")
+ }
+ var probability, degrees formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if probability.Number < 0 || probability.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if degrees.Number < 1 || degrees.Number > math.Pow10(10) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
+ name: "CHISQ.INV",
+ fp: probability.Number,
+ fDF: degrees.Number,
+ }, degrees.Number/2, degrees.Number))
+}
+
+// CHISQdotINVdotRT function calculates the inverse of the right-tailed
+// probability of the Chi-Square Distribution. The syntax of the function is:
+//
+// CHISQ.INV.RT(probability,degrees_freedom)
+//
+func (fn *formulaFuncs) CHISQdotINVdotRT(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.INV.RT requires 2 numeric arguments")
+ }
+ return fn.CHIINV(argsList)
+}
+
+// confidence is an implementation of the formula functions CONFIDENCE and
+// CONFIDENCE.NORM.
+func (fn *formulaFuncs) confidence(name string, argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 numeric arguments", name))
+ }
+ alpha := argsList.Front().Value.(formulaArg).ToNumber()
+ if alpha.Type != ArgNumber {
+ return alpha
+ }
+ if alpha.Number <= 0 || alpha.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ stdDev := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if stdDev.Type != ArgNumber {
+ return stdDev
+ }
+ if stdDev.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ size := argsList.Back().Value.(formulaArg).ToNumber()
+ if size.Type != ArgNumber {
+ return size
+ }
+ if size.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ args := list.New()
+ args.Init()
+ args.PushBack(newNumberFormulaArg(alpha.Number / 2))
+ args.PushBack(newNumberFormulaArg(0))
+ args.PushBack(newNumberFormulaArg(1))
+ return newNumberFormulaArg(-fn.NORMINV(args).Number * (stdDev.Number / math.Sqrt(size.Number)))
+}
+
+// CONFIDENCE function uses a Normal Distribution to calculate a confidence
// value that can be used to construct the Confidence Interval for a
-// population mean, for a supplied probablity and sample size. It is assumed
+// population mean, for a supplied probability and sample size. It is assumed
// that the standard deviation of the population is known. The syntax of the
// function is:
//
-// CONFIDENCE(alpha,standard_dev,size)
+// CONFIDENCE(alpha,standard_dev,size)
+//
+func (fn *formulaFuncs) CONFIDENCE(argsList *list.List) formulaArg {
+ return fn.confidence("CONFIDENCE", argsList)
+}
+
+// CONFIDENCEdotNORM function uses a Normal Distribution to calculate a
+// confidence value that can be used to construct the confidence interval for
+// a population mean, for a supplied probability and sample size. It is
+// assumed that the standard deviation of the population is known. The syntax
+// of the function is:
+//
+// CONFIDENCE.NORM(alpha,standard_dev,size)
+//
+func (fn *formulaFuncs) CONFIDENCEdotNORM(argsList *list.List) formulaArg {
+ return fn.confidence("CONFIDENCE.NORM", argsList)
+}
+
+// CONFIDENCEdotT function uses a Student's T-Distribution to calculate a
+// confidence value that can be used to construct the confidence interval for
+// a population mean, for a supplied probablity and supplied sample size. It
+// is assumed that the standard deviation of the population is known. The
+// syntax of the function is:
+//
+// CONFIDENCE.T(alpha,standard_dev,size)
+//
+func (fn *formulaFuncs) CONFIDENCEdotT(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CONFIDENCE.T requires 3 arguments")
+ }
+ var alpha, standardDev, size formulaArg
+ if alpha = argsList.Front().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
+ return alpha
+ }
+ if standardDev = argsList.Front().Next().Value.(formulaArg).ToNumber(); standardDev.Type != ArgNumber {
+ return standardDev
+ }
+ if size = argsList.Back().Value.(formulaArg).ToNumber(); size.Type != ArgNumber {
+ return size
+ }
+ if alpha.Number <= 0 || alpha.Number >= 1 || standardDev.Number <= 0 || size.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if size.Number == 1 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ return newNumberFormulaArg(standardDev.Number * calcIterateInverse(calcInverseIterator{
+ name: "CONFIDENCE.T",
+ fp: alpha.Number,
+ fDF: size.Number - 1,
+ nT: 2,
+ }, size.Number/2, size.Number) / math.Sqrt(size.Number))
+}
+
+// COVAR function calculates the covariance of two supplied sets of values. The
+// syntax of the function is:
+//
+// COVAR(array1,array2)
+//
+func (fn *formulaFuncs) COVAR(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "COVAR requires 2 arguments")
+ }
+ array1 := argsList.Front().Value.(formulaArg)
+ array2 := argsList.Back().Value.(formulaArg)
+ left, right := array1.ToList(), array2.ToList()
+ n := len(left)
+ if n != len(right) {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ l1, l2 := list.New(), list.New()
+ l1.PushBack(array1)
+ l2.PushBack(array2)
+ result, skip := 0.0, 0
+ mean1, mean2 := fn.AVERAGE(l1), fn.AVERAGE(l2)
+ for i := 0; i < n; i++ {
+ arg1 := left[i].ToNumber()
+ arg2 := right[i].ToNumber()
+ if arg1.Type == ArgError || arg2.Type == ArgError {
+ skip++
+ continue
+ }
+ result += (arg1.Number - mean1.Number) * (arg2.Number - mean2.Number)
+ }
+ return newNumberFormulaArg(result / float64(n-skip))
+}
+
+// COVARIANCEdotP function calculates the population covariance of two supplied
+// sets of values. The syntax of the function is:
+//
+// COVARIANCE.P(array1,array2)
+//
+func (fn *formulaFuncs) COVARIANCEdotP(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "COVARIANCE.P requires 2 arguments")
+ }
+ return fn.COVAR(argsList)
+}
+
+// calcStringCountSum is part of the implementation countSum.
+func calcStringCountSum(countText bool, count, sum float64, num, arg formulaArg) (float64, float64) {
+ if countText && num.Type == ArgError && arg.String != "" {
+ count++
+ }
+ if num.Type == ArgNumber {
+ sum += num.Number
+ count++
+ }
+ return count, sum
+}
+
+// countSum get count and sum for a formula arguments array.
+func (fn *formulaFuncs) countSum(countText bool, args []formulaArg) (count, sum float64) {
+ for _, arg := range args {
+ switch arg.Type {
+ case ArgNumber:
+ if countText || !arg.Boolean {
+ sum += arg.Number
+ count++
+ }
+ case ArgString:
+ if !countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
+ continue
+ } else if countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
+ num := arg.ToBool()
+ if num.Type == ArgNumber {
+ count++
+ sum += num.Number
+ continue
+ }
+ }
+ num := arg.ToNumber()
+ count, sum = calcStringCountSum(countText, count, sum, num, arg)
+ case ArgList, ArgMatrix:
+ cnt, summary := fn.countSum(countText, arg.ToList())
+ sum += summary
+ count += cnt
+ }
+ }
+ return
+}
+
+// CORREL function calculates the Pearson Product-Moment Correlation
+// Coefficient for two sets of values. The syntax of the function is:
+//
+// CORREL(array1,array2)
+//
+func (fn *formulaFuncs) CORREL(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CORREL requires 2 arguments")
+ }
+ array1 := argsList.Front().Value.(formulaArg)
+ array2 := argsList.Back().Value.(formulaArg)
+ left, right := array1.ToList(), array2.ToList()
+ n := len(left)
+ if n != len(right) {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ l1, l2, l3 := list.New(), list.New(), list.New()
+ for i := 0; i < n; i++ {
+ if lhs, rhs := left[i].ToNumber(), right[i].ToNumber(); lhs.Number != 0 && rhs.Number != 0 {
+ l1.PushBack(lhs)
+ l2.PushBack(rhs)
+ }
+ }
+ stdev1, stdev2 := fn.STDEV(l1), fn.STDEV(l2)
+ if stdev1.Number == 0 || stdev2.Number == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ mean1, mean2, skip := fn.AVERAGE(l1), fn.AVERAGE(l2), 0
+ for i := 0; i < n; i++ {
+ lhs, rhs := left[i].ToNumber(), right[i].ToNumber()
+ if lhs.Number == 0 || rhs.Number == 0 {
+ skip++
+ continue
+ }
+ l3.PushBack(newNumberFormulaArg((lhs.Number - mean1.Number) * (rhs.Number - mean2.Number)))
+ }
+ return newNumberFormulaArg(fn.SUM(l3).Number / float64(n-skip-1) / stdev1.Number / stdev2.Number)
+}
+
+// COUNT function returns the count of numeric values in a supplied set of
+// cells or values. This count includes both numbers and dates. The syntax of
+// the function is:
+//
+// COUNT(value1,[value2],...)
+//
+func (fn *formulaFuncs) COUNT(argsList *list.List) formulaArg {
+ var count int
+ for token := argsList.Front(); token != nil; token = token.Next() {
+ arg := token.Value.(formulaArg)
+ switch arg.Type {
+ case ArgString:
+ if arg.ToNumber().Type != ArgError {
+ count++
+ }
+ case ArgNumber:
+ count++
+ case ArgMatrix:
+ for _, row := range arg.Matrix {
+ for _, value := range row {
+ if value.ToNumber().Type != ArgError {
+ count++
+ }
+ }
+ }
+ }
+ }
+ return newNumberFormulaArg(float64(count))
+}
+
+// COUNTA function returns the number of non-blanks within a supplied set of
+// cells or values. The syntax of the function is:
+//
+// COUNTA(value1,[value2],...)
+//
+func (fn *formulaFuncs) COUNTA(argsList *list.List) formulaArg {
+ var count int
+ for token := argsList.Front(); token != nil; token = token.Next() {
+ arg := token.Value.(formulaArg)
+ switch arg.Type {
+ case ArgString:
+ if arg.String != "" {
+ count++
+ }
+ case ArgNumber:
+ count++
+ case ArgMatrix:
+ for _, row := range arg.ToList() {
+ switch row.Type {
+ case ArgString:
+ if row.String != "" {
+ count++
+ }
+ case ArgNumber:
+ count++
+ }
+ }
+ }
+ }
+ return newNumberFormulaArg(float64(count))
+}
+
+// COUNTBLANK function returns the number of blank cells in a supplied range.
+// The syntax of the function is:
+//
+// COUNTBLANK(range)
+//
+func (fn *formulaFuncs) COUNTBLANK(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "COUNTBLANK requires 1 argument")
+ }
+ var count float64
+ for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
+ if cell.Value() == "" {
+ count++
+ }
+ }
+ return newNumberFormulaArg(count)
+}
+
+// COUNTIF function returns the number of cells within a supplied range, that
+// satisfy a given criteria. The syntax of the function is:
+//
+// COUNTIF(range,criteria)
+//
+func (fn *formulaFuncs) COUNTIF(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "COUNTIF requires 2 arguments")
+ }
+ var (
+ criteria = formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg).String)
+ count float64
+ )
+ for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
+ if ok, _ := formulaCriteriaEval(cell.Value(), criteria); ok {
+ count++
+ }
+ }
+ return newNumberFormulaArg(count)
+}
+
+// formulaIfsMatch function returns cells reference array which match criteria.
+func formulaIfsMatch(args []formulaArg) (cellRefs []cellRef) {
+ for i := 0; i < len(args)-1; i += 2 {
+ var match []cellRef
+ matrix, criteria := args[i].Matrix, formulaCriteriaParser(args[i+1].Value())
+ if i == 0 {
+ for rowIdx, row := range matrix {
+ for colIdx, col := range row {
+ if ok, _ := formulaCriteriaEval(col.Value(), criteria); ok {
+ match = append(match, cellRef{Col: colIdx, Row: rowIdx})
+ }
+ }
+ }
+ } else {
+ for _, ref := range cellRefs {
+ value := matrix[ref.Row][ref.Col]
+ if ok, _ := formulaCriteriaEval(value.Value(), criteria); ok {
+ match = append(match, ref)
+ }
+ }
+ }
+ if len(match) == 0 {
+ return
+ }
+ cellRefs = match[:]
+ }
+ return
+}
+
+// COUNTIFS function returns the number of rows within a table, that satisfy a
+// set of given criteria. The syntax of the function is:
+//
+// COUNTIFS(criteria_range1,criteria1,[criteria_range2,criteria2],...)
+//
+func (fn *formulaFuncs) COUNTIFS(argsList *list.List) formulaArg {
+ if argsList.Len() < 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "COUNTIFS requires at least 2 arguments")
+ }
+ if argsList.Len()%2 != 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ var args []formulaArg
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ args = append(args, arg.Value.(formulaArg))
+ }
+ return newNumberFormulaArg(float64(len(formulaIfsMatch(args))))
+}
+
+// CRITBINOM function returns the inverse of the Cumulative Binomial
+// Distribution. I.e. for a specific number of independent trials, the
+// function returns the smallest value (number of successes) for which the
+// cumulative binomial distribution is greater than or equal to a specified
+// value. The syntax of the function is:
+//
+// CRITBINOM(trials,probability_s,alpha)
+//
+func (fn *formulaFuncs) CRITBINOM(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "CRITBINOM requires 3 numeric arguments")
+ }
+ return fn.BINOMdotINV(argsList)
+}
+
+// DEVSQ function calculates the sum of the squared deviations from the sample
+// mean. The syntax of the function is:
+//
+// DEVSQ(number1,[number2],...)
+//
+func (fn *formulaFuncs) DEVSQ(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "DEVSQ requires at least 1 numeric argument")
+ }
+ avg, count, result := fn.AVERAGE(argsList), -1, 0.0
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ for _, number := range arg.Value.(formulaArg).ToList() {
+ num := number.ToNumber()
+ if num.Type != ArgNumber {
+ continue
+ }
+ count++
+ if count == 0 {
+ result = math.Pow(num.Number-avg.Number, 2)
+ continue
+ }
+ result += math.Pow(num.Number-avg.Number, 2)
+ }
+ }
+ if count == -1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(result)
+}
+
+// FISHER function calculates the Fisher Transformation for a supplied value.
+// The syntax of the function is:
+//
+// FISHER(x)
+//
+func (fn *formulaFuncs) FISHER(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ switch token.Type {
+ case ArgString:
+ arg := token.ToNumber()
+ if arg.Type == ArgNumber {
+ if arg.Number <= -1 || arg.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(0.5 * math.Log((1+arg.Number)/(1-arg.Number)))
+ }
+ case ArgNumber:
+ if token.Number <= -1 || token.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(0.5 * math.Log((1+token.Number)/(1-token.Number)))
+ }
+ return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
+}
+
+// FISHERINV function calculates the inverse of the Fisher Transformation and
+// returns a value between -1 and +1. The syntax of the function is:
+//
+// FISHERINV(y)
+//
+func (fn *formulaFuncs) FISHERINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ switch token.Type {
+ case ArgString:
+ arg := token.ToNumber()
+ if arg.Type == ArgNumber {
+ return newNumberFormulaArg((math.Exp(2*arg.Number) - 1) / (math.Exp(2*arg.Number) + 1))
+ }
+ case ArgNumber:
+ return newNumberFormulaArg((math.Exp(2*token.Number) - 1) / (math.Exp(2*token.Number) + 1))
+ }
+ return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
+}
+
+// GAMMA function returns the value of the Gamma Function, Γ(n), for a
+// specified number, n. The syntax of the function is:
+//
+// GAMMA(number)
+//
+func (fn *formulaFuncs) GAMMA(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ switch token.Type {
+ case ArgString:
+ arg := token.ToNumber()
+ if arg.Type == ArgNumber {
+ if arg.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(math.Gamma(arg.Number))
+ }
+ case ArgNumber:
+ if token.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(math.Gamma(token.Number))
+ }
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
+}
+
+// GAMMAdotDIST function returns the Gamma Distribution, which is frequently
+// used to provide probabilities for values that may have a skewed
+// distribution, such as queuing analysis.
+//
+// GAMMA.DIST(x,alpha,beta,cumulative)
+//
+func (fn *formulaFuncs) GAMMAdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMA.DIST requires 4 arguments")
+ }
+ return fn.GAMMADIST(argsList)
+}
+
+// GAMMADIST function returns the Gamma Distribution, which is frequently used
+// to provide probabilities for values that may have a skewed distribution,
+// such as queuing analysis.
+//
+// GAMMADIST(x,alpha,beta,cumulative)
+//
+func (fn *formulaFuncs) GAMMADIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMADIST requires 4 arguments")
+ }
+ var x, alpha, beta, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if x.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if alpha = argsList.Front().Next().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
+ return alpha
+ }
+ if beta = argsList.Back().Prev().Value.(formulaArg).ToNumber(); beta.Type != ArgNumber {
+ return beta
+ }
+ if alpha.Number <= 0 || beta.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(incompleteGamma(alpha.Number, x.Number/beta.Number) / math.Gamma(alpha.Number))
+ }
+ return newNumberFormulaArg((1 / (math.Pow(beta.Number, alpha.Number) * math.Gamma(alpha.Number))) * math.Pow(x.Number, alpha.Number-1) * math.Exp(0-(x.Number/beta.Number)))
+}
+
+// gammainv returns the inverse of the Gamma distribution for the specified
+// value.
+func gammainv(probability, alpha, beta float64) float64 {
+ xLo, xHi := 0.0, alpha*beta*5
+ dx, x, xNew, result := 1024.0, 1.0, 1.0, 0.0
+ for i := 0; math.Abs(dx) > 8.88e-016 && i <= 256; i++ {
+ result = incompleteGamma(alpha, x/beta) / math.Gamma(alpha)
+ e := result - probability
+ if e == 0 {
+ dx = 0
+ } else if e < 0 {
+ xLo = x
+ } else {
+ xHi = x
+ }
+ pdf := (1 / (math.Pow(beta, alpha) * math.Gamma(alpha))) * math.Pow(x, alpha-1) * math.Exp(0-(x/beta))
+ if pdf != 0 {
+ dx = e / pdf
+ xNew = x - dx
+ }
+ if xNew < xLo || xNew > xHi || pdf == 0 {
+ xNew = (xLo + xHi) / 2
+ dx = xNew - x
+ }
+ x = xNew
+ }
+ return x
+}
+
+// GAMMAdotINV function returns the inverse of the Gamma Cumulative
+// Distribution. The syntax of the function is:
+//
+// GAMMA.INV(probability,alpha,beta)
+//
+func (fn *formulaFuncs) GAMMAdotINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMA.INV requires 3 arguments")
+ }
+ return fn.GAMMAINV(argsList)
+}
+
+// GAMMAINV function returns the inverse of the Gamma Cumulative Distribution.
+// The syntax of the function is:
+//
+// GAMMAINV(probability,alpha,beta)
+//
+func (fn *formulaFuncs) GAMMAINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMAINV requires 3 arguments")
+ }
+ var probability, alpha, beta formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if probability.Number < 0 || probability.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if alpha = argsList.Front().Next().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
+ return alpha
+ }
+ if beta = argsList.Back().Value.(formulaArg).ToNumber(); beta.Type != ArgNumber {
+ return beta
+ }
+ if alpha.Number <= 0 || beta.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(gammainv(probability.Number, alpha.Number, beta.Number))
+}
+
+// GAMMALN function returns the natural logarithm of the Gamma Function, Γ
+// (n). The syntax of the function is:
+//
+// GAMMALN(x)
+//
+func (fn *formulaFuncs) GAMMALN(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ switch token.Type {
+ case ArgString:
+ arg := token.ToNumber()
+ if arg.Type == ArgNumber {
+ if arg.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(math.Log(math.Gamma(arg.Number)))
+ }
+ case ArgNumber:
+ if token.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(math.Log(math.Gamma(token.Number)))
+ }
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
+}
+
+// GAMMALNdotPRECISE function returns the natural logarithm of the Gamma
+// Function, Γ(n). The syntax of the function is:
+//
+// GAMMALN.PRECISE(x)
//
-func (fn *formulaFuncs) CONFIDENCE(argsList *list.List) formulaArg {
- return fn.confidence("CONFIDENCE", argsList)
+func (fn *formulaFuncs) GAMMALNdotPRECISE(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN.PRECISE requires 1 numeric argument")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ if x.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(getLogGamma(x.Number))
}
-// CONFIDENCEdotNORM function uses a Normal Distribution to calculate a
-// confidence value that can be used to construct the confidence interval for
-// a population mean, for a supplied probablity and sample size. It is
-// assumed that the standard deviation of the population is known. The syntax
-// of the Confidence.Norm function is:
+// GAUSS function returns the probability that a member of a standard normal
+// population will fall between the mean and a specified number of standard
+// deviations from the mean. The syntax of the function is:
//
-// CONFIDENCE.NORM(alpha,standard_dev,size)
+// GAUSS(z)
//
-func (fn *formulaFuncs) CONFIDENCEdotNORM(argsList *list.List) formulaArg {
- return fn.confidence("CONFIDENCE.NORM", argsList)
+func (fn *formulaFuncs) GAUSS(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GAUSS requires 1 numeric argument")
+ }
+ args := list.New().Init()
+ args.PushBack(argsList.Front().Value.(formulaArg))
+ args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
+ args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
+ args.PushBack(newBoolFormulaArg(true))
+ normdist := fn.NORMDIST(args)
+ if normdist.Type != ArgNumber {
+ return normdist
+ }
+ return newNumberFormulaArg(normdist.Number - 0.5)
}
-// calcStringCountSum is part of the implementation countSum.
-func calcStringCountSum(countText bool, count, sum float64, num, arg formulaArg) (float64, float64) {
- if countText && num.Type == ArgError && arg.String != "" {
- count++
+// GEOMEAN function calculates the geometric mean of a supplied set of values.
+// The syntax of the function is:
+//
+// GEOMEAN(number1,[number2],...)
+//
+func (fn *formulaFuncs) GEOMEAN(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "GEOMEAN requires at least 1 numeric argument")
}
- if num.Type == ArgNumber {
- sum += num.Number
- count++
+ product := fn.PRODUCT(argsList)
+ if product.Type != ArgNumber {
+ return product
}
- return count, sum
+ count := fn.COUNT(argsList)
+ min := fn.MIN(argsList)
+ if product.Number > 0 && min.Number > 0 {
+ return newNumberFormulaArg(math.Pow(product.Number, 1/count.Number))
+ }
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
-// countSum get count and sum for a formula arguments array.
-func (fn *formulaFuncs) countSum(countText bool, args []formulaArg) (count, sum float64) {
- for _, arg := range args {
+// HARMEAN function calculates the harmonic mean of a supplied set of values.
+// The syntax of the function is:
+//
+// HARMEAN(number1,[number2],...)
+//
+func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "HARMEAN requires at least 1 argument")
+ }
+ if min := fn.MIN(argsList); min.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ number, val, cnt := 0.0, 0.0, 0.0
+ for token := argsList.Front(); token != nil; token = token.Next() {
+ arg := token.Value.(formulaArg)
switch arg.Type {
- case ArgNumber:
- if countText || !arg.Boolean {
- sum += arg.Number
- count++
- }
case ArgString:
- if !countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
+ num := arg.ToNumber()
+ if num.Type != ArgNumber {
continue
- } else if countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
- num := arg.ToBool()
- if num.Type == ArgNumber {
- count++
- sum += num.Number
- continue
- }
}
- num := arg.ToNumber()
- count, sum = calcStringCountSum(countText, count, sum, num, arg)
- case ArgList, ArgMatrix:
- cnt, summary := fn.countSum(countText, arg.ToList())
- sum += summary
- count += cnt
+ number = num.Number
+ case ArgNumber:
+ number = arg.Number
+ }
+ if number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
+ val += 1 / number
+ cnt++
}
- return
+ return newNumberFormulaArg(1 / (val / cnt))
}
-// COUNT function returns the count of numeric values in a supplied set of
-// cells or values. This count includes both numbers and dates. The syntax of
-// the function is:
+// checkHYPGEOMDISTArgs checking arguments for the formula function HYPGEOMDIST
+// and HYPGEOM.DIST.
+func checkHYPGEOMDISTArgs(sampleS, numberSample, populationS, numberPop formulaArg) bool {
+ return sampleS.Number < 0 ||
+ sampleS.Number > math.Min(numberSample.Number, populationS.Number) ||
+ sampleS.Number < math.Max(0, numberSample.Number-numberPop.Number+populationS.Number) ||
+ numberSample.Number <= 0 ||
+ numberSample.Number > numberPop.Number ||
+ populationS.Number <= 0 ||
+ populationS.Number > numberPop.Number ||
+ numberPop.Number <= 0
+}
+
+// prepareHYPGEOMDISTArgs prepare arguments for the formula function
+// HYPGEOMDIST and HYPGEOM.DIST.
+func (fn *formulaFuncs) prepareHYPGEOMDISTArgs(name string, argsList *list.List) formulaArg {
+ if name == "HYPGEOMDIST" && argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "HYPGEOMDIST requires 4 numeric arguments")
+ }
+ if name == "HYPGEOM.DIST" && argsList.Len() != 5 {
+ return newErrorFormulaArg(formulaErrorVALUE, "HYPGEOM.DIST requires 5 arguments")
+ }
+ var sampleS, numberSample, populationS, numberPop, cumulative formulaArg
+ if sampleS = argsList.Front().Value.(formulaArg).ToNumber(); sampleS.Type != ArgNumber {
+ return sampleS
+ }
+ if numberSample = argsList.Front().Next().Value.(formulaArg).ToNumber(); numberSample.Type != ArgNumber {
+ return numberSample
+ }
+ if populationS = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); populationS.Type != ArgNumber {
+ return populationS
+ }
+ if numberPop = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); numberPop.Type != ArgNumber {
+ return numberPop
+ }
+ if checkHYPGEOMDISTArgs(sampleS, numberSample, populationS, numberPop) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if name == "HYPGEOM.DIST" {
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ }
+ return newListFormulaArg([]formulaArg{sampleS, numberSample, populationS, numberPop, cumulative})
+}
+
+// HYPGEOMdotDIST function returns the value of the hypergeometric distribution
+// for a specified number of successes from a population sample. The function
+// can calculate the cumulative distribution or the probability density
+// function. The syntax of the function is:
//
-// COUNT(value1,[value2],...)
+// HYPGEOM.DIST(sample_s,number_sample,population_s,number_pop,cumulative)
//
-func (fn *formulaFuncs) COUNT(argsList *list.List) formulaArg {
- var count int
- for token := argsList.Front(); token != nil; token = token.Next() {
- arg := token.Value.(formulaArg)
- switch arg.Type {
- case ArgString:
- if arg.ToNumber().Type != ArgError {
+func (fn *formulaFuncs) HYPGEOMdotDIST(argsList *list.List) formulaArg {
+ args := fn.prepareHYPGEOMDISTArgs("HYPGEOM.DIST", argsList)
+ if args.Type != ArgList {
+ return args
+ }
+ sampleS, numberSample, populationS, numberPop, cumulative := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4]
+ if cumulative.Number == 1 {
+ var res float64
+ for i := 0; i <= int(sampleS.Number); i++ {
+ res += binomCoeff(populationS.Number, float64(i)) *
+ binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-float64(i)) /
+ binomCoeff(numberPop.Number, numberSample.Number)
+ }
+ return newNumberFormulaArg(res)
+ }
+ return newNumberFormulaArg(binomCoeff(populationS.Number, sampleS.Number) *
+ binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-sampleS.Number) /
+ binomCoeff(numberPop.Number, numberSample.Number))
+}
+
+// HYPGEOMDIST function returns the value of the hypergeometric distribution
+// for a given number of successes from a sample of a population. The syntax
+// of the function is:
+//
+// HYPGEOMDIST(sample_s,number_sample,population_s,number_pop)
+//
+func (fn *formulaFuncs) HYPGEOMDIST(argsList *list.List) formulaArg {
+ args := fn.prepareHYPGEOMDISTArgs("HYPGEOMDIST", argsList)
+ if args.Type != ArgList {
+ return args
+ }
+ sampleS, numberSample, populationS, numberPop := args.List[0], args.List[1], args.List[2], args.List[3]
+ return newNumberFormulaArg(binomCoeff(populationS.Number, sampleS.Number) *
+ binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-sampleS.Number) /
+ binomCoeff(numberPop.Number, numberSample.Number))
+}
+
+// KURT function calculates the kurtosis of a supplied set of values. The
+// syntax of the function is:
+//
+// KURT(number1,[number2],...)
+//
+func (fn *formulaFuncs) KURT(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "KURT requires at least 1 argument")
+ }
+ mean, stdev := fn.AVERAGE(argsList), fn.STDEV(argsList)
+ if stdev.Number > 0 {
+ count, summer := 0.0, 0.0
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ token := arg.Value.(formulaArg)
+ switch token.Type {
+ case ArgString, ArgNumber:
+ num := token.ToNumber()
+ if num.Type == ArgError {
+ continue
+ }
+ summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
count++
- }
- case ArgNumber:
- count++
- case ArgMatrix:
- for _, row := range arg.Matrix {
- for _, value := range row {
- if value.ToNumber().Type != ArgError {
+ case ArgList, ArgMatrix:
+ for _, row := range token.ToList() {
+ if row.Type == ArgNumber || row.Type == ArgString {
+ num := row.ToNumber()
+ if num.Type == ArgError {
+ continue
+ }
+ summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
count++
}
}
}
}
+ if count > 3 {
+ return newNumberFormulaArg(summer*(count*(count+1)/((count-1)*(count-2)*(count-3))) - (3 * math.Pow(count-1, 2) / ((count - 2) * (count - 3))))
+ }
+ }
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+}
+
+// EXPONdotDIST function returns the value of the exponential distribution for
+// a give value of x. The user can specify whether the probability density
+// function or the cumulative distribution function is used. The syntax of the
+// Expondist function is:
+//
+// EXPON.DIST(x,lambda,cumulative)
+//
+func (fn *formulaFuncs) EXPONdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "EXPON.DIST requires 3 arguments")
+ }
+ return fn.EXPONDIST(argsList)
+}
+
+// EXPONDIST function returns the value of the exponential distribution for a
+// give value of x. The user can specify whether the probability density
+// function or the cumulative distribution function is used. The syntax of the
+// Expondist function is:
+//
+// EXPONDIST(x,lambda,cumulative)
+//
+func (fn *formulaFuncs) EXPONDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "EXPONDIST requires 3 arguments")
+ }
+ var x, lambda, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if lambda = argsList.Front().Next().Value.(formulaArg).ToNumber(); lambda.Type != ArgNumber {
+ return lambda
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if x.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if lambda.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(1 - math.Exp(-lambda.Number*x.Number))
+ }
+ return newNumberFormulaArg(lambda.Number * math.Exp(-lambda.Number*x.Number))
+}
+
+// FdotDIST function calculates the Probability Density Function or the
+// Cumulative Distribution Function for the F Distribution. This function is
+// frequently used to measure the degree of diversity between two data
+// sets. The syntax of the function is:
+//
+// F.DIST(x,deg_freedom1,deg_freedom2,cumulative)
+//
+func (fn *formulaFuncs) FdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "F.DIST requires 4 arguments")
+ }
+ var x, deg1, deg2, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if deg1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); deg1.Type != ArgNumber {
+ return deg1
+ }
+ if deg2 = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); deg2.Type != ArgNumber {
+ return deg2
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if x.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ maxDeg := math.Pow10(10)
+ if deg1.Number < 1 || deg1.Number >= maxDeg {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if deg2.Number < 1 || deg2.Number >= maxDeg {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(1 - getBetaDist(deg2.Number/(deg2.Number+deg1.Number*x.Number), deg2.Number/2, deg1.Number/2))
+ }
+ return newNumberFormulaArg(math.Gamma((deg2.Number+deg1.Number)/2) / (math.Gamma(deg1.Number/2) * math.Gamma(deg2.Number/2)) * math.Pow(deg1.Number/deg2.Number, deg1.Number/2) * (math.Pow(x.Number, (deg1.Number-2)/2) / math.Pow(1+(deg1.Number/deg2.Number)*x.Number, (deg1.Number+deg2.Number)/2)))
+}
+
+// FDIST function calculates the (right-tailed) F Probability Distribution,
+// which measures the degree of diversity between two data sets. The syntax
+// of the function is:
+//
+// FDIST(x,deg_freedom1,deg_freedom2)
+//
+func (fn *formulaFuncs) FDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "FDIST requires 3 arguments")
+ }
+ var x, deg1, deg2 formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if deg1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); deg1.Type != ArgNumber {
+ return deg1
+ }
+ if deg2 = argsList.Back().Value.(formulaArg).ToNumber(); deg2.Type != ArgNumber {
+ return deg2
+ }
+ if x.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ maxDeg := math.Pow10(10)
+ if deg1.Number < 1 || deg1.Number >= maxDeg {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if deg2.Number < 1 || deg2.Number >= maxDeg {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg(deg1.Number * x.Number / (deg1.Number*x.Number + deg2.Number)))
+ args.PushBack(newNumberFormulaArg(0.5 * deg1.Number))
+ args.PushBack(newNumberFormulaArg(0.5 * deg2.Number))
+ args.PushBack(newNumberFormulaArg(0))
+ args.PushBack(newNumberFormulaArg(1))
+ return newNumberFormulaArg(1 - fn.BETADIST(args).Number)
+}
+
+// FdotDISTdotRT function calculates the (right-tailed) F Probability
+// Distribution, which measures the degree of diversity between two data sets.
+// The syntax of the function is:
+//
+// F.DIST.RT(x,deg_freedom1,deg_freedom2)
+//
+func (fn *formulaFuncs) FdotDISTdotRT(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "F.DIST.RT requires 3 arguments")
}
- return newNumberFormulaArg(float64(count))
+ return fn.FDIST(argsList)
}
-// COUNTA function returns the number of non-blanks within a supplied set of
-// cells or values. The syntax of the function is:
+// prepareFinvArgs checking and prepare arguments for the formula function
+// F.INV, F.INV.RT and FINV.
+func (fn *formulaFuncs) prepareFinvArgs(name string, argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 arguments", name))
+ }
+ var probability, d1, d2 formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if d1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); d1.Type != ArgNumber {
+ return d1
+ }
+ if d2 = argsList.Back().Value.(formulaArg).ToNumber(); d2.Type != ArgNumber {
+ return d2
+ }
+ if probability.Number <= 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if d1.Number < 1 || d1.Number >= math.Pow10(10) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if d2.Number < 1 || d2.Number >= math.Pow10(10) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newListFormulaArg([]formulaArg{probability, d1, d2})
+}
+
+// FdotINV function calculates the inverse of the Cumulative F Distribution
+// for a supplied probability. The syntax of the F.Inv function is:
//
-// COUNTA(value1,[value2],...)
+// F.INV(probability,deg_freedom1,deg_freedom2)
//
-func (fn *formulaFuncs) COUNTA(argsList *list.List) formulaArg {
- var count int
- for token := argsList.Front(); token != nil; token = token.Next() {
- arg := token.Value.(formulaArg)
- switch arg.Type {
- case ArgString:
- if arg.String != "" {
- count++
- }
- case ArgNumber:
- count++
- case ArgMatrix:
- for _, row := range arg.ToList() {
- switch row.Type {
- case ArgString:
- if row.String != "" {
- count++
- }
- case ArgNumber:
- count++
- }
- }
- }
+func (fn *formulaFuncs) FdotINV(argsList *list.List) formulaArg {
+ args := fn.prepareFinvArgs("F.INV", argsList)
+ if args.Type != ArgList {
+ return args
}
- return newNumberFormulaArg(float64(count))
+ probability, d1, d2 := args.List[0], args.List[1], args.List[2]
+ return newNumberFormulaArg((1/calcBetainv(1-probability.Number, d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
}
-// COUNTBLANK function returns the number of blank cells in a supplied range.
-// The syntax of the function is:
+// FdotINVdotRT function calculates the inverse of the (right-tailed) F
+// Probability Distribution for a supplied probability. The syntax of the
+// function is:
//
-// COUNTBLANK(range)
+// F.INV.RT(probability,deg_freedom1,deg_freedom2)
//
-func (fn *formulaFuncs) COUNTBLANK(argsList *list.List) formulaArg {
- if argsList.Len() != 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "COUNTBLANK requires 1 argument")
- }
- var count float64
- for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
- if cell.Value() == "" {
- count++
- }
+func (fn *formulaFuncs) FdotINVdotRT(argsList *list.List) formulaArg {
+ args := fn.prepareFinvArgs("F.INV.RT", argsList)
+ if args.Type != ArgList {
+ return args
}
- return newNumberFormulaArg(count)
+ probability, d1, d2 := args.List[0], args.List[1], args.List[2]
+ return newNumberFormulaArg((1/calcBetainv(1-(1-probability.Number), d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
}
-// COUNTIF function returns the number of cells within a supplied range, that
-// satisfy a given criteria. The syntax of the function is:
+// FINV function calculates the inverse of the (right-tailed) F Probability
+// Distribution for a supplied probability. The syntax of the function is:
//
-// COUNTIF(range,criteria)
+// FINV(probability,deg_freedom1,deg_freedom2)
//
-func (fn *formulaFuncs) COUNTIF(argsList *list.List) formulaArg {
- if argsList.Len() != 2 {
- return newErrorFormulaArg(formulaErrorVALUE, "COUNTIF requires 2 arguments")
- }
- var (
- criteria = formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg).String)
- count float64
- )
- for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
- if ok, _ := formulaCriteriaEval(cell.Value(), criteria); ok {
- count++
- }
+func (fn *formulaFuncs) FINV(argsList *list.List) formulaArg {
+ args := fn.prepareFinvArgs("FINV", argsList)
+ if args.Type != ArgList {
+ return args
}
- return newNumberFormulaArg(count)
+ probability, d1, d2 := args.List[0], args.List[1], args.List[2]
+ return newNumberFormulaArg((1/calcBetainv(1-(1-probability.Number), d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
}
-// formulaIfsMatch function returns cells reference array which match criteria.
-func formulaIfsMatch(args []formulaArg) (cellRefs []cellRef) {
- for i := 0; i < len(args)-1; i += 2 {
- match := []cellRef{}
- matrix, criteria := args[i].Matrix, formulaCriteriaParser(args[i+1].Value())
- if i == 0 {
- for rowIdx, row := range matrix {
- for colIdx, col := range row {
- if ok, _ := formulaCriteriaEval(col.Value(), criteria); ok {
- match = append(match, cellRef{Col: colIdx, Row: rowIdx})
- }
- }
- }
- } else {
- for _, ref := range cellRefs {
- value := matrix[ref.Row][ref.Col]
- if ok, _ := formulaCriteriaEval(value.Value(), criteria); ok {
- match = append(match, ref)
- }
+// FdotTEST function returns the F-Test for two supplied arrays. I.e. the
+// function returns the two-tailed probability that the variances in the two
+// supplied arrays are not significantly different. The syntax of the Ftest
+// function is:
+//
+// F.TEST(array1,array2)
+//
+func (fn *formulaFuncs) FdotTEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "F.TEST requires 2 arguments")
+ }
+ array1 := argsList.Front().Value.(formulaArg)
+ array2 := argsList.Back().Value.(formulaArg)
+ left, right := array1.ToList(), array2.ToList()
+ collectMatrix := func(args []formulaArg) (n, accu float64) {
+ var p, sum float64
+ for _, arg := range args {
+ if num := arg.ToNumber(); num.Type == ArgNumber {
+ x := num.Number - p
+ y := x / (n + 1)
+ p += y
+ accu += n * x * y
+ n++
+ sum += num.Number
}
}
- if len(match) == 0 {
- return
- }
- cellRefs = match[:]
+ return
}
- return
+ nums, accu := collectMatrix(left)
+ f3 := nums - 1
+ if nums == 1 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ f1 := accu / (nums - 1)
+ if f1 == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ nums, accu = collectMatrix(right)
+ f4 := nums - 1
+ if nums == 1 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ f2 := accu / (nums - 1)
+ if f2 == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg(f1 / f2))
+ args.PushBack(newNumberFormulaArg(f3))
+ args.PushBack(newNumberFormulaArg(f4))
+ probability := (1 - fn.FDIST(args).Number) * 2
+ if probability > 1 {
+ probability = 2 - probability
+ }
+ return newNumberFormulaArg(probability)
}
-// COUNTIFS function returns the number of rows within a table, that satisfy a
-// set of given criteria. The syntax of the function is:
+// FTEST function returns the F-Test for two supplied arrays. I.e. the function
+// returns the two-tailed probability that the variances in the two supplied
+// arrays are not significantly different. The syntax of the Ftest function
+// is:
//
-// COUNTIFS(criteria_range1,criteria1,[criteria_range2,criteria2],...)
+// FTEST(array1,array2)
//
-func (fn *formulaFuncs) COUNTIFS(argsList *list.List) formulaArg {
- if argsList.Len() < 2 {
- return newErrorFormulaArg(formulaErrorVALUE, "COUNTIFS requires at least 2 arguments")
- }
- if argsList.Len()%2 != 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- args := []formulaArg{}
- for arg := argsList.Front(); arg != nil; arg = arg.Next() {
- args = append(args, arg.Value.(formulaArg))
+func (fn *formulaFuncs) FTEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "FTEST requires 2 arguments")
}
- return newNumberFormulaArg(float64(len(formulaIfsMatch(args))))
+ return fn.FdotTEST(argsList)
}
-// DEVSQ function calculates the sum of the squared deviations from the sample
-// mean. The syntax of the function is:
+// LOGINV function calculates the inverse of the Cumulative Log-Normal
+// Distribution Function of x, for a supplied probability. The syntax of the
+// function is:
//
-// DEVSQ(number1,[number2],...)
+// LOGINV(probability,mean,standard_dev)
//
-func (fn *formulaFuncs) DEVSQ(argsList *list.List) formulaArg {
- if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "DEVSQ requires at least 1 numeric argument")
+func (fn *formulaFuncs) LOGINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "LOGINV requires 3 arguments")
}
- avg, count, result := fn.AVERAGE(argsList), -1, 0.0
- for arg := argsList.Front(); arg != nil; arg = arg.Next() {
- for _, number := range arg.Value.(formulaArg).ToList() {
- num := number.ToNumber()
- if num.Type != ArgNumber {
- continue
- }
- count++
- if count == 0 {
- result = math.Pow(num.Number-avg.Number, 2)
- continue
- }
- result += math.Pow(num.Number-avg.Number, 2)
- }
+ var probability, mean, stdDev formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
}
- if count == -1 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
+ return mean
}
- return newNumberFormulaArg(result)
+ if stdDev = argsList.Back().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
+ return stdDev
+ }
+ if probability.Number <= 0 || probability.Number >= 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if stdDev.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ args := list.New()
+ args.PushBack(probability)
+ args.PushBack(newNumberFormulaArg(0))
+ args.PushBack(newNumberFormulaArg(1))
+ norminv := fn.NORMINV(args)
+ return newNumberFormulaArg(math.Exp(mean.Number + stdDev.Number*norminv.Number))
}
-// FISHER function calculates the Fisher Transformation for a supplied value.
-// The syntax of the function is:
+// LOGNORMdotINV function calculates the inverse of the Cumulative Log-Normal
+// Distribution Function of x, for a supplied probability. The syntax of the
+// function is:
//
-// FISHER(x)
+// LOGNORM.INV(probability,mean,standard_dev)
//
-func (fn *formulaFuncs) FISHER(argsList *list.List) formulaArg {
- if argsList.Len() != 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
- }
- token := argsList.Front().Value.(formulaArg)
- switch token.Type {
- case ArgString:
- arg := token.ToNumber()
- if arg.Type == ArgNumber {
- if arg.Number <= -1 || arg.Number >= 1 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- return newNumberFormulaArg(0.5 * math.Log((1+arg.Number)/(1-arg.Number)))
- }
- case ArgNumber:
- if token.Number <= -1 || token.Number >= 1 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- return newNumberFormulaArg(0.5 * math.Log((1+token.Number)/(1-token.Number)))
+func (fn *formulaFuncs) LOGNORMdotINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "LOGNORM.INV requires 3 arguments")
}
- return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
+ return fn.LOGINV(argsList)
}
-// FISHERINV function calculates the inverse of the Fisher Transformation and
-// returns a value between -1 and +1. The syntax of the function is:
+// LOGNORMdotDIST function calculates the Log-Normal Probability Density
+// Function or the Cumulative Log-Normal Distribution Function for a supplied
+// value of x. The syntax of the function is:
//
-// FISHERINV(y)
+// LOGNORM.DIST(x,mean,standard_dev,cumulative)
//
-func (fn *formulaFuncs) FISHERINV(argsList *list.List) formulaArg {
- if argsList.Len() != 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
+func (fn *formulaFuncs) LOGNORMdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "LOGNORM.DIST requires 4 arguments")
}
- token := argsList.Front().Value.(formulaArg)
- switch token.Type {
- case ArgString:
- arg := token.ToNumber()
- if arg.Type == ArgNumber {
- return newNumberFormulaArg((math.Exp(2*arg.Number) - 1) / (math.Exp(2*arg.Number) + 1))
- }
- case ArgNumber:
- return newNumberFormulaArg((math.Exp(2*token.Number) - 1) / (math.Exp(2*token.Number) + 1))
+ var x, mean, stdDev, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
}
- return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
+ if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
+ return mean
+ }
+ if stdDev = argsList.Back().Prev().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
+ return stdDev
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
+ return cumulative
+ }
+ if x.Number <= 0 || stdDev.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ args := list.New()
+ args.PushBack(newNumberFormulaArg((math.Log(x.Number) - mean.Number) / stdDev.Number))
+ args.PushBack(newNumberFormulaArg(0))
+ args.PushBack(newNumberFormulaArg(1))
+ args.PushBack(cumulative)
+ return fn.NORMDIST(args)
+ }
+ return newNumberFormulaArg((1 / (math.Sqrt(2*math.Pi) * stdDev.Number * x.Number)) *
+ math.Exp(0-(math.Pow(math.Log(x.Number)-mean.Number, 2)/(2*math.Pow(stdDev.Number, 2)))))
}
-// GAMMA function returns the value of the Gamma Function, Γ(n), for a
-// specified number, n. The syntax of the function is:
+// LOGNORMDIST function calculates the Cumulative Log-Normal Distribution
+// Function at a supplied value of x. The syntax of the function is:
//
-// GAMMA(number)
+// LOGNORMDIST(x,mean,standard_dev)
//
-func (fn *formulaFuncs) GAMMA(argsList *list.List) formulaArg {
- if argsList.Len() != 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
+func (fn *formulaFuncs) LOGNORMDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "LOGNORMDIST requires 3 arguments")
}
- token := argsList.Front().Value.(formulaArg)
- switch token.Type {
- case ArgString:
- arg := token.ToNumber()
- if arg.Type == ArgNumber {
- if arg.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- return newNumberFormulaArg(math.Gamma(arg.Number))
- }
- case ArgNumber:
- if token.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- return newNumberFormulaArg(math.Gamma(token.Number))
+ var x, mean, stdDev formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
+ return mean
}
- return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
+ if stdDev = argsList.Back().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
+ return stdDev
+ }
+ if x.Number <= 0 || stdDev.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg((math.Log(x.Number) - mean.Number) / stdDev.Number))
+ return fn.NORMSDIST(args)
}
-// GAMMALN function returns the natural logarithm of the Gamma Function, Γ
-// (n). The syntax of the function is:
+// MODE function returns the statistical mode (the most frequently occurring
+// value) of a list of supplied numbers. If there are 2 or more most
+// frequently occurring values in the supplied data, the function returns the
+// lowest of these values The syntax of the function is:
//
-// GAMMALN(x)
+// MODE(number1,[number2],...)
//
-func (fn *formulaFuncs) GAMMALN(argsList *list.List) formulaArg {
- if argsList.Len() != 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
+func (fn *formulaFuncs) MODE(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "MODE requires at least 1 argument")
}
- token := argsList.Front().Value.(formulaArg)
- switch token.Type {
- case ArgString:
- arg := token.ToNumber()
- if arg.Type == ArgNumber {
- if arg.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ var values []float64
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ cells := arg.Value.(formulaArg)
+ if cells.Type != ArgMatrix && cells.ToNumber().Type != ArgNumber {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ for _, cell := range cells.ToList() {
+ if num := cell.ToNumber(); num.Type == ArgNumber {
+ values = append(values, num.Number)
}
- return newNumberFormulaArg(math.Log(math.Gamma(arg.Number)))
}
- case ArgNumber:
- if token.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ sort.Float64s(values)
+ cnt := len(values)
+ var count, modeCnt int
+ var mode float64
+ for i := 0; i < cnt; i++ {
+ count = 0
+ for j := 0; j < cnt; j++ {
+ if j != i && values[j] == values[i] {
+ count++
+ }
+ }
+ if count > modeCnt {
+ modeCnt = count
+ mode = values[i]
}
- return newNumberFormulaArg(math.Log(math.Gamma(token.Number)))
}
- return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
+ if modeCnt == 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg(mode)
}
-// GEOMEAN function calculates the geometric mean of a supplied set of values.
+// MODEdotMULT function returns a vertical array of the statistical modes
+// (the most frequently occurring values) within a list of supplied numbers.
// The syntax of the function is:
//
-// GEOMEAN(number1,[number2],...)
+// MODE.MULT(number1,[number2],...)
//
-func (fn *formulaFuncs) GEOMEAN(argsList *list.List) formulaArg {
+func (fn *formulaFuncs) MODEdotMULT(argsList *list.List) formulaArg {
if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "GEOMEAN requires at least 1 numeric argument")
+ return newErrorFormulaArg(formulaErrorVALUE, "MODE.MULT requires at least 1 argument")
}
- product := fn.PRODUCT(argsList)
- if product.Type != ArgNumber {
- return product
+ var values []float64
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ cells := arg.Value.(formulaArg)
+ if cells.Type != ArgMatrix && cells.ToNumber().Type != ArgNumber {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ for _, cell := range cells.ToList() {
+ if num := cell.ToNumber(); num.Type == ArgNumber {
+ values = append(values, num.Number)
+ }
+ }
}
- count := fn.COUNT(argsList)
- min := fn.MIN(argsList)
- if product.Number > 0 && min.Number > 0 {
- return newNumberFormulaArg(math.Pow(product.Number, (1 / count.Number)))
+ sort.Float64s(values)
+ cnt := len(values)
+ var count, modeCnt int
+ var mtx [][]formulaArg
+ for i := 0; i < cnt; i++ {
+ count = 0
+ for j := i + 1; j < cnt; j++ {
+ if values[i] == values[j] {
+ count++
+ }
+ }
+ if count > modeCnt {
+ modeCnt = count
+ mtx = [][]formulaArg{}
+ mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
+ } else if count == modeCnt {
+ mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
+ }
}
- return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ if modeCnt == 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newMatrixFormulaArg(mtx)
}
-// HARMEAN function calculates the harmonic mean of a supplied set of values.
-// The syntax of the function is:
+// MODEdotSNGL function returns the statistical mode (the most frequently
+// occurring value) within a list of supplied numbers. If there are 2 or more
+// most frequently occurring values in the supplied data, the function returns
+// the lowest of these values. The syntax of the function is:
//
-// HARMEAN(number1,[number2],...)
+// MODE.SNGL(number1,[number2],...)
//
-func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg {
+func (fn *formulaFuncs) MODEdotSNGL(argsList *list.List) formulaArg {
if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "HARMEAN requires at least 1 argument")
+ return newErrorFormulaArg(formulaErrorVALUE, "MODE.SNGL requires at least 1 argument")
}
- if min := fn.MIN(argsList); min.Number < 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ return fn.MODE(argsList)
+}
+
+// NEGBINOMdotDIST function calculates the probability mass function or the
+// cumulative distribution function for the Negative Binomial Distribution.
+// This gives the probability that there will be a given number of failures
+// before a required number of successes is achieved. The syntax of the
+// function is:
+//
+// NEGBINOM.DIST(number_f,number_s,probability_s,cumulative)
+//
+func (fn *formulaFuncs) NEGBINOMdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOM.DIST requires 4 arguments")
}
- number, val, cnt := 0.0, 0.0, 0.0
- for token := argsList.Front(); token != nil; token = token.Next() {
- arg := token.Value.(formulaArg)
- switch arg.Type {
- case ArgString:
- num := arg.ToNumber()
- if num.Type != ArgNumber {
- continue
- }
- number = num.Number
- case ArgNumber:
- number = arg.Number
- }
- if number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
- }
- val += (1 / number)
- cnt++
+ var f, s, probability, cumulative formulaArg
+ if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
+ return f
}
- return newNumberFormulaArg(1 / (val / cnt))
+ if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
+ return s
+ }
+ if probability = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(1 - getBetaDist(1-probability.Number, f.Number+1, s.Number))
+ }
+ return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
}
-// KURT function calculates the kurtosis of a supplied set of values. The
-// syntax of the function is:
+// NEGBINOMDIST function calculates the Negative Binomial Distribution for a
+// given set of parameters. This gives the probability that there will be a
+// specified number of failures before a required number of successes is
+// achieved. The syntax of the function is:
//
-// KURT(number1,[number2],...)
+// NEGBINOMDIST(number_f,number_s,probability_s)
//
-func (fn *formulaFuncs) KURT(argsList *list.List) formulaArg {
- if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "KURT requires at least 1 argument")
+func (fn *formulaFuncs) NEGBINOMDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOMDIST requires 3 arguments")
}
- mean, stdev := fn.AVERAGE(argsList), fn.STDEV(argsList)
- if stdev.Number > 0 {
- count, summer := 0.0, 0.0
- for arg := argsList.Front(); arg != nil; arg = arg.Next() {
- token := arg.Value.(formulaArg)
- switch token.Type {
- case ArgString, ArgNumber:
- num := token.ToNumber()
- if num.Type == ArgError {
- continue
- }
- summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
- count++
- case ArgList, ArgMatrix:
- for _, row := range token.ToList() {
- if row.Type == ArgNumber || row.Type == ArgString {
- num := row.ToNumber()
- if num.Type == ArgError {
- continue
- }
- summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
- count++
- }
- }
- }
- }
- if count > 3 {
- return newNumberFormulaArg(summer*(count*(count+1)/((count-1)*(count-2)*(count-3))) - (3 * math.Pow(count-1, 2) / ((count - 2) * (count - 3))))
- }
+ var f, s, probability formulaArg
+ if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
+ return f
}
- return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
+ return s
+ }
+ if probability = argsList.Back().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
}
// NORMdotDIST function calculates the Normal Probability Density Function or
@@ -5710,8 +8373,12 @@ func norminv(p float64) (float64, error) {
// Rational approximation for central region.
q := p - 0.5
r := q * q
- return (((((a[1]*r+a[2])*r+a[3])*r+a[4])*r+a[5])*r + a[6]) * q /
- (((((b[1]*r+b[2])*r+b[3])*r+b[4])*r+b[5])*r + 1), nil
+ f1 := ((((a[1]*r+a[2])*r+a[3])*r+a[4])*r + a[5]) * r
+ f2 := (b[1]*r + b[2]) * r
+ f3 := ((math.Nextafter(f2, f2)+b[3])*r + b[4]) * r
+ f4 := (math.Nextafter(f3, f3) + b[5]) * r
+ return (math.Nextafter(f1, f1) + a[6]) * q /
+ (math.Nextafter(f4, f4) + 1), nil
} else if pHigh < p && p < 1 {
// Rational approximation for upper region.
q := math.Sqrt(-2 * math.Log(1-p))
@@ -5735,7 +8402,7 @@ func (fn *formulaFuncs) kth(name string, argsList *list.List) formulaArg {
if k < 1 {
return newErrorFormulaArg(formulaErrorNUM, "k should be > 0")
}
- data := []float64{}
+ var data []float64
for _, arg := range array {
if numArg := arg.ToNumber(); numArg.Type == ArgNumber {
data = append(data, numArg.Number)
@@ -5799,7 +8466,8 @@ func (fn *formulaFuncs) MAXIFS(argsList *list.List) formulaArg {
if argsList.Len()%2 != 1 {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
- max, maxRange, args := -math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix, []formulaArg{}
+ var args []formulaArg
+ max, maxRange := -math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
@@ -5886,7 +8554,7 @@ func (fn *formulaFuncs) MEDIAN(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "MEDIAN requires at least 1 argument")
}
- var values = []float64{}
+ var values []float64
var median, digits float64
var err error
for token := argsList.Front(); token != nil; token = token.Next() {
@@ -5962,7 +8630,8 @@ func (fn *formulaFuncs) MINIFS(argsList *list.List) formulaArg {
if argsList.Len()%2 != 1 {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
- min, minRange, args := math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix, []formulaArg{}
+ var args []formulaArg
+ min, minRange := math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
@@ -6058,7 +8727,7 @@ func (fn *formulaFuncs) PERCENTILEdotEXC(argsList *list.List) formulaArg {
if k.Number <= 0 || k.Number >= 1 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- numbers := []float64{}
+ var numbers []float64
for _, arg := range array {
if arg.Type == ArgError {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -6073,7 +8742,7 @@ func (fn *formulaFuncs) PERCENTILEdotEXC(argsList *list.List) formulaArg {
idx := k.Number * (float64(cnt) + 1)
base := math.Floor(idx)
next := base - 1
- proportion := idx - base
+ proportion := math.Nextafter(idx, idx) - base
return newNumberFormulaArg(numbers[int(next)] + ((numbers[int(base)] - numbers[int(next)]) * proportion))
}
@@ -6108,7 +8777,7 @@ func (fn *formulaFuncs) PERCENTILE(argsList *list.List) formulaArg {
if k.Number < 0 || k.Number > 1 {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
- numbers := []float64{}
+ var numbers []float64
for _, arg := range array {
if arg.Type == ArgError {
return arg
@@ -6126,7 +8795,7 @@ func (fn *formulaFuncs) PERCENTILE(argsList *list.List) formulaArg {
return newNumberFormulaArg(numbers[int(idx)])
}
next := base + 1
- proportion := idx - base
+ proportion := math.Nextafter(idx, idx) - base
return newNumberFormulaArg(numbers[int(base)] + ((numbers[int(next)] - numbers[int(base)]) * proportion))
}
@@ -6141,7 +8810,7 @@ func (fn *formulaFuncs) percentrank(name string, argsList *list.List) formulaArg
if x.Type != ArgNumber {
return x
}
- numbers := []float64{}
+ var numbers []float64
for _, arg := range array {
if arg.Type == ArgError {
return arg
@@ -6175,10 +8844,10 @@ func (fn *formulaFuncs) percentrank(name string, argsList *list.List) formulaArg
pos--
pos += (x.Number - numbers[int(pos)]) / (cmp - numbers[int(pos)])
}
- pow := math.Pow(10, float64(significance.Number))
- digit := pow * float64(pos) / (float64(cnt) - 1)
+ pow := math.Pow(10, significance.Number)
+ digit := pow * pos / (float64(cnt) - 1)
if name == "PERCENTRANK.EXC" {
- digit = pow * float64(pos+1) / (float64(cnt) + 1)
+ digit = pow * (pos + 1) / (float64(cnt) + 1)
}
return newNumberFormulaArg(math.Floor(digit) / pow)
}
@@ -6260,6 +8929,22 @@ func (fn *formulaFuncs) PERMUTATIONA(argsList *list.List) formulaArg {
return newNumberFormulaArg(math.Pow(num, numChosen))
}
+// PHI function returns the value of the density function for a standard normal
+// distribution for a supplied number. The syntax of the function is:
+//
+// PHI(x)
+//
+func (fn *formulaFuncs) PHI(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "PHI requires 1 argument")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ return newNumberFormulaArg(0.39894228040143268 * math.Exp(-(x.Number*x.Number)/2))
+}
+
// QUARTILE function returns a requested quartile of a supplied range of
// values. The syntax of the function is:
//
@@ -6329,7 +9014,7 @@ func (fn *formulaFuncs) rank(name string, argsList *list.List) formulaArg {
if num.Type != ArgNumber {
return num
}
- arr := []float64{}
+ var arr []float64
for _, arg := range argsList.Front().Next().Value.(formulaArg).ToList() {
n := arg.ToNumber()
if n.Type == ArgNumber {
@@ -6352,7 +9037,7 @@ func (fn *formulaFuncs) rank(name string, argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
-// RANK.EQ function returns the statistical rank of a given value, within a
+// RANKdotEQ function returns the statistical rank of a given value, within a
// supplied array of values. If there are duplicate values in the list, these
// are given the same rank. The syntax of the function is:
//
@@ -6403,77 +9088,436 @@ func (fn *formulaFuncs) SKEW(argsList *list.List) formulaArg {
}
}
}
- if count > 2 {
- return newNumberFormulaArg(summer * (count / ((count - 1) * (count - 2))))
+ if count > 2 {
+ return newNumberFormulaArg(summer * (count / ((count - 1) * (count - 2))))
+ }
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+}
+
+// SMALL function returns the k'th smallest value from an array of numeric
+// values. The syntax of the function is:
+//
+// SMALL(array,k)
+//
+func (fn *formulaFuncs) SMALL(argsList *list.List) formulaArg {
+ return fn.kth("SMALL", argsList)
+}
+
+// STANDARDIZE function returns a normalized value of a distribution that is
+// characterized by a supplied mean and standard deviation. The syntax of the
+// function is:
+//
+// STANDARDIZE(x,mean,standard_dev)
+//
+func (fn *formulaFuncs) STANDARDIZE(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "STANDARDIZE requires 3 arguments")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ mean := argsList.Front().Next().Value.(formulaArg).ToNumber()
+ if mean.Type != ArgNumber {
+ return mean
+ }
+ stdDev := argsList.Back().Value.(formulaArg).ToNumber()
+ if stdDev.Type != ArgNumber {
+ return stdDev
+ }
+ if stdDev.Number <= 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newNumberFormulaArg((x.Number - mean.Number) / stdDev.Number)
+}
+
+// stdevp is an implementation of the formula functions STDEVP and STDEV.P.
+func (fn *formulaFuncs) stdevp(name string, argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
+ }
+ varp := fn.VARP(argsList)
+ if varp.Type != ArgNumber {
+ return varp
+ }
+ return newNumberFormulaArg(math.Sqrt(varp.Number))
+}
+
+// STDEVP function calculates the standard deviation of a supplied set of
+// values. The syntax of the function is:
+//
+// STDEVP(number1,[number2],...)
+//
+func (fn *formulaFuncs) STDEVP(argsList *list.List) formulaArg {
+ return fn.stdevp("STDEVP", argsList)
+}
+
+// STDEVdotP function calculates the standard deviation of a supplied set of
+// values.
+//
+// STDEV.P( number1, [number2], ... )
+//
+func (fn *formulaFuncs) STDEVdotP(argsList *list.List) formulaArg {
+ return fn.stdevp("STDEV.P", argsList)
+}
+
+// getTDist is an implementation for the beta distribution probability density
+// function.
+func getTDist(T, fDF, nType float64) float64 {
+ var res float64
+ switch nType {
+ case 1:
+ res = 0.5 * getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
+ break
+ case 2:
+ res = getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
+ break
+ case 3:
+ res = math.Pow(1+(T*T/fDF), -(fDF+1)/2) / (math.Sqrt(fDF) * getBeta(0.5, fDF/2.0))
+ break
+ case 4:
+ X := fDF / (T*T + fDF)
+ R := 0.5 * getBetaDist(X, 0.5*fDF, 0.5)
+ res = 1 - R
+ if T < 0 {
+ res = R
+ }
+ break
+ }
+ return res
+}
+
+// TdotDIST function calculates the one-tailed Student's T Distribution, which
+// is a continuous probability distribution that is frequently used for
+// testing hypotheses on small sample data sets. The syntax of the function
+// is:
+//
+// T.DIST(x,degrees_freedom,cumulative)
+//
+func (fn *formulaFuncs) TdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.DIST requires 3 arguments")
+ }
+ var x, degrees, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ if cumulative.Number == 1 && degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 0 {
+ if degrees.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if degrees.Number == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 3))
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 4))
+}
+
+// TdotDISTdot2T function calculates the two-tailed Student's T Distribution,
+// which is a continuous probability distribution that is frequently used for
+// testing hypotheses on small sample data sets. The syntax of the function
+// is:
+//
+// T.DIST.2T(x,degrees_freedom)
+//
+func (fn *formulaFuncs) TdotDISTdot2T(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.DIST.2T requires 2 arguments")
+ }
+ var x, degrees formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
}
- return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if x.Number < 0 || degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 2))
}
-// SMALL function returns the k'th smallest value from an array of numeric
-// values. The syntax of the function is:
+// TdotDISTdotRT function calculates the right-tailed Student's T Distribution,
+// which is a continuous probability distribution that is frequently used for
+// testing hypotheses on small sample data sets. The syntax of the function
+// is:
//
-// SMALL(array,k)
+// T.DIST.RT(x,degrees_freedom)
//
-func (fn *formulaFuncs) SMALL(argsList *list.List) formulaArg {
- return fn.kth("SMALL", argsList)
+func (fn *formulaFuncs) TdotDISTdotRT(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.DIST.RT requires 2 arguments")
+ }
+ var x, degrees formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ v := getTDist(x.Number, degrees.Number, 1)
+ if x.Number < 0 {
+ v = 1 - v
+ }
+ return newNumberFormulaArg(v)
}
-// STANDARDIZE function returns a normalized value of a distribution that is
-// characterized by a supplied mean and standard deviation. The syntax of the
-// function is:
+// TDIST function calculates the Student's T Distribution, which is a
+// continuous probability distribution that is frequently used for testing
+// hypotheses on small sample data sets. The syntax of the function is:
//
-// STANDARDIZE(x,mean,standard_dev)
+// TDIST(x,degrees_freedom,tails)
//
-func (fn *formulaFuncs) STANDARDIZE(argsList *list.List) formulaArg {
+func (fn *formulaFuncs) TDIST(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
- return newErrorFormulaArg(formulaErrorVALUE, "STANDARDIZE requires 3 arguments")
+ return newErrorFormulaArg(formulaErrorVALUE, "TDIST requires 3 arguments")
}
- x := argsList.Front().Value.(formulaArg).ToNumber()
- if x.Type != ArgNumber {
+ var x, degrees, tails formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
return x
}
- mean := argsList.Front().Next().Value.(formulaArg).ToNumber()
- if mean.Type != ArgNumber {
- return mean
+ if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
}
- stdDev := argsList.Back().Value.(formulaArg).ToNumber()
- if stdDev.Type != ArgNumber {
- return stdDev
+ if tails = argsList.Back().Value.(formulaArg).ToNumber(); tails.Type != ArgNumber {
+ return tails
}
- if stdDev.Number <= 0 {
- return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ if x.Number < 0 || degrees.Number < 1 || (tails.Number != 1 && tails.Number != 2) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newNumberFormulaArg((x.Number - mean.Number) / stdDev.Number)
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, tails.Number))
}
-// stdevp is an implementation of the formula functions STDEVP and STDEV.P.
-func (fn *formulaFuncs) stdevp(name string, argsList *list.List) formulaArg {
- if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
+// TdotINV function calculates the left-tailed inverse of the Student's T
+// Distribution, which is a continuous probability distribution that is
+// frequently used for testing hypotheses on small sample data sets. The
+// syntax of the function is:
+//
+// T.INV(probability,degrees_freedom)
+//
+func (fn *formulaFuncs) TdotINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.INV requires 2 arguments")
}
- varp := fn.VARP(argsList)
- if varp.Type != ArgNumber {
- return varp
+ var probability, degrees formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
}
- return newNumberFormulaArg(math.Sqrt(varp.Number))
+ if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if probability.Number <= 0 || probability.Number >= 1 || degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if probability.Number < 0.5 {
+ return newNumberFormulaArg(-calcIterateInverse(calcInverseIterator{
+ name: "T.INV",
+ fp: 1 - probability.Number,
+ fDF: degrees.Number,
+ nT: 4,
+ }, degrees.Number/2, degrees.Number))
+ }
+ return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
+ name: "T.INV",
+ fp: probability.Number,
+ fDF: degrees.Number,
+ nT: 4,
+ }, degrees.Number/2, degrees.Number))
+}
+
+// TdotINVdot2T function calculates the inverse of the two-tailed Student's T
+// Distribution, which is a continuous probability distribution that is
+// frequently used for testing hypotheses on small sample data sets. The
+// syntax of the function is:
+//
+// T.INV.2T(probability,degrees_freedom)
+//
+func (fn *formulaFuncs) TdotINVdot2T(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.INV.2T requires 2 arguments")
+ }
+ var probability, degrees formulaArg
+ if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if probability.Number <= 0 || probability.Number > 1 || degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
+ name: "T.INV.2T",
+ fp: probability.Number,
+ fDF: degrees.Number,
+ nT: 2,
+ }, degrees.Number/2, degrees.Number))
}
-// STDEVP function calculates the standard deviation of a supplied set of
-// values. The syntax of the function is:
+// TINV function calculates the inverse of the two-tailed Student's T
+// Distribution, which is a continuous probability distribution that is
+// frequently used for testing hypotheses on small sample data sets. The
+// syntax of the function is:
//
-// STDEVP(number1,[number2],...)
+// TINV(probability,degrees_freedom)
//
-func (fn *formulaFuncs) STDEVP(argsList *list.List) formulaArg {
- return fn.stdevp("STDEVP", argsList)
+func (fn *formulaFuncs) TINV(argsList *list.List) formulaArg {
+ if argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "TINV requires 2 arguments")
+ }
+ return fn.TdotINVdot2T(argsList)
+}
+
+// tTest calculates the probability associated with the Student's T Test.
+func tTest(bTemplin bool, pMat1, pMat2 [][]formulaArg, nC1, nC2, nR1, nR2 int, fT, fF float64) (float64, float64, bool) {
+ var fCount1, fCount2, fSum1, fSumSqr1, fSum2, fSumSqr2 float64
+ var fVal formulaArg
+ for i := 0; i < nC1; i++ {
+ for j := 0; j < nR1; j++ {
+ fVal = pMat1[i][j].ToNumber()
+ if fVal.Type == ArgNumber {
+ fSum1 += fVal.Number
+ fSumSqr1 += fVal.Number * fVal.Number
+ fCount1++
+ }
+ }
+ }
+ for i := 0; i < nC2; i++ {
+ for j := 0; j < nR2; j++ {
+ fVal = pMat2[i][j].ToNumber()
+ if fVal.Type == ArgNumber {
+ fSum2 += fVal.Number
+ fSumSqr2 += fVal.Number * fVal.Number
+ fCount2++
+ }
+ }
+ }
+ if fCount1 < 2.0 || fCount2 < 2.0 {
+ return 0, 0, false
+ }
+ if bTemplin {
+ fS1 := (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1) / fCount1
+ fS2 := (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1) / fCount2
+ if fS1+fS2 == 0 {
+ return 0, 0, false
+ }
+ c := fS1 / (fS1 + fS2)
+ fT = math.Abs(fSum1/fCount1-fSum2/fCount2) / math.Sqrt(fS1+fS2)
+ fF = 1 / (c*c/(fCount1-1) + (1-c)*(1-c)/(fCount2-1))
+ return fT, fF, true
+ }
+ fS1 := (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1)
+ fS2 := (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1)
+ fT = math.Abs(fSum1/fCount1-fSum2/fCount2) / math.Sqrt((fCount1-1)*fS1+(fCount2-1)*fS2) * math.Sqrt(fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2))
+ fF = fCount1 + fCount2 - 2
+ return fT, fF, true
+}
+
+// tTest is an implementation of the formula function TTEST.
+func (fn *formulaFuncs) tTest(pMat1, pMat2 [][]formulaArg, fTails, fTyp float64) formulaArg {
+ var fT, fF float64
+ nC1 := len(pMat1)
+ nC2 := len(pMat2)
+ nR1 := len(pMat1[0])
+ nR2 := len(pMat2[0])
+ ok := true
+ if fTyp == 1 {
+ if nC1 != nC2 || nR1 != nR2 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ var fCount, fSum1, fSum2, fSumSqrD float64
+ var fVal1, fVal2 formulaArg
+ for i := 0; i < nC1; i++ {
+ for j := 0; j < nR1; j++ {
+ fVal1 = pMat1[i][j].ToNumber()
+ fVal2 = pMat2[i][j].ToNumber()
+ if fVal1.Type != ArgNumber || fVal2.Type != ArgNumber {
+ continue
+ }
+ fSum1 += fVal1.Number
+ fSum2 += fVal2.Number
+ fSumSqrD += (fVal1.Number - fVal2.Number) * (fVal1.Number - fVal2.Number)
+ fCount++
+ }
+ }
+ if fCount < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ fSumD := fSum1 - fSum2
+ fDivider := fCount*fSumSqrD - fSumD*fSumD
+ if fDivider == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ fT = math.Abs(fSumD) * math.Sqrt((fCount-1)/fDivider)
+ fF = fCount - 1
+ } else if fTyp == 2 {
+ fT, fF, ok = tTest(false, pMat1, pMat2, nC1, nC2, nR1, nR2, fT, fF)
+ } else {
+ fT, fF, ok = tTest(true, pMat1, pMat2, nC1, nC2, nR1, nR2, fT, fF)
+ }
+ if !ok {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(getTDist(fT, fF, fTails))
}
-// STDEVdotP function calculates the standard deviation of a supplied set of
-// values.
+// TTEST function calculates the probability associated with the Student's T
+// Test, which is commonly used for identifying whether two data sets are
+// likely to have come from the same two underlying populations with the same
+// mean. The syntax of the function is:
//
-// STDEV.P( number1, [number2], ... )
+// TTEST(array1,array2,tails,type)
//
-func (fn *formulaFuncs) STDEVdotP(argsList *list.List) formulaArg {
- return fn.stdevp("STDEV.P", argsList)
+func (fn *formulaFuncs) TTEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "TTEST requires 4 arguments")
+ }
+ var array1, array2, tails, typeArg formulaArg
+ array1 = argsList.Front().Value.(formulaArg)
+ array2 = argsList.Front().Next().Value.(formulaArg)
+ if tails = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); tails.Type != ArgNumber {
+ return tails
+ }
+ if typeArg = argsList.Back().Value.(formulaArg).ToNumber(); typeArg.Type != ArgNumber {
+ return typeArg
+ }
+ if len(array1.Matrix) == 0 || len(array2.Matrix) == 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if tails.Number != 1 && tails.Number != 2 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if typeArg.Number != 1 && typeArg.Number != 2 && typeArg.Number != 3 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return fn.tTest(array1.Matrix, array2.Matrix, tails.Number, typeArg.Number)
+}
+
+// TdotTEST function calculates the probability associated with the Student's T
+// Test, which is commonly used for identifying whether two data sets are
+// likely to have come from the same two underlying populations with the same
+// mean. The syntax of the function is:
+//
+// T.TEST(array1,array2,tails,type)
+//
+func (fn *formulaFuncs) TdotTEST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.TEST requires 4 arguments")
+ }
+ return fn.TTEST(argsList)
}
// TRIMMEAN function calculates the trimmed mean (or truncated mean) of a
@@ -6492,7 +9536,7 @@ func (fn *formulaFuncs) TRIMMEAN(argsList *list.List) formulaArg {
if percent.Number < 0 || percent.Number >= 1 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- arr := []float64{}
+ var arr []float64
arrArg := argsList.Front().Value.(formulaArg).ToList()
for _, cell := range arrArg {
num := cell.ToNumber()
@@ -6534,14 +9578,14 @@ func (fn *formulaFuncs) vars(name string, argsList *list.List) formulaArg {
for _, token := range arg.Value.(formulaArg).ToList() {
num := token.ToNumber()
if token.Value() != "TRUE" && num.Type == ArgNumber {
- summerA += (num.Number * num.Number)
+ summerA += num.Number * num.Number
summerB += num.Number
count++
continue
}
num = token.ToBool()
if num.Type == ArgNumber {
- summerA += (num.Number * num.Number)
+ summerA += num.Number * num.Number
summerB += num.Number
count++
continue
@@ -6632,10 +9676,10 @@ func (fn *formulaFuncs) WEIBULL(argsList *list.List) formulaArg {
}
cumulative := argsList.Back().Value.(formulaArg).ToBool()
if cumulative.Boolean && cumulative.Number == 1 {
- return newNumberFormulaArg(1 - math.Exp(0-math.Pow((x.Number/beta.Number), alpha.Number)))
+ return newNumberFormulaArg(1 - math.Exp(0-math.Pow(x.Number/beta.Number, alpha.Number)))
}
return newNumberFormulaArg((alpha.Number / math.Pow(beta.Number, alpha.Number)) *
- math.Pow(x.Number, (alpha.Number-1)) * math.Exp(0-math.Pow((x.Number/beta.Number), alpha.Number)))
+ math.Pow(x.Number, alpha.Number-1) * math.Exp(0-math.Pow(x.Number/beta.Number, alpha.Number)))
}
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
@@ -6710,6 +9754,29 @@ func (fn *formulaFuncs) ZTEST(argsList *list.List) formulaArg {
// Information Functions
+// ERRORdotTYPE function receives an error value and returns an integer, that
+// tells you the type of the supplied error. The syntax of the function is:
+//
+// ERROR.TYPE(error_val)
+//
+func (fn *formulaFuncs) ERRORdotTYPE(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "ERROR.TYPE requires 1 argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ if token.Type == ArgError {
+ for i, errType := range []string{
+ formulaErrorNULL, formulaErrorDIV, formulaErrorVALUE, formulaErrorREF,
+ formulaErrorNAME, formulaErrorNUM, formulaErrorNA,
+ } {
+ if errType == token.String {
+ return newNumberFormulaArg(float64(i) + 1)
+ }
+ }
+ }
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+}
+
// ISBLANK function tests if a specified cell is blank (empty) and if so,
// returns TRUE; Otherwise the function returns FALSE. The syntax of the
// function is:
@@ -6745,7 +9812,7 @@ func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorVALUE, "ISERR requires 1 argument")
}
token := argsList.Front().Value.(formulaArg)
- result := "FALSE"
+ result := false
if token.Type == ArgError {
for _, errType := range []string{
formulaErrorDIV, formulaErrorNAME, formulaErrorNUM,
@@ -6753,11 +9820,11 @@ func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
formulaErrorSPILL, formulaErrorCALC, formulaErrorGETTINGDATA,
} {
if errType == token.String {
- result = "TRUE"
+ result = true
}
}
}
- return newStringFormulaArg(result)
+ return newBoolFormulaArg(result)
}
// ISERROR function tests if an initial supplied expression (or value) returns
@@ -6771,7 +9838,7 @@ func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorVALUE, "ISERROR requires 1 argument")
}
token := argsList.Front().Value.(formulaArg)
- result := "FALSE"
+ result := false
if token.Type == ArgError {
for _, errType := range []string{
formulaErrorDIV, formulaErrorNAME, formulaErrorNA, formulaErrorNUM,
@@ -6779,11 +9846,11 @@ func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
formulaErrorCALC, formulaErrorGETTINGDATA,
} {
if errType == token.String {
- result = "TRUE"
+ result = true
}
}
}
- return newStringFormulaArg(result)
+ return newBoolFormulaArg(result)
}
// ISEVEN function tests if a supplied number (or numeric expression)
@@ -6869,7 +9936,7 @@ func (fn *formulaFuncs) ISNA(argsList *list.List) formulaArg {
return newStringFormulaArg(result)
}
-// ISNONTEXT function function tests if a supplied value is text. If not, the
+// ISNONTEXT function tests if a supplied value is text. If not, the
// function returns TRUE; If the supplied value is text, the function returns
// FALSE. The syntax of the function is:
//
@@ -6887,7 +9954,7 @@ func (fn *formulaFuncs) ISNONTEXT(argsList *list.List) formulaArg {
return newStringFormulaArg(result)
}
-// ISNUMBER function function tests if a supplied value is a number. If so,
+// ISNUMBER function tests if a supplied value is a number. If so,
// the function returns TRUE; Otherwise it returns FALSE. The syntax of the
// function is:
//
@@ -7061,6 +10128,32 @@ func (fn *formulaFuncs) SHEETS(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
+// TYPE function returns an integer that represents the value's data type. The
+// syntax of the function is:
+//
+// TYPE(value)
+//
+func (fn *formulaFuncs) TYPE(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "TYPE requires 1 argument")
+ }
+ token := argsList.Front().Value.(formulaArg)
+ switch token.Type {
+ case ArgError:
+ return newNumberFormulaArg(16)
+ case ArgMatrix:
+ return newNumberFormulaArg(64)
+ default:
+ if arg := token.ToNumber(); arg.Type != ArgError || len(token.Value()) == 0 {
+ return newNumberFormulaArg(1)
+ }
+ if arg := token.ToBool(); arg.Type != ArgError {
+ return newNumberFormulaArg(4)
+ }
+ return newNumberFormulaArg(2)
+ }
+}
+
// T function tests if a supplied value is text and if so, returns the
// supplied text; Otherwise, the function returns an empty text string. The
// syntax of the function is:
@@ -7124,7 +10217,7 @@ func (fn *formulaFuncs) AND(argsList *list.List) formulaArg {
return newBoolFormulaArg(and)
}
-// FALSE function function returns the logical value FALSE. The syntax of the
+// FALSE function returns the logical value FALSE. The syntax of the
// function is:
//
// FALSE()
@@ -7214,7 +10307,6 @@ func (fn *formulaFuncs) NOT(argsList *list.List) formulaArg {
case ArgNumber:
return newBoolFormulaArg(!(token.Number != 0))
case ArgError:
-
return token
}
return newErrorFormulaArg(formulaErrorVALUE, "NOT expects 1 boolean or numeric argument")
@@ -7453,16 +10545,16 @@ func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
diff--
}
case "m":
- ydiff := ey - sy
- mdiff := em - sm
+ yDiff := ey - sy
+ mDiff := em - sm
if ed < sd {
- mdiff--
+ mDiff--
}
- if mdiff < 0 {
- ydiff--
- mdiff += 12
+ if mDiff < 0 {
+ yDiff--
+ mDiff += 12
}
- diff = float64(ydiff*12 + mdiff)
+ diff = float64(yDiff*12 + mDiff)
case "d", "md", "ym", "yd":
diff = calcDateDif(unit, diff, []int{ey, sy, em, sm, ed, sd}, startArg, endArg)
default:
@@ -7474,8 +10566,8 @@ func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
// isDateOnlyFmt check if the given string matches date-only format regular expressions.
func isDateOnlyFmt(dateString string) bool {
for _, df := range dateOnlyFormats {
- submatch := df.FindStringSubmatch(dateString)
- if len(submatch) > 1 {
+ subMatch := df.FindStringSubmatch(dateString)
+ if len(subMatch) > 1 {
return true
}
}
@@ -7485,8 +10577,8 @@ func isDateOnlyFmt(dateString string) bool {
// isTimeOnlyFmt check if the given string matches time-only format regular expressions.
func isTimeOnlyFmt(timeString string) bool {
for _, tf := range timeFormats {
- submatch := tf.FindStringSubmatch(timeString)
- if len(submatch) > 1 {
+ subMatch := tf.FindStringSubmatch(timeString)
+ if len(subMatch) > 1 {
return true
}
}
@@ -7495,50 +10587,51 @@ func isTimeOnlyFmt(timeString string) bool {
// strToTimePatternHandler1 parse and convert the given string in pattern
// hh to the time.
-func strToTimePatternHandler1(submatch []string) (h, m int, s float64, err error) {
- h, err = strconv.Atoi(submatch[0])
+func strToTimePatternHandler1(subMatch []string) (h, m int, s float64, err error) {
+ h, err = strconv.Atoi(subMatch[0])
return
}
// strToTimePatternHandler2 parse and convert the given string in pattern
// hh:mm to the time.
-func strToTimePatternHandler2(submatch []string) (h, m int, s float64, err error) {
- if h, err = strconv.Atoi(submatch[0]); err != nil {
+func strToTimePatternHandler2(subMatch []string) (h, m int, s float64, err error) {
+ if h, err = strconv.Atoi(subMatch[0]); err != nil {
return
}
- m, err = strconv.Atoi(submatch[2])
+ m, err = strconv.Atoi(subMatch[2])
return
}
// strToTimePatternHandler3 parse and convert the given string in pattern
// mm:ss to the time.
-func strToTimePatternHandler3(submatch []string) (h, m int, s float64, err error) {
- if m, err = strconv.Atoi(submatch[0]); err != nil {
+func strToTimePatternHandler3(subMatch []string) (h, m int, s float64, err error) {
+ if m, err = strconv.Atoi(subMatch[0]); err != nil {
return
}
- s, err = strconv.ParseFloat(submatch[2], 64)
+ s, err = strconv.ParseFloat(subMatch[2], 64)
return
}
// strToTimePatternHandler4 parse and convert the given string in pattern
// hh:mm:ss to the time.
-func strToTimePatternHandler4(submatch []string) (h, m int, s float64, err error) {
- if h, err = strconv.Atoi(submatch[0]); err != nil {
+func strToTimePatternHandler4(subMatch []string) (h, m int, s float64, err error) {
+ if h, err = strconv.Atoi(subMatch[0]); err != nil {
return
}
- if m, err = strconv.Atoi(submatch[2]); err != nil {
+ if m, err = strconv.Atoi(subMatch[2]); err != nil {
return
}
- s, err = strconv.ParseFloat(submatch[4], 64)
+ s, err = strconv.ParseFloat(subMatch[4], 64)
return
}
// strToTime parse and convert the given string to the time.
func strToTime(str string) (int, int, float64, bool, bool, formulaArg) {
- pattern, submatch := "", []string{}
+ var subMatch []string
+ pattern := ""
for key, tf := range timeFormats {
- submatch = tf.FindStringSubmatch(str)
- if len(submatch) > 1 {
+ subMatch = tf.FindStringSubmatch(str)
+ if len(subMatch) > 1 {
pattern = key
break
}
@@ -7546,24 +10639,24 @@ func strToTime(str string) (int, int, float64, bool, bool, formulaArg) {
if pattern == "" {
return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
- dateIsEmpty := submatch[1] == ""
- submatch = submatch[49:]
+ dateIsEmpty := subMatch[1] == ""
+ subMatch = subMatch[49:]
var (
- l = len(submatch)
- last = submatch[l-1]
+ l = len(subMatch)
+ last = subMatch[l-1]
am = last == "am"
pm = last == "pm"
hours, minutes int
seconds float64
err error
)
- if handler, ok := map[string]func(subsubmatch []string) (int, int, float64, error){
+ if handler, ok := map[string]func(match []string) (int, int, float64, error){
"hh": strToTimePatternHandler1,
"hh:mm": strToTimePatternHandler2,
"mm:ss": strToTimePatternHandler3,
"hh:mm:ss": strToTimePatternHandler4,
}[pattern]; ok {
- if hours, minutes, seconds, err = handler(submatch); err != nil {
+ if hours, minutes, seconds, err = handler(subMatch); err != nil {
return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
}
@@ -7584,55 +10677,55 @@ func strToTime(str string) (int, int, float64, bool, bool, formulaArg) {
// strToDatePatternHandler1 parse and convert the given string in pattern
// mm/dd/yy to the date.
-func strToDatePatternHandler1(submatch []string) (int, int, int, bool, error) {
+func strToDatePatternHandler1(subMatch []string) (int, int, int, bool, error) {
var year, month, day int
var err error
- if month, err = strconv.Atoi(submatch[1]); err != nil {
+ if month, err = strconv.Atoi(subMatch[1]); err != nil {
return 0, 0, 0, false, err
}
- if day, err = strconv.Atoi(submatch[3]); err != nil {
+ if day, err = strconv.Atoi(subMatch[3]); err != nil {
return 0, 0, 0, false, err
}
- if year, err = strconv.Atoi(submatch[5]); err != nil {
+ if year, err = strconv.Atoi(subMatch[5]); err != nil {
return 0, 0, 0, false, err
}
if year < 0 || year > 9999 || (year > 99 && year < 1900) {
return 0, 0, 0, false, ErrParameterInvalid
}
- return formatYear(year), month, day, submatch[8] == "", err
+ return formatYear(year), month, day, subMatch[8] == "", err
}
// strToDatePatternHandler2 parse and convert the given string in pattern mm
// dd, yy to the date.
-func strToDatePatternHandler2(submatch []string) (int, int, int, bool, error) {
+func strToDatePatternHandler2(subMatch []string) (int, int, int, bool, error) {
var year, month, day int
var err error
- month = month2num[submatch[1]]
- if day, err = strconv.Atoi(submatch[14]); err != nil {
+ month = month2num[subMatch[1]]
+ if day, err = strconv.Atoi(subMatch[14]); err != nil {
return 0, 0, 0, false, err
}
- if year, err = strconv.Atoi(submatch[16]); err != nil {
+ if year, err = strconv.Atoi(subMatch[16]); err != nil {
return 0, 0, 0, false, err
}
if year < 0 || year > 9999 || (year > 99 && year < 1900) {
return 0, 0, 0, false, ErrParameterInvalid
}
- return formatYear(year), month, day, submatch[19] == "", err
+ return formatYear(year), month, day, subMatch[19] == "", err
}
// strToDatePatternHandler3 parse and convert the given string in pattern
// yy-mm-dd to the date.
-func strToDatePatternHandler3(submatch []string) (int, int, int, bool, error) {
+func strToDatePatternHandler3(subMatch []string) (int, int, int, bool, error) {
var year, month, day int
- v1, err := strconv.Atoi(submatch[1])
+ v1, err := strconv.Atoi(subMatch[1])
if err != nil {
return 0, 0, 0, false, err
}
- v2, err := strconv.Atoi(submatch[3])
+ v2, err := strconv.Atoi(subMatch[3])
if err != nil {
return 0, 0, 0, false, err
}
- v3, err := strconv.Atoi(submatch[5])
+ v3, err := strconv.Atoi(subMatch[5])
if err != nil {
return 0, 0, 0, false, err
}
@@ -7647,30 +10740,31 @@ func strToDatePatternHandler3(submatch []string) (int, int, int, bool, error) {
} else {
return 0, 0, 0, false, ErrParameterInvalid
}
- return year, month, day, submatch[8] == "", err
+ return year, month, day, subMatch[8] == "", err
}
// strToDatePatternHandler4 parse and convert the given string in pattern
// yy-mmStr-dd, yy to the date.
-func strToDatePatternHandler4(submatch []string) (int, int, int, bool, error) {
+func strToDatePatternHandler4(subMatch []string) (int, int, int, bool, error) {
var year, month, day int
var err error
- if year, err = strconv.Atoi(submatch[16]); err != nil {
+ if year, err = strconv.Atoi(subMatch[16]); err != nil {
return 0, 0, 0, false, err
}
- month = month2num[submatch[3]]
- if day, err = strconv.Atoi(submatch[1]); err != nil {
+ month = month2num[subMatch[3]]
+ if day, err = strconv.Atoi(subMatch[1]); err != nil {
return 0, 0, 0, false, err
}
- return formatYear(year), month, day, submatch[19] == "", err
+ return formatYear(year), month, day, subMatch[19] == "", err
}
// strToDate parse and convert the given string to the date.
func strToDate(str string) (int, int, int, bool, formulaArg) {
- pattern, submatch := "", []string{}
+ var subMatch []string
+ pattern := ""
for key, df := range dateFormats {
- submatch = df.FindStringSubmatch(str)
- if len(submatch) > 1 {
+ subMatch = df.FindStringSubmatch(str)
+ if len(subMatch) > 1 {
pattern = key
break
}
@@ -7683,13 +10777,13 @@ func strToDate(str string) (int, int, int, bool, formulaArg) {
year, month, day int
err error
)
- if handler, ok := map[string]func(subsubmatch []string) (int, int, int, bool, error){
+ if handler, ok := map[string]func(match []string) (int, int, int, bool, error){
"mm/dd/yy": strToDatePatternHandler1,
"mm dd, yy": strToDatePatternHandler2,
"yy-mm-dd": strToDatePatternHandler3,
"yy-mmStr-dd": strToDatePatternHandler4,
}[pattern]; ok {
- if year, month, day, timeIsEmpty, err = handler(submatch); err != nil {
+ if year, month, day, timeIsEmpty, err = handler(subMatch); err != nil {
return 0, 0, 0, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
}
@@ -7701,8 +10795,8 @@ func strToDate(str string) (int, int, int, bool, formulaArg) {
// DATEVALUE function converts a text representation of a date into an Excel
// date. For example, the function converts a text string representing a
-// date, into the serial number that represents the date in Excel's date-time
-// code. The syntax of the function is:
+// date, into the serial number that represents the date in Excels' date-time
+// code. The syntax of the function is:
//
// DATEVALUE(date_text)
//
@@ -7785,7 +10879,7 @@ func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
}
date := argsList.Front().Value.(formulaArg)
num := date.ToNumber()
- weeknum := 0
+ weekNum := 0
if num.Type != ArgNumber {
dateString := strings.ToLower(date.Value())
if !isDateOnlyFmt(dateString) {
@@ -7797,14 +10891,48 @@ func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
if err.Type == ArgError {
return err
}
- _, weeknum = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC).ISOWeek()
+ _, weekNum = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC).ISOWeek()
} else {
if num.Number < 0 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- _, weeknum = timeFromExcelTime(num.Number, false).ISOWeek()
+ _, weekNum = timeFromExcelTime(num.Number, false).ISOWeek()
+ }
+ return newNumberFormulaArg(float64(weekNum))
+}
+
+// HOUR function returns an integer representing the hour component of a
+// supplied Excel time. The syntax of the function is:
+//
+// HOUR(serial_number)
+//
+func (fn *formulaFuncs) HOUR(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "HOUR requires exactly 1 argument")
+ }
+ date := argsList.Front().Value.(formulaArg)
+ num := date.ToNumber()
+ if num.Type != ArgNumber {
+ timeString := strings.ToLower(date.Value())
+ if !isTimeOnlyFmt(timeString) {
+ _, _, _, _, err := strToDate(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ }
+ h, _, _, pm, _, err := strToTime(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ if pm {
+ h += 12
+ }
+ return newNumberFormulaArg(float64(h))
+ }
+ if num.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, "HOUR only accepts positive argument")
}
- return newNumberFormulaArg(float64(weeknum))
+ return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Hour()))
}
// MINUTE function returns an integer representing the minute component of a
@@ -8054,9 +11182,40 @@ func (fn *formulaFuncs) NOW(argsList *list.List) formulaArg {
return newNumberFormulaArg(25569.0 + float64(now.Unix()+int64(offset))/86400)
}
+// SECOND function returns an integer representing the second component of a
+// supplied Excel time. The syntax of the function is:
+//
+// SECOND(serial_number)
+//
+func (fn *formulaFuncs) SECOND(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "SECOND requires exactly 1 argument")
+ }
+ date := argsList.Front().Value.(formulaArg)
+ num := date.ToNumber()
+ if num.Type != ArgNumber {
+ timeString := strings.ToLower(date.Value())
+ if !isTimeOnlyFmt(timeString) {
+ _, _, _, _, err := strToDate(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ }
+ _, _, s, _, _, err := strToTime(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ return newNumberFormulaArg(float64(int(s) % 60))
+ }
+ if num.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, "SECOND only accepts positive argument")
+ }
+ return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Second()))
+}
+
// TIME function accepts three integer arguments representing hours, minutes
// and seconds, and returns an Excel time. I.e. the function returns the
-// decimal value that represents the time in Excel. The syntax of the Time
+// decimal value that represents the time in Excel. The syntax of the
// function is:
//
// TIME(hour,minute,second)
@@ -8078,6 +11237,37 @@ func (fn *formulaFuncs) TIME(argsList *list.List) formulaArg {
return newNumberFormulaArg(t)
}
+// TIMEVALUE function converts a text representation of a time, into an Excel
+// time. The syntax of the function is:
+//
+// TIMEVALUE(time_text)
+//
+func (fn *formulaFuncs) TIMEVALUE(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "TIMEVALUE requires exactly 1 argument")
+ }
+ date := argsList.Front().Value.(formulaArg)
+ timeString := strings.ToLower(date.Value())
+ if !isTimeOnlyFmt(timeString) {
+ _, _, _, _, err := strToDate(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ }
+ h, m, s, pm, _, err := strToTime(timeString)
+ if err.Type == ArgError {
+ return err
+ }
+ if pm {
+ h += 12
+ }
+ args := list.New()
+ args.PushBack(newNumberFormulaArg(float64(h)))
+ args.PushBack(newNumberFormulaArg(float64(m)))
+ args.PushBack(newNumberFormulaArg(s))
+ return fn.TIME(args)
+}
+
// TODAY function returns the current date. The function has no arguments and
// therefore. The syntax of the function is:
//
@@ -9011,19 +12201,18 @@ func matchPattern(pattern, name string) (matched bool) {
if pattern == "*" {
return true
}
- rname, rpattern := make([]rune, 0, len(name)), make([]rune, 0, len(pattern))
+ rName, rPattern := make([]rune, 0, len(name)), make([]rune, 0, len(pattern))
for _, r := range name {
- rname = append(rname, r)
+ rName = append(rName, r)
}
for _, r := range pattern {
- rpattern = append(rpattern, r)
+ rPattern = append(rPattern, r)
}
- simple := false // Does extended wildcard '*' and '?' match.
- return deepMatchRune(rname, rpattern, simple)
+ return deepMatchRune(rName, rPattern, false)
}
-// compareFormulaArg compares the left-hand sides and the right-hand sides
-// formula arguments by given conditions such as case sensitive, if exact
+// compareFormulaArg compares the left-hand sides and the right-hand sides'
+// formula arguments by given conditions such as case-sensitive, if exact
// match, and make compare result as formula criteria condition type.
func compareFormulaArg(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte {
if lhs.Type != rhs.Type {
@@ -9047,7 +12236,6 @@ func compareFormulaArg(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte
if matchPattern(rs, ls) {
return criteriaEq
}
-
}
return map[int]byte{1: criteriaG, -1: criteriaL, 0: criteriaEq}[strings.Compare(ls, rs)]
case ArgEmpty:
@@ -9078,7 +12266,7 @@ func compareFormulaArgList(lhs, rhs, matchMode formulaArg, caseSensitive bool) b
return criteriaEq
}
-// compareFormulaArgMatrix compares the left-hand sides and the right-hand sides
+// compareFormulaArgMatrix compares the left-hand sides and the right-hand sides'
// matrix type formula arguments.
func compareFormulaArgMatrix(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte {
if len(lhs.Matrix) < len(rhs.Matrix) {
@@ -9191,6 +12379,32 @@ func (fn *formulaFuncs) COLUMNS(argsList *list.List) formulaArg {
return newNumberFormulaArg(float64(result))
}
+// FORMULATEXT function returns a formula as a text string. The syntax of the
+// function is:
+//
+// FORMULATEXT(reference)
+//
+func (fn *formulaFuncs) FORMULATEXT(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "FORMULATEXT requires 1 argument")
+ }
+ refs := argsList.Front().Value.(formulaArg).cellRefs
+ col, row := 0, 0
+ if refs != nil && refs.Len() > 0 {
+ col, row = refs.Front().Value.(cellRef).Col, refs.Front().Value.(cellRef).Row
+ }
+ ranges := argsList.Front().Value.(formulaArg).cellRanges
+ if ranges != nil && ranges.Len() > 0 {
+ col, row = ranges.Front().Value.(cellRange).From.Col, ranges.Front().Value.(cellRange).From.Row
+ }
+ cell, err := CoordinatesToCellName(col, row)
+ if err != nil {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ formula, _ := fn.f.GetCellFormula(fn.sheet, cell)
+ return newStringFormulaArg(formula)
+}
+
// checkHVLookupArgs checking arguments, prepare extract mode, lookup value,
// and data for the formula functions HLOOKUP and VLOOKUP.
func checkHVLookupArgs(name string, argsList *list.List) (idx int, lookupValue, tableArray, matchMode, errArg formulaArg) {
@@ -9378,7 +12592,7 @@ 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) {
- tableArray := []formulaArg{}
+ var tableArray []formulaArg
if vertical {
for _, row := range lookupArray.Matrix {
tableArray = append(tableArray, row[0])
@@ -9447,7 +12661,7 @@ func (fn *formulaFuncs) VLOOKUP(argsList *list.List) formulaArg {
// is TRUE, if the data of table array can't guarantee be sorted, it will
// return wrong result.
func lookupBinarySearch(vertical bool, lookupValue, lookupArray, matchMode, searchMode formulaArg) (matchIdx int, wasExact bool) {
- tableArray := []formulaArg{}
+ var tableArray []formulaArg
if vertical {
for _, row := range lookupArray.Matrix {
tableArray = append(tableArray, row[0])
@@ -9455,7 +12669,7 @@ func lookupBinarySearch(vertical bool, lookupValue, lookupArray, matchMode, sear
} else {
tableArray = lookupArray.Matrix[0]
}
- var low, high, lastMatchIdx int = 0, len(tableArray) - 1, -1
+ low, high, lastMatchIdx := 0, len(tableArray)-1, -1
count := high
for low <= high {
mid := low + (high-low)/2
@@ -9536,7 +12750,7 @@ func iterateLookupArgs(lookupValue, lookupVector formulaArg) ([]formulaArg, int,
matchIdx = idx
break
}
- // Find nearest match if lookup value is more than or equal to the first value in lookup vector
+ // Find the nearest match if lookup value is more than or equal to the first value in lookup vector
if idx == 0 {
ok = compare == criteriaG
} else if ok && compare == criteriaL && matchIdx == -1 {
@@ -9558,7 +12772,7 @@ func (fn *formulaFuncs) index(array formulaArg, rowIdx, colIdx int) formulaArg {
if colIdx >= len(cellMatrix[0]) {
return newErrorFormulaArg(formulaErrorREF, "INDEX col_num out of range")
}
- column := [][]formulaArg{}
+ var column [][]formulaArg
for _, cells = range cellMatrix {
column = append(column, []formulaArg{cells[colIdx]})
}
@@ -9622,8 +12836,9 @@ func (fn *formulaFuncs) prepareXlookupArgs(argsList *list.List) formulaArg {
// xlookup is an implementation of the formula function XLOOKUP.
func (fn *formulaFuncs) xlookup(lookupRows, lookupCols, returnArrayRows, returnArrayCols, matchIdx int,
- condition1, condition2, condition3, condition4 bool, returnArray formulaArg) formulaArg {
- result := [][]formulaArg{}
+ condition1, condition2, condition3, condition4 bool, returnArray formulaArg,
+) formulaArg {
+ var result [][]formulaArg
for rowIdx, row := range returnArray.Matrix {
for colIdx, cell := range row {
if condition1 {
@@ -9746,6 +12961,68 @@ func (fn *formulaFuncs) INDEX(argsList *list.List) formulaArg {
return cells.List[colIdx]
}
+// INDIRECT function converts a text string into a cell reference. The syntax
+// of the Indirect function is:
+//
+// INDIRECT(ref_text,[a1])
+//
+func (fn *formulaFuncs) INDIRECT(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 && argsList.Len() != 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "INDIRECT requires 1 or 2 arguments")
+ }
+ refText := argsList.Front().Value.(formulaArg).Value()
+ a1 := newBoolFormulaArg(true)
+ if argsList.Len() == 2 {
+ if a1 = argsList.Back().Value.(formulaArg).ToBool(); a1.Type != ArgNumber {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ }
+ R1C1ToA1 := func(ref string) (cell string, err error) {
+ parts := strings.Split(strings.TrimLeft(ref, "R"), "C")
+ if len(parts) != 2 {
+ return
+ }
+ row, err := strconv.Atoi(parts[0])
+ if err != nil {
+ return
+ }
+ col, err := strconv.Atoi(parts[1])
+ if err != nil {
+ return
+ }
+ cell, err = CoordinatesToCellName(col, row)
+ return
+ }
+ refs := strings.Split(refText, ":")
+ fromRef, toRef := refs[0], ""
+ if len(refs) == 2 {
+ toRef = refs[1]
+ }
+ if a1.Number == 0 {
+ from, err := R1C1ToA1(refs[0])
+ if err != nil {
+ return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
+ }
+ fromRef = from
+ if len(refs) == 2 {
+ to, err := R1C1ToA1(refs[1])
+ if err != nil {
+ return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
+ }
+ toRef = to
+ }
+ }
+ if len(refs) == 1 {
+ value, err := fn.f.GetCellValue(fn.sheet, fromRef)
+ if err != nil {
+ return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
+ }
+ return newStringFormulaArg(value)
+ }
+ arg, _ := fn.f.parseReference(fn.sheet, fromRef+":"+toRef)
+ return arg
+}
+
// LOOKUP function performs an approximate match lookup in a one-column or
// one-row range, and returns the corresponding value from another one-column
// or one-row range. The syntax of the function is:
@@ -9899,7 +13176,7 @@ func validateFrequency(freq float64) bool {
return freq == 1 || freq == 2 || freq == 4
}
-// ACCRINT function returns the accrued interest for a security that pays
+// ACCRINT function returns the accrued interest in a security that pays
// periodic interest. The syntax of the function is:
//
// ACCRINT(issue,first_interest,settlement,rate,par,frequency,[basis],[calc_method])
@@ -9931,9 +13208,8 @@ func (fn *formulaFuncs) ACCRINT(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
}
- cm := newBoolFormulaArg(true)
if argsList.Len() == 8 {
- if cm = argsList.Back().Value.(formulaArg).ToBool(); cm.Type != ArgNumber {
+ if cm := argsList.Back().Value.(formulaArg).ToBool(); cm.Type != ArgNumber {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
}
@@ -9944,7 +13220,7 @@ func (fn *formulaFuncs) ACCRINT(argsList *list.List) formulaArg {
return newNumberFormulaArg(par.Number * rate.Number * frac1.Number)
}
-// ACCRINTM function returns the accrued interest for a security that pays
+// ACCRINTM function returns the accrued interest in a security that pays
// interest at maturity. The syntax of the function is:
//
// ACCRINTM(issue,settlement,rate,[par],[basis])
@@ -10111,7 +13387,7 @@ func (fn *formulaFuncs) AMORLINC(argsList *list.List) formulaArg {
if int(period.Number) <= periods {
return newNumberFormulaArg(rate2)
} else if int(period.Number)-1 == periods {
- return newNumberFormulaArg(delta - rate2*float64(periods) - rate1)
+ return newNumberFormulaArg(delta - rate2*float64(periods) - math.Nextafter(rate1, rate1))
}
return newNumberFormulaArg(0)
}
@@ -10154,7 +13430,7 @@ func is30BasisMethod(basis int) bool {
// getDaysInMonthRange return the day by given year, month range and day count
// basis.
-func getDaysInMonthRange(year, fromMonth, toMonth, basis int) int {
+func getDaysInMonthRange(fromMonth, toMonth int) int {
if fromMonth > toMonth {
return 0
}
@@ -10202,14 +13478,12 @@ func coupdays(from, to time.Time, basis int) float64 {
fromDay = 1
date := time.Date(fromY, fromM, fromD, 0, 0, 0, 0, time.UTC).AddDate(0, 1, 0)
if date.Year() < toY {
- days += getDaysInMonthRange(date.Year(), int(date.Month()), 12, basis)
+ days += getDaysInMonthRange(int(date.Month()), 12)
date = date.AddDate(0, 13-int(date.Month()), 0)
}
- days += getDaysInMonthRange(toY, int(date.Month()), int(toM)-1, basis)
- date = date.AddDate(0, int(toM)-int(date.Month()), 0)
+ days += getDaysInMonthRange(int(date.Month()), int(toM)-1)
}
- days += toDay - fromDay
- if days > 0 {
+ if days += toDay - fromDay; days > 0 {
return float64(days)
}
return 0
@@ -10414,7 +13688,7 @@ func (fn *formulaFuncs) cumip(name string, argsList *list.List) formulaArg {
return newNumberFormulaArg(num)
}
-// calcDbArgsCompare implements common arguments comparison for DB and DDB.
+// calcDbArgsCompare implements common arguments' comparison for DB and DDB.
func calcDbArgsCompare(cost, salvage, life, period formulaArg) bool {
return (cost.Number <= 0) || ((salvage.Number / cost.Number) < 0) || (life.Number <= 0) || (period.Number < 1)
}
@@ -10519,7 +13793,7 @@ func (fn *formulaFuncs) DDB(argsList *list.List) formulaArg {
}
pd, depreciation := 0.0, 0.0
for per := 1; per <= int(period.Number); per++ {
- depreciation = math.Min((cost.Number-pd)*(factor.Number/life.Number), (cost.Number - salvage.Number - pd))
+ depreciation = math.Min((cost.Number-pd)*(factor.Number/life.Number), cost.Number-salvage.Number-pd)
pd += depreciation
}
return newNumberFormulaArg(depreciation)
@@ -10529,7 +13803,7 @@ func (fn *formulaFuncs) DDB(argsList *list.List) formulaArg {
// formula functions.
func (fn *formulaFuncs) prepareDataValueArgs(n int, argsList *list.List) formulaArg {
l := list.New()
- dataValues := []formulaArg{}
+ var dataValues []formulaArg
getDateValue := func(arg formulaArg, l *list.List) formulaArg {
switch arg.Type {
case ArgNumber:
@@ -10766,7 +14040,7 @@ func (fn *formulaFuncs) EFFECT(argsList *list.List) formulaArg {
if rate.Number <= 0 || npery.Number < 1 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
- return newNumberFormulaArg(math.Pow((1+rate.Number/npery.Number), npery.Number) - 1)
+ return newNumberFormulaArg(math.Pow(1+rate.Number/npery.Number, npery.Number) - 1)
}
// FV function calculates the Future Value of an investment with periodic
@@ -10836,7 +14110,7 @@ func (fn *formulaFuncs) FVSCHEDULE(argsList *list.List) formulaArg {
if rate.Type != ArgNumber {
return rate
}
- principal *= (1 + rate.Number)
+ principal *= 1 + rate.Number
}
return newNumberFormulaArg(principal)
}
@@ -10996,7 +14270,7 @@ func (fn *formulaFuncs) IRR(argsList *list.List) formulaArg {
if f1.Number*f2.Number < 0 {
break
}
- if math.Abs(f1.Number) < math.Abs((f2.Number)) {
+ if math.Abs(f1.Number) < math.Abs(f2.Number) {
x1.Number += 1.6 * (x1.Number - x2.Number)
args.Front().Value = x1
f1 = fn.NPV(args)
@@ -11027,7 +14301,7 @@ func (fn *formulaFuncs) IRR(argsList *list.List) formulaArg {
if fMid <= 0 {
rtb = xMid
}
- if math.Abs(fMid) < financialPercision || math.Abs(dx) < financialPercision {
+ if math.Abs(fMid) < financialPrecision || math.Abs(dx) < financialPrecision {
break
}
}
@@ -11112,10 +14386,10 @@ func (fn *formulaFuncs) MIRR(argsList *list.List) formulaArg {
for i, v := range values {
val := v.ToNumber()
if val.Number >= 0 {
- npvPos += val.Number / math.Pow(float64(rr), float64(i))
+ npvPos += val.Number / math.Pow(rr, float64(i))
continue
}
- npvNeg += val.Number / math.Pow(float64(fr), float64(i))
+ npvNeg += val.Number / math.Pow(fr, float64(i))
}
if npvNeg == 0 || npvPos == 0 || reinvestRate.Number <= -1 {
return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
@@ -11224,7 +14498,7 @@ func (fn *formulaFuncs) NPV(argsList *list.List) formulaArg {
// aggrBetween is a part of implementation of the formula function ODDFPRICE.
func aggrBetween(startPeriod, endPeriod float64, initialValue []float64, f func(acc []float64, index float64) []float64) []float64 {
- s := []float64{}
+ var s []float64
if startPeriod <= endPeriod {
for i := startPeriod; i <= endPeriod; i++ {
s = append(s, i)
@@ -11262,7 +14536,7 @@ func changeMonth(date time.Time, numMonths float64, returnLastMonth bool) time.T
// datesAggregate is a part of implementation of the formula function
// ODDFPRICE.
-func datesAggregate(startDate, endDate time.Time, numMonths, basis float64, f func(pcd, ncd time.Time) float64, acc float64, returnLastMonth bool) (time.Time, time.Time, float64) {
+func datesAggregate(startDate, endDate time.Time, numMonths float64, f func(pcd, ncd time.Time) float64, acc float64, returnLastMonth bool) (time.Time, time.Time, float64) {
frontDate, trailingDate := startDate, endDate
s1 := frontDate.After(endDate) || frontDate.Equal(endDate)
s2 := endDate.After(frontDate) || endDate.Equal(frontDate)
@@ -11286,7 +14560,7 @@ func datesAggregate(startDate, endDate time.Time, numMonths, basis float64, f fu
}
// coupNumber is a part of implementation of the formula function ODDFPRICE.
-func coupNumber(maturity, settlement, numMonths, basis float64) float64 {
+func coupNumber(maturity, settlement, numMonths float64) float64 {
maturityTime, settlementTime := timeFromExcelTime(maturity, false), timeFromExcelTime(settlement, false)
my, mm, md := maturityTime.Year(), maturityTime.Month(), maturityTime.Day()
sy, sm, sd := settlementTime.Year(), settlementTime.Month(), settlementTime.Day()
@@ -11304,7 +14578,7 @@ func coupNumber(maturity, settlement, numMonths, basis float64) float64 {
f := func(pcd, ncd time.Time) float64 {
return 1
}
- _, _, result := datesAggregate(date, maturityTime, numMonths, basis, f, coupons, endOfMonth)
+ _, _, result := datesAggregate(date, maturityTime, numMonths, f, coupons, endOfMonth)
return result
}
@@ -11375,8 +14649,7 @@ func (fn *formulaFuncs) ODDFPRICE(argsList *list.List) formulaArg {
if args.Type != ArgList {
return args
}
- settlement, maturity, issue, firstCoupon, rate, yld, redemption, frequency, basisArg :=
- args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6], args.List[7], args.List[8]
+ settlement, maturity, issue, firstCoupon, rate, yld, redemption, frequency, basisArg := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6], args.List[7], args.List[8]
if basisArg.Number < 0 || basisArg.Number > 4 {
return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
}
@@ -11390,7 +14663,7 @@ func (fn *formulaFuncs) ODDFPRICE(argsList *list.List) formulaArg {
numMonths := 12 / frequency.Number
numMonthsNeg := -numMonths
mat := changeMonth(maturityTime, numMonthsNeg, returnLastMonth)
- pcd, _, _ := datesAggregate(mat, firstCouponTime, numMonthsNeg, basisArg.Number, func(d1, d2 time.Time) float64 {
+ pcd, _, _ := datesAggregate(mat, firstCouponTime, numMonthsNeg, func(d1, d2 time.Time) float64 {
return 0
}, 0, returnLastMonth)
if !pcd.Equal(firstCouponTime) {
@@ -11471,7 +14744,7 @@ func (fn *formulaFuncs) ODDFPRICE(argsList *list.List) formulaArg {
a := coupdays(d, settlementTime, basis)
dsc = e.Number - a
}
- nq := coupNumber(firstCoupon.Number, settlement.Number, numMonths, basisArg.Number)
+ nq := coupNumber(firstCoupon.Number, settlement.Number, numMonths)
fnArgs.Init()
fnArgs.PushBack(firstCoupon)
fnArgs.PushBack(maturity)
@@ -11560,7 +14833,7 @@ func (fn *formulaFuncs) PMT(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
if rate.Number != 0 {
- p := (-fv.Number - pv.Number*math.Pow((1+rate.Number), nper.Number)) / (1 + rate.Number*typ.Number) / ((math.Pow((1+rate.Number), nper.Number) - 1) / rate.Number)
+ p := (-fv.Number - pv.Number*math.Pow(1+rate.Number, nper.Number)) / (1 + rate.Number*typ.Number) / ((math.Pow(1+rate.Number, nper.Number) - 1) / rate.Number)
return newNumberFormulaArg(p)
}
return newNumberFormulaArg((-pv.Number - fv.Number) / nper.Number)
@@ -11799,19 +15072,21 @@ func (fn *formulaFuncs) PV(argsList *list.List) formulaArg {
}
// rate is an implementation of the formula function RATE.
-func (fn *formulaFuncs) rate(nper, pmt, pv, fv, t, guess formulaArg, argsList *list.List) formulaArg {
- maxIter, iter, close, epsMax, rate := 100, 0, false, 1e-6, guess.Number
- for iter < maxIter && !close {
+func (fn *formulaFuncs) rate(nper, pmt, pv, fv, t, guess formulaArg) formulaArg {
+ maxIter, iter, isClose, epsMax, rate := 100, 0, false, 1e-6, guess.Number
+ for iter < maxIter && !isClose {
t1 := math.Pow(rate+1, nper.Number)
t2 := math.Pow(rate+1, nper.Number-1)
rt := rate*t.Number + 1
p0 := pmt.Number * (t1 - 1)
f1 := fv.Number + t1*pv.Number + p0*rt/rate
- f2 := nper.Number*t2*pv.Number - p0*rt/math.Pow(rate, 2)
+ n1 := nper.Number * t2 * pv.Number
+ n2 := p0 * rt / math.Pow(rate, 2)
+ f2 := math.Nextafter(n1, n1) - math.Nextafter(n2, n2)
f3 := (nper.Number*pmt.Number*t2*rt + p0*t.Number) / rate
delta := f1 / (f2 + f3)
if math.Abs(delta) < epsMax {
- close = true
+ isClose = true
}
iter++
rate -= delta
@@ -11865,7 +15140,7 @@ func (fn *formulaFuncs) RATE(argsList *list.List) formulaArg {
return guess
}
}
- return fn.rate(nper, pmt, pv, fv, t, guess, argsList)
+ return fn.rate(nper, pmt, pv, fv, t, guess)
}
// RECEIVED function calculates the amount received at maturity for a fully
@@ -12209,7 +15484,7 @@ func (fn *formulaFuncs) VDB(argsList *list.List) formulaArg {
}
// prepareXArgs prepare arguments for the formula function XIRR and XNPV.
-func (fn *formulaFuncs) prepareXArgs(name string, values, dates formulaArg) (valuesArg, datesArg []float64, err formulaArg) {
+func (fn *formulaFuncs) prepareXArgs(values, dates formulaArg) (valuesArg, datesArg []float64, err formulaArg) {
for _, arg := range values.ToList() {
if numArg := arg.ToNumber(); numArg.Type == ArgNumber {
valuesArg = append(valuesArg, numArg.Number)
@@ -12317,7 +15592,7 @@ func (fn *formulaFuncs) XIRR(argsList *list.List) formulaArg {
if argsList.Len() != 2 && argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "XIRR requires 2 or 3 arguments")
}
- values, dates, err := fn.prepareXArgs("XIRR", argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg))
+ values, dates, err := fn.prepareXArgs(argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg))
if err.Type != ArgEmpty {
return err
}
@@ -12349,7 +15624,7 @@ func (fn *formulaFuncs) XNPV(argsList *list.List) formulaArg {
if rate.Number <= 0 {
return newErrorFormulaArg(formulaErrorVALUE, "XNPV requires rate > 0")
}
- values, dates, err := fn.prepareXArgs("XNPV", argsList.Front().Next().Value.(formulaArg), argsList.Back().Value.(formulaArg))
+ values, dates, err := fn.prepareXArgs(argsList.Front().Next().Value.(formulaArg), argsList.Back().Value.(formulaArg))
if err.Type != ArgEmpty {
return err
}
@@ -12389,7 +15664,8 @@ func (fn *formulaFuncs) yield(settlement, maturity, rate, pr, redemption, freque
yield2 = yieldN
price2 = priceN
}
- yieldN.Number = yield2.Number - (yield2.Number-yield1.Number)*((pr.Number-price2.Number)/(price1.Number-price2.Number))
+ f1 := (yield2.Number - yield1.Number) * ((pr.Number - price2.Number) / (price1.Number - price2.Number))
+ yieldN.Number = yield2.Number - math.Nextafter(f1, f1)
}
}
return yieldN
@@ -12539,7 +15815,8 @@ func (fn *formulaFuncs) YIELDMAT(argsList *list.List) formulaArg {
}
dis := yearFrac(issue.Number, settlement.Number, int(basis.Number))
dsm := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
- result := 1 + dim.Number*rate.Number
+ f1 := dim.Number * rate.Number
+ result := 1 + math.Nextafter(f1, f1)
result /= pr.Number/100 + dis.Number*rate.Number
result--
result /= dsm.Number
diff --git a/vendor/github.com/xuri/excelize/v2/calcchain.go b/vendor/github.com/xuri/excelize/v2/calcchain.go
index 8f5e2772..a1f9c0c5 100644
--- a/vendor/github.com/xuri/excelize/v2/calcchain.go
+++ b/vendor/github.com/xuri/excelize/v2/calcchain.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -25,7 +25,7 @@ func (f *File) calcChainReader() *xlsxCalcChain {
if f.CalcChain == nil {
f.CalcChain = new(xlsxCalcChain)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(dafaultXMLPathCalcChain)))).
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathCalcChain)))).
Decode(f.CalcChain); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err)
}
@@ -39,7 +39,7 @@ func (f *File) calcChainReader() *xlsxCalcChain {
func (f *File) calcChainWriter() {
if f.CalcChain != nil && f.CalcChain.C != nil {
output, _ := xml.Marshal(f.CalcChain)
- f.saveFileList(dafaultXMLPathCalcChain, output)
+ f.saveFileList(defaultXMLPathCalcChain, output)
}
}
@@ -54,7 +54,7 @@ func (f *File) deleteCalcChain(index int, axis string) {
}
if len(calc.C) == 0 {
f.CalcChain = nil
- f.Pkg.Delete(dafaultXMLPathCalcChain)
+ f.Pkg.Delete(defaultXMLPathCalcChain)
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
diff --git a/vendor/github.com/xuri/excelize/v2/cell.go b/vendor/github.com/xuri/excelize/v2/cell.go
index 146d0a2f..b2818e7f 100644
--- a/vendor/github.com/xuri/excelize/v2/cell.go
+++ b/vendor/github.com/xuri/excelize/v2/cell.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -200,12 +200,12 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
ws.Unlock()
var isNum bool
@@ -214,10 +214,7 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
return err
}
if isNum {
- err = f.setDefaultTimeStyle(sheet, axis, 22)
- if err != nil {
- return err
- }
+ _ = f.setDefaultTimeStyle(sheet, axis, 22)
}
return err
}
@@ -254,13 +251,13 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
defer ws.Unlock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
cellData.T, cellData.V = setCellInt(value)
return err
}
@@ -279,13 +276,13 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
defer ws.Unlock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
cellData.T, cellData.V = setCellBool(value)
return err
}
@@ -302,7 +299,7 @@ func setCellBool(value bool) (t string, v string) {
return
}
-// SetCellFloat sets a floating point value into a cell. The prec parameter
+// SetCellFloat sets a floating point value into a cell. The precision parameter
// specifies how many places after the decimal will be shown while -1 is a
// special value that will use as many decimal places as necessary to
// represent the number. bitSize is 32 or 64 depending on if a float32 or
@@ -311,26 +308,26 @@ func setCellBool(value bool) (t string, v string) {
// var x float32 = 1.325
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
//
-func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
+func (f *File) SetCellFloat(sheet, axis string, value float64, precision, bitSize int) error {
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
defer ws.Unlock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
- cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
+ cellData.T, cellData.V = setCellFloat(value, precision, bitSize)
return err
}
// setCellFloat prepares cell type and string type cell value by a given
// float value.
-func setCellFloat(value float64, prec, bitSize int) (t string, v string) {
- v = strconv.FormatFloat(value, 'f', prec, bitSize)
+func setCellFloat(value float64, precision, bitSize int) (t string, v string) {
+ v = strconv.FormatFloat(value, 'f', precision, bitSize)
return
}
@@ -341,13 +338,13 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
defer ws.Unlock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
cellData.T, cellData.V, err = f.setCellString(value)
return err
}
@@ -372,11 +369,21 @@ func (f *File) setCellString(value string) (t, v string, err error) {
func (f *File) sharedStringsLoader() (err error) {
f.Lock()
defer f.Unlock()
- if path, ok := f.tempFiles.Load(dafaultXMLPathSharedStrings); ok {
- f.Pkg.Store(dafaultXMLPathSharedStrings, f.readBytes(dafaultXMLPathSharedStrings))
- f.tempFiles.Delete(dafaultXMLPathSharedStrings)
- err = os.Remove(path.(string))
- f.SharedStrings, f.sharedStringItemMap = nil, nil
+ if path, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
+ f.Pkg.Store(defaultXMLPathSharedStrings, f.readBytes(defaultXMLPathSharedStrings))
+ f.tempFiles.Delete(defaultXMLPathSharedStrings)
+ if err = os.Remove(path.(string)); err != nil {
+ return
+ }
+ f.SharedStrings = nil
+ }
+ if f.sharedStringTemp != nil {
+ if err := f.sharedStringTemp.Close(); err != nil {
+ return err
+ }
+ f.tempFiles.Delete(defaultTempFileSST)
+ f.sharedStringItem, err = nil, os.Remove(f.sharedStringTemp.Name())
+ f.sharedStringTemp = nil
}
return
}
@@ -429,13 +436,13 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
ws.Lock()
defer ws.Unlock()
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
cellData.T, cellData.V = setCellDefault(value)
return err
}
@@ -443,6 +450,9 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
// setCellDefault prepares cell type and string type cell value by a given
// string.
func setCellDefault(value string) (t string, v string) {
+ if ok, _ := isNumeric(value); !ok {
+ t = "str"
+ }
v = value
return
}
@@ -455,7 +465,7 @@ func (f *File) GetCellFormula(sheet, axis string) (string, error) {
return "", false, nil
}
if c.F.T == STCellFormulaTypeShared && c.F.Si != nil {
- return getSharedForumula(x, *c.F.Si, c.R), true, nil
+ return getSharedFormula(x, *c.F.Si, c.R), true, nil
}
return c.F.Content, true, nil
})
@@ -468,7 +478,7 @@ type FormulaOpts struct {
}
// SetCellFormula provides a function to set formula on the cell is taken
-// according to the given worksheet name (case sensitive) and cell formula
+// according to the given worksheet name (case-sensitive) and cell formula
// settings. The result of the formula cell can be calculated when the
// worksheet is opened by the Office Excel application or can be using
// the "CalcCellValue" function also can get the calculated cell value. If
@@ -550,7 +560,7 @@ func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts)
if err != nil {
return err
}
- cellData, _, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, _, _, err := f.prepareCell(ws, axis)
if err != nil {
return err
}
@@ -621,7 +631,7 @@ func (ws *xlsxWorksheet) countSharedFormula() (count int) {
}
// GetCellHyperLink provides a function to get cell hyperlink by given
-// worksheet name and axis. Boolean type value link will be ture if the cell
+// worksheet name and axis. Boolean type value link will be true if the cell
// has a hyperlink and the target is the address of the hyperlink. Otherwise,
// the value of link will be false and the value of the target will be a blank
// string. For example get hyperlink of Sheet1!H6:
@@ -662,16 +672,27 @@ type HyperlinkOpts struct {
// SetCellHyperLink provides a function to set cell hyperlink by given
// worksheet name and link URL address. LinkType defines two types of
-// hyperlink "External" for web site or "Location" for moving to one of cell
-// in this workbook. Maximum limit hyperlinks in a worksheet is 65530. The
-// below is example for external link.
+// hyperlink "External" for website or "Location" for moving to one of cell in
+// this workbook. Maximum limit hyperlinks in a worksheet is 65530. This
+// function is only used to set the hyperlink of the cell and doesn't affect
+// the value of the cell. If you need to set the value of the cell, please use
+// the other functions such as `SetCellStyle` or `SetSheetRow`. The below is
+// example for external link.
//
-// err := f.SetCellHyperLink("Sheet1", "A3", "https://github.com/xuri/excelize", "External")
+// if err := f.SetCellHyperLink("Sheet1", "A3",
+// "https://github.com/xuri/excelize", "External"); err != nil {
+// fmt.Println(err)
+// }
// // Set underline and font color style for the cell.
-// style, err := f.NewStyle(`{"font":{"color":"#1265BE","underline":"single"}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Font: &excelize.Font{Color: "#1265BE", Underline: "single"},
+// })
+// if err != nil {
+// fmt.Println(err)
+// }
// err = f.SetCellStyle("Sheet1", "A3", "A3", style)
//
-// A this is another example for "Location":
+// This is another example for "Location":
//
// err := f.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
//
@@ -738,7 +759,7 @@ func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err erro
if err != nil {
return
}
- cellData, _, _, err := f.prepareCell(ws, sheet, cell)
+ cellData, _, _, err := f.prepareCell(ws, cell)
if err != nil {
return
}
@@ -919,17 +940,17 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
if err != nil {
return err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, cell)
+ cellData, col, row, err := f.prepareCell(ws, cell)
if err != nil {
return err
}
if err := f.sharedStringsLoader(); err != nil {
return err
}
- cellData.S = f.prepareCellStyle(ws, col, cellData.S)
+ cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
si := xlsxSI{}
sst := f.sharedStringsReader()
- textRuns := []xlsxR{}
+ var textRuns []xlsxR
totalCellChars := 0
for _, textRun := range runs {
totalCellChars += len(textRun.Text)
@@ -979,8 +1000,8 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
for i := 0; i < v.Len(); i++ {
cell, err := CoordinatesToCellName(col+i, row)
- // Error should never happens here. But keep checking to early detect regresions
- // if it will be introduced in future.
+ // Error should never happen here. But keep checking to early detect regressions
+ // if it will be introduced in the future.
if err != nil {
return err
}
@@ -992,7 +1013,7 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
}
// getCellInfo does common preparation for all SetCell* methods.
-func (f *File) prepareCell(ws *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
+func (f *File) prepareCell(ws *xlsxWorksheet, cell string) (*xlsxC, int, int, error) {
var err error
cell, err = f.mergeCellsParser(ws, cell)
if err != nil {
@@ -1064,25 +1085,15 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
// it is possible to apply a format to the cell value, it will do so, if not
// then an error will be returned, along with the raw value of the cell.
func (f *File) formattedValue(s int, v string, raw bool) string {
- precise := v
- isNum, precision := isNumeric(v)
- if isNum && precision > 10 {
- precise = roundPrecision(v, -1)
- }
if raw {
return v
}
- if !isNum {
- v = roundPrecision(v, 15)
- precise = v
- }
if s == 0 {
- return precise
+ return v
}
styleSheet := f.stylesReader()
-
if s >= len(styleSheet.CellXfs.Xf) {
- return precise
+ return v
}
var numFmtID int
if styleSheet.CellXfs.Xf[s].NumFmtID != nil {
@@ -1091,38 +1102,34 @@ func (f *File) formattedValue(s int, v string, raw bool) string {
ok := builtInNumFmtFunc[numFmtID]
if ok != nil {
- return ok(precise, builtInNumFmt[numFmtID])
+ return ok(v, builtInNumFmt[numFmtID])
}
if styleSheet == nil || styleSheet.NumFmts == nil {
- return precise
+ return v
}
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
if xlsxFmt.NumFmtID == numFmtID {
- format := strings.ToLower(xlsxFmt.FormatCode)
- if isTimeNumFmt(format) {
- return parseTime(v, format)
- }
- return precise
+ return format(v, xlsxFmt.FormatCode)
}
}
- return precise
-}
-
-// isTimeNumFmt determine if the given number format expression is a time number format.
-func isTimeNumFmt(format string) bool {
- return strings.Contains(format, "y") || strings.Contains(format, "m") || strings.Contains(strings.Replace(format, "red", "", -1), "d") || strings.Contains(format, "h")
+ return v
}
// prepareCellStyle provides a function to prepare style index of cell in
// worksheet by given column index and style index.
-func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, style int) int {
+func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, row, style int) int {
if ws.Cols != nil && style == 0 {
for _, c := range ws.Cols.Col {
- if c.Min <= col && col <= c.Max {
- style = c.Style
+ if c.Min <= col && col <= c.Max && c.Style != 0 {
+ return c.Style
}
}
}
+ for rowIdx := range ws.SheetData.Row {
+ if styleID := ws.SheetData.Row[rowIdx].S; style == 0 && styleID != 0 {
+ return styleID
+ }
+ }
return style
}
@@ -1132,6 +1139,11 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error)
axis = strings.ToUpper(axis)
if ws.MergeCells != nil {
for i := 0; i < len(ws.MergeCells.Cells); i++ {
+ if ws.MergeCells.Cells[i] == nil {
+ ws.MergeCells.Cells = append(ws.MergeCells.Cells[:i], ws.MergeCells.Cells[i+1:]...)
+ i--
+ continue
+ }
ok, err := f.checkCellInArea(axis, ws.MergeCells.Cells[i].Ref)
if err != nil {
return axis, err
@@ -1152,8 +1164,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) {
return false, err
}
- rng := strings.Split(area, ":")
- if len(rng) != 2 {
+ if rng := strings.Split(area, ":"); len(rng) != 2 {
return false, err
}
coordinates, err := areaRefToCoordinates(area)
@@ -1164,7 +1175,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) {
return cellInRef([]int{col, row}, coordinates), err
}
-// cellInRef provides a function to determine if a given range is within an
+// cellInRef provides a function to determine if a given range is within a
// range.
func cellInRef(cell, ref []int) bool {
return cell[0] >= ref[0] && cell[0] <= ref[2] && cell[1] >= ref[1] && cell[1] <= ref[3]
@@ -1224,15 +1235,15 @@ func parseSharedFormula(dCol, dRow int, orig []byte) (res string, start int) {
return
}
-// getSharedForumula find a cell contains the same formula as another cell,
+// getSharedFormula find a cell contains the same formula as another cell,
// the "shared" value can be used for the t attribute and the si attribute can
// be used to refer to the cell containing the formula. Two formulas are
// considered to be the same when their respective representations in
// R1C1-reference notation, are the same.
//
-// Note that this function not validate ref tag to check the cell if or not in
+// Note that this function not validate ref tag to check the cell whether in
// allow area, and always return origin shared formula.
-func getSharedForumula(ws *xlsxWorksheet, si int, axis string) string {
+func getSharedFormula(ws *xlsxWorksheet, si int, axis string) string {
for _, r := range ws.SheetData.Row {
for _, c := range r.C {
if c.F != nil && c.F.Ref != "" && c.F.T == STCellFormulaTypeShared && c.F.Si != nil && *c.F.Si == si {
@@ -1253,7 +1264,7 @@ func getSharedForumula(ws *xlsxWorksheet, si int, axis string) string {
}
// shiftCell returns the cell shifted according to dCol and dRow taking into
-// consideration of absolute references with dollar sign ($)
+// consideration absolute references with dollar sign ($)
func shiftCell(cellID string, dCol, dRow int) string {
fCol, fRow, _ := CellNameToCoordinates(cellID)
signCol, signRow := "", ""
diff --git a/vendor/github.com/xuri/excelize/v2/chart.go b/vendor/github.com/xuri/excelize/v2/chart.go
index 755c160e..8f521fa0 100644
--- a/vendor/github.com/xuri/excelize/v2/chart.go
+++ b/vendor/github.com/xuri/excelize/v2/chart.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -969,7 +969,7 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
// getFormatChart provides a function to check format set of the chart and
// create chart format.
func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*formatChart, error) {
- comboCharts := []*formatChart{}
+ var comboCharts []*formatChart
formatSet, err := parseFormatChartSet(format)
if err != nil {
return formatSet, comboCharts, err
@@ -980,12 +980,12 @@ func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*f
return formatSet, comboCharts, err
}
if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok {
- return formatSet, comboCharts, newUnsupportChartType(comboChart.Type)
+ return formatSet, comboCharts, newUnsupportedChartType(comboChart.Type)
}
comboCharts = append(comboCharts, comboChart)
}
if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok {
- return formatSet, comboCharts, newUnsupportChartType(formatSet.Type)
+ return formatSet, comboCharts, newUnsupportedChartType(formatSet.Type)
}
return formatSet, comboCharts, err
}
diff --git a/vendor/github.com/xuri/excelize/v2/col.go b/vendor/github.com/xuri/excelize/v2/col.go
index c6882012..ee1a4074 100644
--- a/vendor/github.com/xuri/excelize/v2/col.go
+++ b/vendor/github.com/xuri/excelize/v2/col.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -40,18 +40,7 @@ type Cols struct {
sheetXML []byte
}
-// CurrentCol returns the column number that represents the current column.
-func (cols *Cols) CurrentCol() int {
- return cols.curCol
-}
-
-// TotalCols returns the total columns count in the worksheet.
-func (cols *Cols) TotalCols() int {
- return cols.totalCols
-}
-
-// GetCols return all the columns in a sheet by given worksheet name (case
-// sensitive). For example:
+// GetCols return all the columns in a sheet by given worksheet name (case-sensitive). For example:
//
// cols, err := f.GetCols("Sheet1")
// if err != nil {
@@ -250,20 +239,18 @@ func (f *File) Cols(sheet string) (*Cols, error) {
// visible, err := f.GetColVisible("Sheet1", "D")
//
func (f *File) GetColVisible(sheet, col string) (bool, error) {
- visible := true
colNum, err := ColumnNameToNumber(col)
if err != nil {
- return visible, err
+ return true, err
}
-
ws, err := f.workSheetReader(sheet)
if err != nil {
return false, err
}
if ws.Cols == nil {
- return visible, err
+ return true, err
}
-
+ visible := true
for c := range ws.Cols.Col {
colData := &ws.Cols.Col[c]
if colData.Min <= colNum && colNum <= colData.Max {
@@ -465,12 +452,12 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
// f := excelize.NewFile()
// err := f.SetColWidth("Sheet1", "A", "H", 20)
//
-func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error {
- min, err := ColumnNameToNumber(startcol)
+func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error {
+ min, err := ColumnNameToNumber(startCol)
if err != nil {
return err
}
- max, err := ColumnNameToNumber(endcol)
+ max, err := ColumnNameToNumber(endCol)
if err != nil {
return err
}
@@ -512,7 +499,7 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
// flatCols provides a method for the column's operation functions to flatten
// and check the worksheet columns.
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
- fc := []xlsxCol{}
+ var fc []xlsxCol
for i := col.Min; i <= col.Max; i++ {
c := deepcopy.Copy(col).(xlsxCol)
c.Min, c.Max = i, i
@@ -557,7 +544,7 @@ func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol)
// | | | (x2,y2)|
// +-----+------------+------------+
//
-// Example of an object that covers some of the area from cell A1 to B2.
+// Example of an object that covers some area from cell A1 to B2.
//
// Based on the width and height of the object we need to calculate 8 vars:
//
@@ -602,9 +589,8 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh
row++
}
- // Initialise end cell to the same as the start cell.
- colEnd := col
- rowEnd := row
+ // Initialized end cell to the same as the start cell.
+ colEnd, rowEnd := col, row
width += x1
height += y1
@@ -642,7 +628,7 @@ func (f *File) getColWidth(sheet string, col int) int {
return int(convertColWidthToPixels(width))
}
}
- // Optimisation for when the column widths haven't changed.
+ // Optimization for when the column widths haven't changed.
return int(defaultColWidthPixels)
}
@@ -668,7 +654,7 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
return width, err
}
}
- // Optimisation for when the column widths haven't changed.
+ // Optimization for when the column widths haven't changed.
return defaultColWidth, err
}
@@ -717,7 +703,7 @@ func (f *File) RemoveCol(sheet, col string) error {
return f.adjustHelper(sheet, columns, num, -1)
}
-// convertColWidthToPixels provieds function to convert the width of a cell
+// convertColWidthToPixels provides function to convert the width of a cell
// from user's units to pixels. Excel rounds the column width to the nearest
// pixel. If the width hasn't been set by the user we use the default value.
// If the column is hidden it has a value of zero.
diff --git a/vendor/github.com/xuri/excelize/v2/comment.go b/vendor/github.com/xuri/excelize/v2/comment.go
index 07cd9f21..a7c1415b 100644
--- a/vendor/github.com/xuri/excelize/v2/comment.go
+++ b/vendor/github.com/xuri/excelize/v2/comment.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -47,7 +47,7 @@ func (f *File) GetComments() (comments map[string][]Comment) {
target = "xl" + strings.TrimPrefix(target, "..")
}
if d := f.commentsReader(strings.TrimPrefix(target, "/")); d != nil {
- sheetComments := []Comment{}
+ var sheetComments []Comment
for _, comment := range d.CommentList.Comment {
sheetComment := Comment{}
if comment.AuthorID < len(d.Authors.Author) {
@@ -74,7 +74,7 @@ func (f *File) GetComments() (comments map[string][]Comment) {
// getSheetComments provides the method to get the target comment reference by
// given worksheet file path.
func (f *File) getSheetComments(sheetFile string) string {
- var rels = "xl/worksheets/_rels/" + sheetFile + ".rels"
+ rels := "xl/worksheets/_rels/" + sheetFile + ".rels"
if sheetRels := f.relsReader(rels); sheetRels != nil {
sheetRels.Lock()
defer sheetRels.Unlock()
@@ -256,7 +256,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
if comments == nil {
comments = &xlsxComments{Authors: xlsxAuthor{Author: []string{formatSet.Author}}}
}
- if inStrSlice(comments.Authors.Author, formatSet.Author) == -1 {
+ if inStrSlice(comments.Authors.Author, formatSet.Author, true) == -1 {
comments.Authors.Author = append(comments.Authors.Author, formatSet.Author)
authorID = len(comments.Authors.Author) - 1
}
diff --git a/vendor/github.com/xuri/excelize/v2/crypt.go b/vendor/github.com/xuri/excelize/v2/crypt.go
index ae39bba1..da9feb4a 100644
--- a/vendor/github.com/xuri/excelize/v2/crypt.go
+++ b/vendor/github.com/xuri/excelize/v2/crypt.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -43,6 +43,7 @@ var (
packageOffset = 8 // First 8 bytes are the size of the stream
packageEncryptionChunkSize = 4096
iterCount = 50000
+ sheetProtectionSpinCount = 1e5
oleIdentifier = []byte{
0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1,
}
@@ -127,7 +128,7 @@ type StandardEncryptionVerifier struct {
EncryptedVerifierHash []byte
}
-// Decrypt API decrypt the CFB file format with ECMA-376 agile encryption and
+// Decrypt API decrypts the CFB file format with ECMA-376 agile encryption and
// standard encryption. Support cryptographic algorithm: MD4, MD5, RIPEMD-160,
// SHA1, SHA256, SHA384 and SHA512 currently.
func Decrypt(raw []byte, opt *Options) (packageBuf []byte, err error) {
@@ -146,7 +147,7 @@ func Decrypt(raw []byte, opt *Options) (packageBuf []byte, err error) {
case "standard":
return standardDecrypt(encryptionInfoBuf, encryptedPackageBuf, opt)
default:
- err = ErrUnsupportEncryptMechanism
+ err = ErrUnsupportedEncryptMechanism
}
return
}
@@ -167,16 +168,20 @@ func Encrypt(raw []byte, opt *Options) (packageBuf []byte, err error) {
HashAlgorithm: "SHA512",
SaltValue: base64.StdEncoding.EncodeToString(keyDataSaltValue),
},
- KeyEncryptors: KeyEncryptors{KeyEncryptor: []KeyEncryptor{{
- EncryptedKey: EncryptedKey{SpinCount: 100000, KeyData: KeyData{
- CipherAlgorithm: "AES",
- CipherChaining: "ChainingModeCBC",
- HashAlgorithm: "SHA512",
- HashSize: 64,
- BlockSize: 16,
- KeyBits: 256,
- SaltValue: base64.StdEncoding.EncodeToString(keyEncryptors)},
- }}},
+ KeyEncryptors: KeyEncryptors{
+ KeyEncryptor: []KeyEncryptor{{
+ EncryptedKey: EncryptedKey{
+ SpinCount: 100000, KeyData: KeyData{
+ CipherAlgorithm: "AES",
+ CipherChaining: "ChainingModeCBC",
+ HashAlgorithm: "SHA512",
+ HashSize: 64,
+ BlockSize: 16,
+ KeyBits: 256,
+ SaltValue: base64.StdEncoding.EncodeToString(keyEncryptors),
+ },
+ },
+ }},
},
}
@@ -307,7 +312,7 @@ func encryptionMechanism(buffer []byte) (mechanism string, err error) {
} else if (versionMajor == 3 || versionMajor == 4) && versionMinor == 3 {
mechanism = "extensible"
}
- err = ErrUnsupportEncryptMechanism
+ err = ErrUnsupportedEncryptMechanism
return
}
@@ -387,14 +392,14 @@ func standardConvertPasswdToKey(header StandardEncryptionHeader, verifier Standa
key = hashing("sha1", iterator, key)
}
var block int
- hfinal := hashing("sha1", key, createUInt32LEBuffer(block, 4))
+ hFinal := hashing("sha1", key, createUInt32LEBuffer(block, 4))
cbRequiredKeyLength := int(header.KeySize) / 8
cbHash := sha1.Size
buf1 := bytes.Repeat([]byte{0x36}, 64)
- buf1 = append(standardXORBytes(hfinal, buf1[:cbHash]), buf1[cbHash:]...)
+ buf1 = append(standardXORBytes(hFinal, buf1[:cbHash]), buf1[cbHash:]...)
x1 := hashing("sha1", buf1)
buf2 := bytes.Repeat([]byte{0x5c}, 64)
- buf2 = append(standardXORBytes(hfinal, buf2[:cbHash]), buf2[cbHash:]...)
+ buf2 = append(standardXORBytes(hFinal, buf2[:cbHash]), buf2[cbHash:]...)
x2 := hashing("sha1", buf2)
x3 := append(x1, x2...)
keyDerived := x3[:cbRequiredKeyLength]
@@ -417,7 +422,8 @@ func standardXORBytes(a, b []byte) []byte {
// ECMA-376 Agile Encryption
// agileDecrypt decrypt the CFB file format with ECMA-376 agile encryption.
-// Support cryptographic algorithm: MD4, MD5, RIPEMD-160, SHA1, SHA256, SHA384 and SHA512.
+// Support cryptographic algorithm: MD4, MD5, RIPEMD-160, SHA1, SHA256,
+// SHA384 and SHA512.
func agileDecrypt(encryptionInfoBuf, encryptedPackageBuf []byte, opt *Options) (packageBuf []byte, err error) {
var encryptionInfo Encryption
if encryptionInfo, err = parseEncryptionInfo(encryptionInfoBuf[8:]); err != nil {
@@ -479,7 +485,7 @@ func convertPasswdToKey(passwd string, blockKey []byte, encryption Encryption) (
// hashing data by specified hash algorithm.
func hashing(hashAlgorithm string, buffer ...[]byte) (key []byte) {
- var hashMap = map[string]hash.Hash{
+ hashMap := map[string]hash.Hash{
"md4": md4.New(),
"md5": md5.New(),
"ripemd-160": ripemd160.New(),
@@ -533,8 +539,7 @@ func crypt(encrypt bool, cipherAlgorithm, cipherChaining string, key, iv, input
// cryptPackage encrypt / decrypt package by given packageKey and encryption
// info.
func cryptPackage(encrypt bool, packageKey, input []byte, encryption Encryption) (outputChunks []byte, err error) {
- encryptedKey := encryption.KeyData
- var offset = packageOffset
+ encryptedKey, offset := encryption.KeyData, packageOffset
if encrypt {
offset = 0
}
@@ -605,11 +610,55 @@ func createIV(blockKey interface{}, encryption Encryption) ([]byte, error) {
return iv, nil
}
-// randomBytes returns securely generated random bytes. It will return an error if the system's
-// secure random number generator fails to function correctly, in which case the caller should not
-// continue.
+// randomBytes returns securely generated random bytes. It will return an
+// error if the system's secure random number generator fails to function
+// correctly, in which case the caller should not continue.
func randomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
return b, err
}
+
+// ISO Write Protection Method
+
+// genISOPasswdHash implements the ISO password hashing algorithm by given
+// plaintext password, name of the cryptographic hash algorithm, salt value
+// and spin count.
+func genISOPasswdHash(passwd, hashAlgorithm, salt string, spinCount int) (hashValue, saltValue string, err error) {
+ if len(passwd) < 1 || len(passwd) > MaxFieldLength {
+ err = ErrPasswordLengthInvalid
+ return
+ }
+ algorithmName, ok := map[string]string{
+ "MD4": "md4",
+ "MD5": "md5",
+ "SHA-1": "sha1",
+ "SHA-256": "sha256",
+ "SHA-384": "sha384",
+ "SHA-512": "sha512",
+ }[hashAlgorithm]
+ if !ok {
+ err = ErrUnsupportedHashAlgorithm
+ return
+ }
+ var b bytes.Buffer
+ s, _ := randomBytes(16)
+ if salt != "" {
+ if s, err = base64.StdEncoding.DecodeString(salt); err != nil {
+ return
+ }
+ }
+ b.Write(s)
+ encoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewEncoder()
+ passwordBuffer, _ := encoder.Bytes([]byte(passwd))
+ b.Write(passwordBuffer)
+ // Generate the initial hash.
+ key := hashing(algorithmName, b.Bytes())
+ // Now regenerate until spin count.
+ for i := 0; i < spinCount; i++ {
+ iterator := createUInt32LEBuffer(i, 4)
+ key = hashing(algorithmName, key, iterator)
+ }
+ hashValue, saltValue = base64.StdEncoding.EncodeToString(key), base64.StdEncoding.EncodeToString(s)
+ return
+}
diff --git a/vendor/github.com/xuri/excelize/v2/datavalidation.go b/vendor/github.com/xuri/excelize/v2/datavalidation.go
index 80a0295e..4df2c505 100644
--- a/vendor/github.com/xuri/excelize/v2/datavalidation.go
+++ b/vendor/github.com/xuri/excelize/v2/datavalidation.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -29,7 +29,7 @@ const (
DataValidationTypeDate
DataValidationTypeDecimal
typeList // inline use
- DataValidationTypeTextLeng
+ DataValidationTypeTextLength
DataValidationTypeTime
// DataValidationTypeWhole Integer
DataValidationTypeWhole
@@ -116,7 +116,7 @@ func (dd *DataValidation) SetInput(title, msg string) {
func (dd *DataValidation) SetDropList(keys []string) error {
formula := strings.Join(keys, ",")
if MaxFieldLength < len(utf16.Encode([]rune(formula))) {
- return ErrDataValidationFormulaLenth
+ return ErrDataValidationFormulaLength
}
dd.Formula1 = fmt.Sprintf(`"%s"`, formulaEscaper.Replace(formula))
dd.Type = convDataValidationType(typeList)
@@ -129,33 +129,33 @@ func (dd *DataValidation) SetRange(f1, f2 interface{}, t DataValidationType, o D
var formula1, formula2 string
switch v := f1.(type) {
case int:
- formula1 = fmt.Sprintf("%d", int(v))
+ formula1 = fmt.Sprintf("%d", v)
case float64:
- if math.Abs(float64(v)) > math.MaxFloat32 {
+ if math.Abs(v) > math.MaxFloat32 {
return ErrDataValidationRange
}
- formula1 = fmt.Sprintf("%.17g", float64(v))
+ formula1 = fmt.Sprintf("%.17g", v)
case string:
- formula1 = fmt.Sprintf("%s", string(v))
+ formula1 = fmt.Sprintf("%s", v)
default:
return ErrParameterInvalid
}
switch v := f2.(type) {
case int:
- formula2 = fmt.Sprintf("%d", int(v))
+ formula2 = fmt.Sprintf("%d", v)
case float64:
- if math.Abs(float64(v)) > math.MaxFloat32 {
+ if math.Abs(v) > math.MaxFloat32 {
return ErrDataValidationRange
}
- formula2 = fmt.Sprintf("%.17g", float64(v))
+ formula2 = fmt.Sprintf("%.17g", v)
case string:
- formula2 = fmt.Sprintf("%s", string(v))
+ formula2 = fmt.Sprintf("%s", v)
default:
return ErrParameterInvalid
}
dd.Formula1, dd.Formula2 = formula1, formula2
dd.Type = convDataValidationType(t)
- dd.Operator = convDataValidationOperatior(o)
+ dd.Operator = convDataValidationOperator(o)
return nil
}
@@ -168,16 +168,12 @@ func (dd *DataValidation) SetRange(f1, f2 interface{}, t DataValidationType, o D
//
// dvRange := excelize.NewDataValidation(true)
// dvRange.Sqref = "A7:B8"
-// dvRange.SetSqrefDropList("$E$1:$E$3", true)
+// dvRange.SetSqrefDropList("$E$1:$E$3")
// f.AddDataValidation("Sheet1", dvRange)
//
-func (dd *DataValidation) SetSqrefDropList(sqref string, isCurrentSheet bool) error {
- if isCurrentSheet {
- dd.Formula1 = fmt.Sprintf("%s", sqref)
- dd.Type = convDataValidationType(typeList)
- return nil
- }
- return fmt.Errorf("cross-sheet sqref cell are not supported")
+func (dd *DataValidation) SetSqrefDropList(sqref string) {
+ dd.Formula1 = fmt.Sprintf("%s", sqref)
+ dd.Type = convDataValidationType(typeList)
}
// SetSqref provides function to set data validation range in drop list.
@@ -192,22 +188,21 @@ func (dd *DataValidation) SetSqref(sqref string) {
// convDataValidationType get excel data validation type.
func convDataValidationType(t DataValidationType) string {
typeMap := map[DataValidationType]string{
- typeNone: "none",
- DataValidationTypeCustom: "custom",
- DataValidationTypeDate: "date",
- DataValidationTypeDecimal: "decimal",
- typeList: "list",
- DataValidationTypeTextLeng: "textLength",
- DataValidationTypeTime: "time",
- DataValidationTypeWhole: "whole",
+ typeNone: "none",
+ DataValidationTypeCustom: "custom",
+ DataValidationTypeDate: "date",
+ DataValidationTypeDecimal: "decimal",
+ typeList: "list",
+ DataValidationTypeTextLength: "textLength",
+ DataValidationTypeTime: "time",
+ DataValidationTypeWhole: "whole",
}
return typeMap[t]
-
}
-// convDataValidationOperatior get excel data validation operator.
-func convDataValidationOperatior(o DataValidationOperator) string {
+// convDataValidationOperator get excel data validation operator.
+func convDataValidationOperator(o DataValidationOperator) string {
typeMap := map[DataValidationOperator]string{
DataValidationOperatorBetween: "between",
DataValidationOperatorEqual: "equal",
@@ -220,7 +215,6 @@ func convDataValidationOperatior(o DataValidationOperator) string {
}
return typeMap[o]
-
}
// AddDataValidation provides set data validation on a range of the worksheet
@@ -283,7 +277,7 @@ func (f *File) DeleteDataValidation(sheet, sqref string) error {
}
dv := ws.DataValidations
for i := 0; i < len(dv.DataValidation); i++ {
- applySqref := []string{}
+ var applySqref []string
colCells, err := f.flatSqref(dv.DataValidation[i].Sqref)
if err != nil {
return err
@@ -320,7 +314,8 @@ func (f *File) squashSqref(cells [][]int) []string {
} else if len(cells) == 0 {
return []string{}
}
- l, r, res := 0, 0, []string{}
+ var res []string
+ l, r := 0, 0
for i := 1; i < len(cells); i++ {
if cells[i][0] == cells[r][0] && cells[i][1]-cells[r][1] > 1 {
curr, _ := f.coordinatesToAreaRef(append(cells[l], cells[r]...))
diff --git a/vendor/github.com/xuri/excelize/v2/date.go b/vendor/github.com/xuri/excelize/v2/date.go
index c4acd6d5..83d23ccf 100644
--- a/vendor/github.com/xuri/excelize/v2/date.go
+++ b/vendor/github.com/xuri/excelize/v2/date.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -82,7 +82,6 @@ func shiftJulianToNoon(julianDays, julianFraction float64) (float64, float64) {
// minutes, seconds and nanoseconds that comprised a given fraction of a day.
// values would round to 1 us.
func fractionOfADay(fraction float64) (hours, minutes, seconds, nanoseconds int) {
-
const (
c1us = 1e3
c1s = 1e9
@@ -137,7 +136,7 @@ func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
// representation (stored as a floating point number) to a time.Time.
func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
var date time.Time
- var wholeDaysPart = int(excelTime)
+ wholeDaysPart := int(excelTime)
// Excel uses Julian dates prior to March 1st 1900, and Gregorian
// thereafter.
if wholeDaysPart <= 61 {
@@ -152,7 +151,7 @@ func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
}
return date
}
- var floatPart = excelTime - float64(wholeDaysPart) + roundEpsilon
+ floatPart := excelTime - float64(wholeDaysPart) + roundEpsilon
if date1904 {
date = excel1904Epoc
} else {
diff --git a/vendor/github.com/xuri/excelize/v2/docProps.go b/vendor/github.com/xuri/excelize/v2/docProps.go
index 271b3702..41ea18e2 100644
--- a/vendor/github.com/xuri/excelize/v2/docProps.go
+++ b/vendor/github.com/xuri/excelize/v2/docProps.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -75,7 +75,7 @@ func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
field string
)
app = new(xlsxProperties)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(dafaultXMLPathDocPropsApp)))).
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
Decode(app); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
@@ -95,14 +95,14 @@ func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
}
app.Vt = NameSpaceDocumentPropertiesVariantTypes.Value
output, err = xml.Marshal(app)
- f.saveFileList(dafaultXMLPathDocPropsApp, output)
+ f.saveFileList(defaultXMLPathDocPropsApp, output)
return
}
// GetAppProps provides a function to get document application properties.
func (f *File) GetAppProps() (ret *AppProperties, err error) {
- var app = new(xlsxProperties)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(dafaultXMLPathDocPropsApp)))).
+ app := new(xlsxProperties)
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
Decode(app); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
@@ -181,7 +181,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
)
core = new(decodeCoreProperties)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(dafaultXMLPathDocPropsCore)))).
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
@@ -189,7 +189,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
newProps, err = &xlsxCoreProperties{
Dc: NameSpaceDublinCore,
Dcterms: NameSpaceDublinCoreTerms,
- Dcmitype: NameSpaceDublinCoreMetadataIntiative,
+ Dcmitype: NameSpaceDublinCoreMetadataInitiative,
XSI: NameSpaceXMLSchemaInstance,
Title: core.Title,
Subject: core.Subject,
@@ -204,8 +204,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
Category: core.Category,
Version: core.Version,
}, nil
- newProps.Created.Text, newProps.Created.Type, newProps.Modified.Text, newProps.Modified.Type =
- core.Created.Text, core.Created.Type, core.Modified.Text, core.Modified.Type
+ newProps.Created.Text, newProps.Created.Type, newProps.Modified.Text, newProps.Modified.Type = core.Created.Text, core.Created.Type, core.Modified.Text, core.Modified.Type
fields = []string{
"Category", "ContentStatus", "Creator", "Description", "Identifier", "Keywords",
"LastModifiedBy", "Revision", "Subject", "Title", "Language", "Version",
@@ -223,16 +222,16 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
newProps.Modified.Text = docProperties.Modified
}
output, err = xml.Marshal(newProps)
- f.saveFileList(dafaultXMLPathDocPropsCore, output)
+ f.saveFileList(defaultXMLPathDocPropsCore, output)
return
}
// GetDocProps provides a function to get document core properties.
func (f *File) GetDocProps() (ret *DocProperties, err error) {
- var core = new(decodeCoreProperties)
+ core := new(decodeCoreProperties)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(dafaultXMLPathDocPropsCore)))).
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
diff --git a/vendor/github.com/xuri/excelize/v2/drawing.go b/vendor/github.com/xuri/excelize/v2/drawing.go
index 86d5ca68..d0e9135b 100644
--- a/vendor/github.com/xuri/excelize/v2/drawing.go
+++ b/vendor/github.com/xuri/excelize/v2/drawing.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -157,7 +157,8 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
Cmpd: "sng",
Algn: "ctr",
SolidFill: &aSolidFill{
- SchemeClr: &aSchemeClr{Val: "tx1",
+ SchemeClr: &aSchemeClr{
+ Val: "tx1",
LumMod: &attrValInt{
Val: intPtr(15000),
},
@@ -512,13 +513,18 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
// drawDoughnutChart provides a function to draw the c:plotArea element for
// doughnut chart by given format sets.
func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea {
+ holeSize := 75
+ if formatSet.HoleSize > 0 && formatSet.HoleSize <= 90 {
+ holeSize = formatSet.HoleSize
+ }
+
return &cPlotArea{
DoughnutChart: &cCharts{
VaryColors: &attrValBool{
Val: boolPtr(formatSet.VaryColors),
},
Ser: f.drawChartSeries(formatSet),
- HoleSize: &attrValInt{Val: intPtr(75)},
+ HoleSize: &attrValInt{Val: intPtr(holeSize)},
},
}
}
@@ -734,7 +740,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
// drawChartSeries provides a function to draw the c:ser element by given
// format sets.
func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
- ser := []cSer{}
+ var ser []cSer
for k := range formatSet.Series {
ser = append(ser, cSer{
IDx: &attrValInt{Val: intPtr(k + formatSet.order)},
@@ -941,7 +947,8 @@ func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls {
func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls {
dLbls := f.drawChartDLbls(formatSet)
chartSeriesDLbls := map[string]*cDLbls{
- Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil, Bubble: nil, Bubble3D: nil}
+ Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil, Bubble: nil, Bubble3D: nil,
+ }
if _, ok := chartSeriesDLbls[formatSet.Type]; ok {
return nil
}
@@ -950,14 +957,14 @@ func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls {
// drawPlotAreaCatAx provides a function to draw the c:catAx element.
func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
- min := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Minimum)}
- max := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Maximum)}
- if formatSet.XAxis.Minimum == 0 {
- min = nil
- }
- if formatSet.XAxis.Maximum == 0 {
+ max := &attrValFloat{Val: formatSet.XAxis.Maximum}
+ min := &attrValFloat{Val: formatSet.XAxis.Minimum}
+ if formatSet.XAxis.Maximum == nil {
max = nil
}
+ if formatSet.XAxis.Minimum == nil {
+ min = nil
+ }
axs := []*cAxs{
{
AxID: &attrValInt{Val: intPtr(754001152)},
@@ -999,14 +1006,14 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
// drawPlotAreaValAx provides a function to draw the c:valAx element.
func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
- min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)}
- max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)}
- if formatSet.YAxis.Minimum == 0 {
- min = nil
- }
- if formatSet.YAxis.Maximum == 0 {
+ max := &attrValFloat{Val: formatSet.YAxis.Maximum}
+ min := &attrValFloat{Val: formatSet.YAxis.Minimum}
+ if formatSet.YAxis.Maximum == nil {
max = nil
}
+ if formatSet.YAxis.Minimum == nil {
+ min = nil
+ }
var logBase *attrValFloat
if formatSet.YAxis.LogBase >= 2 && formatSet.YAxis.LogBase <= 1000 {
logBase = &attrValFloat{Val: float64Ptr(formatSet.YAxis.LogBase)}
@@ -1053,14 +1060,14 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
// drawPlotAreaSerAx provides a function to draw the c:serAx element.
func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs {
- min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)}
- max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)}
- if formatSet.YAxis.Minimum == 0 {
- min = nil
- }
- if formatSet.YAxis.Maximum == 0 {
+ max := &attrValFloat{Val: formatSet.YAxis.Maximum}
+ min := &attrValFloat{Val: formatSet.YAxis.Minimum}
+ if formatSet.YAxis.Maximum == nil {
max = nil
}
+ if formatSet.YAxis.Minimum == nil {
+ min = nil
+ }
return []*cAxs{
{
AxID: &attrValInt{Val: intPtr(832256642)},
@@ -1158,6 +1165,12 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
log.Printf("xml decode error: %s", err)
}
content.R = decodeWsDr.R
+ for _, v := range decodeWsDr.AlternateContent {
+ content.AlternateContent = append(content.AlternateContent, &xlsxAlternateContent{
+ Content: v.Content,
+ XMLNSMC: SourceRelationshipCompatibility.Value,
+ })
+ }
for _, v := range decodeWsDr.OneCellAnchor {
content.OneCellAnchor = append(content.OneCellAnchor, &xdrCellAnchor{
EditAs: v.EditAs,
@@ -1194,8 +1207,7 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
width = int(float64(width) * formatSet.XScale)
height = int(float64(height) * formatSet.YScale)
- colStart, rowStart, colEnd, rowEnd, x2, y2 :=
- f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.OffsetX, formatSet.OffsetY, width, height)
+ colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.OffsetX, formatSet.OffsetY, width, height)
content, cNvPrID := f.drawingParser(drawingXML)
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = formatSet.Positioning
diff --git a/vendor/github.com/xuri/excelize/v2/errors.go b/vendor/github.com/xuri/excelize/v2/errors.go
index 9460803c..c9d18cb3 100644
--- a/vendor/github.com/xuri/excelize/v2/errors.go
+++ b/vendor/github.com/xuri/excelize/v2/errors.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -16,42 +16,50 @@ import (
"fmt"
)
-// newInvalidColumnNameError defined the error message on receiving the invalid column name.
+// newInvalidColumnNameError defined the error message on receiving the
+// invalid column name.
func newInvalidColumnNameError(col string) error {
return fmt.Errorf("invalid column name %q", col)
}
-// newInvalidRowNumberError defined the error message on receiving the invalid row number.
+// newInvalidRowNumberError defined the error message on receiving the invalid
+// row number.
func newInvalidRowNumberError(row int) error {
return fmt.Errorf("invalid row number %d", row)
}
-// newInvalidCellNameError defined the error message on receiving the invalid cell name.
+// newInvalidCellNameError defined the error message on receiving the invalid
+// cell name.
func newInvalidCellNameError(cell string) error {
return fmt.Errorf("invalid cell name %q", cell)
}
-// newInvalidExcelDateError defined the error message on receiving the data with negative values.
+// newInvalidExcelDateError defined the error message on receiving the data
+// with negative values.
func newInvalidExcelDateError(dateValue float64) error {
return fmt.Errorf("invalid date value %f, negative values are not supported", dateValue)
}
-// newUnsupportChartType defined the error message on receiving the chart type are unsupported.
-func newUnsupportChartType(chartType string) error {
+// newUnsupportedChartType defined the error message on receiving the chart
+// type are unsupported.
+func newUnsupportedChartType(chartType string) error {
return fmt.Errorf("unsupported chart type %s", chartType)
}
-// newUnzipSizeLimitError defined the error message on unzip size exceeds the limit.
+// newUnzipSizeLimitError defined the error message on unzip size exceeds the
+// limit.
func newUnzipSizeLimitError(unzipSizeLimit int64) error {
return fmt.Errorf("unzip size exceeds the %d bytes limit", unzipSizeLimit)
}
-// newInvalidStyleID defined the error message on receiving the invalid style ID.
+// newInvalidStyleID defined the error message on receiving the invalid style
+// ID.
func newInvalidStyleID(styleID int) error {
return fmt.Errorf("invalid style ID %d, negative values are not supported", styleID)
}
-// newFieldLengthError defined the error message on receiving the field length overflow.
+// newFieldLengthError defined the error message on receiving the field length
+// overflow.
func newFieldLengthError(name string) error {
return fmt.Errorf("field %s must be less or equal than 255 characters", name)
}
@@ -98,17 +106,29 @@ var (
// ErrImgExt defined the error message on receive an unsupported image
// extension.
ErrImgExt = errors.New("unsupported image extension")
+ // ErrWorkbookExt defined the error message on receive an unsupported
+ // workbook extension.
+ ErrWorkbookExt = errors.New("unsupported workbook extension")
// ErrMaxFileNameLength defined the error message on receive the file name
// length overflow.
ErrMaxFileNameLength = errors.New("file name length exceeds maximum limit")
// ErrEncrypt defined the error message on encryption spreadsheet.
ErrEncrypt = errors.New("not support encryption currently")
- // ErrUnknownEncryptMechanism defined the error message on unsupport
+ // ErrUnknownEncryptMechanism defined the error message on unsupported
// encryption mechanism.
ErrUnknownEncryptMechanism = errors.New("unknown encryption mechanism")
- // ErrUnsupportEncryptMechanism defined the error message on unsupport
+ // ErrUnsupportedEncryptMechanism defined the error message on unsupported
// encryption mechanism.
- ErrUnsupportEncryptMechanism = errors.New("unsupport encryption mechanism")
+ ErrUnsupportedEncryptMechanism = errors.New("unsupported encryption mechanism")
+ // ErrUnsupportedHashAlgorithm defined the error message on unsupported
+ // hash algorithm.
+ ErrUnsupportedHashAlgorithm = errors.New("unsupported hash algorithm")
+ // ErrUnsupportedNumberFormat defined the error message on unsupported number format
+ // expression.
+ ErrUnsupportedNumberFormat = errors.New("unsupported number format token")
+ // ErrPasswordLengthInvalid defined the error message on invalid password
+ // length.
+ ErrPasswordLengthInvalid = errors.New("password length invalid")
// ErrParameterRequired defined the error message on receive the empty
// parameter.
ErrParameterRequired = errors.New("parameter is required")
@@ -118,9 +138,9 @@ var (
// ErrDefinedNameScope defined the error message on not found defined name
// in the given scope.
ErrDefinedNameScope = errors.New("no defined name on the scope")
- // ErrDefinedNameduplicate defined the error message on the same name
+ // ErrDefinedNameDuplicate defined the error message on the same name
// already exists on the scope.
- ErrDefinedNameduplicate = errors.New("the same name already exists on the scope")
+ ErrDefinedNameDuplicate = errors.New("the same name already exists on the scope")
// ErrCustomNumFmt defined the error message on receive the empty custom number format.
ErrCustomNumFmt = errors.New("custom number format can not be empty")
// ErrFontLength defined the error message on the length of the font
@@ -131,11 +151,17 @@ var (
// ErrSheetIdx defined the error message on receive the invalid worksheet
// index.
ErrSheetIdx = errors.New("invalid worksheet index")
+ // ErrUnprotectSheet defined the error message on worksheet has set no
+ // protection.
+ ErrUnprotectSheet = errors.New("worksheet has set no protect")
+ // ErrUnprotectSheetPassword defined the error message on remove sheet
+ // protection with password verification failed.
+ ErrUnprotectSheetPassword = errors.New("worksheet protect password not match")
// ErrGroupSheets defined the error message on group sheets.
ErrGroupSheets = errors.New("group worksheet must contain an active worksheet")
- // ErrDataValidationFormulaLenth defined the error message for receiving a
+ // ErrDataValidationFormulaLength defined the error message for receiving a
// data validation formula length that exceeds the limit.
- ErrDataValidationFormulaLenth = errors.New("data validation must be 0-255 characters")
+ ErrDataValidationFormulaLength = errors.New("data validation must be 0-255 characters")
// ErrDataValidationRange defined the error message on set decimal range
// exceeds limit.
ErrDataValidationRange = errors.New("data validation range exceeds limit")
@@ -164,5 +190,5 @@ var (
ErrSparkline = errors.New("must have the same number of 'Location' and 'Range' parameters")
// ErrSparklineStyle defined the error message on receive the invalid
// sparkline Style parameters.
- ErrSparklineStyle = errors.New("parameter 'Style' must betweent 0-35")
+ ErrSparklineStyle = errors.New("parameter 'Style' must between 0-35")
)
diff --git a/vendor/github.com/xuri/excelize/v2/excelize.go b/vendor/github.com/xuri/excelize/v2/excelize.go
index 25acd54d..9fe3d881 100644
--- a/vendor/github.com/xuri/excelize/v2/excelize.go
+++ b/vendor/github.com/xuri/excelize/v2/excelize.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
//
// See https://xuri.me/excelize for more information about this package.
package excelize
@@ -32,30 +32,31 @@ import (
// File define a populated spreadsheet file struct.
type File struct {
sync.Mutex
- options *Options
- xmlAttr map[string][]xml.Attr
- checked map[string]bool
- sheetMap map[string]string
- streams map[string]*StreamWriter
- tempFiles sync.Map
- CalcChain *xlsxCalcChain
- Comments map[string]*xlsxComments
- ContentTypes *xlsxTypes
- Drawings sync.Map
- Path string
- SharedStrings *xlsxSST
- sharedStringsMap map[string]int
- sharedStringItemMap *sync.Map
- Sheet sync.Map
- SheetCount int
- Styles *xlsxStyleSheet
- Theme *xlsxTheme
- DecodeVMLDrawing map[string]*decodeVmlDrawing
- VMLDrawing map[string]*vmlDrawing
- WorkBook *xlsxWorkbook
- Relationships sync.Map
- Pkg sync.Map
- CharsetReader charsetTranscoderFn
+ options *Options
+ xmlAttr map[string][]xml.Attr
+ checked map[string]bool
+ sheetMap map[string]string
+ streams map[string]*StreamWriter
+ tempFiles sync.Map
+ CalcChain *xlsxCalcChain
+ Comments map[string]*xlsxComments
+ ContentTypes *xlsxTypes
+ Drawings sync.Map
+ Path string
+ SharedStrings *xlsxSST
+ sharedStringsMap map[string]int
+ sharedStringItem [][]uint
+ sharedStringTemp *os.File
+ Sheet sync.Map
+ SheetCount int
+ Styles *xlsxStyleSheet
+ Theme *xlsxTheme
+ DecodeVMLDrawing map[string]*decodeVmlDrawing
+ VMLDrawing map[string]*vmlDrawing
+ WorkBook *xlsxWorkbook
+ Relationships sync.Map
+ Pkg sync.Map
+ CharsetReader charsetTranscoderFn
}
type charsetTranscoderFn func(charset string, input io.Reader) (rdr io.Reader, err error)
@@ -101,13 +102,16 @@ func OpenFile(filename string, opt ...Options) (*File, error) {
if err != nil {
return nil, err
}
- defer file.Close()
f, err := OpenReader(file, opt...)
if err != nil {
- return nil, err
+ closeErr := file.Close()
+ if closeErr == nil {
+ return f, err
+ }
+ return f, closeErr
}
f.Path = filename
- return f, nil
+ return f, file.Close()
}
// newFile is object builder
@@ -326,7 +330,7 @@ func checkSheetR0(ws *xlsxWorksheet, sheetData *xlsxSheetData, r0 *xlsxRow) {
// addRels provides a function to add relationships by given XML path,
// relationship type, target and target mode.
func (f *File) addRels(relPath, relType, target, targetMode string) int {
- var uniqPart = map[string]string{
+ uniqPart := map[string]string{
SourceRelationshipSharedStrings: "/xl/sharedStrings.xml",
}
rels := f.relsReader(relPath)
@@ -433,7 +437,6 @@ func (f *File) AddVBAProject(bin string) error {
if path.Ext(bin) != ".bin" {
return ErrAddVBAProject
}
- f.setContentTypePartVBAProjectExtensions()
wb := f.relsReader(f.getWorkbookRelsPath())
wb.Lock()
defer wb.Unlock()
@@ -462,9 +465,9 @@ func (f *File) AddVBAProject(bin string) error {
return err
}
-// setContentTypePartVBAProjectExtensions provides a function to set the
-// content type for relationship parts and the main document part.
-func (f *File) setContentTypePartVBAProjectExtensions() {
+// setContentTypePartProjectExtensions provides a function to set the content
+// type for relationship parts and the main document part.
+func (f *File) setContentTypePartProjectExtensions(contentType string) {
var ok bool
content := f.contentTypesReader()
content.Lock()
@@ -476,7 +479,7 @@ func (f *File) setContentTypePartVBAProjectExtensions() {
}
for idx, o := range content.Overrides {
if o.PartName == "/xl/workbook.xml" {
- content.Overrides[idx].ContentType = ContentTypeMacro
+ content.Overrides[idx].ContentType = contentType
}
}
if !ok {
diff --git a/vendor/github.com/xuri/excelize/v2/file.go b/vendor/github.com/xuri/excelize/v2/file.go
index 6c8bd93f..9707a793 100644
--- a/vendor/github.com/xuri/excelize/v2/file.go
+++ b/vendor/github.com/xuri/excelize/v2/file.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -29,8 +29,8 @@ import (
func NewFile() *File {
f := newFile()
f.Pkg.Store("_rels/.rels", []byte(xml.Header+templateRels))
- f.Pkg.Store(dafaultXMLPathDocPropsApp, []byte(xml.Header+templateDocpropsApp))
- f.Pkg.Store(dafaultXMLPathDocPropsCore, []byte(xml.Header+templateDocpropsCore))
+ f.Pkg.Store(defaultXMLPathDocPropsApp, []byte(xml.Header+templateDocpropsApp))
+ f.Pkg.Store(defaultXMLPathDocPropsCore, []byte(xml.Header+templateDocpropsCore))
f.Pkg.Store("xl/_rels/workbook.xml.rels", []byte(xml.Header+templateWorkbookRels))
f.Pkg.Store("xl/theme/theme1.xml", []byte(xml.Header+templateTheme))
f.Pkg.Store("xl/worksheets/sheet1.xml", []byte(xml.Header+templateSheet))
@@ -63,14 +63,25 @@ func (f *File) Save() error {
return f.SaveAs(f.Path)
}
-// SaveAs provides a function to create or update to an spreadsheet at the
+// SaveAs provides a function to create or update to a spreadsheet at the
// provided path.
func (f *File) SaveAs(name string, opt ...Options) error {
if len(name) > MaxFileNameLength {
return ErrMaxFileNameLength
}
f.Path = name
- file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
+ contentType, ok := map[string]string{
+ ".xlam": ContentTypeAddinMacro,
+ ".xlsm": ContentTypeMacro,
+ ".xlsx": ContentTypeSheetML,
+ ".xltm": ContentTypeTemplateMacro,
+ ".xltx": ContentTypeTemplate,
+ }[filepath.Ext(f.Path)]
+ if !ok {
+ return ErrWorkbookExt
+ }
+ f.setContentTypePartProjectExtensions(contentType)
+ file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
if err != nil {
return err
}
@@ -85,6 +96,11 @@ func (f *File) SaveAs(name string, opt ...Options) error {
// Close closes and cleanup the open temporary file for the spreadsheet.
func (f *File) Close() error {
var err error
+ if f.sharedStringTemp != nil {
+ if err := f.sharedStringTemp.Close(); err != nil {
+ return err
+ }
+ }
f.tempFiles.Range(func(k, v interface{}) bool {
if err = os.Remove(v.(string)); err != nil {
return false
diff --git a/vendor/github.com/xuri/excelize/v2/lib.go b/vendor/github.com/xuri/excelize/v2/lib.go
index 8ec121b4..723b976f 100644
--- a/vendor/github.com/xuri/excelize/v2/lib.go
+++ b/vendor/github.com/xuri/excelize/v2/lib.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -31,7 +31,7 @@ func (f *File) ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
err error
docPart = map[string]string{
"[content_types].xml": defaultXMLPathContentTypes,
- "xl/sharedstrings.xml": dafaultXMLPathSharedStrings,
+ "xl/sharedstrings.xml": defaultXMLPathSharedStrings,
}
fileList = make(map[string][]byte, len(r.File))
worksheets int
@@ -47,7 +47,7 @@ func (f *File) ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
if partName, ok := docPart[strings.ToLower(fileName)]; ok {
fileName = partName
}
- if strings.EqualFold(fileName, dafaultXMLPathSharedStrings) && fileSize > f.options.UnzipXMLSizeLimit {
+ if strings.EqualFold(fileName, defaultXMLPathSharedStrings) && fileSize > f.options.UnzipXMLSizeLimit {
if tempFile, err := f.unzipToTemp(v); err == nil {
f.tempFiles.Store(fileName, tempFile)
continue
@@ -80,10 +80,13 @@ func (f *File) unzipToTemp(zipFile *zip.File) (string, error) {
if err != nil {
return tmp.Name(), err
}
- _, err = io.Copy(tmp, rc)
- rc.Close()
- tmp.Close()
- return tmp.Name(), err
+ if _, err = io.Copy(tmp, rc); err != nil {
+ return tmp.Name(), err
+ }
+ if err = rc.Close(); err != nil {
+ return tmp.Name(), err
+ }
+ return tmp.Name(), tmp.Close()
}
// readXML provides a function to read XML content as bytes.
@@ -109,7 +112,7 @@ func (f *File) readBytes(name string) []byte {
}
content, _ = ioutil.ReadAll(file)
f.Pkg.Store(name, content)
- file.Close()
+ _ = file.Close()
return content
}
@@ -129,7 +132,7 @@ func (f *File) saveFileList(name string, content []byte) {
f.Pkg.Store(name, append([]byte(xml.Header), content...))
}
-// Read file content as string in a archive file.
+// Read file content as string in an archive file.
func readFile(file *zip.File) ([]byte, error) {
rc, err := file.Open()
if err != nil {
@@ -154,8 +157,8 @@ func SplitCellName(cell string) (string, int, error) {
if strings.IndexFunc(cell, alpha) == 0 {
i := strings.LastIndexFunc(cell, alpha)
if i >= 0 && i < len(cell)-1 {
- col, rowstr := strings.ReplaceAll(cell[:i+1], "$", ""), cell[i+1:]
- if row, err := strconv.Atoi(rowstr); err == nil && row > 0 {
+ col, rowStr := strings.ReplaceAll(cell[:i+1], "$", ""), cell[i+1:]
+ if row, err := strconv.Atoi(rowStr); err == nil && row > 0 {
return col, row, nil
}
}
@@ -184,7 +187,7 @@ func JoinCellName(col string, row int) (string, error) {
}
// ColumnNameToNumber provides a function to convert Excel sheet column name
-// to int. Column name case insensitive. The function returns an error if
+// to int. Column name case-insensitive. The function returns an error if
// column name incorrect.
//
// Example:
@@ -245,14 +248,14 @@ func ColumnNumberToName(num int) (string, error) {
// excelize.CellNameToCoordinates("Z3") // returns 26, 3, nil
//
func CellNameToCoordinates(cell string) (int, int, error) {
- colname, row, err := SplitCellName(cell)
+ colName, row, err := SplitCellName(cell)
if err != nil {
return -1, -1, newCellNameToCoordinatesError(cell, err)
}
if row > TotalRows {
return -1, -1, ErrMaxRows
}
- col, err := ColumnNameToNumber(colname)
+ col, err := ColumnNameToNumber(colName)
return col, row, err
}
@@ -274,8 +277,8 @@ func CoordinatesToCellName(col, row int, abs ...bool) (string, error) {
sign = "$"
}
}
- colname, err := ColumnNumberToName(col)
- return sign + colname + sign + strconv.Itoa(row), err
+ colName, err := ColumnNumberToName(col)
+ return sign + colName + sign + strconv.Itoa(row), err
}
// areaRefToCoordinates provides a function to convert area reference to a
@@ -333,6 +336,27 @@ func (f *File) coordinatesToAreaRef(coordinates []int) (string, error) {
return firstCell + ":" + lastCell, err
}
+// getDefinedNameRefTo convert defined name to reference range.
+func (f *File) getDefinedNameRefTo(definedNameName string, currentSheet string) (refTo string) {
+ var workbookRefTo, worksheetRefTo string
+ for _, definedName := range f.GetDefinedName() {
+ if definedName.Name == definedNameName {
+ // worksheet scope takes precedence over scope workbook when both definedNames exist
+ if definedName.Scope == "Workbook" {
+ workbookRefTo = definedName.RefersTo
+ }
+ if definedName.Scope == currentSheet {
+ worksheetRefTo = definedName.RefersTo
+ }
+ }
+ }
+ refTo = workbookRefTo
+ if worksheetRefTo != "" {
+ refTo = worksheetRefTo
+ }
+ return
+}
+
// flatSqref convert reference sequence to cell coordinates list.
func (f *File) flatSqref(sqref string) (cells map[int][][]int, err error) {
var coordinates []int
@@ -362,7 +386,7 @@ func (f *File) flatSqref(sqref string) (cells map[int][][]int, err error) {
return
}
-// inCoordinates provides a method to check if an coordinate is present in
+// inCoordinates provides a method to check if a coordinate is present in
// coordinates array, and return the index of its location, otherwise
// return -1.
func inCoordinates(a [][]int, x []int) int {
@@ -376,8 +400,11 @@ func inCoordinates(a [][]int, x []int) int {
// inStrSlice provides a method to check if an element is present in an array,
// and return the index of its location, otherwise return -1.
-func inStrSlice(a []string, x string) int {
+func inStrSlice(a []string, x string, caseSensitive bool) int {
for idx, n := range a {
+ if !caseSensitive && strings.EqualFold(x, n) {
+ return idx
+ }
if x == n {
return idx
}
@@ -385,7 +412,7 @@ func inStrSlice(a []string, x string) int {
return -1
}
-// inFloat64Slice provides a method to check if an element is present in an
+// inFloat64Slice provides a method to check if an element is present in a
// float64 array, and return the index of its location, otherwise return -1.
func inFloat64Slice(a []float64, x float64) int {
for idx, n := range a {
@@ -399,7 +426,7 @@ func inFloat64Slice(a []float64, x float64) int {
// boolPtr returns a pointer to a bool with the given value.
func boolPtr(b bool) *bool { return &b }
-// intPtr returns a pointer to a int with the given value.
+// intPtr returns a pointer to an int with the given value.
func intPtr(i int) *int { return &i }
// float64Ptr returns a pointer to a float64 with the given value.
@@ -434,9 +461,10 @@ func (avb attrValBool) MarshalXML(e *xml.Encoder, start xml.StartElement) error
}
}
start.Attr = []xml.Attr{attr}
- e.EncodeToken(start)
- e.EncodeToken(start.End())
- return nil
+ if err := e.EncodeToken(start); err != nil {
+ return err
+ }
+ return e.EncodeToken(start.End())
}
// UnmarshalXML convert the literal values true, false, 1, 0 of the XML
@@ -473,6 +501,8 @@ func (avb *attrValBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
return nil
}
}
+ defaultVal := true
+ avb.Val = &defaultVal
return nil
}
@@ -488,7 +518,7 @@ func parseFormatSet(formatSet string) []byte {
// namespaceStrictToTransitional provides a method to convert Strict and
// Transitional namespaces.
func namespaceStrictToTransitional(content []byte) []byte {
- var namespaceTranslationDic = map[string]string{
+ namespaceTranslationDic := map[string]string{
StrictSourceRelationship: SourceRelationship.Value,
StrictSourceRelationshipOfficeDocument: SourceRelationshipOfficeDocument,
StrictSourceRelationshipChart: SourceRelationshipChart,
@@ -553,7 +583,7 @@ func genSheetPasswd(plaintext string) string {
charPos++
rotatedBits := value >> 15 // rotated bits beyond bit 15
value &= 0x7fff // first 15 bits
- password ^= (value | rotatedBits)
+ password ^= value | rotatedBits
}
password ^= int64(len(plaintext))
password ^= 0xCE4B
@@ -609,15 +639,15 @@ func getXMLNamespace(space string, attr []xml.Attr) string {
// replaceNameSpaceBytes provides a function to replace the XML root element
// attribute by the given component part path and XML content.
func (f *File) replaceNameSpaceBytes(path string, contentMarshal []byte) []byte {
- var oldXmlns = []byte(`xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
- var newXmlns = []byte(templateNamespaceIDMap)
+ oldXmlns := []byte(`xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
+ newXmlns := []byte(templateNamespaceIDMap)
if attr, ok := f.xmlAttr[path]; ok {
newXmlns = []byte(genXMLNamespace(attr))
}
return bytesReplace(contentMarshal, oldXmlns, newXmlns, -1)
}
-// addNameSpaces provides a function to add a XML attribute by the given
+// addNameSpaces provides a function to add an XML attribute by the given
// component part path.
func (f *File) addNameSpaces(path string, ns xml.Attr) {
exist := false
@@ -656,7 +686,7 @@ func (f *File) addNameSpaces(path string, ns xml.Attr) {
// by the given attribute.
func (f *File) setIgnorableNameSpace(path string, index int, ns xml.Attr) {
ignorableNS := []string{"c14", "cdr14", "a14", "pic14", "x14", "xdr14", "x14ac", "dsp", "mso14", "dgm14", "x15", "x12ac", "x15ac", "xr", "xr2", "xr3", "xr4", "xr5", "xr6", "xr7", "xr8", "xr9", "xr10", "xr11", "xr12", "xr13", "xr14", "xr15", "x15", "x16", "x16r2", "mo", "mx", "mv", "o", "v"}
- if inStrSlice(strings.Fields(f.xmlAttr[path][index].Value), ns.Name.Local) == -1 && inStrSlice(ignorableNS, ns.Name.Local) != -1 {
+ if inStrSlice(strings.Fields(f.xmlAttr[path][index].Value), ns.Name.Local, true) == -1 && inStrSlice(ignorableNS, ns.Name.Local, true) != -1 {
f.xmlAttr[path][index].Value = strings.TrimSpace(fmt.Sprintf("%s %s", f.xmlAttr[path][index].Value, ns.Name.Local))
}
}
@@ -670,24 +700,33 @@ func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) {
// isNumeric determines whether an expression is a valid numeric type and get
// the precision for the numeric.
func isNumeric(s string) (bool, int) {
- dot := false
- p := 0
+ dot, e, n, p := false, false, false, 0
for i, v := range s {
if v == '.' {
if dot {
return false, 0
}
dot = true
+ } else if v == 'E' || v == 'e' {
+ e = true
} else if v < '0' || v > '9' {
if i == 0 && v == '-' {
continue
}
+ if e && v == '-' {
+ return true, 0
+ }
+ if e && v == '+' {
+ p = 15
+ continue
+ }
return false, 0
- } else if dot {
+ } else {
p++
}
+ n = true
}
- return true, p
+ return n, p
}
var (
@@ -697,7 +736,7 @@ var (
// bstrUnmarshal parses the binary basic string, this will trim escaped string
// literal which not permitted in an XML 1.0 document. The basic string
-// variant type can store any valid Unicode character. Unicode characters
+// variant type can store any valid Unicode character. Unicode's characters
// that cannot be directly represented in XML as defined by the XML 1.0
// specification, shall be escaped using the Unicode numerical character
// representation escape character format _xHHHH_, where H represents a
@@ -779,8 +818,8 @@ type Stack struct {
// NewStack create a new stack.
func NewStack() *Stack {
- list := list.New()
- return &Stack{list}
+ l := list.New()
+ return &Stack{l}
}
// Push a value onto the top of the stack.
diff --git a/vendor/github.com/xuri/excelize/v2/merge.go b/vendor/github.com/xuri/excelize/v2/merge.go
index 2d699a23..376b68b2 100644
--- a/vendor/github.com/xuri/excelize/v2/merge.go
+++ b/vendor/github.com/xuri/excelize/v2/merge.go
@@ -1,17 +1,19 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
-import "strings"
+import (
+ "strings"
+)
// Rect gets merged cell rectangle coordinates sequence.
func (mc *xlsxMergeCell) Rect() ([]int, error) {
@@ -46,29 +48,30 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) {
// |A8(x3,y4) C8(x4,y4)|
// +------------------------+
//
-func (f *File) MergeCell(sheet, hcell, vcell string) error {
- rect, err := areaRefToCoordinates(hcell + ":" + vcell)
+func (f *File) MergeCell(sheet, hCell, vCell string) error {
+ rect, err := areaRefToCoordinates(hCell + ":" + vCell)
if err != nil {
return err
}
// Correct the coordinate area, such correct C1:B3 to B1:C3.
_ = sortCoordinates(rect)
- hcell, _ = CoordinatesToCellName(rect[0], rect[1])
- vcell, _ = CoordinatesToCellName(rect[2], rect[3])
+ hCell, _ = CoordinatesToCellName(rect[0], rect[1])
+ vCell, _ = CoordinatesToCellName(rect[2], rect[3])
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
- ref := hcell + ":" + vcell
+ ref := hCell + ":" + vCell
if ws.MergeCells != nil {
ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref, rect: rect})
} else {
ws.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref, rect: rect}}}
}
ws.MergeCells.Count = len(ws.MergeCells.Cells)
- return err
+ styleID, _ := f.GetCellStyle(sheet, hCell)
+ return f.SetCellStyle(sheet, hCell, vCell, styleID)
}
// UnmergeCell provides a function to unmerge a given coordinate area.
@@ -77,12 +80,12 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
// err := f.UnmergeCell("Sheet1", "D3", "E9")
//
// Attention: overlapped areas will also be unmerged.
-func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
+func (f *File) UnmergeCell(sheet string, hCell, vCell string) error {
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
- rect1, err := areaRefToCoordinates(hcell + ":" + vcell)
+ rect1, err := areaRefToCoordinates(hCell + ":" + vCell)
if err != nil {
return err
}
@@ -254,9 +257,9 @@ func mergeCell(cell1, cell2 *xlsxMergeCell) *xlsxMergeCell {
if rect1[3] < rect2[3] {
rect1[3], rect2[3] = rect2[3], rect1[3]
}
- hcell, _ := CoordinatesToCellName(rect1[0], rect1[1])
- vcell, _ := CoordinatesToCellName(rect1[2], rect1[3])
- return &xlsxMergeCell{rect: rect1, Ref: hcell + ":" + vcell}
+ hCell, _ := CoordinatesToCellName(rect1[0], rect1[1])
+ vCell, _ := CoordinatesToCellName(rect1[2], rect1[3])
+ return &xlsxMergeCell{rect: rect1, Ref: hCell + ":" + vCell}
}
// MergeCell define a merged cell data.
diff --git a/vendor/github.com/xuri/excelize/v2/numfmt.go b/vendor/github.com/xuri/excelize/v2/numfmt.go
new file mode 100644
index 00000000..6cb7fc74
--- /dev/null
+++ b/vendor/github.com/xuri/excelize/v2/numfmt.go
@@ -0,0 +1,953 @@
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
+// this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+//
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
+
+package excelize
+
+import (
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/xuri/nfp"
+)
+
+// languageInfo defined the required fields of localization support for number format.
+type languageInfo struct {
+ apFmt string
+ tags []string
+ localMonth func(t time.Time, abbr int) string
+}
+
+// numberFormat directly maps the number format parser runtime required
+// fields.
+type numberFormat struct {
+ section []nfp.Section
+ t time.Time
+ sectionIdx int
+ isNumeric, hours, seconds bool
+ number float64
+ ap, afterPoint, beforePoint, localCode, result, value, valueSectionType string
+}
+
+var (
+ // supportedTokenTypes list the supported number format token types currently.
+ supportedTokenTypes = []string{
+ nfp.TokenSubTypeLanguageInfo,
+ nfp.TokenTypeColor,
+ nfp.TokenTypeCurrencyLanguage,
+ nfp.TokenTypeDateTimes,
+ nfp.TokenTypeElapsedDateTimes,
+ nfp.TokenTypeGeneral,
+ nfp.TokenTypeLiteral,
+ nfp.TokenTypeTextPlaceHolder,
+ nfp.TokenTypeZeroPlaceHolder,
+ }
+ // supportedLanguageInfo directly maps the supported language ID and tags.
+ supportedLanguageInfo = map[string]languageInfo{
+ "36": {tags: []string{"af"}, localMonth: localMonthsNameAfrikaans, apFmt: apFmtAfrikaans},
+ "445": {tags: []string{"bn-IN"}, localMonth: localMonthsNameBangla, apFmt: nfp.AmPm[0]},
+ "4": {tags: []string{"zh-Hans"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
+ "7804": {tags: []string{"zh"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
+ "804": {tags: []string{"zh-CN"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
+ "1004": {tags: []string{"zh-SG"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2]},
+ "7C04": {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
+ "C04": {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2]},
+ "1404": {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
+ "404": {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
+ "9": {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "1000": {tags: []string{
+ "aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML",
+ "gsw-LI", "gsw-CH", "ar-TD", "ar-KM", "ar-DJ", "ar-ER", "ar-IL", "ar-MR", "ar-PS",
+ "ar-SO", "ar-SS", "ar-SD", "ar-001", "ast", "ast-ES", "asa", "asa-TZ", "ksf", "ksf-CM",
+ "bm", "bm-Latn-ML", "bas", "bas-CM", "bem", "bem-ZM", "bez", "bez-TZ", "byn", "byn-ER",
+ "brx", "brx-IN", "ca-AD", "ca-FR", "ca-IT", "ceb", "ceb-Latn", "ceb-Latn-PH", "tzm-Latn-MA",
+ "ccp", "ccp-Cakm", "ccp-Cakm-BD", "ccp-Cakm-IN", "ce-RU", "cgg", "cgg-UG", "cu-RU", "swc",
+ "swc-CD", "kw", "ke-GB", "da-GL", "dua", "dua-CM", "nl-AW", "nl-BQ", "nl-CW", "nl-SX",
+ "nl-SR", "dz", "ebu", "ebu-KE", "en-AS", "en-AI", "en-AG", "en-AT", "en-BS", "en-BB",
+ "en-BE", "en-BM", "en-BW", "en-IO", "en-VG", "en-BI", "en-CM", "en-KY", "en-CX", "en-CC",
+ "en-CK", "en-CY", "en-DK", "en-DM", "en-ER", "en-150", "en-FK", "en-FI", "en-FJ", "en-GM",
+ "en-DE", "en-GH", "en-GI", "en-GD", "en-GU", "en-GG", "en-GY", "en-IM", "en-IL", "en-JE",
+ "en-KE", "en-KI", "en-LS", "en-LR", "en-MO", "en-MG", "en-MW", "en-MT", "en-MH", "en-MU",
+ "en-FM", "en-MS", "en-NA", "en-NR", "en-NL", "en-NG", "en-NU", "en-NF", "en-MP", "en-PK",
+ "en-PW", "en-PG", "en-PN", "en-PR", "en-RW", "en-KN", "en-LC", "en-VC", "en-WS", "en-SC",
+ "en-SL", "en-SX", "en-SI", "en-SB", "en-SS", "en-SH", "en-SD", "en-SZ", "en-SE", "en-CH",
+ "en-TZ", "en-TK", "en-TO", "en-TC", "en-TV", "en-UG", "en-UM", "en-VI", "en-VU", "en-001",
+ "en-ZM", "eo", "eo-001", "ee", "ee-GH", "ee-TG", "ewo", "ewo-CM", "fo-DK", "fr-DZ",
+ "fr-BJ", "fr-BF", "fr-BI", "fr-CF", "fr-TD", "fr-KM", "fr-CG", "fr-DJ", "fr-GQ", "fr-GF",
+ "fr-PF", "fr-GA", "fr-GP", "fr-GN", "fr-MG", "fr-MQ", "fr-MR", "fr-MU", "fr-YT", "fr-NC",
+ "fr-NE", "fr-RW", "fr-BL", "fr-MF", "fr-PM", "fr-SC", "fr-SY", "fr-TG", "fr-TN", "fr-VU",
+ "fr-WF", "fur", "fur-IT", "ff-Latn-BF", "ff-CM", "ff-Latn-CM", "ff-Latn-GM", "ff-Latn-GH",
+ "ff-GN", "ff-Latn-GN", "ff-Latn-GW", "ff-Latn-LR", "ff-MR", "ff-Latn-MR", "ff-Latn-NE",
+ "ff-Latn-SL", "lg", "lg-UG", "de-BE", "de-IT", "el-CY", "guz", "guz-KE", "ha-Latn-GH",
+ "ha-Latn-NG", "ia-FR", "ia-001", "it-SM", "it-VA", "jv", "jv-Latn", "jv-Latn-ID", "dyo",
+ "dyo-SN", "kea", "kea-CV", "kab", "kab-DZ", "kkj", "kkj-CM", "kln", "kln-KE", "kam",
+ "kam-KE", "ks-Arab-IN", "ki", "ki-KE", "sw-TZ", "sw-UG", "ko-KP", "khq", "khq-ML", "ses",
+ "ses-ML", "nmg", "nmq-CM", "ku-Arab-IR", "lkt", "lkt-US", "lag", "lag-TZ", "ln", "ln-AO",
+ "ln-CF", "ln-CD", "nds", "nds-DE", "nds-NL", "lu", "lu-CD", "luo", "luo", "luo-KE", "luy",
+ "luy-KE", "jmc", "jmc-TZ", "mgh", "mgh-MZ", "kde", "kde-TZ", "mg", "mg-MG", "gv", "gv-IM",
+ "mas", "mas-KE", "mas-TZ", "mas-IR", "mer", "mer-KE", "mgo", "mgo-CM", "mfe", "mfe-MU",
+ "mua", "mua-CM", "nqo", "nqo-GN", "nqa", "naq-NA", "nnh", "nnh-CM", "jgo", "jgo-CM",
+ "lrc-IQ", "lrc-IR", "nd", "nd-ZW", "nb-SJ", "nus", "nus-SD", "nus-SS", "nyn", "nyn-UG",
+ "om-KE", "os", "os-GE", "os-RU", "ps-PK", "fa-AF", "pt-AO", "pt-CV", "pt-GQ", "pt-GW",
+ "pt-LU", "pt-MO", "pt-MZ", "pt-ST", "pt-CH", "pt-TL", "prg-001", "ksh", "ksh-DE", "rof",
+ "rof-TZ", "rn", "rn-BI", "ru-BY", "ru-KZ", "ru-KG", "ru-UA", "rwk", "rwk-TZ", "ssy",
+ "ssy-ER", "saq", "saq-KE", "sg", "sq-CF", "sbp", "sbp-TZ", "seh", "seh-MZ", "ksb", "ksb-TZ",
+ "sn", "sn-Latn", "sn-Latn-ZW", "xog", "xog-UG", "so-DJ", "so-ET", "so-KE", "nr", "nr-ZA",
+ "st-LS", "es-BZ", "es-BR", "es-PH", "zgh", "zgh-Tfng-MA", "zgh-Tfng", "ss", "ss-ZA",
+ "ss-SZ", "sv-AX", "shi", "shi-Tfng", "shi-Tfng-MA", "shi-Latn", "shi-Latn-MA", "dav",
+ "dav-KE", "ta-MY", "ta-SG", "twq", "twq-NE", "teo", "teo-KE", "teo-UG", "bo-IN", "tig",
+ "tig-ER", "to", "to-TO", "tr-CY", "uz-Arab", "us-Arab-AF", "vai", "vai-Vaii",
+ "vai-Vaii-LR", "vai-Latn-LR", "vai-Latn", "vo", "vo-001", "vun", "vun-TZ", "wae",
+ "wae-CH", "wal", "wae-ET", "yav", "yav-CM", "yo-BJ", "dje", "dje-NE",
+ }, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "C09": {tags: []string{"en-AU"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
+ "2829": {tags: []string{"en-BZ"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "1009": {tags: []string{"en-CA"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "2409": {tags: []string{"en-029"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "3C09": {tags: []string{"en-HK"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "4009": {tags: []string{"en-IN"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "1809": {tags: []string{"en-IE"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
+ "2009": {tags: []string{"en-JM"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "4409": {tags: []string{"en-MY"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "1409": {tags: []string{"en-NZ"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "3409": {tags: []string{"en-PH"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "4809": {tags: []string{"en-SG"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "1C09": {tags: []string{"en-ZA"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "2C09": {tags: []string{"en-TT"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "4C09": {tags: []string{"en-AE"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "809": {tags: []string{"en-GB"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
+ "409": {tags: []string{"en-US"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "3009": {tags: []string{"en-ZW"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
+ "C": {tags: []string{"fr"}, localMonth: localMonthsNameFrench, apFmt: nfp.AmPm[0]},
+ "7": {tags: []string{"de"}, localMonth: localMonthsNameGerman, apFmt: nfp.AmPm[0]},
+ "C07": {tags: []string{"de-AT"}, localMonth: localMonthsNameAustria, apFmt: nfp.AmPm[0]},
+ "407": {tags: []string{"de-DE"}, localMonth: localMonthsNameGerman, apFmt: nfp.AmPm[0]},
+ "3C": {tags: []string{"ga"}, localMonth: localMonthsNameIrish, apFmt: apFmtIrish},
+ "83C": {tags: []string{"ga-IE"}, localMonth: localMonthsNameIrish, apFmt: apFmtIrish},
+ "10": {tags: []string{"it"}, localMonth: localMonthsNameItalian, apFmt: nfp.AmPm[0]},
+ "11": {tags: []string{"ja"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese},
+ "411": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese},
+ "12": {tags: []string{"ko"}, localMonth: localMonthsNameKorean, apFmt: apFmtKorean},
+ "412": {tags: []string{"ko-KR"}, localMonth: localMonthsNameKorean, apFmt: apFmtKorean},
+ "7C50": {tags: []string{"mn-Mong"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
+ "850": {tags: []string{"mn-Mong-CN"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
+ "C50": {tags: []string{"mn-Mong-MN"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
+ "19": {tags: []string{"ru"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
+ "819": {tags: []string{"ru-MD"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
+ "419": {tags: []string{"ru-RU"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
+ "A": {tags: []string{"es"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "2C0A": {tags: []string{"es-AR"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "200A": {tags: []string{"es-VE"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "400A": {tags: []string{"es-BO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "340A": {tags: []string{"es-CL"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "240A": {tags: []string{"es-CO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "140A": {tags: []string{"es-CR"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "5C0A": {tags: []string{"es-CU"}, localMonth: localMonthsNameSpanish, apFmt: apFmtCuba},
+ "1C0A": {tags: []string{"es-DO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "300A": {tags: []string{"es-EC"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "440A": {tags: []string{"es-SV"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
+ "1E": {tags: []string{"th"}, localMonth: localMonthsNameThai, apFmt: nfp.AmPm[0]},
+ "41E": {tags: []string{"th-TH"}, localMonth: localMonthsNameThai, apFmt: nfp.AmPm[0]},
+ "51": {tags: []string{"bo"}, localMonth: localMonthsNameTibetan, apFmt: apFmtTibetan},
+ "451": {tags: []string{"bo-CN"}, localMonth: localMonthsNameTibetan, apFmt: apFmtTibetan},
+ "1F": {tags: []string{"tr"}, localMonth: localMonthsNameTurkish, apFmt: apFmtTurkish},
+ "41F": {tags: []string{"tr-TR"}, localMonth: localMonthsNameTurkish, apFmt: apFmtTurkish},
+ "52": {tags: []string{"cy"}, localMonth: localMonthsNameWelsh, apFmt: apFmtWelsh},
+ "452": {tags: []string{"cy-GB"}, localMonth: localMonthsNameWelsh, apFmt: apFmtWelsh},
+ "2A": {tags: []string{"vi"}, localMonth: localMonthsNameVietnamese, apFmt: apFmtVietnamese},
+ "42A": {tags: []string{"vi-VN"}, localMonth: localMonthsNameVietnamese, apFmt: apFmtVietnamese},
+ "88": {tags: []string{"wo"}, localMonth: localMonthsNameWolof, apFmt: apFmtWolof},
+ "488": {tags: []string{"wo-SN"}, localMonth: localMonthsNameWolof, apFmt: apFmtWolof},
+ "34": {tags: []string{"xh"}, localMonth: localMonthsNameXhosa, apFmt: nfp.AmPm[0]},
+ "434": {tags: []string{"xh-ZA"}, localMonth: localMonthsNameXhosa, apFmt: nfp.AmPm[0]},
+ "78": {tags: []string{"ii"}, localMonth: localMonthsNameYi, apFmt: apFmtYi},
+ "478": {tags: []string{"ii-CN"}, localMonth: localMonthsNameYi, apFmt: apFmtYi},
+ "35": {tags: []string{"zu"}, localMonth: localMonthsNameZulu, apFmt: nfp.AmPm[0]},
+ "435": {tags: []string{"zu-ZA"}, localMonth: localMonthsNameZulu, apFmt: nfp.AmPm[0]},
+ }
+ // monthNamesBangla list the month names in the Bangla.
+ monthNamesBangla = []string{
+ "\u099C\u09BE\u09A8\u09C1\u09AF\u09BC\u09BE\u09B0\u09C0",
+ "\u09AB\u09C7\u09AC\u09CD\u09B0\u09C1\u09AF\u09BC\u09BE\u09B0\u09C0",
+ "\u09AE\u09BE\u09B0\u09CD\u099A",
+ "\u098F\u09AA\u09CD\u09B0\u09BF\u09B2",
+ "\u09AE\u09C7",
+ "\u099C\u09C1\u09A8",
+ "\u099C\u09C1\u09B2\u09BE\u0987",
+ "\u0986\u0997\u09B8\u09CD\u099F",
+ "\u09B8\u09C7\u09AA\u09CD\u099F\u09C7\u09AE\u09CD\u09AC\u09B0",
+ "\u0985\u0995\u09CD\u099F\u09CB\u09AC\u09B0",
+ "\u09A8\u09AD\u09C7\u09AE\u09CD\u09AC\u09B0",
+ "\u09A1\u09BF\u09B8\u09C7\u09AE\u09CD\u09AC\u09B0",
+ }
+ // monthNamesAfrikaans list the month names in the Afrikaans.
+ monthNamesAfrikaans = []string{"Januarie", "Februarie", "Maart", "April", "Mei", "Junie", "Julie", "Augustus", "September", "Oktober", "November", "Desember"}
+ // monthNamesChinese list the month names in the Chinese.
+ monthNamesChinese = []string{"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"}
+ // monthNamesFrench list the month names in the French.
+ monthNamesFrench = []string{"janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"}
+ // monthNamesGerman list the month names in the German.
+ monthNamesGerman = []string{"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
+ // monthNamesAustria list the month names in the Austria.
+ monthNamesAustria = []string{"Jänner", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
+ // monthNamesIrish list the month names in the Irish.
+ monthNamesIrish = []string{"Eanáir", "Feabhra", "Márta", "Aibreán", "Bealtaine", "Meitheamh", "Iúil", "Lúnasa", "Meán Fómhair", "Deireadh Fómhair", "Samhain", "Nollaig"}
+ // monthNamesItalian list the month names in the Italian.
+ monthNamesItalian = []string{"gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"}
+ // monthNamesRussian list the month names in the Russian.
+ monthNamesRussian = []string{"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"}
+ // monthNamesSpanish list the month names in the Spanish.
+ monthNamesSpanish = []string{"enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"}
+ // monthNamesThai list the month names in the Thai.
+ monthNamesThai = []string{
+ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21",
+ "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c",
+ "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21",
+ "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19",
+ "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21",
+ "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19",
+ "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21",
+ "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21",
+ "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19",
+ "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21",
+ "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19",
+ "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21",
+ }
+ // monthNamesTibetan list the month names in the Tibetan.
+ monthNamesTibetan = []string{
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0d",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ }
+ // monthNamesTurkish list the month names in the Turkish.
+ monthNamesTurkish = []string{"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}
+ // monthNamesWelsh list the month names in the Welsh.
+ monthNamesWelsh = []string{"Ionawr", "Chwefror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorffennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"}
+ // monthNamesWolof list the month names in the Wolof.
+ monthNamesWolof = []string{"Samwiye", "Fewriye", "Maars", "Awril", "Me", "Suwe", "Sullet", "Ut", "Septàmbar", "Oktoobar", "Noowàmbar", "Desàmbar"}
+ // monthNamesXhosa list the month names in the Xhosa.
+ monthNamesXhosa = []string{"Januwari", "Febuwari", "Matshi", "Aprili", "Meyi", "Juni", "Julayi", "Agasti", "Septemba", "Oktobha", "Novemba", "Disemba"}
+ // monthNamesYi list the month names in the Yi.
+ monthNamesYi = []string{"\ua2cd", "\ua44d", "\ua315", "\ua1d6", "\ua26c", "\ua0d8", "\ua3c3", "\ua246", "\ua22c", "\ua2b0", "\ua2b0\ua2aa", "\ua2b0\ua44b"}
+ // monthNamesZulu list the month names in the Zulu.
+ monthNamesZulu = []string{"Januwari", "Febhuwari", "Mashi", "Ephreli", "Meyi", "Juni", "Julayi", "Agasti", "Septemba", "Okthoba", "Novemba", "Disemba"}
+ // apFmtAfrikaans defined the AM/PM name in the Afrikaans.
+ apFmtAfrikaans = "vm./nm."
+ // apFmtCuba defined the AM/PM name in the Cuba.
+ apFmtCuba = "a.m./p.m."
+ // apFmtIrish defined the AM/PM name in the Irish.
+ apFmtIrish = "r.n./i.n."
+ // apFmtJapanese defined the AM/PM name in the Japanese.
+ apFmtJapanese = "午前/午後"
+ // apFmtKorean defined the AM/PM name in the Korean.
+ apFmtKorean = "오전/오후"
+ // apFmtSpanish defined the AM/PM name in the Spanish.
+ apFmtSpanish = "a. m./p. m."
+ // apFmtTibetan defined the AM/PM name in the Tibetan.
+ apFmtTibetan = "\u0f66\u0f94\u0f0b\u0f51\u0fb2\u0f7c\u0f0b/\u0f55\u0fb1\u0f72\u0f0b\u0f51\u0fb2\u0f7c\u0f0b"
+ // apFmtTurkish defined the AM/PM name in the Turkish.
+ apFmtTurkish = "\u00F6\u00F6/\u00F6\u0053"
+ // apFmtVietnamese defined the AM/PM name in the Vietnamese.
+ apFmtVietnamese = "SA/CH"
+ // apFmtWolof defined the AM/PM name in the Wolof.
+ apFmtWolof = "Sub/Ngo"
+ // apFmtYi defined the AM/PM name in the Yi.
+ apFmtYi = "\ua3b8\ua111/\ua06f\ua2d2"
+ // apFmtWelsh defined the AM/PM name in the Welsh.
+ apFmtWelsh = "yb/yh"
+)
+
+// prepareNumberic split the number into two before and after parts by a
+// decimal point.
+func (nf *numberFormat) prepareNumberic(value string) {
+ if nf.isNumeric, _ = isNumeric(value); !nf.isNumeric {
+ return
+ }
+}
+
+// format provides a function to return a string parse by number format
+// expression. If the given number format is not supported, this will return
+// the original cell value.
+func format(value, numFmt string) string {
+ p := nfp.NumberFormatParser()
+ nf := numberFormat{section: p.Parse(numFmt), value: value}
+ nf.number, nf.valueSectionType = nf.getValueSectionType(value)
+ nf.prepareNumberic(value)
+ for i, section := range nf.section {
+ nf.sectionIdx = i
+ if section.Type != nf.valueSectionType {
+ continue
+ }
+ if nf.isNumeric {
+ switch section.Type {
+ case nfp.TokenSectionPositive:
+ return nf.positiveHandler()
+ case nfp.TokenSectionNegative:
+ return nf.negativeHandler()
+ default:
+ return nf.zeroHandler()
+ }
+ }
+ return nf.textHandler()
+ }
+ return value
+}
+
+// positiveHandler will be handling positive selection for a number format
+// expression.
+func (nf *numberFormat) positiveHandler() (result string) {
+ nf.t, nf.hours, nf.seconds = timeFromExcelTime(nf.number, false), false, false
+ for i, token := range nf.section[nf.sectionIdx].Items {
+ if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral {
+ result = nf.value
+ return
+ }
+ if token.TType == nfp.TokenTypeCurrencyLanguage {
+ if err := nf.currencyLanguageHandler(i, token); err != nil {
+ result = nf.value
+ return
+ }
+ }
+ if token.TType == nfp.TokenTypeDateTimes {
+ nf.dateTimesHandler(i, token)
+ }
+ if token.TType == nfp.TokenTypeElapsedDateTimes {
+ nf.elapsedDateTimesHandler(token)
+ }
+ if token.TType == nfp.TokenTypeLiteral {
+ nf.result += token.TValue
+ continue
+ }
+ if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == "0" {
+ if isNum, precision := isNumeric(nf.value); isNum {
+ if nf.number < 1 {
+ nf.result += "0"
+ continue
+ }
+ if precision > 15 {
+ nf.result += roundPrecision(nf.value, 15)
+ } else {
+ nf.result += fmt.Sprintf("%.f", nf.number)
+ }
+ continue
+ }
+ }
+ }
+ result = nf.result
+ return
+}
+
+// currencyLanguageHandler will be handling currency and language types tokens for a number
+// format expression.
+func (nf *numberFormat) currencyLanguageHandler(i int, token nfp.Token) (err error) {
+ for _, part := range token.Parts {
+ if inStrSlice(supportedTokenTypes, part.Token.TType, true) == -1 {
+ err = ErrUnsupportedNumberFormat
+ return
+ }
+ if _, ok := supportedLanguageInfo[strings.ToUpper(part.Token.TValue)]; !ok {
+ err = ErrUnsupportedNumberFormat
+ return
+ }
+ nf.localCode = strings.ToUpper(part.Token.TValue)
+ }
+ return
+}
+
+// localAmPm return AM/PM name by supported language ID.
+func (nf *numberFormat) localAmPm(ap string) string {
+ if languageInfo, ok := supportedLanguageInfo[nf.localCode]; ok {
+ return languageInfo.apFmt
+ }
+ return ap
+}
+
+// localMonthsNameEnglish returns the English name of the month.
+func localMonthsNameEnglish(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return t.Month().String()[:3]
+ }
+ if abbr == 4 {
+ return t.Month().String()
+ }
+ return t.Month().String()[:1]
+}
+
+// localMonthsNameAfrikaans returns the Afrikaans name of the month.
+func localMonthsNameAfrikaans(t time.Time, abbr int) string {
+ if abbr == 3 {
+ month := monthNamesAfrikaans[int(t.Month())-1]
+ if len([]rune(month)) <= 3 {
+ return month
+ }
+ return string([]rune(month)[:3]) + "."
+ }
+ if abbr == 4 {
+ return monthNamesAfrikaans[int(t.Month())-1]
+ }
+ return monthNamesAfrikaans[int(t.Month())-1][:1]
+}
+
+// localMonthsNameAustria returns the Austria name of the month.
+func localMonthsNameAustria(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return string([]rune(monthNamesAustria[int(t.Month())-1])[:3])
+ }
+ if abbr == 4 {
+ return monthNamesAustria[int(t.Month())-1]
+ }
+ return monthNamesAustria[int(t.Month())-1][:1]
+}
+
+// localMonthsNameBangla returns the German name of the month.
+func localMonthsNameBangla(t time.Time, abbr int) string {
+ if abbr == 3 || abbr == 4 {
+ return monthNamesBangla[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesBangla[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameFrench returns the French name of the month.
+func localMonthsNameFrench(t time.Time, abbr int) string {
+ if abbr == 3 {
+ month := monthNamesFrench[int(t.Month())-1]
+ if len([]rune(month)) <= 4 {
+ return month
+ }
+ return string([]rune(month)[:4]) + "."
+ }
+ if abbr == 4 {
+ return monthNamesFrench[int(t.Month())-1]
+ }
+ return monthNamesFrench[int(t.Month())-1][:1]
+}
+
+// localMonthsNameIrish returns the Irish name of the month.
+func localMonthsNameIrish(t time.Time, abbr int) string {
+ if abbr == 3 {
+ switch int(t.Month()) {
+ case 1, 4, 8:
+ return string([]rune(monthNamesIrish[int(t.Month())-1])[:3])
+ case 2, 3, 6:
+ return string([]rune(monthNamesIrish[int(t.Month())-1])[:5])
+ case 9, 10:
+ return string([]rune(monthNamesIrish[int(t.Month())-1])[:1]) + "Fómh"
+ default:
+ return string([]rune(monthNamesIrish[int(t.Month())-1])[:4])
+ }
+ }
+ if abbr == 4 {
+ return monthNamesIrish[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesIrish[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameItalian returns the Italian name of the month.
+func localMonthsNameItalian(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return monthNamesItalian[int(t.Month())-1][:3]
+ }
+ if abbr == 4 {
+ return monthNamesItalian[int(t.Month())-1]
+ }
+ return monthNamesItalian[int(t.Month())-1][:1]
+}
+
+// localMonthsNameGerman returns the German name of the month.
+func localMonthsNameGerman(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return string([]rune(monthNamesGerman[int(t.Month())-1])[:3])
+ }
+ if abbr == 4 {
+ return monthNamesGerman[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesGerman[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameChinese1 returns the Chinese name of the month.
+func localMonthsNameChinese1(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return strconv.Itoa(int(t.Month())) + "月"
+ }
+ if abbr == 4 {
+ return monthNamesChinese[int(t.Month())-1] + "月"
+ }
+ return monthNamesChinese[int(t.Month())-1]
+}
+
+// localMonthsNameChinese2 returns the Chinese name of the month.
+func localMonthsNameChinese2(t time.Time, abbr int) string {
+ if abbr == 3 || abbr == 4 {
+ return monthNamesChinese[int(t.Month())-1] + "月"
+ }
+ return monthNamesChinese[int(t.Month())-1]
+}
+
+// localMonthsNameChinese3 returns the Chinese name of the month.
+func localMonthsNameChinese3(t time.Time, abbr int) string {
+ if abbr == 3 || abbr == 4 {
+ return strconv.Itoa(int(t.Month())) + "月"
+ }
+ return strconv.Itoa(int(t.Month()))
+}
+
+// localMonthsNameKorean returns the Korean name of the month.
+func localMonthsNameKorean(t time.Time, abbr int) string {
+ if abbr == 3 || abbr == 4 {
+ return strconv.Itoa(int(t.Month())) + "월"
+ }
+ return strconv.Itoa(int(t.Month()))
+}
+
+// localMonthsNameTraditionalMongolian returns the Traditional Mongolian name of the month.
+func localMonthsNameTraditionalMongolian(t time.Time, abbr int) string {
+ if abbr == 5 {
+ return "M"
+ }
+ return fmt.Sprintf("M%02d", int(t.Month()))
+}
+
+// localMonthsNameRussian returns the Russian name of the month.
+func localMonthsNameRussian(t time.Time, abbr int) string {
+ if abbr == 3 {
+ month := monthNamesRussian[int(t.Month())-1]
+ if len([]rune(month)) <= 4 {
+ return month
+ }
+ return string([]rune(month)[:3]) + "."
+ }
+ if abbr == 4 {
+ return monthNamesRussian[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesRussian[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameSpanish returns the Spanish name of the month.
+func localMonthsNameSpanish(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return monthNamesSpanish[int(t.Month())-1][:3]
+ }
+ if abbr == 4 {
+ return monthNamesSpanish[int(t.Month())-1]
+ }
+ return monthNamesSpanish[int(t.Month())-1][:1]
+}
+
+// localMonthsNameThai returns the Thai name of the month.
+func localMonthsNameThai(t time.Time, abbr int) string {
+ if abbr == 3 {
+ r := []rune(monthNamesThai[int(t.Month())-1])
+ return string(r[:1]) + "." + string(r[len(r)-2:len(r)-1]) + "."
+ }
+ if abbr == 4 {
+ return monthNamesThai[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesThai[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameTibetan returns the Tibetan name of the month.
+func localMonthsNameTibetan(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return "\u0f5f\u0fb3\u0f0b" + []string{"\u0f21", "\u0f22", "\u0f23", "\u0f24", "\u0f25", "\u0f26", "\u0f27", "\u0f28", "\u0f29", "\u0f21\u0f20", "\u0f21\u0f21", "\u0f21\u0f22"}[int(t.Month())-1]
+ }
+ if abbr == 5 {
+ if t.Month() == 10 {
+ return "\u0f66"
+ }
+ return "\u0f5f"
+ }
+ return monthNamesTibetan[int(t.Month())-1]
+}
+
+// localMonthsNameTurkish returns the Turkish name of the month.
+func localMonthsNameTurkish(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return string([]rune(monthNamesTurkish[int(t.Month())-1])[:3])
+ }
+ if abbr == 4 {
+ return monthNamesTurkish[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesTurkish[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameWelsh returns the Welsh name of the month.
+func localMonthsNameWelsh(t time.Time, abbr int) string {
+ if abbr == 3 {
+ switch int(t.Month()) {
+ case 2, 7:
+ return string([]rune(monthNamesWelsh[int(t.Month())-1])[:5])
+ case 8, 9, 11, 12:
+ return string([]rune(monthNamesWelsh[int(t.Month())-1])[:4])
+ default:
+ return string([]rune(monthNamesWelsh[int(t.Month())-1])[:3])
+ }
+ }
+ if abbr == 4 {
+ return monthNamesWelsh[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesWelsh[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameVietnamese returns the Vietnamese name of the month.
+func localMonthsNameVietnamese(t time.Time, abbr int) string {
+ if abbr == 3 {
+ return "Thg " + strconv.Itoa(int(t.Month()))
+ }
+ if abbr == 5 {
+ return "T " + strconv.Itoa(int(t.Month()))
+ }
+ return "Tháng " + strconv.Itoa(int(t.Month()))
+}
+
+// localMonthsNameWolof returns the Wolof name of the month.
+func localMonthsNameWolof(t time.Time, abbr int) string {
+ if abbr == 3 {
+ switch int(t.Month()) {
+ case 3, 6:
+ return string([]rune(monthNamesWolof[int(t.Month())-1])[:3])
+ case 5, 8:
+ return string([]rune(monthNamesWolof[int(t.Month())-1])[:2])
+ case 9:
+ return string([]rune(monthNamesWolof[int(t.Month())-1])[:4]) + "."
+ case 11:
+ return "Now."
+ default:
+ return string([]rune(monthNamesWolof[int(t.Month())-1])[:3]) + "."
+ }
+ }
+ if abbr == 4 {
+ return monthNamesWolof[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesWolof[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameXhosa returns the Xhosa name of the month.
+func localMonthsNameXhosa(t time.Time, abbr int) string {
+ if abbr == 3 {
+ switch int(t.Month()) {
+ case 4:
+ return "uEpr."
+ case 8:
+ return "u" + string([]rune(monthNamesXhosa[int(t.Month())-1])[:2]) + "."
+ default:
+ return "u" + string([]rune(monthNamesXhosa[int(t.Month())-1])[:3]) + "."
+ }
+ }
+ if abbr == 4 {
+ return "u" + monthNamesXhosa[int(t.Month())-1]
+ }
+ return "u"
+}
+
+// localMonthsNameYi returns the Yi name of the month.
+func localMonthsNameYi(t time.Time, abbr int) string {
+ if abbr == 3 || abbr == 4 {
+ return string(monthNamesYi[int(t.Month())-1]) + "\ua1aa"
+ }
+ return string([]rune(monthNamesYi[int(t.Month())-1])[:1])
+}
+
+// localMonthsNameZulu returns the Zulu name of the month.
+func localMonthsNameZulu(t time.Time, abbr int) string {
+ if abbr == 3 {
+ if int(t.Month()) == 8 {
+ return string([]rune(monthNamesZulu[int(t.Month())-1])[:4])
+ }
+ return string([]rune(monthNamesZulu[int(t.Month())-1])[:3])
+ }
+ if abbr == 4 {
+ return monthNamesZulu[int(t.Month())-1]
+ }
+ return string([]rune(monthNamesZulu[int(t.Month())-1])[:1])
+}
+
+// localMonthName return months name by supported language ID.
+func (nf *numberFormat) localMonthsName(abbr int) string {
+ if languageInfo, ok := supportedLanguageInfo[nf.localCode]; ok {
+ return languageInfo.localMonth(nf.t, abbr)
+ }
+ return localMonthsNameEnglish(nf.t, abbr)
+}
+
+// dateTimesHandler will be handling date and times types tokens for a number
+// format expression.
+func (nf *numberFormat) dateTimesHandler(i int, token nfp.Token) {
+ if idx := inStrSlice(nfp.AmPm, strings.ToUpper(token.TValue), false); idx != -1 {
+ if nf.ap == "" {
+ nextHours := nf.hoursNext(i)
+ aps := strings.Split(nf.localAmPm(token.TValue), "/")
+ nf.ap = aps[0]
+ if nextHours > 12 {
+ nf.ap = aps[1]
+ }
+ }
+ nf.result += nf.ap
+ return
+ }
+ if strings.Contains(strings.ToUpper(token.TValue), "M") {
+ l := len(token.TValue)
+ if l == 1 && !nf.hours && !nf.secondsNext(i) {
+ nf.result += strconv.Itoa(int(nf.t.Month()))
+ return
+ }
+ if l == 2 && !nf.hours && !nf.secondsNext(i) {
+ nf.result += fmt.Sprintf("%02d", int(nf.t.Month()))
+ return
+ }
+ if l == 3 {
+ nf.result += nf.localMonthsName(3)
+ return
+ }
+ if l == 4 || l > 5 {
+ nf.result += nf.localMonthsName(4)
+ return
+ }
+ if l == 5 {
+ nf.result += nf.localMonthsName(5)
+ return
+ }
+ }
+ nf.yearsHandler(i, token)
+ nf.daysHandler(i, token)
+ nf.hoursHandler(i, token)
+ nf.minutesHandler(token)
+ nf.secondsHandler(token)
+}
+
+// yearsHandler will be handling years in the date and times types tokens for a
+// number format expression.
+func (nf *numberFormat) yearsHandler(i int, token nfp.Token) {
+ years := strings.Contains(strings.ToUpper(token.TValue), "Y")
+ if years && len(token.TValue) <= 2 {
+ nf.result += strconv.Itoa(nf.t.Year())[2:]
+ return
+ }
+ if years && len(token.TValue) > 2 {
+ nf.result += strconv.Itoa(nf.t.Year())
+ return
+ }
+}
+
+// daysHandler will be handling days in the date and times types tokens for a
+// number format expression.
+func (nf *numberFormat) daysHandler(i int, token nfp.Token) {
+ if strings.Contains(strings.ToUpper(token.TValue), "D") {
+ switch len(token.TValue) {
+ case 1:
+ nf.result += strconv.Itoa(nf.t.Day())
+ return
+ case 2:
+ nf.result += fmt.Sprintf("%02d", nf.t.Day())
+ return
+ case 3:
+ nf.result += nf.t.Weekday().String()[:3]
+ return
+ default:
+ nf.result += nf.t.Weekday().String()
+ return
+ }
+ }
+}
+
+// hoursHandler will be handling hours in the date and times types tokens for a
+// number format expression.
+func (nf *numberFormat) hoursHandler(i int, token nfp.Token) {
+ nf.hours = strings.Contains(strings.ToUpper(token.TValue), "H")
+ if nf.hours {
+ h := nf.t.Hour()
+ ap, ok := nf.apNext(i)
+ if ok {
+ nf.ap = ap[0]
+ if h > 12 {
+ h -= 12
+ nf.ap = ap[1]
+ }
+ }
+ if nf.ap != "" && nf.hoursNext(i) == -1 && h > 12 {
+ h -= 12
+ }
+ switch len(token.TValue) {
+ case 1:
+ nf.result += strconv.Itoa(h)
+ return
+ default:
+ nf.result += fmt.Sprintf("%02d", h)
+ return
+ }
+ }
+}
+
+// minutesHandler will be handling minutes in the date and times types tokens
+// for a number format expression.
+func (nf *numberFormat) minutesHandler(token nfp.Token) {
+ if strings.Contains(strings.ToUpper(token.TValue), "M") {
+ nf.hours = false
+ switch len(token.TValue) {
+ case 1:
+ nf.result += strconv.Itoa(nf.t.Minute())
+ return
+ default:
+ nf.result += fmt.Sprintf("%02d", nf.t.Minute())
+ return
+ }
+ }
+}
+
+// secondsHandler will be handling seconds in the date and times types tokens
+// for a number format expression.
+func (nf *numberFormat) secondsHandler(token nfp.Token) {
+ nf.seconds = strings.Contains(strings.ToUpper(token.TValue), "S")
+ if nf.seconds {
+ switch len(token.TValue) {
+ case 1:
+ nf.result += strconv.Itoa(nf.t.Second())
+ return
+ default:
+ nf.result += fmt.Sprintf("%02d", nf.t.Second())
+ return
+ }
+ }
+}
+
+// elapsedDateTimesHandler will be handling elapsed date and times types tokens
+// for a number format expression.
+func (nf *numberFormat) elapsedDateTimesHandler(token nfp.Token) {
+ if strings.Contains(strings.ToUpper(token.TValue), "H") {
+ nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Hours())
+ return
+ }
+ if strings.Contains(strings.ToUpper(token.TValue), "M") {
+ nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Minutes())
+ return
+ }
+ if strings.Contains(strings.ToUpper(token.TValue), "S") {
+ nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Seconds())
+ return
+ }
+}
+
+// hoursNext detects if a token of type hours exists after a given tokens list.
+func (nf *numberFormat) hoursNext(i int) int {
+ tokens := nf.section[nf.sectionIdx].Items
+ for idx := i + 1; idx < len(tokens); idx++ {
+ if tokens[idx].TType == nfp.TokenTypeDateTimes {
+ if strings.Contains(strings.ToUpper(tokens[idx].TValue), "H") {
+ t := timeFromExcelTime(nf.number, false)
+ return t.Hour()
+ }
+ }
+ }
+ return -1
+}
+
+// apNext detects if a token of type AM/PM exists after a given tokens list.
+func (nf *numberFormat) apNext(i int) ([]string, bool) {
+ tokens := nf.section[nf.sectionIdx].Items
+ for idx := i + 1; idx < len(tokens); idx++ {
+ if tokens[idx].TType == nfp.TokenTypeDateTimes {
+ if strings.Contains(strings.ToUpper(tokens[idx].TValue), "H") {
+ return nil, false
+ }
+ if i := inStrSlice(nfp.AmPm, tokens[idx].TValue, false); i != -1 {
+ return strings.Split(nf.localAmPm(tokens[idx].TValue), "/"), true
+ }
+ }
+ }
+ return nil, false
+}
+
+// secondsNext detects if a token of type seconds exists after a given tokens
+// list.
+func (nf *numberFormat) secondsNext(i int) bool {
+ tokens := nf.section[nf.sectionIdx].Items
+ for idx := i + 1; idx < len(tokens); idx++ {
+ if tokens[idx].TType == nfp.TokenTypeDateTimes {
+ return strings.Contains(strings.ToUpper(tokens[idx].TValue), "S")
+ }
+ }
+ return false
+}
+
+// negativeHandler will be handling negative selection for a number format
+// expression.
+func (nf *numberFormat) negativeHandler() (result string) {
+ for _, token := range nf.section[nf.sectionIdx].Items {
+ if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral {
+ result = nf.value
+ return
+ }
+ if token.TType == nfp.TokenTypeLiteral {
+ nf.result += token.TValue
+ continue
+ }
+ if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == "0" {
+ if isNum, precision := isNumeric(nf.value); isNum {
+ if math.Abs(nf.number) < 1 {
+ nf.result += "0"
+ continue
+ }
+ if precision > 15 {
+ nf.result += strings.TrimLeft(roundPrecision(nf.value, 15), "-")
+ } else {
+ nf.result += fmt.Sprintf("%.f", math.Abs(nf.number))
+ }
+ continue
+ }
+ }
+ }
+ result = nf.result
+ return
+}
+
+// zeroHandler will be handling zero selection for a number format expression.
+func (nf *numberFormat) zeroHandler() string {
+ return nf.value
+}
+
+// textHandler will be handling text selection for a number format expression.
+func (nf *numberFormat) textHandler() (result string) {
+ for _, token := range nf.section[nf.sectionIdx].Items {
+ if token.TType == nfp.TokenTypeLiteral {
+ result += token.TValue
+ }
+ if token.TType == nfp.TokenTypeTextPlaceHolder {
+ result += nf.value
+ }
+ }
+ return result
+}
+
+// getValueSectionType returns its applicable number format expression section
+// based on the given value.
+func (nf *numberFormat) getValueSectionType(value string) (float64, string) {
+ number, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ return number, nfp.TokenSectionText
+ }
+ if number > 0 {
+ return number, nfp.TokenSectionPositive
+ }
+ if number < 0 {
+ return number, nfp.TokenSectionNegative
+ }
+ return number, nfp.TokenSectionZero
+}
diff --git a/vendor/github.com/xuri/excelize/v2/picture.go b/vendor/github.com/xuri/excelize/v2/picture.go
index 2956ff1a..515f15f9 100644
--- a/vendor/github.com/xuri/excelize/v2/picture.go
+++ b/vendor/github.com/xuri/excelize/v2/picture.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -76,7 +76,7 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// }
// }
//
-// The optional parameter "autofit" specifies if make image size auto fits the
+// The optional parameter "autofit" specifies if you make image size auto-fits the
// cell, the default value of that is 'false'.
//
// The optional parameter "hyperlink" specifies the hyperlink of the image.
@@ -86,7 +86,7 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// cells in this workbook. When the "hyperlink_type" is "Location",
// coordinates need to start with "#".
//
-// The optional parameter "positioning" defines two types of the position of a
+// The optional parameter "positioning" defines two types of the position of an
// image in an Excel spreadsheet, "oneCell" (Move but don't size with
// cells) or "absolute" (Don't move or size with cells). If you don't set this
// parameter, the default positioning is move and size with cells.
@@ -209,7 +209,7 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
if !ok {
name = strings.ToLower(sheet) + ".xml"
}
- var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
+ rels := "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
sheetRels := f.relsReader(rels)
if sheetRels == nil {
sheetRels = &xlsxRelationships{}
@@ -288,8 +288,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
}
col--
row--
- colStart, rowStart, colEnd, rowEnd, x2, y2 :=
- f.positionObjectPixels(sheet, col, row, formatSet.OffsetX, formatSet.OffsetY, width, height)
+ colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, col, row, formatSet.OffsetX, formatSet.OffsetY, width, height)
content, cNvPrID := f.drawingParser(drawingXML)
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = formatSet.Positioning
@@ -372,7 +371,7 @@ func (f *File) addMedia(file []byte, ext string) string {
// setContentTypePartImageExtensions provides a function to set the content
// type for relationship parts and the Main Document part.
func (f *File) setContentTypePartImageExtensions() {
- var imageTypes = map[string]bool{"jpeg": false, "png": false, "gif": false, "tiff": false}
+ imageTypes := map[string]bool{"jpeg": false, "png": false, "gif": false, "tiff": false}
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
@@ -465,7 +464,7 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
if !ok {
name = strings.ToLower(sheet) + ".xml"
}
- var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
+ rels := "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
sheetRels := f.relsReader(rels)
if sheetRels == nil {
sheetRels = &xlsxRelationships{}
diff --git a/vendor/github.com/xuri/excelize/v2/pivotTable.go b/vendor/github.com/xuri/excelize/v2/pivotTable.go
index 270ee992..437d22f0 100644
--- a/vendor/github.com/xuri/excelize/v2/pivotTable.go
+++ b/vendor/github.com/xuri/excelize/v2/pivotTable.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -132,7 +132,7 @@ type PivotTableField struct {
//
func (f *File) AddPivotTable(opt *PivotTableOption) error {
// parameter validation
- dataSheet, pivotTableSheetPath, err := f.parseFormatPivotTableSet(opt)
+ _, pivotTableSheetPath, err := f.parseFormatPivotTableSet(opt)
if err != nil {
return err
}
@@ -143,7 +143,7 @@ func (f *File) AddPivotTable(opt *PivotTableOption) error {
sheetRelationshipsPivotTableXML := "../pivotTables/pivotTable" + strconv.Itoa(pivotTableID) + ".xml"
pivotTableXML := strings.Replace(sheetRelationshipsPivotTableXML, "..", "xl", -1)
pivotCacheXML := "xl/pivotCache/pivotCacheDefinition" + strconv.Itoa(pivotCacheID) + ".xml"
- err = f.addPivotCache(pivotCacheID, pivotCacheXML, opt, dataSheet)
+ err = f.addPivotCache(pivotCacheXML, opt)
if err != nil {
return err
}
@@ -230,7 +230,7 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
// getPivotFieldsOrder provides a function to get order list of pivot table
// fields.
func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
- order := []string{}
+ var order []string
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
if dataRange == "" {
dataRange = opt.DataRange
@@ -251,7 +251,7 @@ func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
}
// addPivotCache provides a function to create a pivot cache by given properties.
-func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotTableOption, ws *xlsxWorksheet) error {
+func (f *File) addPivotCache(pivotCacheXML string, opt *PivotTableOption) error {
// validate data range
definedNameRef := true
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
@@ -265,8 +265,8 @@ func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotT
}
// data range has been checked
order, _ := f.getPivotFieldsOrder(opt)
- hcell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
- vcell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
+ hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
+ vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
pc := xlsxPivotCacheDefinition{
SaveData: false,
RefreshOnLoad: true,
@@ -276,7 +276,7 @@ func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotT
CacheSource: &xlsxCacheSource{
Type: "worksheet",
WorksheetSource: &xlsxWorksheetSource{
- Ref: hcell + ":" + vcell,
+ Ref: hCell + ":" + vCell,
Sheet: dataSheet,
},
},
@@ -320,8 +320,8 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
return fmt.Errorf("parameter 'PivotTableRange' parsing error: %s", err.Error())
}
- hcell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
- vcell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
+ hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
+ vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
pivotTableStyle := func() string {
if opt.PivotTableStyleName == "" {
@@ -345,7 +345,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
ShowError: &opt.ShowError,
DataCaption: "Values",
Location: &xlsxLocation{
- Ref: hcell + ":" + vcell,
+ Ref: hCell + ":" + vCell,
FirstDataCol: 1,
FirstDataRow: 1,
FirstHeaderRow: 1,
@@ -509,7 +509,7 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opt *PivotTableOp
})
}
- //in order to create pivot in case there is many Columns and Many Datas
+ // in order to create pivot in case there is many Columns and Data
if len(opt.Data) > 1 {
pt.ColFields.Field = append(pt.ColFields.Field, &xlsxField{
X: -2,
@@ -626,13 +626,13 @@ func (f *File) countPivotCache() int {
// getPivotFieldsIndex convert the column of the first row in the data region
// to a sequential index by given fields and pivot option.
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opt *PivotTableOption) ([]int, error) {
- pivotFieldsIndex := []int{}
+ var pivotFieldsIndex []int
orders, err := f.getPivotFieldsOrder(opt)
if err != nil {
return pivotFieldsIndex, err
}
for _, field := range fields {
- if pos := inStrSlice(orders, field.Data); pos != -1 {
+ if pos := inStrSlice(orders, field.Data, true); pos != -1 {
pivotFieldsIndex = append(pivotFieldsIndex, pos)
}
}
diff --git a/vendor/github.com/xuri/excelize/v2/rows.go b/vendor/github.com/xuri/excelize/v2/rows.go
index 5071bb6b..e0918bc6 100644
--- a/vendor/github.com/xuri/excelize/v2/rows.go
+++ b/vendor/github.com/xuri/excelize/v2/rows.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -16,12 +16,12 @@ import (
"encoding/xml"
"fmt"
"io"
+ "io/ioutil"
"log"
"math"
"math/big"
"os"
"strconv"
- "sync"
"github.com/mohae/deepcopy"
)
@@ -68,29 +68,44 @@ func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) {
// Rows defines an iterator to a sheet.
type Rows struct {
- err error
- curRow, totalRows, stashRow int
- rawCellValue bool
- sheet string
- f *File
- tempFile *os.File
- decoder *xml.Decoder
-}
-
-// CurrentRow returns the row number that represents the current row.
-func (rows *Rows) CurrentRow() int {
- return rows.curRow
-}
-
-// TotalRows returns the total rows count in the worksheet.
-func (rows *Rows) TotalRows() int {
- return rows.totalRows
+ err error
+ curRow, seekRow int
+ needClose, rawCellValue bool
+ sheet string
+ f *File
+ tempFile *os.File
+ sst *xlsxSST
+ decoder *xml.Decoder
+ token xml.Token
}
// Next will return true if find the next row element.
func (rows *Rows) Next() bool {
- rows.curRow++
- return rows.curRow <= rows.totalRows
+ rows.seekRow++
+ if rows.curRow >= rows.seekRow {
+ return true
+ }
+ for {
+ token, _ := rows.decoder.Token()
+ if token == nil {
+ return false
+ }
+ switch xmlElement := token.(type) {
+ case xml.StartElement:
+ if xmlElement.Name.Local == "row" {
+ rows.curRow++
+ if rowNum, _ := attrValToInt("r", xmlElement.Attr); rowNum != 0 {
+ rows.curRow = rowNum
+ }
+ rows.token = token
+ return true
+ }
+ case xml.EndElement:
+ if xmlElement.Name.Local == "sheetData" {
+ return false
+ }
+ }
+ }
}
// Error will return the error when the error occurs.
@@ -109,44 +124,40 @@ func (rows *Rows) Close() error {
// Columns return the current row's column values.
func (rows *Rows) Columns(opts ...Options) ([]string, error) {
- var rowIterator rowXMLIterator
- if rows.stashRow >= rows.curRow {
- return rowIterator.columns, rowIterator.err
+ if rows.curRow > rows.seekRow {
+ return nil, nil
}
- rows.rawCellValue = parseOptions(opts...).RawCellValue
- rowIterator.rows = rows
- rowIterator.d = rows.f.sharedStringsReader()
+ var rowIterator rowXMLIterator
+ var token xml.Token
+ rows.rawCellValue, rows.sst = parseOptions(opts...).RawCellValue, rows.f.sharedStringsReader()
for {
- token, _ := rows.decoder.Token()
- if token == nil {
+ if rows.token != nil {
+ token = rows.token
+ } else if token, _ = rows.decoder.Token(); token == nil {
break
}
switch xmlElement := token.(type) {
case xml.StartElement:
rowIterator.inElement = xmlElement.Name.Local
if rowIterator.inElement == "row" {
- rowIterator.row++
- if rowIterator.attrR, rowIterator.err = attrValToInt("r", xmlElement.Attr); rowIterator.attrR != 0 {
- rowIterator.row = rowIterator.attrR
+ rowNum := 0
+ if rowNum, rowIterator.err = attrValToInt("r", xmlElement.Attr); rowNum != 0 {
+ rows.curRow = rowNum
+ } else if rows.token == nil {
+ rows.curRow++
}
- if rowIterator.row > rowIterator.rows.curRow {
- rowIterator.rows.stashRow = rowIterator.row - 1
+ if rows.curRow > rows.seekRow {
+ rows.token = nil
return rowIterator.columns, rowIterator.err
}
}
- rowXMLHandler(&rowIterator, &xmlElement, rows.rawCellValue)
- if rowIterator.err != nil {
+ if rows.rowXMLHandler(&rowIterator, &xmlElement, rows.rawCellValue); rowIterator.err != nil {
+ rows.token = nil
return rowIterator.columns, rowIterator.err
}
+ rows.token = nil
case xml.EndElement:
- rowIterator.inElement = xmlElement.Name.Local
- if rowIterator.row == 0 && rowIterator.rows.curRow > 1 {
- rowIterator.row = rowIterator.rows.curRow
- }
- if rowIterator.inElement == "row" && rowIterator.row+1 < rowIterator.rows.curRow {
- return rowIterator.columns, rowIterator.err
- }
- if rowIterator.inElement == "sheetData" {
+ if xmlElement.Name.Local == "sheetData" {
return rowIterator.columns, rowIterator.err
}
}
@@ -168,34 +179,30 @@ type ErrSheetNotExist struct {
}
func (err ErrSheetNotExist) Error() string {
- return fmt.Sprintf("sheet %s is not exist", string(err.SheetName))
+ return fmt.Sprintf("sheet %s is not exist", err.SheetName)
}
// rowXMLIterator defined runtime use field for the worksheet row SAX parser.
type rowXMLIterator struct {
- err error
- inElement string
- attrR, cellCol, row int
- columns []string
- rows *Rows
- d *xlsxSST
+ err error
+ inElement string
+ cellCol int
+ columns []string
}
// rowXMLHandler parse the row XML element of the worksheet.
-func rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.StartElement, raw bool) {
- rowIterator.err = nil
+func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.StartElement, raw bool) {
if rowIterator.inElement == "c" {
rowIterator.cellCol++
colCell := xlsxC{}
- _ = rowIterator.rows.decoder.DecodeElement(&colCell, xmlElement)
+ _ = rows.decoder.DecodeElement(&colCell, xmlElement)
if colCell.R != "" {
if rowIterator.cellCol, _, rowIterator.err = CellNameToCoordinates(colCell.R); rowIterator.err != nil {
return
}
}
blank := rowIterator.cellCol - len(rowIterator.columns)
- val, _ := colCell.getValueFrom(rowIterator.rows.f, rowIterator.d, raw)
- if val != "" || colCell.F != nil {
+ if val, _ := colCell.getValueFrom(rows.f, rows.sst, raw); val != "" || colCell.F != nil {
rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val)
}
}
@@ -236,67 +243,36 @@ func (f *File) Rows(sheet string) (*Rows, error) {
output, _ := xml.Marshal(worksheet)
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
}
- var (
- err error
- inElement string
- row int
- rows Rows
- needClose bool
- decoder *xml.Decoder
- tempFile *os.File
- )
- if needClose, decoder, tempFile, err = f.xmlDecoder(name); needClose && err == nil {
- defer tempFile.Close()
- }
- for {
- token, _ := decoder.Token()
- if token == nil {
- break
- }
- switch xmlElement := token.(type) {
- case xml.StartElement:
- inElement = xmlElement.Name.Local
- if inElement == "row" {
- row++
- for _, attr := range xmlElement.Attr {
- if attr.Name.Local == "r" {
- row, err = strconv.Atoi(attr.Value)
- if err != nil {
- return &rows, err
- }
- }
- }
- rows.totalRows = row
- }
- case xml.EndElement:
- if xmlElement.Name.Local == "sheetData" {
- rows.f = f
- rows.sheet = name
- _, rows.decoder, rows.tempFile, err = f.xmlDecoder(name)
- return &rows, err
- }
- }
- }
- return &rows, nil
+ var err error
+ rows := Rows{f: f, sheet: name}
+ rows.needClose, rows.decoder, rows.tempFile, err = f.xmlDecoder(name)
+ return &rows, err
}
-// getFromStringItemMap build shared string item map from system temporary
+// getFromStringItem build shared string item offset list from system temporary
// file at one time, and return value by given to string index.
-func (f *File) getFromStringItemMap(index int) string {
- if f.sharedStringItemMap != nil {
- if value, ok := f.sharedStringItemMap.Load(index); ok {
- return value.(string)
+func (f *File) getFromStringItem(index int) string {
+ if f.sharedStringTemp != nil {
+ if len(f.sharedStringItem) <= index {
+ return strconv.Itoa(index)
}
- return strconv.Itoa(index)
+ offsetRange := f.sharedStringItem[index]
+ buf := make([]byte, offsetRange[1]-offsetRange[0])
+ if _, err := f.sharedStringTemp.ReadAt(buf, int64(offsetRange[0])); err != nil {
+ return strconv.Itoa(index)
+ }
+ return string(buf)
}
- f.sharedStringItemMap = &sync.Map{}
- needClose, decoder, tempFile, err := f.xmlDecoder(dafaultXMLPathSharedStrings)
+ needClose, decoder, tempFile, err := f.xmlDecoder(defaultXMLPathSharedStrings)
if needClose && err == nil {
defer tempFile.Close()
}
+ f.sharedStringItem = [][]uint{}
+ f.sharedStringTemp, _ = ioutil.TempFile(os.TempDir(), "excelize-")
+ f.tempFiles.Store(defaultTempFileSST, f.sharedStringTemp.Name())
var (
inElement string
- i int
+ i, offset uint
)
for {
token, _ := decoder.Token()
@@ -309,12 +285,16 @@ func (f *File) getFromStringItemMap(index int) string {
if inElement == "si" {
si := xlsxSI{}
_ = decoder.DecodeElement(&si, &xmlElement)
- f.sharedStringItemMap.Store(i, si.String())
+
+ startIdx := offset
+ n, _ := f.sharedStringTemp.WriteString(si.String())
+ offset += uint(n)
+ f.sharedStringItem = append(f.sharedStringItem, []uint{startIdx, offset})
i++
}
}
}
- return f.getFromStringItemMap(index)
+ return f.getFromStringItem(index)
}
// xmlDecoder creates XML decoder by given path in the zip from memory data
@@ -369,7 +349,7 @@ func (f *File) getRowHeight(sheet string, row int) int {
return int(convertRowHeightToPixels(v.Ht))
}
}
- // Optimisation for when the row heights haven't changed.
+ // Optimization for when the row heights haven't changed.
return int(defaultRowHeightPixels)
}
@@ -382,7 +362,7 @@ func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
if row < 1 {
return defaultRowHeightPixels, newInvalidRowNumberError(row)
}
- var ht = defaultRowHeight
+ ht := defaultRowHeight
ws, err := f.workSheetReader(sheet)
if err != nil {
return ht, err
@@ -398,7 +378,7 @@ func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
return v.Ht, nil
}
}
- // Optimisation for when the row heights haven't changed.
+ // Optimization for when the row heights haven't changed.
return ht, nil
}
@@ -411,7 +391,7 @@ func (f *File) sharedStringsReader() *xlsxSST {
relPath := f.getWorkbookRelsPath()
if f.SharedStrings == nil {
var sharedStrings xlsxSST
- ss := f.readXML(dafaultXMLPathSharedStrings)
+ ss := f.readXML(defaultXMLPathSharedStrings)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))).
Decode(&sharedStrings); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err)
@@ -443,18 +423,28 @@ func (f *File) sharedStringsReader() *xlsxSST {
}
// getValueFrom return a value from a column/row cell, this function is
-// inteded to be used with for range on rows an argument with the spreadsheet
+// intended to be used with for range on rows an argument with the spreadsheet
// opened file.
func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
f.Lock()
defer f.Unlock()
switch c.T {
+ case "b":
+ if !raw {
+ if c.V == "1" {
+ return "TRUE", nil
+ }
+ if c.V == "0" {
+ return "FALSE", nil
+ }
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
case "s":
if c.V != "" {
xlsxSI := 0
xlsxSI, _ = strconv.Atoi(c.V)
- if _, ok := f.tempFiles.Load(dafaultXMLPathSharedStrings); ok {
- return f.formattedValue(c.S, f.getFromStringItemMap(xlsxSI), raw), nil
+ if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
+ return f.formattedValue(c.S, f.getFromStringItem(xlsxSI), raw), nil
}
if len(d.SI) > xlsxSI {
return f.formattedValue(c.S, d.SI[xlsxSI].String(), raw), nil
@@ -469,6 +459,13 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
}
return f.formattedValue(c.S, c.V, raw), nil
default:
+ if isNum, precision := isNumeric(c.V); isNum && !raw {
+ if precision == 0 {
+ c.V = roundPrecision(c.V, 15)
+ } else {
+ c.V = roundPrecision(c.V, -1)
+ }
+ }
return f.formattedValue(c.S, c.V, raw), nil
}
}
@@ -481,7 +478,7 @@ func roundPrecision(text string, prec int) string {
if _, ok := decimal.SetString(text); ok {
flt, _ := decimal.Float64()
if prec == -1 {
- return decimal.Text('G', 15)
+ return strconv.FormatFloat(flt, 'G', 15, 64)
}
return strconv.FormatFloat(flt, 'f', -1, 64)
}
@@ -650,7 +647,8 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
if err != nil {
return err
}
- if row > len(ws.SheetData.Row) || row2 < 1 || row == row2 {
+
+ if row2 < 1 || row == row2 {
return nil
}
@@ -664,14 +662,15 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
break
}
}
- if !ok {
- return nil
- }
if err := f.adjustHelper(sheet, rows, row2, 1); err != nil {
return err
}
+ if !ok {
+ return nil
+ }
+
idx2 := -1
for i, r := range ws.SheetData.Row {
if r.R == row2 {
@@ -684,7 +683,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
}
rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...)
- f.ajustSingleRowDimensions(&rowCopy, row2)
+ f.adjustSingleRowDimensions(&rowCopy, row2)
if idx2 != -1 {
ws.SheetData.Row[idx2] = rowCopy
diff --git a/vendor/github.com/xuri/excelize/v2/shape.go b/vendor/github.com/xuri/excelize/v2/shape.go
index 61322dd9..514171a8 100644
--- a/vendor/github.com/xuri/excelize/v2/shape.go
+++ b/vendor/github.com/xuri/excelize/v2/shape.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -351,9 +351,8 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
width := int(float64(formatSet.Width) * formatSet.Format.XScale)
height := int(float64(formatSet.Height) * formatSet.Format.YScale)
- colStart, rowStart, colEnd, rowEnd, x2, y2 :=
- f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.Format.OffsetX, formatSet.Format.OffsetY,
- width, height)
+ colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.Format.OffsetX, formatSet.Format.OffsetY,
+ width, height)
content, cNvPrID := f.drawingParser(drawingXML)
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = formatSet.Format.Positioning
diff --git a/vendor/github.com/xuri/excelize/v2/sheet.go b/vendor/github.com/xuri/excelize/v2/sheet.go
index 17f66939..3986cd86 100644
--- a/vendor/github.com/xuri/excelize/v2/sheet.go
+++ b/vendor/github.com/xuri/excelize/v2/sheet.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -36,7 +36,7 @@ import (
// NewSheet provides the function to create a new sheet by given a worksheet
// name and returns the index of the sheets in the workbook
// (spreadsheet) after it appended. Note that the worksheet names are not
-// case sensitive, when creating a new spreadsheet file, the default
+// case-sensitive, when creating a new spreadsheet file, the default
// worksheet named `Sheet1` will be created.
func (f *File) NewSheet(name string) int {
// Check if the worksheet already exists
@@ -93,35 +93,6 @@ func (f *File) contentTypesWriter() {
}
}
-// getWorkbookPath provides a function to get the path of the workbook.xml in
-// the spreadsheet.
-func (f *File) getWorkbookPath() (path string) {
- if rels := f.relsReader("_rels/.rels"); rels != nil {
- rels.Lock()
- defer rels.Unlock()
- for _, rel := range rels.Relationships {
- if rel.Type == SourceRelationshipOfficeDocument {
- path = strings.TrimPrefix(rel.Target, "/")
- return
- }
- }
- }
- return
-}
-
-// getWorkbookRelsPath provides a function to get the path of the workbook.xml.rels
-// in the spreadsheet.
-func (f *File) getWorkbookRelsPath() (path string) {
- wbPath := f.getWorkbookPath()
- wbDir := filepath.Dir(wbPath)
- if wbDir == "." {
- path = "_rels/" + filepath.Base(wbPath) + ".rels"
- return
- }
- path = strings.TrimPrefix(filepath.Dir(wbPath)+"/_rels/"+filepath.Base(wbPath)+".rels", "/")
- return
-}
-
// getWorksheetPath construct a target XML as xl/worksheets/sheet%d by split
// path, compatible with different types of relative paths in
// workbook.xml.rels, for example: worksheets/sheet%d.xml
@@ -135,41 +106,12 @@ func (f *File) getWorksheetPath(relTarget string) (path string) {
return path
}
-// workbookReader provides a function to get the pointer to the workbook.xml
-// structure after deserialization.
-func (f *File) workbookReader() *xlsxWorkbook {
- var err error
- if f.WorkBook == nil {
- wbPath := f.getWorkbookPath()
- f.WorkBook = new(xlsxWorkbook)
- if _, ok := f.xmlAttr[wbPath]; !ok {
- d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath))))
- f.xmlAttr[wbPath] = append(f.xmlAttr[wbPath], getRootElement(d)...)
- f.addNameSpaces(wbPath, SourceRelationship)
- }
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath)))).
- Decode(f.WorkBook); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
- }
- }
- return f.WorkBook
-}
-
-// workBookWriter provides a function to save workbook.xml after serialize
-// structure.
-func (f *File) workBookWriter() {
- if f.WorkBook != nil {
- output, _ := xml.Marshal(f.WorkBook)
- f.saveFileList(f.getWorkbookPath(), replaceRelationshipsBytes(f.replaceNameSpaceBytes(f.getWorkbookPath(), output)))
- }
-}
-
// mergeExpandedCols merge expanded columns.
func (f *File) mergeExpandedCols(ws *xlsxWorksheet) {
sort.Slice(ws.Cols.Col, func(i, j int) bool {
return ws.Cols.Col[i].Min < ws.Cols.Col[j].Min
})
- columns := []xlsxCol{}
+ var columns []xlsxCol
for i, n := 0, len(ws.Cols.Col); i < n; {
left := i
for i++; i < n && reflect.DeepEqual(
@@ -216,6 +158,13 @@ func (f *File) workSheetWriter() {
if sheet.SheetPr != nil || sheet.Drawing != nil || sheet.Hyperlinks != nil || sheet.Picture != nil || sheet.TableParts != nil {
f.addNameSpaces(p.(string), SourceRelationship)
}
+ if sheet.DecodeAlternateContent != nil {
+ sheet.AlternateContent = &xlsxAlternateContent{
+ Content: sheet.DecodeAlternateContent.Content,
+ XMLNSMC: SourceRelationshipCompatibility.Value,
+ }
+ }
+ sheet.DecodeAlternateContent = nil
// reusing buffer
_ = encoder.Encode(sheet)
f.saveFileList(p.(string), replaceRelationshipsBytes(f.replaceNameSpaceBytes(p.(string), buffer.Bytes())))
@@ -270,21 +219,10 @@ func (f *File) setSheet(index int, name string) {
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
},
}
- path := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
- f.sheetMap[trimSheetName(name)] = path
- f.Sheet.Store(path, &ws)
- f.xmlAttr[path] = []xml.Attr{NameSpaceSpreadSheet}
-}
-
-// setWorkbook update workbook property of the spreadsheet. Maximum 31
-// characters are allowed in sheet title.
-func (f *File) setWorkbook(name string, sheetID, rid int) {
- content := f.workbookReader()
- content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
- Name: trimSheetName(name),
- SheetID: sheetID,
- ID: "rId" + strconv.Itoa(rid),
- })
+ sheetXMLPath := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
+ f.sheetMap[trimSheetName(name)] = sheetXMLPath
+ f.Sheet.Store(sheetXMLPath, &ws)
+ f.xmlAttr[sheetXMLPath] = []xml.Attr{NameSpaceSpreadSheet}
}
// relsWriter provides a function to save relationships after
@@ -304,7 +242,7 @@ func (f *File) relsWriter() {
// setAppXML update docProps/app.xml file of XML.
func (f *File) setAppXML() {
- f.saveFileList(dafaultXMLPathDocPropsApp, []byte(templateDocpropsApp))
+ f.saveFileList(defaultXMLPathDocPropsApp, []byte(templateDocpropsApp))
}
// replaceRelationshipsBytes; Some tools that read spreadsheet files have very
@@ -368,7 +306,7 @@ func (f *File) SetActiveSheet(index int) {
// GetActiveSheetIndex provides a function to get active sheet index of the
// spreadsheet. If not found the active sheet will be return integer 0.
func (f *File) GetActiveSheetIndex() (index int) {
- var sheetID = f.getActiveSheetID()
+ sheetID := f.getActiveSheetID()
wb := f.workbookReader()
if wb != nil {
for idx, sheet := range wb.Sheets.Sheet {
@@ -446,7 +384,7 @@ func (f *File) getSheetID(name string) int {
}
// GetSheetIndex provides a function to get a sheet index of the workbook by
-// the given sheet name, the sheet names are not case sensitive. If the given
+// the given sheet name, the sheet names are not case-sensitive. If the given
// sheet name is invalid or sheet doesn't exist, it will return an integer
// type value -1.
func (f *File) GetSheetIndex(name string) int {
@@ -504,12 +442,12 @@ func (f *File) getSheetMap() map[string]string {
for _, v := range f.workbookReader().Sheets.Sheet {
for _, rel := range f.relsReader(f.getWorkbookRelsPath()).Relationships {
if rel.ID == v.ID {
- path := f.getWorksheetPath(rel.Target)
- if _, ok := f.Pkg.Load(path); ok {
- maps[v.Name] = path
+ sheetXMLPath := f.getWorksheetPath(rel.Target)
+ if _, ok := f.Pkg.Load(sheetXMLPath); ok {
+ maps[v.Name] = sheetXMLPath
}
- if _, ok := f.tempFiles.Load(path); ok {
- maps[v.Name] = path
+ if _, ok := f.tempFiles.Load(sheetXMLPath); ok {
+ maps[v.Name] = sheetXMLPath
}
}
}
@@ -540,8 +478,8 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
}
// DeleteSheet provides a function to delete worksheet in a workbook by given
-// worksheet name, the sheet names are not case sensitive.the sheet names are
-// not case sensitive. Use this method with caution, which will affect
+// worksheet name, the sheet names are not case-sensitive. The sheet names are
+// not case-sensitive. Use this method with caution, which will affect
// changes in references such as formulas, charts, and so on. If there is any
// referenced value of the deleted worksheet, it will cause a file error when
// you open it. This function will be invalid when only the one worksheet is
@@ -663,14 +601,14 @@ func (f *File) copySheet(from, to int) error {
}
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
- path := "xl/worksheets/sheet" + toSheetID + ".xml"
+ sheetXMLPath := "xl/worksheets/sheet" + toSheetID + ".xml"
if len(worksheet.SheetViews.SheetView) > 0 {
worksheet.SheetViews.SheetView[0].TabSelected = false
}
worksheet.Drawing = nil
worksheet.TableParts = nil
worksheet.PageSetUp = nil
- f.Sheet.Store(path, worksheet)
+ f.Sheet.Store(sheetXMLPath, worksheet)
toRels := "xl/worksheets/_rels/sheet" + toSheetID + ".xml.rels"
fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(f.getSheetID(fromSheet)) + ".xml.rels"
if rels, ok := f.Pkg.Load(fromRels); ok && rels != nil {
@@ -678,7 +616,7 @@ func (f *File) copySheet(from, to int) error {
}
fromSheetXMLPath := f.sheetMap[trimSheetName(fromSheet)]
fromSheetAttr := f.xmlAttr[fromSheetXMLPath]
- f.xmlAttr[path] = fromSheetAttr
+ f.xmlAttr[sheetXMLPath] = fromSheetAttr
return err
}
@@ -841,7 +779,7 @@ func (f *File) SetPanes(sheet, panes string) error {
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Pane = nil
}
}
- s := []*xlsxSelection{}
+ var s []*xlsxSelection
for _, p := range fs.Panes {
s = append(s, &xlsxSelection{
ActiveCell: p.ActiveCell,
@@ -1129,10 +1067,14 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error
}
// ProtectSheet provides a function to prevent other users from accidentally
-// or deliberately changing, moving, or deleting data in a worksheet. For
-// example, protect Sheet1 with protection settings:
+// or deliberately changing, moving, or deleting data in a worksheet. The
+// optional field AlgorithmName specified hash algorithm, support XOR, MD4,
+// MD5, SHA1, SHA256, SHA384, and SHA512 currently, if no hash algorithm
+// specified, will be using the XOR algorithm as default. For example,
+// protect Sheet1 with protection settings:
//
// err := f.ProtectSheet("Sheet1", &excelize.FormatSheetProtection{
+// AlgorithmName: "SHA-512",
// Password: "password",
// EditScenarios: false,
// })
@@ -1168,22 +1110,55 @@ func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error
Sort: settings.Sort,
}
if settings.Password != "" {
- ws.SheetProtection.Password = genSheetPasswd(settings.Password)
+ if settings.AlgorithmName == "" {
+ ws.SheetProtection.Password = genSheetPasswd(settings.Password)
+ return err
+ }
+ hashValue, saltValue, err := genISOPasswdHash(settings.Password, settings.AlgorithmName, "", int(sheetProtectionSpinCount))
+ if err != nil {
+ return err
+ }
+ ws.SheetProtection.Password = ""
+ ws.SheetProtection.AlgorithmName = settings.AlgorithmName
+ ws.SheetProtection.SaltValue = saltValue
+ ws.SheetProtection.HashValue = hashValue
+ ws.SheetProtection.SpinCount = int(sheetProtectionSpinCount)
}
return err
}
-// UnprotectSheet provides a function to unprotect an Excel worksheet.
-func (f *File) UnprotectSheet(sheet string) error {
+// UnprotectSheet provides a function to remove protection for a sheet,
+// specified the second optional password parameter to remove sheet
+// protection with password verification.
+func (f *File) UnprotectSheet(sheet string, password ...string) error {
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
+ // password verification
+ if len(password) > 0 {
+ if ws.SheetProtection == nil {
+ return ErrUnprotectSheet
+ }
+ if ws.SheetProtection.AlgorithmName == "" && ws.SheetProtection.Password != genSheetPasswd(password[0]) {
+ return ErrUnprotectSheetPassword
+ }
+ if ws.SheetProtection.AlgorithmName != "" {
+ // check with given salt value
+ hashValue, _, err := genISOPasswdHash(password[0], ws.SheetProtection.AlgorithmName, ws.SheetProtection.SaltValue, ws.SheetProtection.SpinCount)
+ if err != nil {
+ return err
+ }
+ if ws.SheetProtection.HashValue != hashValue {
+ return ErrUnprotectSheetPassword
+ }
+ }
+ }
ws.SheetProtection = nil
return err
}
-// trimSheetName provides a function to trim invaild characters by given worksheet
+// trimSheetName provides a function to trim invalid characters by given worksheet
// name.
func trimSheetName(name string) string {
if strings.ContainsAny(name, ":\\/?*[]") || utf8.RuneCountInString(name) > 31 {
@@ -1232,7 +1207,7 @@ type (
// FitToWidth specified the number of horizontal pages to fit on.
FitToWidth int
// PageLayoutScale defines the print scaling. This attribute is restricted
- // to values ranging from 10 (10%) to 400 (400%). This setting is
+ // to value ranging from 10 (10%) to 400 (400%). This setting is
// overridden when fitToWidth and/or fitToHeight are in use.
PageLayoutScale uint
)
@@ -1298,49 +1273,49 @@ func (o *PageLayoutOrientation) getPageLayout(ps *xlsxPageSetUp) {
// setPageLayout provides a method to set the paper size for the worksheet.
func (p PageLayoutPaperSize) setPageLayout(ps *xlsxPageSetUp) {
- ps.PaperSize = int(p)
+ ps.PaperSize = intPtr(int(p))
}
// getPageLayout provides a method to get the paper size for the worksheet.
func (p *PageLayoutPaperSize) getPageLayout(ps *xlsxPageSetUp) {
// Excel default: 1
- if ps == nil || ps.PaperSize == 0 {
+ if ps == nil || ps.PaperSize == nil {
*p = 1
return
}
- *p = PageLayoutPaperSize(ps.PaperSize)
+ *p = PageLayoutPaperSize(*ps.PaperSize)
}
// setPageLayout provides a method to set the fit to height for the worksheet.
func (p FitToHeight) setPageLayout(ps *xlsxPageSetUp) {
if int(p) > 0 {
- ps.FitToHeight = int(p)
+ ps.FitToHeight = intPtr(int(p))
}
}
// getPageLayout provides a method to get the fit to height for the worksheet.
func (p *FitToHeight) getPageLayout(ps *xlsxPageSetUp) {
- if ps == nil || ps.FitToHeight == 0 {
+ if ps == nil || ps.FitToHeight == nil {
*p = 1
return
}
- *p = FitToHeight(ps.FitToHeight)
+ *p = FitToHeight(*ps.FitToHeight)
}
// setPageLayout provides a method to set the fit to width for the worksheet.
func (p FitToWidth) setPageLayout(ps *xlsxPageSetUp) {
if int(p) > 0 {
- ps.FitToWidth = int(p)
+ ps.FitToWidth = intPtr(int(p))
}
}
// getPageLayout provides a method to get the fit to width for the worksheet.
func (p *FitToWidth) getPageLayout(ps *xlsxPageSetUp) {
- if ps == nil || ps.FitToWidth == 0 {
+ if ps == nil || ps.FitToWidth == nil {
*p = 1
return
}
- *p = FitToWidth(ps.FitToWidth)
+ *p = FitToWidth(*ps.FitToWidth)
}
// setPageLayout provides a method to set the scale for the worksheet.
@@ -1559,7 +1534,7 @@ func (f *File) SetDefinedName(definedName *DefinedName) error {
scope = f.GetSheetName(*dn.LocalSheetID)
}
if scope == definedName.Scope && dn.Name == definedName.Name {
- return ErrDefinedNameduplicate
+ return ErrDefinedNameDuplicate
}
}
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName, d)
@@ -1641,7 +1616,7 @@ func (f *File) GroupSheets(sheets []string) error {
return ErrGroupSheets
}
// check worksheet exists
- wss := []*xlsxWorksheet{}
+ var wss []*xlsxWorksheet
for _, sheet := range sheets {
worksheet, err := f.workSheetReader(sheet)
if err != nil {
@@ -1686,7 +1661,7 @@ func (f *File) UngroupSheets() error {
func (f *File) InsertPageBreak(sheet, cell string) (err error) {
var ws *xlsxWorksheet
var row, col int
- var rowBrk, colBrk = -1, -1
+ rowBrk, colBrk := -1, -1
if ws, err = f.workSheetReader(sheet); err != nil {
return
}
diff --git a/vendor/github.com/xuri/excelize/v2/sheetpr.go b/vendor/github.com/xuri/excelize/v2/sheetpr.go
index 6f46040c..e8e6e9d4 100644
--- a/vendor/github.com/xuri/excelize/v2/sheetpr.go
+++ b/vendor/github.com/xuri/excelize/v2/sheetpr.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -25,7 +25,7 @@ type SheetPrOptionPtr interface {
}
type (
- // CodeName is a SheetPrOption
+ // CodeName is an option used for SheetPrOption and WorkbookPrOption
CodeName string
// EnableFormatConditionsCalculation is a SheetPrOption
EnableFormatConditionsCalculation bool
diff --git a/vendor/github.com/xuri/excelize/v2/sheetview.go b/vendor/github.com/xuri/excelize/v2/sheetview.go
index 91df04c1..bf8f0237 100644
--- a/vendor/github.com/xuri/excelize/v2/sheetview.go
+++ b/vendor/github.com/xuri/excelize/v2/sheetview.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -27,59 +27,49 @@ type SheetViewOptionPtr interface {
}
type (
- // DefaultGridColor is a SheetViewOption. It specifies a flag indicating that
- // the consuming application should use the default grid lines color (system
- // dependent). Overrides any color specified in colorId.
+ // DefaultGridColor is a SheetViewOption. It specifies a flag indicating
+ // that the consuming application should use the default grid lines color
+ // (system dependent). Overrides any color specified in colorId.
DefaultGridColor bool
- // RightToLeft is a SheetViewOption. It specifies a flag indicating whether
- // the sheet is in 'right to left' display mode. When in this mode, Column A
- // is on the far right, Column B ;is one column left of Column A, and so on.
- // Also, information in cells is displayed in the Right to Left format.
- RightToLeft bool
- // ShowFormulas is a SheetViewOption. It specifies a flag indicating whether
- // this sheet should display formulas.
+ // ShowFormulas is a SheetViewOption. It specifies a flag indicating
+ // whether this sheet should display formulas.
ShowFormulas bool
- // ShowGridLines is a SheetViewOption. It specifies a flag indicating whether
- // this sheet should display gridlines.
+ // ShowGridLines is a SheetViewOption. It specifies a flag indicating
+ // whether this sheet should display gridlines.
ShowGridLines bool
// ShowRowColHeaders is a SheetViewOption. It specifies a flag indicating
// whether the sheet should display row and column headings.
ShowRowColHeaders bool
- // ZoomScale is a SheetViewOption. It specifies a window zoom magnification
- // for current view representing percent values. This attribute is restricted
- // to values ranging from 10 to 400. Horizontal & Vertical scale together.
- ZoomScale float64
- // TopLeftCell is a SheetViewOption. It specifies a location of the top left
- // visible cell Location of the top left visible cell in the bottom right
- // pane (when in Left-to-Right mode).
- TopLeftCell string
- // ShowZeros is a SheetViewOption. It specifies a flag indicating
- // whether to "show a zero in cells that have zero value".
- // When using a formula to reference another cell which is empty, the referenced value becomes 0
+ // ShowZeros is a SheetViewOption. It specifies a flag indicating whether
+ // to "show a zero in cells that have zero value". When using a formula to
+ // reference another cell which is empty, the referenced value becomes 0
// when the flag is true. (Default setting is true.)
ShowZeros bool
-
- /* TODO
- // ShowWhiteSpace is a SheetViewOption. It specifies a flag indicating
- // whether page layout view shall display margins. False means do not display
- // left, right, top (header), and bottom (footer) margins (even when there is
- // data in the header or footer).
- ShowWhiteSpace bool
- // WindowProtection is a SheetViewOption.
- WindowProtection bool
- */
+ // RightToLeft is a SheetViewOption. It specifies a flag indicating whether
+ // the sheet is in 'right to left' display mode. When in this mode, Column
+ // A is on the far right, Column B ;is one column left of Column A, and so
+ // on. Also, information in cells is displayed in the Right to Left format.
+ RightToLeft bool
+ // ShowRuler is a SheetViewOption. It specifies a flag indicating this
+ // sheet should display ruler.
+ ShowRuler bool
+ // View is a SheetViewOption. It specifies a flag indicating how sheet is
+ // displayed, by default it uses empty string available options: normal,
+ // pageLayout, pageBreakPreview
+ View string
+ // TopLeftCell is a SheetViewOption. It specifies a location of the top
+ // left visible cell Location of the top left visible cell in the bottom
+ // right pane (when in Left-to-Right mode).
+ TopLeftCell string
+ // ZoomScale is a SheetViewOption. It specifies a window zoom magnification
+ // for current view representing percent values. This attribute is
+ // restricted to values ranging from 10 to 400. Horizontal & Vertical
+ // scale together.
+ ZoomScale float64
)
// Defaults for each option are described in XML schema for CT_SheetView
-func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
- view.TopLeftCell = string(o)
-}
-
-func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
- *o = TopLeftCell(string(view.TopLeftCell))
-}
-
func (o DefaultGridColor) setSheetViewOption(view *xlsxSheetView) {
view.DefaultGridColor = boolPtr(bool(o))
}
@@ -88,14 +78,6 @@ func (o *DefaultGridColor) getSheetViewOption(view *xlsxSheetView) {
*o = DefaultGridColor(defaultTrue(view.DefaultGridColor)) // Excel default: true
}
-func (o RightToLeft) setSheetViewOption(view *xlsxSheetView) {
- view.RightToLeft = bool(o) // Excel default: false
-}
-
-func (o *RightToLeft) getSheetViewOption(view *xlsxSheetView) {
- *o = RightToLeft(view.RightToLeft)
-}
-
func (o ShowFormulas) setSheetViewOption(view *xlsxSheetView) {
view.ShowFormulas = bool(o) // Excel default: false
}
@@ -112,6 +94,14 @@ func (o *ShowGridLines) getSheetViewOption(view *xlsxSheetView) {
*o = ShowGridLines(defaultTrue(view.ShowGridLines)) // Excel default: true
}
+func (o ShowRowColHeaders) setSheetViewOption(view *xlsxSheetView) {
+ view.ShowRowColHeaders = boolPtr(bool(o))
+}
+
+func (o *ShowRowColHeaders) getSheetViewOption(view *xlsxSheetView) {
+ *o = ShowRowColHeaders(defaultTrue(view.ShowRowColHeaders)) // Excel default: true
+}
+
func (o ShowZeros) setSheetViewOption(view *xlsxSheetView) {
view.ShowZeros = boolPtr(bool(o))
}
@@ -120,12 +110,40 @@ func (o *ShowZeros) getSheetViewOption(view *xlsxSheetView) {
*o = ShowZeros(defaultTrue(view.ShowZeros)) // Excel default: true
}
-func (o ShowRowColHeaders) setSheetViewOption(view *xlsxSheetView) {
- view.ShowRowColHeaders = boolPtr(bool(o))
+func (o RightToLeft) setSheetViewOption(view *xlsxSheetView) {
+ view.RightToLeft = bool(o) // Excel default: false
}
-func (o *ShowRowColHeaders) getSheetViewOption(view *xlsxSheetView) {
- *o = ShowRowColHeaders(defaultTrue(view.ShowRowColHeaders)) // Excel default: true
+func (o *RightToLeft) getSheetViewOption(view *xlsxSheetView) {
+ *o = RightToLeft(view.RightToLeft)
+}
+
+func (o ShowRuler) setSheetViewOption(view *xlsxSheetView) {
+ view.ShowRuler = boolPtr(bool(o))
+}
+
+func (o *ShowRuler) getSheetViewOption(view *xlsxSheetView) {
+ *o = ShowRuler(defaultTrue(view.ShowRuler)) // Excel default: true
+}
+
+func (o View) setSheetViewOption(view *xlsxSheetView) {
+ view.View = string(o)
+}
+
+func (o *View) getSheetViewOption(view *xlsxSheetView) {
+ if view.View != "" {
+ *o = View(view.View)
+ return
+ }
+ *o = "normal"
+}
+
+func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
+ view.TopLeftCell = string(o)
+}
+
+func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
+ *o = TopLeftCell(view.TopLeftCell)
}
func (o ZoomScale) setSheetViewOption(view *xlsxSheetView) {
@@ -163,13 +181,15 @@ func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error)
// Available options:
//
// DefaultGridColor(bool)
-// RightToLeft(bool)
// ShowFormulas(bool)
// ShowGridLines(bool)
// ShowRowColHeaders(bool)
-// ZoomScale(float64)
-// TopLeftCell(string)
// ShowZeros(bool)
+// RightToLeft(bool)
+// ShowRuler(bool)
+// View(string)
+// TopLeftCell(string)
+// ZoomScale(float64)
//
// Example:
//
@@ -193,13 +213,15 @@ func (f *File) SetSheetViewOptions(name string, viewIndex int, opts ...SheetView
// Available options:
//
// DefaultGridColor(bool)
-// RightToLeft(bool)
// ShowFormulas(bool)
// ShowGridLines(bool)
// ShowRowColHeaders(bool)
-// ZoomScale(float64)
-// TopLeftCell(string)
// ShowZeros(bool)
+// RightToLeft(bool)
+// ShowRuler(bool)
+// View(string)
+// TopLeftCell(string)
+// ZoomScale(float64)
//
// Example:
//
diff --git a/vendor/github.com/xuri/excelize/v2/sparkline.go b/vendor/github.com/xuri/excelize/v2/sparkline.go
index 0d5ef6e1..880724a4 100644
--- a/vendor/github.com/xuri/excelize/v2/sparkline.go
+++ b/vendor/github.com/xuri/excelize/v2/sparkline.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -362,7 +362,7 @@ func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
// given formatting options. Sparklines are small charts that fit in a single
// cell and are used to show trends in data. Sparklines are a feature of Excel
// 2010 and later only. You can write them to an XLSX file that can be read by
-// Excel 2007 but they won't be displayed. For example, add a grouped
+// Excel 2007, but they won't be displayed. For example, add a grouped
// sparkline. Changes are applied to all three:
//
// err := f.AddSparkline("Sheet1", &excelize.SparklineOption{
diff --git a/vendor/github.com/xuri/excelize/v2/stream.go b/vendor/github.com/xuri/excelize/v2/stream.go
index 8df308d4..c2eda68a 100644
--- a/vendor/github.com/xuri/excelize/v2/stream.go
+++ b/vendor/github.com/xuri/excelize/v2/stream.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -52,7 +52,7 @@ type StreamWriter struct {
// if err != nil {
// fmt.Println(err)
// }
-// styleID, err := file.NewStyle(`{"font":{"color":"#777777"}}`)
+// styleID, err := file.NewStyle(&excelize.Style{Font: &excelize.Font{Color: "#777777"}})
// if err != nil {
// fmt.Println(err)
// }
@@ -136,17 +136,17 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
// Note that the table must be at least two lines including the header. The
// header cells must contain strings and must be unique.
//
-// Currently only one table is allowed for a StreamWriter. AddTable must be
+// Currently, only one table is allowed for a StreamWriter. AddTable must be
// called after the rows are written but before Flush.
//
// See File.AddTable for details on the table format.
-func (sw *StreamWriter) AddTable(hcell, vcell, format string) error {
+func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
formatSet, err := parseFormatTableSet(format)
if err != nil {
return err
}
- coordinates, err := areaRangeToCoordinates(hcell, vcell)
+ coordinates, err := areaRangeToCoordinates(hCell, vCell)
if err != nil {
return err
}
@@ -223,8 +223,8 @@ func (sw *StreamWriter) AddTable(hcell, vcell, format string) error {
}
// Extract values from a row in the StreamWriter.
-func (sw *StreamWriter) getRowValues(hrow, hcol, vcol int) (res []string, err error) {
- res = make([]string, vcol-hcol+1)
+func (sw *StreamWriter) getRowValues(hRow, hCol, vCol int) (res []string, err error) {
+ res = make([]string, vCol-hCol+1)
r, err := sw.rawData.Reader()
if err != nil {
@@ -240,7 +240,7 @@ func (sw *StreamWriter) getRowValues(hrow, hcol, vcol int) (res []string, err er
if err != nil {
return nil, err
}
- startElement, ok := getRowElement(token, hrow)
+ startElement, ok := getRowElement(token, hRow)
if !ok {
continue
}
@@ -254,17 +254,17 @@ func (sw *StreamWriter) getRowValues(hrow, hcol, vcol int) (res []string, err er
if err != nil {
return nil, err
}
- if col < hcol || col > vcol {
+ if col < hCol || col > vCol {
continue
}
- res[col-hcol] = c.V
+ res[col-hCol] = c.V
}
return res, nil
}
}
// Check if the token is an XLSX row with the matching row number.
-func getRowElement(token xml.Token, hrow int) (startElement xml.StartElement, ok bool) {
+func getRowElement(token xml.Token, hRow int) (startElement xml.StartElement, ok bool) {
startElement, ok = token.(xml.StartElement)
if !ok {
return
@@ -279,7 +279,7 @@ func getRowElement(token xml.Token, hrow int) (startElement xml.StartElement, ok
continue
}
row, _ := strconv.Atoi(attr.Value)
- if row == hrow {
+ if row == hRow {
ok = true
return
}
@@ -406,13 +406,13 @@ func (sw *StreamWriter) SetColWidth(min, max int, width float64) error {
// MergeCell provides a function to merge cells by a given coordinate area for
// the StreamWriter. Don't create a merged cell that overlaps with another
// existing merged cell.
-func (sw *StreamWriter) MergeCell(hcell, vcell string) error {
- _, err := areaRangeToCoordinates(hcell, vcell)
+func (sw *StreamWriter) MergeCell(hCell, vCell string) error {
+ _, err := areaRangeToCoordinates(hCell, vCell)
if err != nil {
return err
}
sw.mergeCellsCount++
- sw.mergeCells += fmt.Sprintf(``, hcell, vcell)
+ sw.mergeCells += fmt.Sprintf(``, hCell, vCell)
return nil
}
@@ -563,7 +563,7 @@ func (bw *bufferedWriter) Write(p []byte) (n int, err error) {
return bw.buf.Write(p)
}
-// WriteString wites to the in-memory buffer. The err is always nil.
+// WriteString wite to the in-memory buffer. The err is always nil.
func (bw *bufferedWriter) WriteString(p string) (n int, err error) {
return bw.buf.WriteString(p)
}
diff --git a/vendor/github.com/xuri/excelize/v2/styles.go b/vendor/github.com/xuri/excelize/v2/styles.go
index da532fd1..c04ca3b3 100644
--- a/vendor/github.com/xuri/excelize/v2/styles.go
+++ b/vendor/github.com/xuri/excelize/v2/styles.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -20,7 +20,6 @@ import (
"log"
"math"
"reflect"
- "regexp"
"strconv"
"strings"
)
@@ -53,7 +52,7 @@ var builtInNumFmt = map[int]string{
39: "#,##0.00;(#,##0.00)",
40: "#,##0.00;[red](#,##0.00)",
41: `_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)`,
- 42: `_("$"* #,##0_);_("$* \(#,##0\);_("$"* "-"_);_(@_)`,
+ 42: `_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)`,
43: `_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)`,
44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`,
45: "mm:ss",
@@ -756,7 +755,7 @@ var currencyNumFmt = map[int]string{
// builtInNumFmtFunc defined the format conversion functions map. Partial format
// code doesn't support currently and will return original string.
var builtInNumFmtFunc = map[int]func(v string, format string) string{
- 0: formatToString,
+ 0: format,
1: formatToInt,
2: formatToFloat,
3: formatToInt,
@@ -764,30 +763,30 @@ var builtInNumFmtFunc = map[int]func(v string, format string) string{
9: formatToC,
10: formatToD,
11: formatToE,
- 12: formatToString, // Doesn't support currently
- 13: formatToString, // Doesn't support currently
- 14: parseTime,
- 15: parseTime,
- 16: parseTime,
- 17: parseTime,
- 18: parseTime,
- 19: parseTime,
- 20: parseTime,
- 21: parseTime,
- 22: parseTime,
+ 12: format, // Doesn't support currently
+ 13: format, // Doesn't support currently
+ 14: format,
+ 15: format,
+ 16: format,
+ 17: format,
+ 18: format,
+ 19: format,
+ 20: format,
+ 21: format,
+ 22: format,
37: formatToA,
38: formatToA,
39: formatToB,
40: formatToB,
- 41: formatToString, // Doesn't support currently
- 42: formatToString, // Doesn't support currently
- 43: formatToString, // Doesn't support currently
- 44: formatToString, // Doesn't support currently
- 45: parseTime,
- 46: parseTime,
- 47: parseTime,
+ 41: format, // Doesn't support currently
+ 42: format, // Doesn't support currently
+ 43: format, // Doesn't support currently
+ 44: format, // Doesn't support currently
+ 45: format,
+ 46: format,
+ 47: format,
48: formatToE,
- 49: formatToString,
+ 49: format,
}
// validType defined the list of valid validation types.
@@ -845,12 +844,6 @@ var criteriaType = map[string]string{
"continue month": "continueMonth",
}
-// formatToString provides a function to return original string by given
-// built-in number formats code and cell string.
-func formatToString(v string, format string) string {
- return v
-}
-
// formatToInt provides a function to convert original string to integer
// format as string type by given built-in number formats code and cell
// string.
@@ -933,157 +926,16 @@ func formatToE(v string, format string) string {
return fmt.Sprintf("%.2E", f)
}
-// parseTime provides a function to returns a string parsed using time.Time.
-// Replace Excel placeholders with Go time placeholders. For example, replace
-// yyyy with 2006. These are in a specific order, due to the fact that m is
-// used in month, minute, and am/pm. It would be easier to fix that with
-// regular expressions, but if it's possible to keep this simple it would be
-// easier to maintain. Full-length month and days (e.g. March, Tuesday) have
-// letters in them that would be replaced by other characters below (such as
-// the 'h' in March, or the 'd' in Tuesday) below. First we convert them to
-// arbitrary characters unused in Excel Date formats, and then at the end,
-// turn them to what they should actually be. Based off:
-// http://www.ozgrid.com/Excel/CustomFormats.htm
-func parseTime(v string, format string) string {
- var (
- f float64
- err error
- goFmt string
- )
- f, err = strconv.ParseFloat(v, 64)
- if err != nil {
- return v
- }
- val := timeFromExcelTime(f, false)
-
- if format == "" {
- return v
- }
-
- goFmt = format
-
- if strings.Contains(goFmt, "[") {
- var re = regexp.MustCompile(`\[.+\]`)
- goFmt = re.ReplaceAllLiteralString(goFmt, "")
- }
-
- // use only first variant
- if strings.Contains(goFmt, ";") {
- goFmt = goFmt[:strings.IndexByte(goFmt, ';')]
- }
-
- replacements := []struct{ xltime, gotime string }{
- {"YYYY", "2006"},
- {"YY", "06"},
- {"MM", "01"},
- {"M", "1"},
- {"DD", "02"},
- {"D", "2"},
- {"yyyy", "2006"},
- {"yy", "06"},
- {"MMMM", "%%%%"},
- {"mmmm", "%%%%"},
- {"DDDD", "&&&&"},
- {"dddd", "&&&&"},
- {"DD", "02"},
- {"dd", "02"},
- {"D", "2"},
- {"d", "2"},
- {"MMM", "Jan"},
- {"mmm", "Jan"},
- {"MMSS", "0405"},
- {"mmss", "0405"},
- {"SS", "05"},
- {"ss", "05"},
- {"s", "5"},
- {"MM:", "04:"},
- {"mm:", "04:"},
- {":MM", ":04"},
- {":mm", ":04"},
- {"m:", "4:"},
- {":m", ":4"},
- {"MM", "01"},
- {"mm", "01"},
- {"AM/PM", "PM"},
- {"am/pm", "PM"},
- {"M/", "1/"},
- {"m/", "1/"},
- {"%%%%", "January"},
- {"&&&&", "Monday"},
- }
-
- replacementsGlobal := []struct{ xltime, gotime string }{
- {"\\-", "-"},
- {"\\ ", " "},
- {"\\.", "."},
- {"\\", ""},
- {"\"", ""},
- }
- // It is the presence of the "am/pm" indicator that determines if this is
- // a 12 hour or 24 hours time format, not the number of 'h' characters.
- var padding bool
- if val.Hour() == 0 && !strings.Contains(format, "hh") && !strings.Contains(format, "HH") {
- padding = true
- }
- if is12HourTime(format) {
- goFmt = strings.Replace(goFmt, "hh", "3", 1)
- goFmt = strings.Replace(goFmt, "h", "3", 1)
- goFmt = strings.Replace(goFmt, "HH", "3", 1)
- goFmt = strings.Replace(goFmt, "H", "3", 1)
- } else {
- goFmt = strings.Replace(goFmt, "hh", "15", 1)
- goFmt = strings.Replace(goFmt, "HH", "15", 1)
- if 0 < val.Hour() && val.Hour() < 12 {
- goFmt = strings.Replace(goFmt, "h", "3", 1)
- goFmt = strings.Replace(goFmt, "H", "3", 1)
- } else {
- goFmt = strings.Replace(goFmt, "h", "15", 1)
- goFmt = strings.Replace(goFmt, "H", "15", 1)
- }
- }
-
- for _, repl := range replacements {
- goFmt = strings.Replace(goFmt, repl.xltime, repl.gotime, 1)
- }
- for _, repl := range replacementsGlobal {
- goFmt = strings.Replace(goFmt, repl.xltime, repl.gotime, -1)
- }
- // If the hour is optional, strip it out, along with the possible dangling
- // colon that would remain.
- if val.Hour() < 1 {
- goFmt = strings.Replace(goFmt, "]:", "]", 1)
- goFmt = strings.Replace(goFmt, "[03]", "", 1)
- goFmt = strings.Replace(goFmt, "[3]", "", 1)
- goFmt = strings.Replace(goFmt, "[15]", "", 1)
- } else {
- goFmt = strings.Replace(goFmt, "[3]", "3", 1)
- goFmt = strings.Replace(goFmt, "[15]", "15", 1)
- }
- s := val.Format(goFmt)
- if padding {
- s = strings.Replace(s, "00:", "0:", 1)
- }
- return s
-}
-
-// is12HourTime checks whether an Excel time format string is a 12 hours form.
-func is12HourTime(format string) bool {
- return strings.Contains(format, "am/pm") || strings.Contains(format, "AM/PM") || strings.Contains(format, "a/p") || strings.Contains(format, "A/P")
-}
-
// stylesReader provides a function to get the pointer to the structure after
// deserialization of xl/styles.xml.
func (f *File) stylesReader() *xlsxStyleSheet {
- var err error
-
if f.Styles == nil {
f.Styles = new(xlsxStyleSheet)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
+ if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
Decode(f.Styles); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err)
}
}
-
return f.Styles
}
@@ -1101,7 +953,7 @@ func (f *File) styleSheetWriter() {
func (f *File) sharedStringsWriter() {
if f.SharedStrings != nil {
output, _ := xml.Marshal(f.SharedStrings)
- f.saveFileList(dafaultXMLPathSharedStrings, f.replaceNameSpaceBytes(dafaultXMLPathSharedStrings, output))
+ f.saveFileList(defaultXMLPathSharedStrings, f.replaceNameSpaceBytes(defaultXMLPathSharedStrings, output))
}
}
@@ -2168,7 +2020,7 @@ func (f *File) SetDefaultFont(fontName string) {
s.CellStyles.CellStyle[0].CustomBuiltIn = &custom
}
-// readDefaultFont provides an unmarshalled font value.
+// readDefaultFont provides an un-marshalled font value.
func (f *File) readDefaultFont() *xlsxFont {
s := f.stylesReader()
return s.Fonts.Font[0]
@@ -2388,7 +2240,7 @@ func getFillID(styleSheet *xlsxStyleSheet, style *Style) (fillID int) {
// newFills provides a function to add fill elements in the styles.xml by
// given cell format settings.
func newFills(style *Style, fg bool) *xlsxFill {
- var patterns = []string{
+ patterns := []string{
"none",
"solid",
"mediumGray",
@@ -2410,7 +2262,7 @@ func newFills(style *Style, fg bool) *xlsxFill {
"gray0625",
}
- var variants = []float64{
+ variants := []float64{
90,
0,
45,
@@ -2522,7 +2374,7 @@ func getBorderID(styleSheet *xlsxStyleSheet, style *Style) (borderID int) {
// newBorders provides a function to add border elements in the styles.xml by
// given borders format settings.
func newBorders(style *Style) *xlsxBorder {
- var styles = []string{
+ styles := []string{
"none",
"thin",
"medium",
@@ -2613,11 +2465,11 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
if err != nil {
return 0, err
}
- cellData, col, _, err := f.prepareCell(ws, sheet, axis)
+ cellData, col, row, err := f.prepareCell(ws, axis)
if err != nil {
return 0, err
}
- return f.prepareCellStyle(ws, col, cellData.S), err
+ return f.prepareCellStyle(ws, col, row, cellData.S), err
}
// SetCellStyle provides a function to add style attribute for cells by given
@@ -2628,7 +2480,16 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// For example create a borders of cell H9 on Sheet1:
//
-// style, err := f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":3},{"type":"top","color":"00FF00","style":4},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":7},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Border: []excelize.Border{
+// {Type: "left", Color: "0000FF", Style: 3},
+// {Type: "top", Color: "00FF00", Style: 4},
+// {Type: "bottom", Color: "FFFF00", Style: 5},
+// {Type: "right", Color: "FF0000", Style: 6},
+// {Type: "diagonalDown", Color: "A020F0", Style: 7},
+// {Type: "diagonalUp", Color: "A020F0", Style: 8},
+// },
+// })
// if err != nil {
// fmt.Println(err)
// }
@@ -2637,7 +2498,9 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
// Set gradient fill with vertical variants shading styles for cell H9 on
// Sheet1:
//
-// style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Fill: excelize.Fill{Type: "gradient", Color: []string{"#FFFFFF", "#E0EBF5"}, Shading: 1},
+// })
// if err != nil {
// fmt.Println(err)
// }
@@ -2645,7 +2508,9 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// Set solid style pattern fill for cell H9 on Sheet1:
//
-// style, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Fill: excelize.Fill{Type: "pattern", Color: []string{"#E0EBF5"}, Pattern: 1},
+// })
// if err != nil {
// fmt.Println(err)
// }
@@ -2653,7 +2518,19 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// Set alignment style for cell H9 on Sheet1:
//
-// style, err := f.NewStyle(`{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"","wrap_text":true}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Alignment: &excelize.Alignment{
+// Horizontal: "center",
+// Indent: 1,
+// JustifyLastLine: true,
+// ReadingOrder: 0,
+// RelativeIndent: 1,
+// ShrinkToFit: true,
+// TextRotation: 45,
+// Vertical: "",
+// WrapText: true,
+// },
+// })
// if err != nil {
// fmt.Println(err)
// }
@@ -2664,7 +2541,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
// for cell H9 on Sheet1:
//
// f.SetCellValue("Sheet1", "H9", 42920.5)
-// style, err := f.NewStyle(`{"number_format": 22}`)
+// style, err := f.NewStyle(&excelize.Style{NumFmt: 22})
// if err != nil {
// fmt.Println(err)
// }
@@ -2672,7 +2549,15 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// Set font style for cell H9 on Sheet1:
//
-// style, err := f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777"}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Font: &excelize.Font{
+// Bold: true,
+// Italic: true,
+// Family: "Times New Roman",
+// Size: 36,
+// Color: "#777777",
+// },
+// })
// if err != nil {
// fmt.Println(err)
// }
@@ -2680,48 +2565,53 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// Hide and lock for cell H9 on Sheet1:
//
-// style, err := f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
+// style, err := f.NewStyle(&excelize.Style{
+// Protection: &excelize.Protection{
+// Hidden: true,
+// Locked: true,
+// },
+// })
// if err != nil {
// fmt.Println(err)
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
-func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
- hcol, hrow, err := CellNameToCoordinates(hcell)
+func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
+ hCol, hRow, err := CellNameToCoordinates(hCell)
if err != nil {
return err
}
- vcol, vrow, err := CellNameToCoordinates(vcell)
+ vCol, vRow, err := CellNameToCoordinates(vCell)
if err != nil {
return err
}
// Normalize the coordinate area, such correct C1:B3 to B1:C3.
- if vcol < hcol {
- vcol, hcol = hcol, vcol
+ if vCol < hCol {
+ vCol, hCol = hCol, vCol
}
- if vrow < hrow {
- vrow, hrow = hrow, vrow
+ if vRow < hRow {
+ vRow, hRow = hRow, vRow
}
- hcolIdx := hcol - 1
- hrowIdx := hrow - 1
+ hColIdx := hCol - 1
+ hRowIdx := hRow - 1
- vcolIdx := vcol - 1
- vrowIdx := vrow - 1
+ vColIdx := vCol - 1
+ vRowIdx := vRow - 1
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
- prepareSheetXML(ws, vcol, vrow)
- makeContiguousColumns(ws, hrow, vrow, vcol)
+ prepareSheetXML(ws, vCol, vRow)
+ makeContiguousColumns(ws, hRow, vRow, vCol)
ws.Lock()
defer ws.Unlock()
- for r := hrowIdx; r <= vrowIdx; r++ {
- for k := hcolIdx; k <= vcolIdx; k++ {
+ for r := hRowIdx; r <= vRowIdx; r++ {
+ for k := hColIdx; k <= vColIdx; k++ {
ws.SheetData.Row[r].C[k].S = styleID
}
}
@@ -2961,7 +2851,7 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
if err != nil {
return err
}
- cfRule := []*xlsxCfRule{}
+ var cfRule []*xlsxCfRule
for p, v := range format {
var vt, ct string
var ok bool
@@ -3162,7 +3052,7 @@ func ThemeColor(baseColor string, tint float64) string {
h, s, l = RGBToHSL(uint8(r), uint8(g), uint8(b))
}
if tint < 0 {
- l *= (1 + tint)
+ l *= 1 + tint
} else {
l = l*(1-tint) + (1 - (1 - tint))
}
diff --git a/vendor/github.com/xuri/excelize/v2/table.go b/vendor/github.com/xuri/excelize/v2/table.go
index a6959a42..0311a8ed 100644
--- a/vendor/github.com/xuri/excelize/v2/table.go
+++ b/vendor/github.com/xuri/excelize/v2/table.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -61,27 +61,27 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
// TableStyleMedium1 - TableStyleMedium28
// TableStyleDark1 - TableStyleDark11
//
-func (f *File) AddTable(sheet, hcell, vcell, format string) error {
+func (f *File) AddTable(sheet, hCell, vCell, format string) error {
formatSet, err := parseFormatTableSet(format)
if err != nil {
return err
}
// Coordinate conversion, convert C1:B3 to 2,0,1,2.
- hcol, hrow, err := CellNameToCoordinates(hcell)
+ hCol, hRow, err := CellNameToCoordinates(hCell)
if err != nil {
return err
}
- vcol, vrow, err := CellNameToCoordinates(vcell)
+ vCol, vRow, err := CellNameToCoordinates(vCell)
if err != nil {
return err
}
- if vcol < hcol {
- vcol, hcol = hcol, vcol
+ if vCol < hCol {
+ vCol, hCol = hCol, vCol
}
- if vrow < hrow {
- vrow, hrow = hrow, vrow
+ if vRow < hRow {
+ vRow, hRow = hRow, vRow
}
tableID := f.countTables() + 1
@@ -94,7 +94,7 @@ func (f *File) AddTable(sheet, hcell, vcell, format string) error {
return err
}
f.addSheetNameSpace(sheet, SourceRelationship)
- if err = f.addTable(sheet, tableXML, hcol, hrow, vcol, vrow, tableID, formatSet); err != nil {
+ if err = f.addTable(sheet, tableXML, hCol, hRow, vCol, vRow, tableID, formatSet); err != nil {
return err
}
f.addContentTypePart(tableID, "table")
@@ -257,9 +257,9 @@ func parseAutoFilterSet(formatSet string) (*formatAutoFilter, error) {
// Excel also allows some simple string matching operations:
//
// x == b* // begins with b
-// x != b* // doesnt begin with b
+// x != b* // doesn't begin with b
// x == *b // ends with b
-// x != *b // doesnt end with b
+// x != *b // doesn't end with b
// x == *b* // contains b
// x != *b* // doesn't contains b
//
@@ -276,31 +276,31 @@ func parseAutoFilterSet(formatSet string) (*formatAutoFilter, error) {
// col < 2000
// Price < 2000
//
-func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
- hcol, hrow, err := CellNameToCoordinates(hcell)
+func (f *File) AutoFilter(sheet, hCell, vCell, format string) error {
+ hCol, hRow, err := CellNameToCoordinates(hCell)
if err != nil {
return err
}
- vcol, vrow, err := CellNameToCoordinates(vcell)
+ vCol, vRow, err := CellNameToCoordinates(vCell)
if err != nil {
return err
}
- if vcol < hcol {
- vcol, hcol = hcol, vcol
+ if vCol < hCol {
+ vCol, hCol = hCol, vCol
}
- if vrow < hrow {
- vrow, hrow = hrow, vrow
+ if vRow < hRow {
+ vRow, hRow = hRow, vRow
}
formatSet, _ := parseAutoFilterSet(format)
- cellStart, _ := CoordinatesToCellName(hcol, hrow, true)
- cellEnd, _ := CoordinatesToCellName(vcol, vrow, true)
+ cellStart, _ := CoordinatesToCellName(hCol, hRow, true)
+ cellEnd, _ := CoordinatesToCellName(vCol, vRow, true)
ref, filterDB := cellStart+":"+cellEnd, "_xlnm._FilterDatabase"
wb := f.workbookReader()
sheetID := f.GetSheetIndex(sheet)
- filterRange := fmt.Sprintf("%s!%s", sheet, ref)
+ filterRange := fmt.Sprintf("'%s'!%s", sheet, ref)
d := xlsxDefinedName{
Name: filterDB,
Hidden: true,
@@ -324,8 +324,8 @@ func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName, d)
}
}
- refRange := vcol - hcol
- return f.autoFilter(sheet, ref, refRange, hcol, formatSet)
+ refRange := vCol - hCol
+ return f.autoFilter(sheet, ref, refRange, hCol, formatSet)
}
// autoFilter provides a function to extract the tokens from the filter
@@ -383,7 +383,7 @@ func (f *File) writeAutoFilter(filter *xlsxAutoFilter, exp []int, tokens []strin
filter.FilterColumn[0].Filters = &xlsxFilters{Filter: filters}
} else if len(exp) == 3 && exp[0] == 2 && exp[1] == 1 && exp[2] == 2 {
// Double equality with "or" operator.
- filters := []*xlsxFilter{}
+ var filters []*xlsxFilter
for _, v := range tokens {
filters = append(filters, &xlsxFilter{Val: v})
}
@@ -419,7 +419,7 @@ func (f *File) writeCustomFilter(filter *xlsxAutoFilter, operator int, val strin
if filter.FilterColumn[0].CustomFilters != nil {
filter.FilterColumn[0].CustomFilters.CustomFilter = append(filter.FilterColumn[0].CustomFilters.CustomFilter, &customFilter)
} else {
- customFilters := []*xlsxCustomFilter{}
+ var customFilters []*xlsxCustomFilter
customFilters = append(customFilters, &customFilter)
filter.FilterColumn[0].CustomFilters = &xlsxCustomFilters{CustomFilter: customFilters}
}
@@ -435,8 +435,8 @@ func (f *File) writeCustomFilter(filter *xlsxAutoFilter, operator int, val strin
// ('x', '>', 2000, 'and', 'x', '<', 5000) -> exp1 and exp2
//
func (f *File) parseFilterExpression(expression string, tokens []string) ([]int, []string, error) {
- expressions := []int{}
- t := []string{}
+ var expressions []int
+ var t []string
if len(tokens) == 7 {
// The number of tokens will be either 3 (for 1 expression) or 7 (for 2
// expressions).
diff --git a/vendor/github.com/xuri/excelize/v2/templates.go b/vendor/github.com/xuri/excelize/v2/templates.go
index 1783d7c3..1e46b561 100644
--- a/vendor/github.com/xuri/excelize/v2/templates.go
+++ b/vendor/github.com/xuri/excelize/v2/templates.go
@@ -1,35 +1,28 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
//
// This file contains default templates for XML files we don't yet populated
// based on content.
package excelize
-import "encoding/xml"
-
-var (
- // XMLHeaderByte define an XML declaration can also contain a standalone
- // declaration.
- XMLHeaderByte = []byte(xml.Header)
-)
-
const (
defaultXMLPathContentTypes = "[Content_Types].xml"
- dafaultXMLPathDocPropsApp = "docProps/app.xml"
- dafaultXMLPathDocPropsCore = "docProps/core.xml"
- dafaultXMLPathCalcChain = "xl/calcChain.xml"
- dafaultXMLPathSharedStrings = "xl/sharedStrings.xml"
+ defaultXMLPathDocPropsApp = "docProps/app.xml"
+ defaultXMLPathDocPropsCore = "docProps/core.xml"
+ defaultXMLPathCalcChain = "xl/calcChain.xml"
+ defaultXMLPathSharedStrings = "xl/sharedStrings.xml"
defaultXMLPathStyles = "xl/styles.xml"
defaultXMLPathWorkbook = "xl/workbook.xml"
+ defaultTempFileSST = "sharedStrings"
)
const templateDocpropsApp = `0Go Excelize`
diff --git a/vendor/github.com/xuri/excelize/v2/vmlDrawing.go b/vendor/github.com/xuri/excelize/v2/vmlDrawing.go
index 58166fa6..f9de4991 100644
--- a/vendor/github.com/xuri/excelize/v2/vmlDrawing.go
+++ b/vendor/github.com/xuri/excelize/v2/vmlDrawing.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/workbook.go b/vendor/github.com/xuri/excelize/v2/workbook.go
new file mode 100644
index 00000000..c65397b6
--- /dev/null
+++ b/vendor/github.com/xuri/excelize/v2/workbook.go
@@ -0,0 +1,176 @@
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
+// this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+//
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
+
+package excelize
+
+import (
+ "bytes"
+ "encoding/xml"
+ "io"
+ "log"
+ "path/filepath"
+ "strconv"
+ "strings"
+)
+
+// WorkbookPrOption is an option of a view of a workbook. See SetWorkbookPrOptions().
+type WorkbookPrOption interface {
+ setWorkbookPrOption(pr *xlsxWorkbookPr)
+}
+
+// WorkbookPrOptionPtr is a writable WorkbookPrOption. See GetWorkbookPrOptions().
+type WorkbookPrOptionPtr interface {
+ WorkbookPrOption
+ getWorkbookPrOption(pr *xlsxWorkbookPr)
+}
+
+type (
+ // FilterPrivacy is an option used for WorkbookPrOption
+ FilterPrivacy bool
+)
+
+// setWorkbook update workbook property of the spreadsheet. Maximum 31
+// characters are allowed in sheet title.
+func (f *File) setWorkbook(name string, sheetID, rid int) {
+ content := f.workbookReader()
+ content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
+ Name: trimSheetName(name),
+ SheetID: sheetID,
+ ID: "rId" + strconv.Itoa(rid),
+ })
+}
+
+// getWorkbookPath provides a function to get the path of the workbook.xml in
+// the spreadsheet.
+func (f *File) getWorkbookPath() (path string) {
+ if rels := f.relsReader("_rels/.rels"); rels != nil {
+ rels.Lock()
+ defer rels.Unlock()
+ for _, rel := range rels.Relationships {
+ if rel.Type == SourceRelationshipOfficeDocument {
+ path = strings.TrimPrefix(rel.Target, "/")
+ return
+ }
+ }
+ }
+ return
+}
+
+// getWorkbookRelsPath provides a function to get the path of the workbook.xml.rels
+// in the spreadsheet.
+func (f *File) getWorkbookRelsPath() (path string) {
+ wbPath := f.getWorkbookPath()
+ wbDir := filepath.Dir(wbPath)
+ if wbDir == "." {
+ path = "_rels/" + filepath.Base(wbPath) + ".rels"
+ return
+ }
+ path = strings.TrimPrefix(filepath.Dir(wbPath)+"/_rels/"+filepath.Base(wbPath)+".rels", "/")
+ return
+}
+
+// workbookReader provides a function to get the pointer to the workbook.xml
+// structure after deserialization.
+func (f *File) workbookReader() *xlsxWorkbook {
+ var err error
+ if f.WorkBook == nil {
+ wbPath := f.getWorkbookPath()
+ f.WorkBook = new(xlsxWorkbook)
+ if _, ok := f.xmlAttr[wbPath]; !ok {
+ d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath))))
+ f.xmlAttr[wbPath] = append(f.xmlAttr[wbPath], getRootElement(d)...)
+ f.addNameSpaces(wbPath, SourceRelationship)
+ }
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath)))).
+ Decode(f.WorkBook); err != nil && err != io.EOF {
+ log.Printf("xml decode error: %s", err)
+ }
+ }
+ return f.WorkBook
+}
+
+// workBookWriter provides a function to save workbook.xml after serialize
+// structure.
+func (f *File) workBookWriter() {
+ if f.WorkBook != nil {
+ if f.WorkBook.DecodeAlternateContent != nil {
+ f.WorkBook.AlternateContent = &xlsxAlternateContent{
+ Content: f.WorkBook.DecodeAlternateContent.Content,
+ XMLNSMC: SourceRelationshipCompatibility.Value,
+ }
+ }
+ f.WorkBook.DecodeAlternateContent = nil
+ output, _ := xml.Marshal(f.WorkBook)
+ f.saveFileList(f.getWorkbookPath(), replaceRelationshipsBytes(f.replaceNameSpaceBytes(f.getWorkbookPath(), output)))
+ }
+}
+
+// SetWorkbookPrOptions provides a function to sets workbook properties.
+//
+// Available options:
+// FilterPrivacy(bool)
+// CodeName(string)
+func (f *File) SetWorkbookPrOptions(opts ...WorkbookPrOption) error {
+ wb := f.workbookReader()
+ pr := wb.WorkbookPr
+ if pr == nil {
+ pr = new(xlsxWorkbookPr)
+ wb.WorkbookPr = pr
+ }
+ for _, opt := range opts {
+ opt.setWorkbookPrOption(pr)
+ }
+ return nil
+}
+
+// setWorkbookPrOption implements the WorkbookPrOption interface.
+func (o FilterPrivacy) setWorkbookPrOption(pr *xlsxWorkbookPr) {
+ pr.FilterPrivacy = bool(o)
+}
+
+// setWorkbookPrOption implements the WorkbookPrOption interface.
+func (o CodeName) setWorkbookPrOption(pr *xlsxWorkbookPr) {
+ pr.CodeName = string(o)
+}
+
+// GetWorkbookPrOptions provides a function to gets workbook properties.
+//
+// Available options:
+// FilterPrivacy(bool)
+// CodeName(string)
+func (f *File) GetWorkbookPrOptions(opts ...WorkbookPrOptionPtr) error {
+ wb := f.workbookReader()
+ pr := wb.WorkbookPr
+ for _, opt := range opts {
+ opt.getWorkbookPrOption(pr)
+ }
+ return nil
+}
+
+// getWorkbookPrOption implements the WorkbookPrOption interface and get the
+// filter privacy of thw workbook.
+func (o *FilterPrivacy) getWorkbookPrOption(pr *xlsxWorkbookPr) {
+ if pr == nil {
+ *o = false
+ return
+ }
+ *o = FilterPrivacy(pr.FilterPrivacy)
+}
+
+// getWorkbookPrOption implements the WorkbookPrOption interface and get the
+// code name of thw workbook.
+func (o *CodeName) getWorkbookPrOption(pr *xlsxWorkbookPr) {
+ if pr == nil {
+ *o = ""
+ return
+ }
+ *o = CodeName(pr.CodeName)
+}
diff --git a/vendor/github.com/xuri/excelize/v2/xmlApp.go b/vendor/github.com/xuri/excelize/v2/xmlApp.go
index 32264066..abfd82b3 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlApp.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlApp.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlCalcChain.go b/vendor/github.com/xuri/excelize/v2/xmlCalcChain.go
index dfbb074e..f5780339 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlCalcChain.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlCalcChain.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -66,13 +66,13 @@ type xlsxCalcChain struct {
// | same dependency level. Child chains are series of
// | calculations that can be independently farmed out to
// | other threads or processors.The possible values for
-// | this attribute are defined by the W3C XML Schema
+// | this attribute is defined by the W3C XML Schema
// | boolean datatype.
// |
// t (New Thread) | A Boolean flag indicating whether the cell's formula
// | starts a new thread. True if the cell's formula starts
// | a new thread, false otherwise.The possible values for
-// | this attribute are defined by the W3C XML Schema
+// | this attribute is defined by the W3C XML Schema
// | boolean datatype.
//
type xlsxCalcChainC struct {
diff --git a/vendor/github.com/xuri/excelize/v2/xmlChart.go b/vendor/github.com/xuri/excelize/v2/xmlChart.go
index a838f51d..b6ee3cd8 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlChart.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlChart.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -520,23 +520,23 @@ type cPageMargins struct {
// formatChartAxis directly maps the format settings of the chart axis.
type formatChartAxis struct {
- None bool `json:"none"`
- Crossing string `json:"crossing"`
- MajorGridlines bool `json:"major_grid_lines"`
- MinorGridlines bool `json:"minor_grid_lines"`
- MajorTickMark string `json:"major_tick_mark"`
- MinorTickMark string `json:"minor_tick_mark"`
- MinorUnitType string `json:"minor_unit_type"`
- MajorUnit float64 `json:"major_unit"`
- MajorUnitType string `json:"major_unit_type"`
- TickLabelSkip int `json:"tick_label_skip"`
- DisplayUnits string `json:"display_units"`
- DisplayUnitsVisible bool `json:"display_units_visible"`
- DateAxis bool `json:"date_axis"`
- ReverseOrder bool `json:"reverse_order"`
- Maximum float64 `json:"maximum"`
- Minimum float64 `json:"minimum"`
- NumFormat string `json:"num_format"`
+ None bool `json:"none"`
+ Crossing string `json:"crossing"`
+ MajorGridlines bool `json:"major_grid_lines"`
+ MinorGridlines bool `json:"minor_grid_lines"`
+ MajorTickMark string `json:"major_tick_mark"`
+ MinorTickMark string `json:"minor_tick_mark"`
+ MinorUnitType string `json:"minor_unit_type"`
+ MajorUnit float64 `json:"major_unit"`
+ MajorUnitType string `json:"major_unit_type"`
+ TickLabelSkip int `json:"tick_label_skip"`
+ DisplayUnits string `json:"display_units"`
+ DisplayUnitsVisible bool `json:"display_units_visible"`
+ DateAxis bool `json:"date_axis"`
+ ReverseOrder bool `json:"reverse_order"`
+ Maximum *float64 `json:"maximum"`
+ Minimum *float64 `json:"minimum"`
+ NumFormat string `json:"num_format"`
NumFont struct {
Color string `json:"color"`
Bold bool `json:"bold"`
@@ -599,7 +599,7 @@ type formatChart struct {
ShowBlanksAs string `json:"show_blanks_as"`
ShowHiddenData bool `json:"show_hidden_data"`
SetRotation int `json:"set_rotation"`
- SetHoleSize int `json:"set_hole_size"`
+ HoleSize int `json:"hole_size"`
order int
}
diff --git a/vendor/github.com/xuri/excelize/v2/xmlChartSheet.go b/vendor/github.com/xuri/excelize/v2/xmlChartSheet.go
index fcc34432..f0f2f628 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlChartSheet.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlChartSheet.go
@@ -1,15 +1,15 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// struct code generated by github.com/xuri/xgen
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlComments.go b/vendor/github.com/xuri/excelize/v2/xmlComments.go
index 7965c863..b4602fc9 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlComments.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlComments.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlContentTypes.go b/vendor/github.com/xuri/excelize/v2/xmlContentTypes.go
index 6b6db639..4b3cd642 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlContentTypes.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlContentTypes.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -16,7 +16,7 @@ import (
"sync"
)
-// xlsxTypes directly maps the types element of content types for relationship
+// xlsxTypes directly maps the types' element of content types for relationship
// parts, it takes a Multipurpose Internet Mail Extension (MIME) media type as a
// value.
type xlsxTypes struct {
diff --git a/vendor/github.com/xuri/excelize/v2/xmlCore.go b/vendor/github.com/xuri/excelize/v2/xmlCore.go
index 8ed8f304..22ae6bc0 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlCore.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlCore.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlDecodeDrawing.go b/vendor/github.com/xuri/excelize/v2/xmlDecodeDrawing.go
index da333ef9..fb920be1 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlDecodeDrawing.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlDecodeDrawing.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -63,12 +63,13 @@ type decodeCNvSpPr struct {
// changed after serialization and deserialization, two different structures
// are defined. decodeWsDr just for deserialization.
type decodeWsDr struct {
- A string `xml:"xmlns a,attr"`
- Xdr string `xml:"xmlns xdr,attr"`
- R string `xml:"xmlns r,attr"`
- OneCellAnchor []*decodeCellAnchor `xml:"oneCellAnchor,omitempty"`
- TwoCellAnchor []*decodeCellAnchor `xml:"twoCellAnchor,omitempty"`
- XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing wsDr,omitempty"`
+ XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing wsDr,omitempty"`
+ A string `xml:"xmlns a,attr"`
+ Xdr string `xml:"xmlns xdr,attr"`
+ R string `xml:"xmlns r,attr"`
+ AlternateContent []*xlsxInnerXML `xml:"http://schemas.openxmlformats.org/markup-compatibility/2006 AlternateContent"`
+ OneCellAnchor []*decodeCellAnchor `xml:"oneCellAnchor,omitempty"`
+ TwoCellAnchor []*decodeCellAnchor `xml:"twoCellAnchor,omitempty"`
}
// decodeTwoCellAnchor directly maps the oneCellAnchor (One Cell Anchor Shape
@@ -78,7 +79,7 @@ type decodeWsDr struct {
type decodeTwoCellAnchor struct {
From *decodeFrom `xml:"from"`
To *decodeTo `xml:"to"`
- Pic *decodePic `xml:"pic,omitempty"`
+ Pic *decodePic `xml:"pic"`
ClientData *decodeClientData `xml:"clientData"`
}
@@ -111,10 +112,8 @@ type decodePicLocks struct {
NoSelect bool `xml:"noSelect,attr,omitempty"`
}
-// decodeBlip directly maps the blip element in the namespace
-// http://purl.oclc.org/ooxml/officeDoc ument/relationships - This element
-// specifies the existence of an image (binary large image or picture) and
-// contains a reference to the image data.
+// decodeBlip element specifies the existence of an image (binary large image
+// or picture) and contains a reference to the image data.
type decodeBlip struct {
Embed string `xml:"embed,attr"`
Cstate string `xml:"cstate,attr,omitempty"`
diff --git a/vendor/github.com/xuri/excelize/v2/xmlDrawing.go b/vendor/github.com/xuri/excelize/v2/xmlDrawing.go
index 4ae6a295..4bf43ec8 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlDrawing.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlDrawing.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -62,10 +62,14 @@ const (
StrictNameSpaceSpreadSheet = "http://purl.oclc.org/ooxml/spreadsheetml/main"
NameSpaceDublinCore = "http://purl.org/dc/elements/1.1/"
NameSpaceDublinCoreTerms = "http://purl.org/dc/terms/"
- NameSpaceDublinCoreMetadataIntiative = "http://purl.org/dc/dcmitype/"
+ NameSpaceDublinCoreMetadataInitiative = "http://purl.org/dc/dcmitype/"
ContentTypeDrawing = "application/vnd.openxmlformats-officedocument.drawing+xml"
ContentTypeDrawingML = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
+ ContentTypeSheetML = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
+ ContentTypeTemplate = "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
+ ContentTypeAddinMacro = "application/vnd.ms-excel.addin.macroEnabled.main+xml"
ContentTypeMacro = "application/vnd.ms-excel.sheet.macroEnabled.main+xml"
+ ContentTypeTemplateMacro = "application/vnd.ms-excel.template.macroEnabled.main+xml"
ContentTypeSpreadSheetMLChartsheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml"
ContentTypeSpreadSheetMLComments = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
ContentTypeSpreadSheetMLPivotCacheDefinition = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"
@@ -160,10 +164,8 @@ type xlsxPicLocks struct {
NoSelect bool `xml:"noSelect,attr,omitempty"`
}
-// xlsxBlip directly maps the blip element in the namespace
-// http://purl.oclc.org/ooxml/officeDoc ument/relationships - This element
-// specifies the existence of an image (binary large image or picture) and
-// contains a reference to the image data.
+// xlsxBlip element specifies the existence of an image (binary large image or
+// picture) and contains a reference to the image data.
type xlsxBlip struct {
Embed string `xml:"r:embed,attr"`
Cstate string `xml:"cstate,attr,omitempty"`
@@ -318,13 +320,14 @@ type xlsxPoint2D struct {
// wsDr.
type xlsxWsDr struct {
sync.Mutex
- XMLName xml.Name `xml:"xdr:wsDr"`
- AbsoluteAnchor []*xdrCellAnchor `xml:"xdr:absoluteAnchor"`
- OneCellAnchor []*xdrCellAnchor `xml:"xdr:oneCellAnchor"`
- TwoCellAnchor []*xdrCellAnchor `xml:"xdr:twoCellAnchor"`
- A string `xml:"xmlns:a,attr,omitempty"`
- Xdr string `xml:"xmlns:xdr,attr,omitempty"`
- R string `xml:"xmlns:r,attr,omitempty"`
+ XMLName xml.Name `xml:"xdr:wsDr"`
+ A string `xml:"xmlns:a,attr,omitempty"`
+ Xdr string `xml:"xmlns:xdr,attr,omitempty"`
+ R string `xml:"xmlns:r,attr,omitempty"`
+ AlternateContent []*xlsxAlternateContent `xml:"mc:AlternateContent"`
+ AbsoluteAnchor []*xdrCellAnchor `xml:"xdr:absoluteAnchor"`
+ OneCellAnchor []*xdrCellAnchor `xml:"xdr:oneCellAnchor"`
+ TwoCellAnchor []*xdrCellAnchor `xml:"xdr:twoCellAnchor"`
}
// xlsxGraphicFrame (Graphic Frame) directly maps the xdr:graphicFrame element.
diff --git a/vendor/github.com/xuri/excelize/v2/xmlPivotCache.go b/vendor/github.com/xuri/excelize/v2/xmlPivotCache.go
index 2812cf41..0af7c44d 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlPivotCache.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlPivotCache.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -79,8 +79,7 @@ type xlsxWorksheetSource struct {
// PivotTable is a collection of ranges in the workbook. The ranges are
// specified in the rangeSets collection. The logic for how the application
// consolidates the data in the ranges is application- defined.
-type xlsxConsolidation struct {
-}
+type xlsxConsolidation struct{}
// xlsxCacheFields represents the collection of field definitions in the
// source data.
@@ -144,8 +143,7 @@ type xlsxSharedItems struct {
}
// xlsxMissing represents a value that was not specified.
-type xlsxMissing struct {
-}
+type xlsxMissing struct{}
// xlsxNumber represents a numeric value in the PivotTable.
type xlsxNumber struct {
@@ -167,18 +165,15 @@ type xlsxNumber struct {
// xlsxTuples represents members for the OLAP sheet data entry, also known as
// a tuple.
-type xlsxTuples struct {
-}
+type xlsxTuples struct{}
// xlsxBoolean represents a boolean value for an item in the PivotTable.
-type xlsxBoolean struct {
-}
+type xlsxBoolean struct{}
// xlsxError represents an error value. The use of this item indicates that an
// error value is present in the PivotTable source. The error is recorded in
// the value attribute.
-type xlsxError struct {
-}
+type xlsxError struct{}
// xlsxString represents a character value in a PivotTable.
type xlsxString struct {
@@ -199,45 +194,35 @@ type xlsxString struct {
}
// xlsxDateTime represents a date-time value in the PivotTable.
-type xlsxDateTime struct {
-}
+type xlsxDateTime struct{}
// xlsxFieldGroup represents the collection of properties for a field group.
-type xlsxFieldGroup struct {
-}
+type xlsxFieldGroup struct{}
// xlsxCacheHierarchies represents the collection of OLAP hierarchies in the
// PivotCache.
-type xlsxCacheHierarchies struct {
-}
+type xlsxCacheHierarchies struct{}
// xlsxKpis represents the collection of Key Performance Indicators (KPIs)
// defined on the OLAP server and stored in the PivotCache.
-type xlsxKpis struct {
-}
+type xlsxKpis struct{}
// xlsxTupleCache represents the cache of OLAP sheet data members, or tuples.
-type xlsxTupleCache struct {
-}
+type xlsxTupleCache struct{}
// xlsxCalculatedItems represents the collection of calculated items.
-type xlsxCalculatedItems struct {
-}
+type xlsxCalculatedItems struct{}
// xlsxCalculatedMembers represents the collection of calculated members in an
// OLAP PivotTable.
-type xlsxCalculatedMembers struct {
-}
+type xlsxCalculatedMembers struct{}
// xlsxDimensions represents the collection of PivotTable OLAP dimensions.
-type xlsxDimensions struct {
-}
+type xlsxDimensions struct{}
// xlsxMeasureGroups represents the collection of PivotTable OLAP measure
// groups.
-type xlsxMeasureGroups struct {
-}
+type xlsxMeasureGroups struct{}
// xlsxMaps represents the PivotTable OLAP measure group - Dimension maps.
-type xlsxMaps struct {
-}
+type xlsxMaps struct{}
diff --git a/vendor/github.com/xuri/excelize/v2/xmlPivotTable.go b/vendor/github.com/xuri/excelize/v2/xmlPivotTable.go
index 529b867a..897669ba 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlPivotTable.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlPivotTable.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -195,8 +195,7 @@ type xlsxItem struct {
}
// xlsxAutoSortScope represents the sorting scope for the PivotTable.
-type xlsxAutoSortScope struct {
-}
+type xlsxAutoSortScope struct{}
// xlsxRowFields represents the collection of row fields for the PivotTable.
type xlsxRowFields struct {
@@ -225,8 +224,7 @@ type xlsxI struct {
}
// xlsxX represents an array of indexes to cached shared item values.
-type xlsxX struct {
-}
+type xlsxX struct{}
// xlsxColFields represents the collection of fields that are on the column
// axis of the PivotTable.
@@ -281,8 +279,7 @@ type xlsxDataField struct {
// xlsxConditionalFormats represents the collection of conditional formats
// applied to a PivotTable.
-type xlsxConditionalFormats struct {
-}
+type xlsxConditionalFormats struct{}
// xlsxPivotTableStyleInfo represent information on style applied to the
// PivotTable.
diff --git a/vendor/github.com/xuri/excelize/v2/xmlSharedStrings.go b/vendor/github.com/xuri/excelize/v2/xmlSharedStrings.go
index e505d262..683105e3 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlSharedStrings.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlSharedStrings.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlStyles.go b/vendor/github.com/xuri/excelize/v2/xmlStyles.go
index afdc1700..71fe9a66 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlStyles.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlStyles.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -20,16 +20,16 @@ import (
type xlsxStyleSheet struct {
sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main styleSheet"`
- NumFmts *xlsxNumFmts `xml:"numFmts,omitempty"`
- Fonts *xlsxFonts `xml:"fonts,omitempty"`
- Fills *xlsxFills `xml:"fills,omitempty"`
- Borders *xlsxBorders `xml:"borders,omitempty"`
- CellStyleXfs *xlsxCellStyleXfs `xml:"cellStyleXfs,omitempty"`
- CellXfs *xlsxCellXfs `xml:"cellXfs,omitempty"`
- CellStyles *xlsxCellStyles `xml:"cellStyles,omitempty"`
- Dxfs *xlsxDxfs `xml:"dxfs,omitempty"`
- TableStyles *xlsxTableStyles `xml:"tableStyles,omitempty"`
- Colors *xlsxStyleColors `xml:"colors,omitempty"`
+ NumFmts *xlsxNumFmts `xml:"numFmts"`
+ Fonts *xlsxFonts `xml:"fonts"`
+ Fills *xlsxFills `xml:"fills"`
+ Borders *xlsxBorders `xml:"borders"`
+ CellStyleXfs *xlsxCellStyleXfs `xml:"cellStyleXfs"`
+ CellXfs *xlsxCellXfs `xml:"cellXfs"`
+ CellStyles *xlsxCellStyles `xml:"cellStyles"`
+ Dxfs *xlsxDxfs `xml:"dxfs"`
+ TableStyles *xlsxTableStyles `xml:"tableStyles"`
+ Colors *xlsxStyleColors `xml:"colors"`
ExtLst *xlsxExtLst `xml:"extLst"`
}
@@ -60,7 +60,7 @@ type xlsxProtection struct {
// xlsxLine expresses a single set of cell border.
type xlsxLine struct {
Style string `xml:"style,attr,omitempty"`
- Color *xlsxColor `xml:"color,omitempty"`
+ Color *xlsxColor `xml:"color"`
}
// xlsxColor is a common mapping used for both the fgColor and bgColor elements.
@@ -87,13 +87,13 @@ type xlsxFonts struct {
// xlsxFont directly maps the font element. This element defines the
// properties for one of the fonts used in this workbook.
type xlsxFont struct {
- B *attrValBool `xml:"b,omitempty"`
- I *attrValBool `xml:"i,omitempty"`
- Strike *attrValBool `xml:"strike,omitempty"`
- Outline *attrValBool `xml:"outline,omitempty"`
- Shadow *attrValBool `xml:"shadow,omitempty"`
- Condense *attrValBool `xml:"condense,omitempty"`
- Extend *attrValBool `xml:"extend,omitempty"`
+ B *attrValBool `xml:"b"`
+ I *attrValBool `xml:"i"`
+ Strike *attrValBool `xml:"strike"`
+ Outline *attrValBool `xml:"outline"`
+ Shadow *attrValBool `xml:"shadow"`
+ Condense *attrValBool `xml:"condense"`
+ Extend *attrValBool `xml:"extend"`
U *attrValString `xml:"u"`
Sz *attrValFloat `xml:"sz"`
Color *xlsxColor `xml:"color"`
@@ -109,14 +109,14 @@ type xlsxFont struct {
// applied across the cell.
type xlsxFills struct {
Count int `xml:"count,attr"`
- Fill []*xlsxFill `xml:"fill,omitempty"`
+ Fill []*xlsxFill `xml:"fill"`
}
// xlsxFill directly maps the fill element. This element specifies fill
// formatting.
type xlsxFill struct {
- PatternFill *xlsxPatternFill `xml:"patternFill,omitempty"`
- GradientFill *xlsxGradientFill `xml:"gradientFill,omitempty"`
+ PatternFill *xlsxPatternFill `xml:"patternFill"`
+ GradientFill *xlsxGradientFill `xml:"gradientFill"`
}
// xlsxPatternFill is used to specify cell fill information for pattern and
@@ -138,7 +138,7 @@ type xlsxGradientFill struct {
Right float64 `xml:"right,attr,omitempty"`
Top float64 `xml:"top,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
- Stop []*xlsxGradientFillStop `xml:"stop,omitempty"`
+ Stop []*xlsxGradientFillStop `xml:"stop"`
}
// xlsxGradientFillStop directly maps the stop element.
@@ -152,7 +152,7 @@ type xlsxGradientFillStop struct {
// the workbook.
type xlsxBorders struct {
Count int `xml:"count,attr"`
- Border []*xlsxBorder `xml:"border,omitempty"`
+ Border []*xlsxBorder `xml:"border"`
}
// xlsxBorder directly maps the border element. Expresses a single set of cell
@@ -177,7 +177,7 @@ type xlsxBorder struct {
type xlsxCellStyles struct {
XMLName xml.Name `xml:"cellStyles"`
Count int `xml:"count,attr"`
- CellStyle []*xlsxCellStyle `xml:"cellStyle,omitempty"`
+ CellStyle []*xlsxCellStyle `xml:"cellStyle"`
}
// xlsxCellStyle directly maps the cellStyle element. This element represents
@@ -187,17 +187,17 @@ type xlsxCellStyle struct {
XMLName xml.Name `xml:"cellStyle"`
Name string `xml:"name,attr"`
XfID int `xml:"xfId,attr"`
- BuiltInID *int `xml:"builtinId,attr,omitempty"`
- ILevel *int `xml:"iLevel,attr,omitempty"`
- Hidden *bool `xml:"hidden,attr,omitempty"`
- CustomBuiltIn *bool `xml:"customBuiltin,attr,omitempty"`
+ BuiltInID *int `xml:"builtinId,attr"`
+ ILevel *int `xml:"iLevel,attr"`
+ Hidden *bool `xml:"hidden,attr"`
+ CustomBuiltIn *bool `xml:"customBuiltin,attr"`
}
// xlsxCellStyleXfs directly maps the cellStyleXfs element. This element
// contains the master formatting records (xf's) which define the formatting for
// all named cell styles in this workbook. Master formatting records reference
// individual elements of formatting (e.g., number format, font definitions,
-// cell fills, etc) by specifying a zero-based index into those collections.
+// cell fills, etc.) by specifying a zero-based index into those collections.
// Master formatting records also specify whether to apply or ignore particular
// aspects of formatting.
type xlsxCellStyleXfs struct {
@@ -245,7 +245,7 @@ type xlsxCellXfs struct {
// to any formatting already present on the object using the dxf record.
type xlsxDxfs struct {
Count int `xml:"count,attr"`
- Dxfs []*xlsxDxf `xml:"dxf,omitempty"`
+ Dxfs []*xlsxDxf `xml:"dxf"`
}
// xlsxDxf directly maps the dxf element. A single dxf record, expressing
@@ -273,7 +273,7 @@ type xlsxTableStyles struct {
Count int `xml:"count,attr"`
DefaultPivotStyle string `xml:"defaultPivotStyle,attr"`
DefaultTableStyle string `xml:"defaultTableStyle,attr"`
- TableStyles []*xlsxTableStyle `xml:"tableStyle,omitempty"`
+ TableStyles []*xlsxTableStyle `xml:"tableStyle"`
}
// xlsxTableStyle directly maps the tableStyle element. This element represents
@@ -293,7 +293,7 @@ type xlsxTableStyle struct {
// to format and render the numeric value of a cell.
type xlsxNumFmts struct {
Count int `xml:"count,attr"`
- NumFmt []*xlsxNumFmt `xml:"numFmt,omitempty"`
+ NumFmt []*xlsxNumFmt `xml:"numFmt"`
}
// xlsxNumFmt directly maps the numFmt element. This element specifies number
diff --git a/vendor/github.com/xuri/excelize/v2/xmlTable.go b/vendor/github.com/xuri/excelize/v2/xmlTable.go
index cb343bd3..5a56a833 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlTable.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlTable.go
@@ -1,20 +1,20 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
import "encoding/xml"
// xlsxTable directly maps the table element. A table helps organize and provide
-// structure to lists of information in a worksheet. Tables have clearly labeled
+// structure to list of information in a worksheet. Tables have clearly labeled
// columns, rows, and data regions. Tables make it easier for users to sort,
// analyze, format, manage, add, and delete information. This element is the
// root element for a table that is not a single cell XML table.
diff --git a/vendor/github.com/xuri/excelize/v2/xmlTheme.go b/vendor/github.com/xuri/excelize/v2/xmlTheme.go
index ad557384..6b9e207c 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlTheme.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlTheme.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
diff --git a/vendor/github.com/xuri/excelize/v2/xmlWorkbook.go b/vendor/github.com/xuri/excelize/v2/xmlWorkbook.go
index 0e8839b3..a0fce15f 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlWorkbook.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlWorkbook.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -35,27 +35,29 @@ type xlsxRelationship struct {
// content of the workbook. The workbook's child elements each have their own
// subclause references.
type xlsxWorkbook struct {
- XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main workbook"`
- Conformance string `xml:"conformance,attr,omitempty"`
- FileVersion *xlsxFileVersion `xml:"fileVersion"`
- FileSharing *xlsxExtLst `xml:"fileSharing"`
- WorkbookPr *xlsxWorkbookPr `xml:"workbookPr"`
- WorkbookProtection *xlsxWorkbookProtection `xml:"workbookProtection"`
- BookViews *xlsxBookViews `xml:"bookViews"`
- Sheets xlsxSheets `xml:"sheets"`
- FunctionGroups *xlsxExtLst `xml:"functionGroups"`
- ExternalReferences *xlsxExternalReferences `xml:"externalReferences"`
- DefinedNames *xlsxDefinedNames `xml:"definedNames"`
- CalcPr *xlsxCalcPr `xml:"calcPr"`
- OleSize *xlsxExtLst `xml:"oleSize"`
- CustomWorkbookViews *xlsxCustomWorkbookViews `xml:"customWorkbookViews"`
- PivotCaches *xlsxPivotCaches `xml:"pivotCaches"`
- SmartTagPr *xlsxExtLst `xml:"smartTagPr"`
- SmartTagTypes *xlsxExtLst `xml:"smartTagTypes"`
- WebPublishing *xlsxExtLst `xml:"webPublishing"`
- FileRecoveryPr *xlsxFileRecoveryPr `xml:"fileRecoveryPr"`
- WebPublishObjects *xlsxExtLst `xml:"webPublishObjects"`
- ExtLst *xlsxExtLst `xml:"extLst"`
+ XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main workbook"`
+ Conformance string `xml:"conformance,attr,omitempty"`
+ FileVersion *xlsxFileVersion `xml:"fileVersion"`
+ FileSharing *xlsxExtLst `xml:"fileSharing"`
+ WorkbookPr *xlsxWorkbookPr `xml:"workbookPr"`
+ AlternateContent *xlsxAlternateContent `xml:"mc:AlternateContent"`
+ DecodeAlternateContent *xlsxInnerXML `xml:"http://schemas.openxmlformats.org/markup-compatibility/2006 AlternateContent"`
+ WorkbookProtection *xlsxWorkbookProtection `xml:"workbookProtection"`
+ BookViews *xlsxBookViews `xml:"bookViews"`
+ Sheets xlsxSheets `xml:"sheets"`
+ FunctionGroups *xlsxExtLst `xml:"functionGroups"`
+ ExternalReferences *xlsxExternalReferences `xml:"externalReferences"`
+ DefinedNames *xlsxDefinedNames `xml:"definedNames"`
+ CalcPr *xlsxCalcPr `xml:"calcPr"`
+ OleSize *xlsxExtLst `xml:"oleSize"`
+ CustomWorkbookViews *xlsxCustomWorkbookViews `xml:"customWorkbookViews"`
+ PivotCaches *xlsxPivotCaches `xml:"pivotCaches"`
+ SmartTagPr *xlsxExtLst `xml:"smartTagPr"`
+ SmartTagTypes *xlsxExtLst `xml:"smartTagTypes"`
+ WebPublishing *xlsxExtLst `xml:"webPublishing"`
+ FileRecoveryPr *xlsxFileRecoveryPr `xml:"fileRecoveryPr"`
+ WebPublishObjects *xlsxExtLst `xml:"webPublishObjects"`
+ ExtLst *xlsxExtLst `xml:"extLst"`
}
// xlsxFileRecoveryPr maps sheet recovery information. This element defines
@@ -107,24 +109,24 @@ type xlsxFileVersion struct {
// http://schemas.openxmlformats.org/spreadsheetml/2006/main This element
// defines a collection of workbook properties.
type xlsxWorkbookPr struct {
- AllowRefreshQuery bool `xml:"allowRefreshQuery,attr,omitempty"`
- AutoCompressPictures bool `xml:"autoCompressPictures,attr,omitempty"`
- BackupFile bool `xml:"backupFile,attr,omitempty"`
- CheckCompatibility bool `xml:"checkCompatibility,attr,omitempty"`
- CodeName string `xml:"codeName,attr,omitempty"`
Date1904 bool `xml:"date1904,attr,omitempty"`
- DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
+ ShowObjects string `xml:"showObjects,attr,omitempty"`
+ ShowBorderUnselectedTables *bool `xml:"showBorderUnselectedTables,attr"`
FilterPrivacy bool `xml:"filterPrivacy,attr,omitempty"`
- HidePivotFieldList bool `xml:"hidePivotFieldList,attr,omitempty"`
PromptedSolutions bool `xml:"promptedSolutions,attr,omitempty"`
+ ShowInkAnnotation *bool `xml:"showInkAnnotation,attr"`
+ BackupFile bool `xml:"backupFile,attr,omitempty"`
+ SaveExternalLinkValues *bool `xml:"saveExternalLinkValues,attr"`
+ UpdateLinks string `xml:"updateLinks,attr,omitempty"`
+ CodeName string `xml:"codeName,attr,omitempty"`
+ HidePivotFieldList bool `xml:"hidePivotFieldList,attr,omitempty"`
+ ShowPivotChartFilter bool `xml:"showPivotChartFilter,attr,omitempty"`
+ AllowRefreshQuery bool `xml:"allowRefreshQuery,attr,omitempty"`
PublishItems bool `xml:"publishItems,attr,omitempty"`
+ CheckCompatibility bool `xml:"checkCompatibility,attr,omitempty"`
+ AutoCompressPictures *bool `xml:"autoCompressPictures,attr"`
RefreshAllConnections bool `xml:"refreshAllConnections,attr,omitempty"`
- SaveExternalLinkValues bool `xml:"saveExternalLinkValues,attr,omitempty"`
- ShowBorderUnselectedTables bool `xml:"showBorderUnselectedTables,attr,omitempty"`
- ShowInkAnnotation bool `xml:"showInkAnnotation,attr,omitempty"`
- ShowObjects string `xml:"showObjects,attr,omitempty"`
- ShowPivotChartFilter bool `xml:"showPivotChartFilter,attr,omitempty"`
- UpdateLinks string `xml:"updateLinks,attr,omitempty"`
+ DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
}
// xlsxBookViews directly maps the bookViews element. This element specifies the
@@ -139,19 +141,19 @@ type xlsxBookViews struct {
// http://schemas.openxmlformats.org/spreadsheetml/2006/main This element
// specifies a single Workbook view.
type xlsxWorkBookView struct {
- ActiveTab int `xml:"activeTab,attr,omitempty"`
- AutoFilterDateGrouping bool `xml:"autoFilterDateGrouping,attr,omitempty"`
- FirstSheet int `xml:"firstSheet,attr,omitempty"`
- Minimized bool `xml:"minimized,attr,omitempty"`
- ShowHorizontalScroll bool `xml:"showHorizontalScroll,attr,omitempty"`
- ShowSheetTabs bool `xml:"showSheetTabs,attr,omitempty"`
- ShowVerticalScroll bool `xml:"showVerticalScroll,attr,omitempty"`
- TabRatio int `xml:"tabRatio,attr,omitempty"`
Visibility string `xml:"visibility,attr,omitempty"`
- WindowHeight int `xml:"windowHeight,attr,omitempty"`
- WindowWidth int `xml:"windowWidth,attr,omitempty"`
+ Minimized bool `xml:"minimized,attr,omitempty"`
+ ShowHorizontalScroll *bool `xml:"showHorizontalScroll,attr"`
+ ShowVerticalScroll *bool `xml:"showVerticalScroll,attr"`
+ ShowSheetTabs *bool `xml:"showSheetTabs,attr"`
XWindow string `xml:"xWindow,attr,omitempty"`
YWindow string `xml:"yWindow,attr,omitempty"`
+ WindowWidth int `xml:"windowWidth,attr,omitempty"`
+ WindowHeight int `xml:"windowHeight,attr,omitempty"`
+ TabRatio int `xml:"tabRatio,attr,omitempty"`
+ FirstSheet int `xml:"firstSheet,attr,omitempty"`
+ ActiveTab int `xml:"activeTab,attr,omitempty"`
+ AutoFilterDateGrouping *bool `xml:"autoFilterDateGrouping,attr"`
}
// xlsxSheets directly maps the sheets element from the namespace
diff --git a/vendor/github.com/xuri/excelize/v2/xmlWorksheet.go b/vendor/github.com/xuri/excelize/v2/xmlWorksheet.go
index 217f367d..eb855c53 100644
--- a/vendor/github.com/xuri/excelize/v2/xmlWorksheet.go
+++ b/vendor/github.com/xuri/excelize/v2/xmlWorksheet.go
@@ -1,13 +1,13 @@
-// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of
+// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
-// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX / XLSM / XLTM files. Supports reading and writing
-// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
-// complex components by high compatibility, and provided streaming API for
-// generating or reading data from a worksheet with huge amounts of data. This
-// library needs Go version 1.15 or later.
+// Package excelize providing a set of functions that allow you to write to and
+// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
+// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
+// Supports complex components by high compatibility, and provided streaming
+// API for generating or reading data from a worksheet with huge amounts of
+// data. This library needs Go version 1.15 or later.
package excelize
@@ -20,46 +20,48 @@ import (
// http://schemas.openxmlformats.org/spreadsheetml/2006/main.
type xlsxWorksheet struct {
sync.Mutex
- XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
- SheetPr *xlsxSheetPr `xml:"sheetPr"`
- Dimension *xlsxDimension `xml:"dimension"`
- SheetViews *xlsxSheetViews `xml:"sheetViews"`
- SheetFormatPr *xlsxSheetFormatPr `xml:"sheetFormatPr"`
- Cols *xlsxCols `xml:"cols"`
- SheetData xlsxSheetData `xml:"sheetData"`
- SheetCalcPr *xlsxInnerXML `xml:"sheetCalcPr"`
- SheetProtection *xlsxSheetProtection `xml:"sheetProtection"`
- ProtectedRanges *xlsxInnerXML `xml:"protectedRanges"`
- Scenarios *xlsxInnerXML `xml:"scenarios"`
- AutoFilter *xlsxAutoFilter `xml:"autoFilter"`
- SortState *xlsxSortState `xml:"sortState"`
- DataConsolidate *xlsxInnerXML `xml:"dataConsolidate"`
- CustomSheetViews *xlsxCustomSheetViews `xml:"customSheetViews"`
- MergeCells *xlsxMergeCells `xml:"mergeCells"`
- PhoneticPr *xlsxPhoneticPr `xml:"phoneticPr"`
- ConditionalFormatting []*xlsxConditionalFormatting `xml:"conditionalFormatting"`
- DataValidations *xlsxDataValidations `xml:"dataValidations"`
- Hyperlinks *xlsxHyperlinks `xml:"hyperlinks"`
- PrintOptions *xlsxPrintOptions `xml:"printOptions"`
- PageMargins *xlsxPageMargins `xml:"pageMargins"`
- PageSetUp *xlsxPageSetUp `xml:"pageSetup"`
- HeaderFooter *xlsxHeaderFooter `xml:"headerFooter"`
- RowBreaks *xlsxBreaks `xml:"rowBreaks"`
- ColBreaks *xlsxBreaks `xml:"colBreaks"`
- CustomProperties *xlsxInnerXML `xml:"customProperties"`
- CellWatches *xlsxInnerXML `xml:"cellWatches"`
- IgnoredErrors *xlsxInnerXML `xml:"ignoredErrors"`
- SmartTags *xlsxInnerXML `xml:"smartTags"`
- Drawing *xlsxDrawing `xml:"drawing"`
- LegacyDrawing *xlsxLegacyDrawing `xml:"legacyDrawing"`
- LegacyDrawingHF *xlsxLegacyDrawingHF `xml:"legacyDrawingHF"`
- DrawingHF *xlsxDrawingHF `xml:"drawingHF"`
- Picture *xlsxPicture `xml:"picture"`
- OleObjects *xlsxInnerXML `xml:"oleObjects"`
- Controls *xlsxInnerXML `xml:"controls"`
- WebPublishItems *xlsxInnerXML `xml:"webPublishItems"`
- TableParts *xlsxTableParts `xml:"tableParts"`
- ExtLst *xlsxExtLst `xml:"extLst"`
+ XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
+ SheetPr *xlsxSheetPr `xml:"sheetPr"`
+ Dimension *xlsxDimension `xml:"dimension"`
+ SheetViews *xlsxSheetViews `xml:"sheetViews"`
+ SheetFormatPr *xlsxSheetFormatPr `xml:"sheetFormatPr"`
+ Cols *xlsxCols `xml:"cols"`
+ SheetData xlsxSheetData `xml:"sheetData"`
+ SheetCalcPr *xlsxInnerXML `xml:"sheetCalcPr"`
+ SheetProtection *xlsxSheetProtection `xml:"sheetProtection"`
+ ProtectedRanges *xlsxInnerXML `xml:"protectedRanges"`
+ Scenarios *xlsxInnerXML `xml:"scenarios"`
+ AutoFilter *xlsxAutoFilter `xml:"autoFilter"`
+ SortState *xlsxSortState `xml:"sortState"`
+ DataConsolidate *xlsxInnerXML `xml:"dataConsolidate"`
+ CustomSheetViews *xlsxCustomSheetViews `xml:"customSheetViews"`
+ MergeCells *xlsxMergeCells `xml:"mergeCells"`
+ PhoneticPr *xlsxPhoneticPr `xml:"phoneticPr"`
+ ConditionalFormatting []*xlsxConditionalFormatting `xml:"conditionalFormatting"`
+ DataValidations *xlsxDataValidations `xml:"dataValidations"`
+ Hyperlinks *xlsxHyperlinks `xml:"hyperlinks"`
+ PrintOptions *xlsxPrintOptions `xml:"printOptions"`
+ PageMargins *xlsxPageMargins `xml:"pageMargins"`
+ PageSetUp *xlsxPageSetUp `xml:"pageSetup"`
+ HeaderFooter *xlsxHeaderFooter `xml:"headerFooter"`
+ RowBreaks *xlsxBreaks `xml:"rowBreaks"`
+ ColBreaks *xlsxBreaks `xml:"colBreaks"`
+ CustomProperties *xlsxInnerXML `xml:"customProperties"`
+ CellWatches *xlsxInnerXML `xml:"cellWatches"`
+ IgnoredErrors *xlsxInnerXML `xml:"ignoredErrors"`
+ SmartTags *xlsxInnerXML `xml:"smartTags"`
+ Drawing *xlsxDrawing `xml:"drawing"`
+ LegacyDrawing *xlsxLegacyDrawing `xml:"legacyDrawing"`
+ LegacyDrawingHF *xlsxLegacyDrawingHF `xml:"legacyDrawingHF"`
+ DrawingHF *xlsxDrawingHF `xml:"drawingHF"`
+ Picture *xlsxPicture `xml:"picture"`
+ OleObjects *xlsxInnerXML `xml:"oleObjects"`
+ Controls *xlsxInnerXML `xml:"controls"`
+ WebPublishItems *xlsxInnerXML `xml:"webPublishItems"`
+ AlternateContent *xlsxAlternateContent `xml:"mc:AlternateContent"`
+ TableParts *xlsxTableParts `xml:"tableParts"`
+ ExtLst *xlsxExtLst `xml:"extLst"`
+ DecodeAlternateContent *xlsxInnerXML `xml:"http://schemas.openxmlformats.org/markup-compatibility/2006 AlternateContent"`
}
// xlsxDrawing change r:id to rid in the namespace.
@@ -112,19 +114,19 @@ type xlsxPageSetUp struct {
Draft bool `xml:"draft,attr,omitempty"`
Errors string `xml:"errors,attr,omitempty"`
FirstPageNumber string `xml:"firstPageNumber,attr,omitempty"`
- FitToHeight int `xml:"fitToHeight,attr,omitempty"`
- FitToWidth int `xml:"fitToWidth,attr,omitempty"`
- HorizontalDPI int `xml:"horizontalDpi,attr,omitempty"`
+ FitToHeight *int `xml:"fitToHeight,attr"`
+ FitToWidth *int `xml:"fitToWidth,attr"`
+ HorizontalDPI string `xml:"horizontalDpi,attr,omitempty"`
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
Orientation string `xml:"orientation,attr,omitempty"`
PageOrder string `xml:"pageOrder,attr,omitempty"`
PaperHeight string `xml:"paperHeight,attr,omitempty"`
- PaperSize int `xml:"paperSize,attr,omitempty"`
+ PaperSize *int `xml:"paperSize,attr"`
PaperWidth string `xml:"paperWidth,attr,omitempty"`
Scale int `xml:"scale,attr,omitempty"`
UseFirstPageNumber bool `xml:"useFirstPageNumber,attr,omitempty"`
UsePrinterDefaults bool `xml:"usePrinterDefaults,attr,omitempty"`
- VerticalDPI int `xml:"verticalDpi,attr,omitempty"`
+ VerticalDPI string `xml:"verticalDpi,attr,omitempty"`
}
// xlsxPrintOptions directly maps the printOptions element in the namespace
@@ -191,6 +193,7 @@ type xlsxSheetView struct {
ShowZeros *bool `xml:"showZeros,attr,omitempty"`
RightToLeft bool `xml:"rightToLeft,attr,omitempty"`
TabSelected bool `xml:"tabSelected,attr,omitempty"`
+ ShowRuler *bool `xml:"showRuler,attr,omitempty"`
ShowWhiteSpace *bool `xml:"showWhiteSpace,attr"`
ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr,omitempty"`
DefaultGridColor *bool `xml:"defaultGridColor,attr"`
@@ -239,9 +242,9 @@ type xlsxSheetPr struct {
CodeName string `xml:"codeName,attr,omitempty"`
FilterMode bool `xml:"filterMode,attr,omitempty"`
EnableFormatConditionsCalculation *bool `xml:"enableFormatConditionsCalculation,attr"`
- TabColor *xlsxTabColor `xml:"tabColor,omitempty"`
- OutlinePr *xlsxOutlinePr `xml:"outlinePr,omitempty"`
- PageSetUpPr *xlsxPageSetUpPr `xml:"pageSetUpPr,omitempty"`
+ TabColor *xlsxTabColor `xml:"tabColor"`
+ OutlinePr *xlsxOutlinePr `xml:"outlinePr"`
+ PageSetUpPr *xlsxPageSetUpPr `xml:"pageSetUpPr"`
}
// xlsxOutlinePr maps to the outlinePr element. SummaryBelow allows you to
@@ -691,6 +694,16 @@ type xlsxLegacyDrawingHF struct {
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
}
+// xlsxAlternateContent is a container for a sequence of multiple
+// representations of a given piece of content. The program reading the file
+// should only process one of these, and the one chosen should be based on
+// which conditions match.
+type xlsxAlternateContent struct {
+ XMLNSMC string `xml:"xmlns:mc,attr,omitempty"`
+ Content string `xml:",innerxml"`
+}
+
+// xlsxInnerXML holds parts of XML content currently not unmarshal.
type xlsxInnerXML struct {
Content string `xml:",innerxml"`
}
@@ -838,6 +851,7 @@ type formatConditional struct {
// FormatSheetProtection directly maps the settings of worksheet protection.
type FormatSheetProtection struct {
+ AlgorithmName string
AutoFilter bool
DeleteColumns bool
DeleteRows bool
diff --git a/vendor/github.com/xuri/nfp/CODE_OF_CONDUCT.md b/vendor/github.com/xuri/nfp/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..572b5612
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [xuri.me](https://xuri.me). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct][version]
+
+[homepage]: https://www.contributor-covenant.org
+[version]: https://www.contributor-covenant.org/version/2/0/code_of_conduct
diff --git a/vendor/github.com/xuri/nfp/LICENSE b/vendor/github.com/xuri/nfp/LICENSE
new file mode 100644
index 00000000..e0749f94
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/LICENSE
@@ -0,0 +1,28 @@
+BSD 3-Clause License
+
+Copyright (c) 2022 Ri Xu All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of nfp nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/vendor/github.com/xuri/nfp/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/xuri/nfp/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..d2ac755e
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,45 @@
+# PR Details
+
+
+
+## Description
+
+
+
+## Related Issue
+
+
+
+
+
+
+## Motivation and Context
+
+
+
+## How Has This Been Tested
+
+
+
+
+
+## Types of changes
+
+
+
+- [ ] Docs change / refactoring / dependency upgrade
+- [ ] Bug fix (non-breaking change which fixes an issue)
+- [ ] New feature (non-breaking change which adds functionality)
+- [ ] Breaking change (fix or feature that would cause existing functionality to change)
+
+## Checklist
+
+
+
+
+- [ ] My code follows the code style of this project.
+- [ ] My change requires a change to the documentation.
+- [ ] I have updated the documentation accordingly.
+- [ ] I have read the **CONTRIBUTING** document.
+- [ ] I have added tests to cover my changes.
+- [ ] All new and existing tests passed.
diff --git a/vendor/github.com/xuri/nfp/README.md b/vendor/github.com/xuri/nfp/README.md
new file mode 100644
index 00000000..125758f9
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/README.md
@@ -0,0 +1,66 @@
+# NFP (Number Format Parser)
+
+[![Build Status](https://github.com/xuri/nfp/workflows/Go/badge.svg)](https://github.com/xuri/nfp/actions?workflow=Go)
+[![Code Coverage](https://codecov.io/gh/xuri/nfp/branch/main/graph/badge.svg)](https://codecov.io/gh/xuri/nfp)
+[![Go Report Card](https://goreportcard.com/badge/github.com/xuri/nfp)](https://goreportcard.com/report/github.com/xuri/nfp)
+[![go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/xuri/nfp)
+[![Licenses](https://img.shields.io/badge/license-bsd-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)
+
+Using NFP (Number Format Parser) you can get an Abstract Syntax Tree (AST) from Excel number format expression.
+
+## Installation
+
+```bash
+go get github.com/xuri/nfp
+```
+
+## Example
+
+```go
+package main
+
+import "github.com/xuri/nfp"
+
+func main() {
+ ps := nfp.NumberFormatParser()
+ tokens := ps.Parse("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)")
+ println(p.PrettyPrint())
+}
+```
+
+Get AST
+
+```text
+
+
+ #
+
+ ##
+ 0
+ .
+ 00
+
+
+ (
+ #
+ ,
+ ##
+ 0
+ .
+ 00
+ )
+
+
+ -
+ ??
+
+ @
+```
+
+## Contributing
+
+Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change.
+
+## Licenses
+
+This program is under the terms of the BSD 3-Clause License. See [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause).
diff --git a/vendor/github.com/xuri/nfp/SECURITY.md b/vendor/github.com/xuri/nfp/SECURITY.md
new file mode 100644
index 00000000..2221c893
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/SECURITY.md
@@ -0,0 +1,9 @@
+# Security Policy
+
+## Supported Versions
+
+We will dive into any security-related issue as long as your nfp version is still supported by us. When reporting an issue, include as much information as possible, but no need to fill fancy forms or answer tedious questions. Just tell us what you found, how to reproduce it, and any concerns you have about it. We will respond as soon as possible and follow up with any missing information.
+
+## Reporting a Vulnerability
+
+Please e-mail us directly at `xuri.me@gmail.com` or use the security issue template on GitHub. In general, public disclosure is made after the issue has been fully identified and a patch is ready to be released. A security issue gets the highest priority assigned and a reply regarding the vulnerability is given within a typical 24 hours. Thank you!
diff --git a/vendor/github.com/xuri/nfp/nfp.go b/vendor/github.com/xuri/nfp/nfp.go
new file mode 100644
index 00000000..94a399f3
--- /dev/null
+++ b/vendor/github.com/xuri/nfp/nfp.go
@@ -0,0 +1,800 @@
+// Copyright 2022 The nfp Authors. All rights reserved. Use of this source code
+// is governed by a BSD-style license that can be found in the LICENSE file.
+//
+// This package NFP (Number Format Parser) produce syntax trees for number
+// format expression. Excel Number format controls options such the number of
+// decimal digits, the currency sign, commas to separate thousands, and
+// display of negative numbers. The number format of an index applies wherever
+// that index is used, including row or column headers of a table, or graph
+// axis that uses that index.
+//
+// Implementation with Go language by Ri Xu: https://xuri.me
+
+package nfp
+
+import "strings"
+
+// Asterisk, At and other's constants are token definitions.
+const (
+ // Character constants
+ Asterisk = "*"
+ At = "@"
+ BackSlash = "\\"
+ BlockDelimiter = ";"
+ BracketClose = "]"
+ BracketOpen = "["
+ Colon = ":"
+ Comma = ","
+ Dash = "-"
+ Dollar = "$"
+ Dot = "."
+ Hash = "#"
+ ParenClose = ")"
+ ParenOpen = "("
+ Percent = "%"
+ Plus = "+"
+ Question = "?"
+ QuoteDouble = "\""
+ QuoteSingle = "'"
+ Slash = "/"
+ Underscore = "_"
+ Whitespace = " "
+ Zero = "0"
+ // DatesTimesCodeChars defined dates and times control codes in upper case
+ DatesTimesCodeChars = "EYMDHSG"
+ // NumCodeChars defined numeric code character
+ NumCodeChars = "0123456789"
+ // Token section types
+ TokenSectionNegative = "Negative"
+ TokenSectionPositive = "Positive"
+ TokenSectionText = "Text"
+ TokenSectionZero = "Zero"
+ // Token subtypes
+ TokenSubTypeCurrencyString = "CurrencyString"
+ TokenSubTypeLanguageInfo = "LanguageInfo"
+ TokenTypeColor = "Color"
+ // Token types
+ TokenTypeCondition = "Condition"
+ TokenTypeCurrencyLanguage = "CurrencyLanguage"
+ TokenTypeDateTimes = "DateTimes"
+ TokenTypeDecimalPoint = "DecimalPoint"
+ TokenTypeDenominator = "Denominator"
+ TokenTypeDigitalPlaceHolder = "DigitalPlaceHolder"
+ TokenTypeElapsedDateTimes = "ElapsedDateTimes"
+ TokenTypeExponential = "Exponential"
+ TokenTypeFraction = "Fraction"
+ TokenTypeGeneral = "General"
+ TokenTypeHashPlaceHolder = "HashPlaceHolder"
+ TokenTypeLiteral = "Literal"
+ TokenTypeOperand = "Operand"
+ TokenTypeOperator = "Operator"
+ TokenTypePercent = "Percent"
+ TokenTypeRepeatsChar = "RepeatsChar"
+ TokenTypeSwitchArgument = "SwitchArgument"
+ TokenTypeTextPlaceHolder = "TextPlaceHolder"
+ TokenTypeThousandsSeparator = "ThousandsSeparator"
+ TokenTypeUnknown = "Unknown"
+ TokenTypeZeroPlaceHolder = "ZeroPlaceHolder"
+)
+
+// ColorNames defined colors name used in for a section of the format, use the
+// name of one of the following eight colors in square brackets in the
+// section. The color code shall be the first item in the section.
+var ColorNames = []string{
+ "black",
+ "blue",
+ "cyan",
+ "green",
+ "magenta",
+ "red",
+ "white",
+ "yellow",
+}
+
+// GeneralFormattingSwitchArguments defined switch-arguments apply to fields
+// whose field result is a numeric value. If the result type of the field is
+// not numeric, then these switches have no effect.
+var GeneralFormattingSwitchArguments = []string{
+ "AIUEO",
+ "ALPHABETIC",
+ "alphabetic",
+ "Arabic",
+ "ARABICABJAD",
+ "ARABICALPHA",
+ "ArabicDash",
+ "BAHTTEXT",
+ "CardText",
+ "CHINESENUM1",
+ "CHINESENUM2",
+ "CHINESENUM3",
+ "CHOSUNG",
+ "CIRCLENUM",
+ "DBCHAR",
+ "DBNUM1",
+ "DBNUM2",
+ "DBNUM3",
+ "DBNUM4",
+ "DollarText",
+ "GANADA",
+ "GB1",
+ "GB2",
+ "GB3",
+ "GB4",
+ "HEBREW1",
+ "HEBREW2",
+ "Hex",
+ "HINDIARABIC",
+ "HINDICARDTEXT",
+ "HINDILETTER1",
+ "HINDILETTER2",
+ "IROHA",
+ "KANJINUM1",
+ "KANJINUM2",
+ "KANJINUM3",
+ "Ordinal",
+ "OrdText",
+ "Roman",
+ "roman",
+ "SBCHAR",
+ "THAIARABIC",
+ "THAICARDTEXT",
+ "THAILETTER",
+ "VIETCARDTEXT",
+ "ZODIAC1",
+ "ZODIAC2",
+ "ZODIAC3",
+}
+
+// AmPm defined the AM and PM with international considerations.
+var AmPm = []string{"AM/PM", "A/P", "上午/下午"}
+
+// ConditionOperators defined the condition operators.
+var ConditionOperators = []string{"<", "<=", ">", ">=", "<>", "="}
+
+// Part directly maps the sub part of the token.
+type Part struct {
+ Token Token
+ Value string
+}
+
+// Token encapsulate a number format token.
+type Token struct {
+ TValue string
+ TType string
+ Parts []Part
+}
+
+// Section directly maps sections of the number format. Up to four sections of
+// format codes can be specified. The format codes, separated by semicolons,
+// define the formats for positive numbers, negative numbers, zero values, and
+// text, in that order. If only two sections are specified, the first is used
+// for positive numbers and zeros, and the second is used for negative
+// numbers. If only one section is specified, it is used for all numbers. To
+// skip a section, the ending semicolon for that section shall be written.
+type Section struct {
+ Type string
+ Items []Token
+}
+
+// Tokens directly maps the ordered list of tokens.
+// Attributes:
+//
+// Index - Current position in the number format expression
+// SectionIndex - Current position in section
+// Sections - Ordered section of token sequences
+//
+type Tokens struct {
+ Index int
+ SectionIndex int
+ Sections []Section
+}
+
+// fTokens provides function to handle an ordered list of tokens.
+func fTokens() Tokens {
+ return Tokens{
+ Index: -1,
+ }
+}
+
+// fToken provides function to encapsulate a number format token.
+func fToken(value, tokenType string, parts []Part) Token {
+ return Token{
+ TValue: value,
+ TType: tokenType,
+ Parts: parts,
+ }
+}
+
+// add provides function to add a token to the end of the list.
+func (tk *Tokens) add(value, tokenType string, parts []Part) Token {
+ token := fToken(value, tokenType, parts)
+ tk.addRef(token)
+ return token
+}
+
+// addRef provides function to add a token to the end of the list.
+func (tk *Tokens) addRef(token Token) {
+ if len(tk.Sections) <= tk.SectionIndex {
+ sectionType := []string{TokenSectionPositive, TokenSectionNegative, TokenSectionZero, TokenSectionText}[tk.SectionIndex]
+ for i := len(tk.Sections) - 1; i < tk.SectionIndex; i++ {
+ tk.Sections = append(tk.Sections, Section{Type: sectionType})
+ }
+ }
+ tk.Sections[tk.SectionIndex].Items = append(tk.Sections[tk.SectionIndex].Items, token)
+}
+
+// reset provides function to reset the index to -1.
+func (tk *Tokens) reset() {
+ tk.Index = -1
+}
+
+// Parser inheritable container.
+type Parser struct {
+ InBracket bool
+ InString bool
+ InPlaceholder bool
+ NumFmt string
+ Offset int
+ Tokens Tokens
+ Token Token
+}
+
+// NumberFormatParser provides function to parse an Excel number format into a
+// stream of tokens.
+func NumberFormatParser() Parser {
+ return Parser{}
+}
+
+// EOF provides function to check whether end of tokens stack.
+func (ps *Parser) EOF() bool {
+ return ps.Offset >= len([]rune(ps.NumFmt))
+}
+
+// getTokens return a token stream (list).
+func (ps *Parser) getTokens() Tokens {
+ ps.NumFmt = strings.TrimSpace(ps.NumFmt)
+ // state-dependent character evaluation (order is important)
+ for !ps.EOF() {
+ if ps.InBracket {
+ if ps.Token.TType == TokenTypeCurrencyLanguage {
+ if ps.currentChar() != Dash && ps.currentChar() != BracketClose {
+ ps.Token.Parts[1].Token.TValue += ps.currentChar()
+ }
+ if ps.currentChar() == Dash {
+ ps.Token.Parts[0].Token.TValue, ps.Token.Parts[1].Token.TValue = ps.Token.Parts[1].Token.TValue, ps.Token.Parts[0].Token.TValue
+ }
+ }
+
+ if len(ps.Token.TValue) > 1 && inStrSlice(ConditionOperators, ps.Token.TValue[1:], true) != -1 {
+ if ps.currentChar() == Dash || strings.ContainsAny(NumCodeChars, ps.currentChar()) {
+ ps.Token.TType = TokenTypeCondition
+ ps.Token.Parts = []Part{
+ {Token: Token{TType: TokenTypeOperator, TValue: ps.Token.TValue[1:]}},
+ {Token: Token{TType: TokenTypeOperand}},
+ }
+ ps.Token.TValue = ""
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+ }
+
+ if ps.currentChar() == BracketClose {
+ ps.InBracket = false
+ if ps.Token.TType == TokenTypeCondition && len(ps.Token.Parts) == 2 {
+ ps.Token.Parts[1].Token.TValue = ps.Token.TValue
+ ps.Tokens.add(ps.Token.Parts[0].Token.TValue+ps.Token.Parts[1].Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ ps.Token.TValue += ps.currentChar()
+ if l := len(ps.Token.TValue); l > 2 {
+ lit := ps.Token.TValue[1 : l-1]
+
+ if idx := inStrSlice(ColorNames, lit, false); idx != -1 {
+ ps.Tokens.add(lit, TokenTypeColor, nil)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+
+ if idx := inStrSlice(GeneralFormattingSwitchArguments, lit, false); idx != -1 {
+ ps.Tokens.add(ps.Token.TValue, TokenTypeSwitchArgument, nil)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+
+ if ps.Token.TType == TokenTypeCurrencyLanguage {
+ if ps.Token.Parts[0].Token.TValue == "" {
+ ps.Token.Parts = []Part{{Token: Token{TType: ps.Token.Parts[1].Token.TType, TValue: ps.Token.Parts[1].Token.TValue}}}
+ }
+
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ ps.Token.TType, ps.Token.TValue = TokenTypeUnknown, lit
+ isDateTime := true
+ for _, ch := range lit {
+ if !strings.ContainsAny(DatesTimesCodeChars, strings.ToUpper(string(ch))) {
+ isDateTime = false
+ }
+ }
+ if isDateTime {
+ ps.Token.TType = TokenTypeElapsedDateTimes
+ }
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ }
+ }
+
+ if !ps.InBracket {
+ if strings.ContainsAny(NumCodeChars, ps.currentChar()) {
+ if ps.Token.TType == TokenTypeZeroPlaceHolder || ps.Token.TType == TokenTypeDenominator {
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+ if ps.Token.TType == TokenTypeFraction {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeDenominator, TValue: ps.currentChar()}
+ ps.Offset++
+ continue
+ }
+ if ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeZeroPlaceHolder
+ if ps.currentChar() != Zero {
+ ps.Token.TType = TokenTypeLiteral
+ }
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Hash {
+ if ps.Token.TType != TokenTypeHashPlaceHolder && ps.Token.TType != "" {
+ if ps.Token.TValue == Dot {
+ ps.Token.TType = TokenTypeDecimalPoint
+ }
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeHashPlaceHolder
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Dot {
+ if ps.Token.TType == TokenTypeZeroPlaceHolder || ps.Token.TType == TokenTypeHashPlaceHolder {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Tokens.add(ps.currentChar(), TokenTypeDecimalPoint, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ if !ps.InString {
+ if ps.Token.TType != "" && strings.ContainsAny(NumCodeChars, ps.nextChar()) {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeDecimalPoint
+ }
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+ }
+
+ if strings.ContainsAny(Dollar+Dash+Plus+ParenOpen+ParenClose+Colon+Whitespace, ps.currentChar()) {
+ if ps.InBracket {
+ if len(ps.Token.Parts) == 0 {
+ ps.Token.Parts = []Part{
+ {Token: Token{TType: TokenSubTypeCurrencyString}},
+ {Token: Token{TType: TokenSubTypeLanguageInfo}},
+ }
+ }
+ ps.Token.TValue += ps.currentChar()
+ ps.Token.TType = TokenTypeCurrencyLanguage
+ ps.Offset++
+ continue
+ }
+
+ if ps.Token.TType != TokenTypeLiteral && ps.Token.TType != TokenTypeDateTimes && ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeLiteral, TValue: ps.currentChar()}
+ ps.Offset++
+ continue
+ }
+
+ if ps.Token.TValue != BackSlash && ps.Token.TType == "" && inStrSlice(AmPm, ps.Token.TValue, false) == -1 {
+ ps.Token.TType = TokenTypeLiteral
+ }
+
+ if ps.Token.TType == TokenTypeLiteral {
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+ }
+
+ if ps.currentChar() == Underscore {
+ ps.Offset += 2
+ continue
+ }
+
+ if ps.currentChar() == Asterisk {
+ ps.Tokens.add(ps.nextChar(), TokenTypeRepeatsChar, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset += 2
+ continue
+ }
+
+ if ps.currentChar() == BackSlash {
+ if ps.Token.TValue != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Tokens.add(ps.nextChar(), TokenTypeLiteral, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset += 2
+ continue
+ }
+
+ if ps.currentChar() == Dash {
+ if ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ }
+ ps.Token.TType = TokenTypeLiteral
+ if ps.currentChar() != ps.nextChar() {
+ ps.Tokens.add(ps.currentChar(), ps.Token.TType, ps.Token.Parts)
+ }
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Comma {
+ if ps.Token.TType == TokenTypeZeroPlaceHolder || ps.Token.TType == TokenTypeHashPlaceHolder {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Tokens.add(ps.currentChar(), TokenTypeThousandsSeparator, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ if !ps.InString {
+ if ps.Token.TType == TokenTypeLiteral {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeThousandsSeparator}
+ }
+ if ps.Token.TType == TokenTypeDateTimes {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeLiteral}
+ }
+ if ps.currentChar() != ps.nextChar() {
+ if ps.Token.TType == "" {
+ ps.Token.TType = TokenTypeLiteral
+ }
+ ps.Tokens.add(ps.currentChar(), ps.Token.TType, ps.Token.Parts)
+ }
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ ps.Token.TType = TokenTypeLiteral
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Whitespace {
+ if inStrSlice(AmPm, ps.Token.TValue, false) != -1 {
+ ps.Token.TType = TokenTypeDateTimes
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ if ps.Token.TType != "" && ps.Token.TType != TokenTypeLiteral {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ }
+ ps.Token.TType = TokenTypeLiteral
+ ps.Tokens.add(ps.currentChar(), ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Slash {
+ if ps.Token.TType == TokenTypeDateTimes {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Tokens.add(ps.currentChar(), TokenTypeLiteral, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+ if ps.Token.TType == TokenTypeDigitalPlaceHolder {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeFraction, TValue: ps.currentChar()}
+ ps.Offset++
+ continue
+ }
+ }
+
+ if ps.currentChar() == Colon && ps.Token.TType == TokenTypeDateTimes {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Tokens.add(ps.currentChar(), TokenTypeLiteral, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == QuoteDouble {
+ ps.Offset++
+ if ps.InString && len(ps.Token.TValue) > 0 {
+ ps.Tokens.add(ps.Token.TValue, TokenTypeLiteral, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.InString = false
+ continue
+ }
+ if ps.Token.TValue != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ }
+ ps.InString = true
+ ps.Token = Token{TType: TokenTypeLiteral}
+ continue
+ }
+
+ if ps.currentChar() == At {
+ if len(ps.Tokens.Sections) <= ps.Tokens.SectionIndex {
+ ps.Tokens.Sections = append(ps.Tokens.Sections, Section{Type: TokenSectionText})
+ }
+ ps.Tokens.Sections[ps.Tokens.SectionIndex].Type = TokenSectionText
+ if ps.Token.TType != "" && !ps.InBracket {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ }
+ ps.Token = Token{TType: TokenTypeTextPlaceHolder, TValue: ps.currentChar()}
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == BracketOpen {
+ if ps.Token.TType != "" && !ps.InBracket {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.InBracket = true
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Question {
+ if ps.Token.TType != "" && ps.Token.TType != TokenTypeDigitalPlaceHolder {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeDigitalPlaceHolder
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == Percent {
+ if ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypePercent
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+
+ if ps.currentChar() == BlockDelimiter {
+ sectionTypes := []string{TokenSectionPositive, TokenSectionNegative, TokenSectionZero, TokenSectionText}
+ if ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ }
+ if len(ps.Tokens.Sections) <= ps.Tokens.SectionIndex {
+ ps.Tokens.Sections = append(ps.Tokens.Sections, Section{Type: sectionTypes[ps.Tokens.SectionIndex]})
+ }
+ ps.Tokens.SectionIndex++
+ if ps.Tokens.SectionIndex > 3 {
+ tokens := fTokens()
+ tokens.reset()
+ return Tokens{}
+ }
+ ps.Token = Token{}
+ ps.Tokens.Sections = append(ps.Tokens.Sections, Section{Type: sectionTypes[ps.Tokens.SectionIndex]})
+ ps.Offset++
+ continue
+ }
+
+ if strings.EqualFold("E+", ps.doubleChar()) {
+ if ps.Token.TType != "" {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeExponential
+ ps.Token.TValue += ps.doubleChar()
+ ps.Offset += 2
+ continue
+ }
+
+ if ap, matched := ps.apPattern(); ap != -1 {
+ ps.Tokens.add(matched, TokenTypeDateTimes, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset += len(matched)
+ continue
+ }
+
+ if general, matched := ps.generalPattern(); general != -1 {
+ ps.Tokens.add(matched, TokenTypeGeneral, ps.Token.Parts)
+ ps.Token = Token{}
+ ps.Offset += len(matched)
+ continue
+ }
+
+ // token accumulation
+ if !ps.InBracket && !ps.InString {
+ if strings.ContainsAny(DatesTimesCodeChars, strings.ToUpper(ps.currentChar())) {
+ if inStrSlice(AmPm, ps.Token.TValue, false) != -1 {
+ ps.Token.TType = TokenTypeDateTimes
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ if ps.Token.TType == TokenTypeLiteral || ps.Token.TType == TokenTypeDateTimes && !strings.ContainsAny(ps.Token.TValue, ps.currentChar()) {
+ ps.Tokens.add(ps.Token.TValue, ps.Token.TType, ps.Token.Parts)
+ ps.Token = Token{}
+ }
+ ps.Token.TType = TokenTypeDateTimes
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ continue
+ }
+ if strings.ContainsAny(DatesTimesCodeChars, strings.ToUpper(ps.Token.TValue)) {
+ ps.Tokens.add(ps.Token.TValue, TokenTypeDateTimes, ps.Token.Parts)
+ ps.Token = Token{TType: TokenTypeLiteral, TValue: ps.currentChar()}
+ ps.Offset++
+ continue
+ }
+ if strings.ContainsAny(DatesTimesCodeChars, strings.ToUpper(ps.nextChar())) {
+ ps.Token.TValue += ps.currentChar()
+ ps.Token.TType = TokenTypeLiteral
+ ps.Offset++
+ continue
+ }
+ if ps.currentChar() == QuoteSingle {
+ ps.Offset++
+ continue
+ }
+ }
+ ps.Token.TValue += ps.currentChar()
+ ps.Offset++
+ }
+
+ // dump remaining accumulation
+ if len(ps.Token.TValue) > 0 {
+ tokenType := TokenTypeLiteral
+ if ps.Token.TType != "" {
+ tokenType = ps.Token.TType
+ }
+ ps.Tokens.add(ps.Token.TValue, tokenType, nil)
+ }
+
+ tokens := fTokens()
+ tokens.reset()
+ return ps.Tokens
+}
+
+// Parse provides function to parse number format as a token stream (list).
+func (ps *Parser) Parse(numFmt string) []Section {
+ ps.NumFmt = numFmt
+ ps.Tokens = ps.getTokens()
+ return ps.Tokens.Sections
+}
+
+// doubleChar provides function to get two characters after the current
+// position.
+func (ps *Parser) doubleChar() string {
+ if len([]rune(ps.NumFmt)) >= ps.Offset+2 {
+ return string([]rune(ps.NumFmt)[ps.Offset : ps.Offset+2])
+ }
+ return ""
+}
+
+// currentChar provides function to get the character of the current position.
+func (ps *Parser) currentChar() string {
+ return string([]rune(ps.NumFmt)[ps.Offset])
+}
+
+// nextChar provides function to get the next character of the current
+// position.
+func (ps *Parser) nextChar() string {
+ if len([]rune(ps.NumFmt)) >= ps.Offset+2 {
+ return string([]rune(ps.NumFmt)[ps.Offset+1 : ps.Offset+2])
+ }
+ return ""
+}
+
+// apPattern infers whether the subsequent characters match the AM/PM pattern,
+// it will be returned matched index and result.
+func (ps *Parser) apPattern() (int, string) {
+ for i, pattern := range AmPm {
+ l := len(pattern)
+ if len([]rune(ps.NumFmt)) >= ps.Offset+l {
+ matched := string([]rune(ps.NumFmt)[ps.Offset : ps.Offset+l])
+ if strings.EqualFold(matched, pattern) {
+ return i, matched
+ }
+ }
+ }
+ return -1, ""
+}
+
+// generalPattern infers whether the subsequent characters match the
+// general pattern, it will be returned matched result and result.
+func (ps *Parser) generalPattern() (int, string) {
+ l := len(TokenTypeGeneral)
+ if len([]rune(ps.NumFmt)) >= ps.Offset+l {
+ matched := string([]rune(ps.NumFmt)[ps.Offset : ps.Offset+l])
+ if strings.EqualFold(matched, TokenTypeGeneral) {
+ return 0, matched
+ }
+ }
+ return -1, ""
+}
+
+// inStrSlice provides a method to check if an element is present in an array,
+// and return the index of its location, otherwise return -1.
+func inStrSlice(a []string, x string, caseSensitive bool) int {
+ for idx, n := range a {
+ if !caseSensitive && strings.EqualFold(x, n) {
+ return idx
+ }
+ if x == n {
+ return idx
+ }
+ }
+ return -1
+}
+
+// PrettyPrint provides function to pretty the parsed result with the indented
+// format.
+func (ps *Parser) PrettyPrint() string {
+ indent, output := 0, ""
+ for _, section := range ps.Tokens.Sections {
+ output += "<" + section.Type + ">" + "\n"
+ for _, item := range section.Items {
+ indent++
+ for i := 0; i < indent; i++ {
+ output += "\t"
+ }
+ if len(item.Parts) == 0 {
+ output += item.TValue + " <" + item.TType + ">" + "\n"
+ } else {
+ output += "<" + item.TType + ">" + "\n"
+ }
+ for _, part := range item.Parts {
+ indent++
+ for i := 0; i < indent; i++ {
+ output += "\t"
+ }
+ output += part.Token.TValue + " <" + part.Token.TType + ">" + "\n"
+ indent--
+ }
+ indent--
+ }
+ }
+ return output
+}
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go
index 71ad917d..a7828345 100644
--- a/vendor/golang.org/x/crypto/ed25519/ed25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -1,13 +1,7 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// In Go 1.13, the ed25519 package was promoted to the standard library as
-// crypto/ed25519, and this package became a wrapper for the standard library one.
-//
-//go:build !go1.13
-// +build !go1.13
-
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
@@ -16,21 +10,15 @@
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
+//
+// Beginning with Go 1.13, the functionality of this package was moved to the
+// standard library as crypto/ed25519. This package only acts as a compatibility
+// wrapper.
package ed25519
-// This code is a port of the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
-
import (
- "bytes"
- "crypto"
- cryptorand "crypto/rand"
- "crypto/sha512"
- "errors"
+ "crypto/ed25519"
"io"
- "strconv"
-
- "golang.org/x/crypto/ed25519/internal/edwards25519"
)
const (
@@ -45,57 +33,21 @@ const (
)
// PublicKey is the type of Ed25519 public keys.
-type PublicKey []byte
+//
+// This type is an alias for crypto/ed25519's PublicKey type.
+// See the crypto/ed25519 package for the methods on this type.
+type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
-type PrivateKey []byte
-
-// Public returns the PublicKey corresponding to priv.
-func (priv PrivateKey) Public() crypto.PublicKey {
- publicKey := make([]byte, PublicKeySize)
- copy(publicKey, priv[32:])
- return PublicKey(publicKey)
-}
-
-// Seed returns the private key seed corresponding to priv. It is provided for
-// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
-// in this package.
-func (priv PrivateKey) Seed() []byte {
- seed := make([]byte, SeedSize)
- copy(seed, priv[:32])
- return seed
-}
-
-// Sign signs the given message with priv.
-// Ed25519 performs two passes over messages to be signed and therefore cannot
-// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
-// indicate the message hasn't been hashed. This can be achieved by passing
-// crypto.Hash(0) as the value for opts.
-func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
- if opts.HashFunc() != crypto.Hash(0) {
- return nil, errors.New("ed25519: cannot sign hashed message")
- }
-
- return Sign(priv, message), nil
-}
+//
+// This type is an alias for crypto/ed25519's PrivateKey type.
+// See the crypto/ed25519 package for the methods on this type.
+type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
- if rand == nil {
- rand = cryptorand.Reader
- }
-
- seed := make([]byte, SeedSize)
- if _, err := io.ReadFull(rand, seed); err != nil {
- return nil, nil, err
- }
-
- privateKey := NewKeyFromSeed(seed)
- publicKey := make([]byte, PublicKeySize)
- copy(publicKey, privateKey[32:])
-
- return publicKey, privateKey, nil
+ return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
@@ -103,121 +55,17 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
- if l := len(seed); l != SeedSize {
- panic("ed25519: bad seed length: " + strconv.Itoa(l))
- }
-
- digest := sha512.Sum512(seed)
- digest[0] &= 248
- digest[31] &= 127
- digest[31] |= 64
-
- var A edwards25519.ExtendedGroupElement
- var hBytes [32]byte
- copy(hBytes[:], digest[:])
- edwards25519.GeScalarMultBase(&A, &hBytes)
- var publicKeyBytes [32]byte
- A.ToBytes(&publicKeyBytes)
-
- privateKey := make([]byte, PrivateKeySize)
- copy(privateKey, seed)
- copy(privateKey[32:], publicKeyBytes[:])
-
- return privateKey
+ return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
- if l := len(privateKey); l != PrivateKeySize {
- panic("ed25519: bad private key length: " + strconv.Itoa(l))
- }
-
- h := sha512.New()
- h.Write(privateKey[:32])
-
- var digest1, messageDigest, hramDigest [64]byte
- var expandedSecretKey [32]byte
- h.Sum(digest1[:0])
- copy(expandedSecretKey[:], digest1[:])
- expandedSecretKey[0] &= 248
- expandedSecretKey[31] &= 63
- expandedSecretKey[31] |= 64
-
- h.Reset()
- h.Write(digest1[32:])
- h.Write(message)
- h.Sum(messageDigest[:0])
-
- var messageDigestReduced [32]byte
- edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
- var R edwards25519.ExtendedGroupElement
- edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
-
- var encodedR [32]byte
- R.ToBytes(&encodedR)
-
- h.Reset()
- h.Write(encodedR[:])
- h.Write(privateKey[32:])
- h.Write(message)
- h.Sum(hramDigest[:0])
- var hramDigestReduced [32]byte
- edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
-
- var s [32]byte
- edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
-
- signature := make([]byte, SignatureSize)
- copy(signature[:], encodedR[:])
- copy(signature[32:], s[:])
-
- return signature
+ return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
- if l := len(publicKey); l != PublicKeySize {
- panic("ed25519: bad public key length: " + strconv.Itoa(l))
- }
-
- if len(sig) != SignatureSize || sig[63]&224 != 0 {
- return false
- }
-
- var A edwards25519.ExtendedGroupElement
- var publicKeyBytes [32]byte
- copy(publicKeyBytes[:], publicKey)
- if !A.FromBytes(&publicKeyBytes) {
- return false
- }
- edwards25519.FeNeg(&A.X, &A.X)
- edwards25519.FeNeg(&A.T, &A.T)
-
- h := sha512.New()
- h.Write(sig[:32])
- h.Write(publicKey[:])
- h.Write(message)
- var digest [64]byte
- h.Sum(digest[:0])
-
- var hReduced [32]byte
- edwards25519.ScReduce(&hReduced, &digest)
-
- var R edwards25519.ProjectiveGroupElement
- var s [32]byte
- copy(s[:], sig[32:])
-
- // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
- // the range [0, order) in order to prevent signature malleability.
- if !edwards25519.ScMinimal(&s) {
- return false
- }
-
- edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
-
- var checkR [32]byte
- R.ToBytes(&checkR)
- return bytes.Equal(sig[:32], checkR[:])
+ return ed25519.Verify(publicKey, message, sig)
}
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go b/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go
deleted file mode 100644
index b5974dc8..00000000
--- a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.13
-// +build go1.13
-
-// Package ed25519 implements the Ed25519 signature algorithm. See
-// https://ed25519.cr.yp.to/.
-//
-// These functions are also compatible with the “Ed25519” function defined in
-// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
-// representation includes a public key suffix to make multiple signing
-// operations with the same key more efficient. This package refers to the RFC
-// 8032 private key as the “seed”.
-//
-// Beginning with Go 1.13, the functionality of this package was moved to the
-// standard library as crypto/ed25519. This package only acts as a compatibility
-// wrapper.
-package ed25519
-
-import (
- "crypto/ed25519"
- "io"
-)
-
-const (
- // PublicKeySize is the size, in bytes, of public keys as used in this package.
- PublicKeySize = 32
- // PrivateKeySize is the size, in bytes, of private keys as used in this package.
- PrivateKeySize = 64
- // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
- SignatureSize = 64
- // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
- SeedSize = 32
-)
-
-// PublicKey is the type of Ed25519 public keys.
-//
-// This type is an alias for crypto/ed25519's PublicKey type.
-// See the crypto/ed25519 package for the methods on this type.
-type PublicKey = ed25519.PublicKey
-
-// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
-//
-// This type is an alias for crypto/ed25519's PrivateKey type.
-// See the crypto/ed25519 package for the methods on this type.
-type PrivateKey = ed25519.PrivateKey
-
-// GenerateKey generates a public/private key pair using entropy from rand.
-// If rand is nil, crypto/rand.Reader will be used.
-func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
- return ed25519.GenerateKey(rand)
-}
-
-// NewKeyFromSeed calculates a private key from a seed. It will panic if
-// len(seed) is not SeedSize. This function is provided for interoperability
-// with RFC 8032. RFC 8032's private keys correspond to seeds in this
-// package.
-func NewKeyFromSeed(seed []byte) PrivateKey {
- return ed25519.NewKeyFromSeed(seed)
-}
-
-// Sign signs the message with privateKey and returns a signature. It will
-// panic if len(privateKey) is not PrivateKeySize.
-func Sign(privateKey PrivateKey, message []byte) []byte {
- return ed25519.Sign(privateKey, message)
-}
-
-// Verify reports whether sig is a valid signature of message by publicKey. It
-// will panic if len(publicKey) is not PublicKeySize.
-func Verify(publicKey PublicKey, message, sig []byte) bool {
- return ed25519.Verify(publicKey, message, sig)
-}
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
deleted file mode 100644
index e39f086c..00000000
--- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
+++ /dev/null
@@ -1,1422 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package edwards25519
-
-// These values are from the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
-
-// d is a constant in the Edwards curve equation.
-var d = FieldElement{
- -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
-}
-
-// d2 is 2*d.
-var d2 = FieldElement{
- -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
-}
-
-// SqrtM1 is the square-root of -1 in the field.
-var SqrtM1 = FieldElement{
- -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482,
-}
-
-// A is a constant in the Montgomery-form of curve25519.
-var A = FieldElement{
- 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-}
-
-// bi contains precomputed multiples of the base-point. See the Ed25519 paper
-// for a discussion about how these values are used.
-var bi = [8]PreComputedGroupElement{
- {
- FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
- FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
- FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
- },
- {
- FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
- FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
- FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
- },
- {
- FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
- FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
- FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
- },
- {
- FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
- FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
- FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
- },
- {
- FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
- FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
- FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784},
- },
- {
- FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
- FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
- FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877},
- },
- {
- FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
- FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
- FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300},
- },
- {
- FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
- FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
- FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683},
- },
-}
-
-// base contains precomputed multiples of the base-point. See the Ed25519 paper
-// for a discussion about how these values are used.
-var base = [32][8]PreComputedGroupElement{
- {
- {
- FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
- FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
- FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
- },
- {
- FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
- FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
- FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697},
- },
- {
- FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
- FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
- FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
- },
- {
- FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
- FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
- FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325},
- },
- {
- FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
- FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
- FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
- },
- {
- FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
- FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
- FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652},
- },
- {
- FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
- FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
- FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
- },
- {
- FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
- FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
- FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425},
- },
- },
- {
- {
- FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
- FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
- FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660},
- },
- {
- FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
- FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
- FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950},
- },
- {
- FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
- FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
- FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628},
- },
- {
- FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
- FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
- FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653},
- },
- {
- FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
- FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
- FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372},
- },
- {
- FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
- FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
- FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953},
- },
- {
- FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
- FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
- FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876},
- },
- {
- FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
- FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
- FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038},
- },
- },
- {
- {
- FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
- FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
- FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664},
- },
- {
- FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
- FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
- FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222},
- },
- {
- FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
- FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
- FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092},
- },
- {
- FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
- FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
- FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553},
- },
- {
- FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
- FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
- FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033},
- },
- {
- FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
- FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
- FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890},
- },
- {
- FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
- FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
- FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891},
- },
- {
- FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
- FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
- FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606},
- },
- },
- {
- {
- FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
- FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
- FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341},
- },
- {
- FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
- FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
- FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655},
- },
- {
- FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
- FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
- FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099},
- },
- {
- FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
- FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
- FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930},
- },
- {
- FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
- FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
- FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066},
- },
- {
- FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
- FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
- FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383},
- },
- {
- FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
- FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
- FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948},
- },
- {
- FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
- FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
- FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629},
- },
- },
- {
- {
- FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
- FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
- FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919},
- },
- {
- FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
- FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
- FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771},
- },
- {
- FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
- FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
- FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409},
- },
- {
- FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
- FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
- FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420},
- },
- {
- FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
- FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
- FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384},
- },
- {
- FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
- FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
- FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708},
- },
- {
- FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
- FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
- FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387},
- },
- {
- FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
- FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
- FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665},
- },
- },
- {
- {
- FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
- FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
- FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628},
- },
- {
- FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
- FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
- FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822},
- },
- {
- FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
- FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
- FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508},
- },
- {
- FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
- FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
- FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158},
- },
- {
- FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
- FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
- FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664},
- },
- {
- FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
- FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
- FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070},
- },
- {
- FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
- FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
- FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083},
- },
- {
- FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
- FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
- FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396},
- },
- },
- {
- {
- FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
- FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
- FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294},
- },
- {
- FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
- FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
- FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195},
- },
- {
- FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
- FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
- FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762},
- },
- {
- FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
- FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
- FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605},
- },
- {
- FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
- FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
- FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482},
- },
- {
- FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
- FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
- FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170},
- },
- {
- FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
- FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
- FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392},
- },
- {
- FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
- FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
- FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958},
- },
- },
- {
- {
- FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
- FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
- FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692},
- },
- {
- FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
- FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
- FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001},
- },
- {
- FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
- FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
- FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762},
- },
- {
- FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
- FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
- FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035},
- },
- {
- FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
- FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
- FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812},
- },
- {
- FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
- FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
- FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158},
- },
- {
- FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
- FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
- FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857},
- },
- {
- FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
- FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
- FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483},
- },
- },
- {
- {
- FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
- FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
- FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751},
- },
- {
- FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
- FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
- FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230},
- },
- {
- FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
- FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
- FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968},
- },
- {
- FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
- FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
- FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304},
- },
- {
- FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
- FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
- FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566},
- },
- {
- FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
- FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
- FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943},
- },
- {
- FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
- FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
- FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971},
- },
- {
- FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
- FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
- FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883},
- },
- },
- {
- {
- FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
- FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
- FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849},
- },
- {
- FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
- FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
- FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335},
- },
- {
- FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
- FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
- FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735},
- },
- {
- FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
- FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
- FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336},
- },
- {
- FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
- FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
- FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388},
- },
- {
- FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
- FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
- FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462},
- },
- {
- FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
- FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
- FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797},
- },
- {
- FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
- FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
- FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688},
- },
- },
- {
- {
- FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
- FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
- FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707},
- },
- {
- FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
- FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
- FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044},
- },
- {
- FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
- FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
- FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197},
- },
- {
- FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
- FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
- FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878},
- },
- {
- FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
- FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
- FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730},
- },
- {
- FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
- FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
- FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715},
- },
- {
- FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
- FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
- FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865},
- },
- {
- FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
- FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
- FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348},
- },
- },
- {
- {
- FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
- FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
- FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086},
- },
- {
- FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
- FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
- FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233},
- },
- {
- FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
- FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
- FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435},
- },
- {
- FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
- FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
- FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563},
- },
- {
- FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
- FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
- FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030},
- },
- {
- FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
- FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
- FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844},
- },
- {
- FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
- FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
- FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760},
- },
- {
- FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
- FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
- FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112},
- },
- },
- {
- {
- FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
- FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
- FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289},
- },
- {
- FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
- FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
- FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226},
- },
- {
- FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
- FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
- FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811},
- },
- {
- FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
- FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
- FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121},
- },
- {
- FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
- FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
- FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400},
- },
- {
- FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
- FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
- FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045},
- },
- {
- FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
- FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
- FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079},
- },
- {
- FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
- FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
- FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836},
- },
- },
- {
- {
- FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
- FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
- FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065},
- },
- {
- FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
- FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
- FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101},
- },
- {
- FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
- FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
- FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966},
- },
- {
- FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
- FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
- FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689},
- },
- {
- FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
- FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
- FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982},
- },
- {
- FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
- FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
- FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265},
- },
- {
- FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
- FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
- FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798},
- },
- {
- FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
- FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
- FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927},
- },
- },
- {
- {
- FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
- FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
- FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862},
- },
- {
- FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
- FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
- FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020},
- },
- {
- FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
- FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
- FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795},
- },
- {
- FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
- FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
- FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531},
- },
- {
- FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
- FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
- FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431},
- },
- {
- FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
- FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
- FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320},
- },
- {
- FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
- FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
- FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878},
- },
- {
- FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
- FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
- FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585},
- },
- },
- {
- {
- FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
- FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
- FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661},
- },
- {
- FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
- FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
- FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525},
- },
- {
- FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
- FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
- FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988},
- },
- {
- FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
- FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
- FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697},
- },
- {
- FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
- FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
- FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656},
- },
- {
- FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
- FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
- FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203},
- },
- {
- FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
- FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
- FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084},
- },
- {
- FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
- FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
- FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667},
- },
- },
- {
- {
- FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
- FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
- FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255},
- },
- {
- FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
- FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
- FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333},
- },
- {
- FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
- FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
- FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409},
- },
- {
- FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
- FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
- FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363},
- },
- {
- FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
- FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
- FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940},
- },
- {
- FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
- FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
- FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290},
- },
- {
- FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
- FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
- FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236},
- },
- {
- FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
- FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
- FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347},
- },
- },
- {
- {
- FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
- FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
- FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906},
- },
- {
- FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
- FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
- FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926},
- },
- {
- FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
- FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
- FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286},
- },
- {
- FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
- FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
- FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896},
- },
- {
- FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
- FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
- FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437},
- },
- {
- FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
- FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
- FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193},
- },
- {
- FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
- FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
- FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961},
- },
- {
- FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
- FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
- FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362},
- },
- },
- {
- {
- FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
- FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
- FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063},
- },
- {
- FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
- FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
- FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369},
- },
- {
- FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
- FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
- FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906},
- },
- {
- FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
- FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
- FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962},
- },
- {
- FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
- FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
- FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404},
- },
- {
- FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
- FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
- FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804},
- },
- {
- FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
- FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
- FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849},
- },
- {
- FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
- FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
- FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319},
- },
- },
- {
- {
- FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
- FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
- FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084},
- },
- {
- FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
- FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
- FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920},
- },
- {
- FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
- FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
- FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397},
- },
- {
- FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
- FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
- FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165},
- },
- {
- FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
- FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
- FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861},
- },
- {
- FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
- FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
- FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870},
- },
- {
- FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
- FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
- FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168},
- },
- {
- FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
- FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
- FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598},
- },
- },
- {
- {
- FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
- FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
- FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479},
- },
- {
- FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
- FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
- FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719},
- },
- {
- FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
- FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
- FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132},
- },
- {
- FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
- FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
- FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670},
- },
- {
- FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
- FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
- FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317},
- },
- {
- FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
- FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
- FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078},
- },
- {
- FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
- FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
- FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654},
- },
- {
- FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
- FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
- FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579},
- },
- },
- {
- {
- FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
- FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
- FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743},
- },
- {
- FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
- FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
- FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155},
- },
- {
- FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
- FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
- FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943},
- },
- {
- FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
- FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
- FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406},
- },
- {
- FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
- FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
- FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693},
- },
- {
- FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
- FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
- FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410},
- },
- {
- FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
- FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
- FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710},
- },
- {
- FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
- FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
- FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895},
- },
- },
- {
- {
- FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
- FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
- FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880},
- },
- {
- FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
- FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
- FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899},
- },
- {
- FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
- FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
- FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080},
- },
- {
- FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
- FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
- FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133},
- },
- {
- FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
- FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
- FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197},
- },
- {
- FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
- FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
- FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755},
- },
- {
- FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
- FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
- FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171},
- },
- {
- FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
- FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
- FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270},
- },
- },
- {
- {
- FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
- FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
- FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562},
- },
- {
- FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
- FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
- FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269},
- },
- {
- FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
- FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
- FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461},
- },
- {
- FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
- FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
- FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218},
- },
- {
- FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
- FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
- FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037},
- },
- {
- FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
- FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
- FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841},
- },
- {
- FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
- FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
- FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040},
- },
- {
- FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
- FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
- FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814},
- },
- },
- {
- {
- FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
- FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
- FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646},
- },
- {
- FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
- FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
- FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453},
- },
- {
- FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
- FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
- FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921},
- },
- {
- FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
- FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
- FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072},
- },
- {
- FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
- FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
- FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943},
- },
- {
- FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
- FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
- FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494},
- },
- {
- FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
- FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
- FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915},
- },
- {
- FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
- FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
- FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224},
- },
- },
- {
- {
- FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
- FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
- FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101},
- },
- {
- FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
- FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
- FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930},
- },
- {
- FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
- FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
- FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404},
- },
- {
- FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
- FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
- FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525},
- },
- {
- FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
- FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
- FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865},
- },
- {
- FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
- FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
- FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138},
- },
- {
- FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
- FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
- FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941},
- },
- {
- FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
- FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
- FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819},
- },
- },
- {
- {
- FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
- FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
- FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075},
- },
- {
- FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
- FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
- FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817},
- },
- {
- FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
- FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
- FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278},
- },
- {
- FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
- FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
- FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480},
- },
- {
- FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
- FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
- FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525},
- },
- {
- FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
- FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
- FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892},
- },
- {
- FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
- FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
- FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140},
- },
- {
- FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
- FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
- FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127},
- },
- },
- {
- {
- FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
- FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
- FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160},
- },
- {
- FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
- FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
- FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478},
- },
- {
- FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
- FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
- FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248},
- },
- {
- FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
- FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
- FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184},
- },
- {
- FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
- FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
- FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948},
- },
- {
- FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
- FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
- FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416},
- },
- {
- FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
- FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
- FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659},
- },
- {
- FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
- FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
- FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329},
- },
- },
- {
- {
- FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
- FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
- FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948},
- },
- {
- FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
- FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
- FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517},
- },
- {
- FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
- FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
- FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589},
- },
- {
- FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
- FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
- FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930},
- },
- {
- FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
- FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
- FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876},
- },
- {
- FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
- FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
- FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112},
- },
- {
- FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
- FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
- FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221},
- },
- {
- FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
- FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
- FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310},
- },
- },
- {
- {
- FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
- FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
- FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008},
- },
- {
- FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
- FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
- FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066},
- },
- {
- FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
- FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
- FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053},
- },
- {
- FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
- FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
- FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095},
- },
- {
- FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
- FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
- FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424},
- },
- {
- FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
- FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
- FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079},
- },
- {
- FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
- FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
- FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576},
- },
- {
- FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
- FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
- FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099},
- },
- },
- {
- {
- FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
- FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
- FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242},
- },
- {
- FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
- FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
- FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373},
- },
- {
- FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
- FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
- FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657},
- },
- {
- FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
- FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
- FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014},
- },
- {
- FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
- FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
- FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718},
- },
- {
- FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
- FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
- FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444},
- },
- {
- FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
- FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
- FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799},
- },
- {
- FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
- FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
- FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032},
- },
- },
- {
- {
- FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
- FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
- FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062},
- },
- {
- FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
- FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
- FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240},
- },
- {
- FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
- FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
- FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103},
- },
- {
- FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
- FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
- FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016},
- },
- {
- FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
- FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
- FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141},
- },
- {
- FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
- FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
- FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376},
- },
- {
- FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
- FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
- FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577},
- },
- {
- FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
- FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
- FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476},
- },
- },
-}
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
deleted file mode 100644
index fd03c252..00000000
--- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
+++ /dev/null
@@ -1,1793 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package edwards25519
-
-import "encoding/binary"
-
-// This code is a port of the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
-
-// FieldElement represents an element of the field GF(2^255 - 19). An element
-// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
-// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
-// context.
-type FieldElement [10]int32
-
-var zero FieldElement
-
-func FeZero(fe *FieldElement) {
- copy(fe[:], zero[:])
-}
-
-func FeOne(fe *FieldElement) {
- FeZero(fe)
- fe[0] = 1
-}
-
-func FeAdd(dst, a, b *FieldElement) {
- dst[0] = a[0] + b[0]
- dst[1] = a[1] + b[1]
- dst[2] = a[2] + b[2]
- dst[3] = a[3] + b[3]
- dst[4] = a[4] + b[4]
- dst[5] = a[5] + b[5]
- dst[6] = a[6] + b[6]
- dst[7] = a[7] + b[7]
- dst[8] = a[8] + b[8]
- dst[9] = a[9] + b[9]
-}
-
-func FeSub(dst, a, b *FieldElement) {
- dst[0] = a[0] - b[0]
- dst[1] = a[1] - b[1]
- dst[2] = a[2] - b[2]
- dst[3] = a[3] - b[3]
- dst[4] = a[4] - b[4]
- dst[5] = a[5] - b[5]
- dst[6] = a[6] - b[6]
- dst[7] = a[7] - b[7]
- dst[8] = a[8] - b[8]
- dst[9] = a[9] - b[9]
-}
-
-func FeCopy(dst, src *FieldElement) {
- copy(dst[:], src[:])
-}
-
-// Replace (f,g) with (g,g) if b == 1;
-// replace (f,g) with (f,g) if b == 0.
-//
-// Preconditions: b in {0,1}.
-func FeCMove(f, g *FieldElement, b int32) {
- b = -b
- f[0] ^= b & (f[0] ^ g[0])
- f[1] ^= b & (f[1] ^ g[1])
- f[2] ^= b & (f[2] ^ g[2])
- f[3] ^= b & (f[3] ^ g[3])
- f[4] ^= b & (f[4] ^ g[4])
- f[5] ^= b & (f[5] ^ g[5])
- f[6] ^= b & (f[6] ^ g[6])
- f[7] ^= b & (f[7] ^ g[7])
- f[8] ^= b & (f[8] ^ g[8])
- f[9] ^= b & (f[9] ^ g[9])
-}
-
-func load3(in []byte) int64 {
- var r int64
- r = int64(in[0])
- r |= int64(in[1]) << 8
- r |= int64(in[2]) << 16
- return r
-}
-
-func load4(in []byte) int64 {
- var r int64
- r = int64(in[0])
- r |= int64(in[1]) << 8
- r |= int64(in[2]) << 16
- r |= int64(in[3]) << 24
- return r
-}
-
-func FeFromBytes(dst *FieldElement, src *[32]byte) {
- h0 := load4(src[:])
- h1 := load3(src[4:]) << 6
- h2 := load3(src[7:]) << 5
- h3 := load3(src[10:]) << 3
- h4 := load3(src[13:]) << 2
- h5 := load4(src[16:])
- h6 := load3(src[20:]) << 7
- h7 := load3(src[23:]) << 5
- h8 := load3(src[26:]) << 4
- h9 := (load3(src[29:]) & 8388607) << 2
-
- FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
-}
-
-// FeToBytes marshals h to s.
-// Preconditions:
-// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Write p=2^255-19; q=floor(h/p).
-// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
-//
-// Proof:
-// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
-// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
-//
-// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
-// Then 0> 25
- q = (h[0] + q) >> 26
- q = (h[1] + q) >> 25
- q = (h[2] + q) >> 26
- q = (h[3] + q) >> 25
- q = (h[4] + q) >> 26
- q = (h[5] + q) >> 25
- q = (h[6] + q) >> 26
- q = (h[7] + q) >> 25
- q = (h[8] + q) >> 26
- q = (h[9] + q) >> 25
-
- // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
- h[0] += 19 * q
- // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
-
- carry[0] = h[0] >> 26
- h[1] += carry[0]
- h[0] -= carry[0] << 26
- carry[1] = h[1] >> 25
- h[2] += carry[1]
- h[1] -= carry[1] << 25
- carry[2] = h[2] >> 26
- h[3] += carry[2]
- h[2] -= carry[2] << 26
- carry[3] = h[3] >> 25
- h[4] += carry[3]
- h[3] -= carry[3] << 25
- carry[4] = h[4] >> 26
- h[5] += carry[4]
- h[4] -= carry[4] << 26
- carry[5] = h[5] >> 25
- h[6] += carry[5]
- h[5] -= carry[5] << 25
- carry[6] = h[6] >> 26
- h[7] += carry[6]
- h[6] -= carry[6] << 26
- carry[7] = h[7] >> 25
- h[8] += carry[7]
- h[7] -= carry[7] << 25
- carry[8] = h[8] >> 26
- h[9] += carry[8]
- h[8] -= carry[8] << 26
- carry[9] = h[9] >> 25
- h[9] -= carry[9] << 25
- // h10 = carry9
-
- // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
- // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
- // evidently 2^255 h10-2^255 q = 0.
- // Goal: Output h[0]+...+2^230 h[9].
-
- s[0] = byte(h[0] >> 0)
- s[1] = byte(h[0] >> 8)
- s[2] = byte(h[0] >> 16)
- s[3] = byte((h[0] >> 24) | (h[1] << 2))
- s[4] = byte(h[1] >> 6)
- s[5] = byte(h[1] >> 14)
- s[6] = byte((h[1] >> 22) | (h[2] << 3))
- s[7] = byte(h[2] >> 5)
- s[8] = byte(h[2] >> 13)
- s[9] = byte((h[2] >> 21) | (h[3] << 5))
- s[10] = byte(h[3] >> 3)
- s[11] = byte(h[3] >> 11)
- s[12] = byte((h[3] >> 19) | (h[4] << 6))
- s[13] = byte(h[4] >> 2)
- s[14] = byte(h[4] >> 10)
- s[15] = byte(h[4] >> 18)
- s[16] = byte(h[5] >> 0)
- s[17] = byte(h[5] >> 8)
- s[18] = byte(h[5] >> 16)
- s[19] = byte((h[5] >> 24) | (h[6] << 1))
- s[20] = byte(h[6] >> 7)
- s[21] = byte(h[6] >> 15)
- s[22] = byte((h[6] >> 23) | (h[7] << 3))
- s[23] = byte(h[7] >> 5)
- s[24] = byte(h[7] >> 13)
- s[25] = byte((h[7] >> 21) | (h[8] << 4))
- s[26] = byte(h[8] >> 4)
- s[27] = byte(h[8] >> 12)
- s[28] = byte((h[8] >> 20) | (h[9] << 6))
- s[29] = byte(h[9] >> 2)
- s[30] = byte(h[9] >> 10)
- s[31] = byte(h[9] >> 18)
-}
-
-func FeIsNegative(f *FieldElement) byte {
- var s [32]byte
- FeToBytes(&s, f)
- return s[0] & 1
-}
-
-func FeIsNonZero(f *FieldElement) int32 {
- var s [32]byte
- FeToBytes(&s, f)
- var x uint8
- for _, b := range s {
- x |= b
- }
- x |= x >> 4
- x |= x >> 2
- x |= x >> 1
- return int32(x & 1)
-}
-
-// FeNeg sets h = -f
-//
-// Preconditions:
-// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Postconditions:
-// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func FeNeg(h, f *FieldElement) {
- h[0] = -f[0]
- h[1] = -f[1]
- h[2] = -f[2]
- h[3] = -f[3]
- h[4] = -f[4]
- h[5] = -f[5]
- h[6] = -f[6]
- h[7] = -f[7]
- h[8] = -f[8]
- h[9] = -f[9]
-}
-
-func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
- var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
-
- /*
- |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
- i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
- |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
- i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
- */
-
- c0 = (h0 + (1 << 25)) >> 26
- h1 += c0
- h0 -= c0 << 26
- c4 = (h4 + (1 << 25)) >> 26
- h5 += c4
- h4 -= c4 << 26
- /* |h0| <= 2^25 */
- /* |h4| <= 2^25 */
- /* |h1| <= 1.51*2^58 */
- /* |h5| <= 1.51*2^58 */
-
- c1 = (h1 + (1 << 24)) >> 25
- h2 += c1
- h1 -= c1 << 25
- c5 = (h5 + (1 << 24)) >> 25
- h6 += c5
- h5 -= c5 << 25
- /* |h1| <= 2^24; from now on fits into int32 */
- /* |h5| <= 2^24; from now on fits into int32 */
- /* |h2| <= 1.21*2^59 */
- /* |h6| <= 1.21*2^59 */
-
- c2 = (h2 + (1 << 25)) >> 26
- h3 += c2
- h2 -= c2 << 26
- c6 = (h6 + (1 << 25)) >> 26
- h7 += c6
- h6 -= c6 << 26
- /* |h2| <= 2^25; from now on fits into int32 unchanged */
- /* |h6| <= 2^25; from now on fits into int32 unchanged */
- /* |h3| <= 1.51*2^58 */
- /* |h7| <= 1.51*2^58 */
-
- c3 = (h3 + (1 << 24)) >> 25
- h4 += c3
- h3 -= c3 << 25
- c7 = (h7 + (1 << 24)) >> 25
- h8 += c7
- h7 -= c7 << 25
- /* |h3| <= 2^24; from now on fits into int32 unchanged */
- /* |h7| <= 2^24; from now on fits into int32 unchanged */
- /* |h4| <= 1.52*2^33 */
- /* |h8| <= 1.52*2^33 */
-
- c4 = (h4 + (1 << 25)) >> 26
- h5 += c4
- h4 -= c4 << 26
- c8 = (h8 + (1 << 25)) >> 26
- h9 += c8
- h8 -= c8 << 26
- /* |h4| <= 2^25; from now on fits into int32 unchanged */
- /* |h8| <= 2^25; from now on fits into int32 unchanged */
- /* |h5| <= 1.01*2^24 */
- /* |h9| <= 1.51*2^58 */
-
- c9 = (h9 + (1 << 24)) >> 25
- h0 += c9 * 19
- h9 -= c9 << 25
- /* |h9| <= 2^24; from now on fits into int32 unchanged */
- /* |h0| <= 1.8*2^37 */
-
- c0 = (h0 + (1 << 25)) >> 26
- h1 += c0
- h0 -= c0 << 26
- /* |h0| <= 2^25; from now on fits into int32 unchanged */
- /* |h1| <= 1.01*2^24 */
-
- h[0] = int32(h0)
- h[1] = int32(h1)
- h[2] = int32(h2)
- h[3] = int32(h3)
- h[4] = int32(h4)
- h[5] = int32(h5)
- h[6] = int32(h6)
- h[7] = int32(h7)
- h[8] = int32(h8)
- h[9] = int32(h9)
-}
-
-// FeMul calculates h = f * g
-// Can overlap h with f or g.
-//
-// Preconditions:
-// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Notes on implementation strategy:
-//
-// Using schoolbook multiplication.
-// Karatsuba would save a little in some cost models.
-//
-// Most multiplications by 2 and 19 are 32-bit precomputations;
-// cheaper than 64-bit postcomputations.
-//
-// There is one remaining multiplication by 19 in the carry chain;
-// one *19 precomputation can be merged into this,
-// but the resulting data flow is considerably less clean.
-//
-// There are 12 carries below.
-// 10 of them are 2-way parallelizable and vectorizable.
-// Can get away with 11 carries, but then data flow is much deeper.
-//
-// With tighter constraints on inputs, can squeeze carries into int32.
-func FeMul(h, f, g *FieldElement) {
- f0 := int64(f[0])
- f1 := int64(f[1])
- f2 := int64(f[2])
- f3 := int64(f[3])
- f4 := int64(f[4])
- f5 := int64(f[5])
- f6 := int64(f[6])
- f7 := int64(f[7])
- f8 := int64(f[8])
- f9 := int64(f[9])
-
- f1_2 := int64(2 * f[1])
- f3_2 := int64(2 * f[3])
- f5_2 := int64(2 * f[5])
- f7_2 := int64(2 * f[7])
- f9_2 := int64(2 * f[9])
-
- g0 := int64(g[0])
- g1 := int64(g[1])
- g2 := int64(g[2])
- g3 := int64(g[3])
- g4 := int64(g[4])
- g5 := int64(g[5])
- g6 := int64(g[6])
- g7 := int64(g[7])
- g8 := int64(g[8])
- g9 := int64(g[9])
-
- g1_19 := int64(19 * g[1]) /* 1.4*2^29 */
- g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */
- g3_19 := int64(19 * g[3])
- g4_19 := int64(19 * g[4])
- g5_19 := int64(19 * g[5])
- g6_19 := int64(19 * g[6])
- g7_19 := int64(19 * g[7])
- g8_19 := int64(19 * g[8])
- g9_19 := int64(19 * g[9])
-
- h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19
- h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19
- h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19
- h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19
- h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19
- h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19
- h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19
- h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19
- h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19
- h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0
-
- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
-}
-
-func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
- f0 := int64(f[0])
- f1 := int64(f[1])
- f2 := int64(f[2])
- f3 := int64(f[3])
- f4 := int64(f[4])
- f5 := int64(f[5])
- f6 := int64(f[6])
- f7 := int64(f[7])
- f8 := int64(f[8])
- f9 := int64(f[9])
- f0_2 := int64(2 * f[0])
- f1_2 := int64(2 * f[1])
- f2_2 := int64(2 * f[2])
- f3_2 := int64(2 * f[3])
- f4_2 := int64(2 * f[4])
- f5_2 := int64(2 * f[5])
- f6_2 := int64(2 * f[6])
- f7_2 := int64(2 * f[7])
- f5_38 := 38 * f5 // 1.31*2^30
- f6_19 := 19 * f6 // 1.31*2^30
- f7_38 := 38 * f7 // 1.31*2^30
- f8_19 := 19 * f8 // 1.31*2^30
- f9_38 := 38 * f9 // 1.31*2^30
-
- h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38
- h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19
- h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19
- h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38
- h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38
- h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19
- h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19
- h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38
- h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38
- h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5
-
- return
-}
-
-// FeSquare calculates h = f*f. Can overlap h with f.
-//
-// Preconditions:
-// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func FeSquare(h, f *FieldElement) {
- h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
-}
-
-// FeSquare2 sets h = 2 * f * f
-//
-// Can overlap h with f.
-//
-// Preconditions:
-// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-//
-// Postconditions:
-// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
-// See fe_mul.c for discussion of implementation strategy.
-func FeSquare2(h, f *FieldElement) {
- h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
-
- h0 += h0
- h1 += h1
- h2 += h2
- h3 += h3
- h4 += h4
- h5 += h5
- h6 += h6
- h7 += h7
- h8 += h8
- h9 += h9
-
- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
-}
-
-func FeInvert(out, z *FieldElement) {
- var t0, t1, t2, t3 FieldElement
- var i int
-
- FeSquare(&t0, z) // 2^1
- FeSquare(&t1, &t0) // 2^2
- for i = 1; i < 2; i++ { // 2^3
- FeSquare(&t1, &t1)
- }
- FeMul(&t1, z, &t1) // 2^3 + 2^0
- FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0
- FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1
- FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0
- FeSquare(&t2, &t1) // 5,4,3,2,1
- for i = 1; i < 5; i++ { // 9,8,7,6,5
- FeSquare(&t2, &t2)
- }
- FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
- FeSquare(&t2, &t1) // 10..1
- for i = 1; i < 10; i++ { // 19..10
- FeSquare(&t2, &t2)
- }
- FeMul(&t2, &t2, &t1) // 19..0
- FeSquare(&t3, &t2) // 20..1
- for i = 1; i < 20; i++ { // 39..20
- FeSquare(&t3, &t3)
- }
- FeMul(&t2, &t3, &t2) // 39..0
- FeSquare(&t2, &t2) // 40..1
- for i = 1; i < 10; i++ { // 49..10
- FeSquare(&t2, &t2)
- }
- FeMul(&t1, &t2, &t1) // 49..0
- FeSquare(&t2, &t1) // 50..1
- for i = 1; i < 50; i++ { // 99..50
- FeSquare(&t2, &t2)
- }
- FeMul(&t2, &t2, &t1) // 99..0
- FeSquare(&t3, &t2) // 100..1
- for i = 1; i < 100; i++ { // 199..100
- FeSquare(&t3, &t3)
- }
- FeMul(&t2, &t3, &t2) // 199..0
- FeSquare(&t2, &t2) // 200..1
- for i = 1; i < 50; i++ { // 249..50
- FeSquare(&t2, &t2)
- }
- FeMul(&t1, &t2, &t1) // 249..0
- FeSquare(&t1, &t1) // 250..1
- for i = 1; i < 5; i++ { // 254..5
- FeSquare(&t1, &t1)
- }
- FeMul(out, &t1, &t0) // 254..5,3,1,0
-}
-
-func fePow22523(out, z *FieldElement) {
- var t0, t1, t2 FieldElement
- var i int
-
- FeSquare(&t0, z)
- for i = 1; i < 1; i++ {
- FeSquare(&t0, &t0)
- }
- FeSquare(&t1, &t0)
- for i = 1; i < 2; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t1, z, &t1)
- FeMul(&t0, &t0, &t1)
- FeSquare(&t0, &t0)
- for i = 1; i < 1; i++ {
- FeSquare(&t0, &t0)
- }
- FeMul(&t0, &t1, &t0)
- FeSquare(&t1, &t0)
- for i = 1; i < 5; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t0, &t1, &t0)
- FeSquare(&t1, &t0)
- for i = 1; i < 10; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t1, &t1, &t0)
- FeSquare(&t2, &t1)
- for i = 1; i < 20; i++ {
- FeSquare(&t2, &t2)
- }
- FeMul(&t1, &t2, &t1)
- FeSquare(&t1, &t1)
- for i = 1; i < 10; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t0, &t1, &t0)
- FeSquare(&t1, &t0)
- for i = 1; i < 50; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t1, &t1, &t0)
- FeSquare(&t2, &t1)
- for i = 1; i < 100; i++ {
- FeSquare(&t2, &t2)
- }
- FeMul(&t1, &t2, &t1)
- FeSquare(&t1, &t1)
- for i = 1; i < 50; i++ {
- FeSquare(&t1, &t1)
- }
- FeMul(&t0, &t1, &t0)
- FeSquare(&t0, &t0)
- for i = 1; i < 2; i++ {
- FeSquare(&t0, &t0)
- }
- FeMul(out, &t0, z)
-}
-
-// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 *
-// y^2 where d = -121665/121666.
-//
-// Several representations are used:
-// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z
-// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
-// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
-// PreComputedGroupElement: (y+x,y-x,2dxy)
-
-type ProjectiveGroupElement struct {
- X, Y, Z FieldElement
-}
-
-type ExtendedGroupElement struct {
- X, Y, Z, T FieldElement
-}
-
-type CompletedGroupElement struct {
- X, Y, Z, T FieldElement
-}
-
-type PreComputedGroupElement struct {
- yPlusX, yMinusX, xy2d FieldElement
-}
-
-type CachedGroupElement struct {
- yPlusX, yMinusX, Z, T2d FieldElement
-}
-
-func (p *ProjectiveGroupElement) Zero() {
- FeZero(&p.X)
- FeOne(&p.Y)
- FeOne(&p.Z)
-}
-
-func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) {
- var t0 FieldElement
-
- FeSquare(&r.X, &p.X)
- FeSquare(&r.Z, &p.Y)
- FeSquare2(&r.T, &p.Z)
- FeAdd(&r.Y, &p.X, &p.Y)
- FeSquare(&t0, &r.Y)
- FeAdd(&r.Y, &r.Z, &r.X)
- FeSub(&r.Z, &r.Z, &r.X)
- FeSub(&r.X, &t0, &r.Y)
- FeSub(&r.T, &r.T, &r.Z)
-}
-
-func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) {
- var recip, x, y FieldElement
-
- FeInvert(&recip, &p.Z)
- FeMul(&x, &p.X, &recip)
- FeMul(&y, &p.Y, &recip)
- FeToBytes(s, &y)
- s[31] ^= FeIsNegative(&x) << 7
-}
-
-func (p *ExtendedGroupElement) Zero() {
- FeZero(&p.X)
- FeOne(&p.Y)
- FeOne(&p.Z)
- FeZero(&p.T)
-}
-
-func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) {
- var q ProjectiveGroupElement
- p.ToProjective(&q)
- q.Double(r)
-}
-
-func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) {
- FeAdd(&r.yPlusX, &p.Y, &p.X)
- FeSub(&r.yMinusX, &p.Y, &p.X)
- FeCopy(&r.Z, &p.Z)
- FeMul(&r.T2d, &p.T, &d2)
-}
-
-func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) {
- FeCopy(&r.X, &p.X)
- FeCopy(&r.Y, &p.Y)
- FeCopy(&r.Z, &p.Z)
-}
-
-func (p *ExtendedGroupElement) ToBytes(s *[32]byte) {
- var recip, x, y FieldElement
-
- FeInvert(&recip, &p.Z)
- FeMul(&x, &p.X, &recip)
- FeMul(&y, &p.Y, &recip)
- FeToBytes(s, &y)
- s[31] ^= FeIsNegative(&x) << 7
-}
-
-func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
- var u, v, v3, vxx, check FieldElement
-
- FeFromBytes(&p.Y, s)
- FeOne(&p.Z)
- FeSquare(&u, &p.Y)
- FeMul(&v, &u, &d)
- FeSub(&u, &u, &p.Z) // y = y^2-1
- FeAdd(&v, &v, &p.Z) // v = dy^2+1
-
- FeSquare(&v3, &v)
- FeMul(&v3, &v3, &v) // v3 = v^3
- FeSquare(&p.X, &v3)
- FeMul(&p.X, &p.X, &v)
- FeMul(&p.X, &p.X, &u) // x = uv^7
-
- fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8)
- FeMul(&p.X, &p.X, &v3)
- FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8)
-
- var tmpX, tmp2 [32]byte
-
- FeSquare(&vxx, &p.X)
- FeMul(&vxx, &vxx, &v)
- FeSub(&check, &vxx, &u) // vx^2-u
- if FeIsNonZero(&check) == 1 {
- FeAdd(&check, &vxx, &u) // vx^2+u
- if FeIsNonZero(&check) == 1 {
- return false
- }
- FeMul(&p.X, &p.X, &SqrtM1)
-
- FeToBytes(&tmpX, &p.X)
- for i, v := range tmpX {
- tmp2[31-i] = v
- }
- }
-
- if FeIsNegative(&p.X) != (s[31] >> 7) {
- FeNeg(&p.X, &p.X)
- }
-
- FeMul(&p.T, &p.X, &p.Y)
- return true
-}
-
-func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) {
- FeMul(&r.X, &p.X, &p.T)
- FeMul(&r.Y, &p.Y, &p.Z)
- FeMul(&r.Z, &p.Z, &p.T)
-}
-
-func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) {
- FeMul(&r.X, &p.X, &p.T)
- FeMul(&r.Y, &p.Y, &p.Z)
- FeMul(&r.Z, &p.Z, &p.T)
- FeMul(&r.T, &p.X, &p.Y)
-}
-
-func (p *PreComputedGroupElement) Zero() {
- FeOne(&p.yPlusX)
- FeOne(&p.yMinusX)
- FeZero(&p.xy2d)
-}
-
-func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
- var t0 FieldElement
-
- FeAdd(&r.X, &p.Y, &p.X)
- FeSub(&r.Y, &p.Y, &p.X)
- FeMul(&r.Z, &r.X, &q.yPlusX)
- FeMul(&r.Y, &r.Y, &q.yMinusX)
- FeMul(&r.T, &q.T2d, &p.T)
- FeMul(&r.X, &p.Z, &q.Z)
- FeAdd(&t0, &r.X, &r.X)
- FeSub(&r.X, &r.Z, &r.Y)
- FeAdd(&r.Y, &r.Z, &r.Y)
- FeAdd(&r.Z, &t0, &r.T)
- FeSub(&r.T, &t0, &r.T)
-}
-
-func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
- var t0 FieldElement
-
- FeAdd(&r.X, &p.Y, &p.X)
- FeSub(&r.Y, &p.Y, &p.X)
- FeMul(&r.Z, &r.X, &q.yMinusX)
- FeMul(&r.Y, &r.Y, &q.yPlusX)
- FeMul(&r.T, &q.T2d, &p.T)
- FeMul(&r.X, &p.Z, &q.Z)
- FeAdd(&t0, &r.X, &r.X)
- FeSub(&r.X, &r.Z, &r.Y)
- FeAdd(&r.Y, &r.Z, &r.Y)
- FeSub(&r.Z, &t0, &r.T)
- FeAdd(&r.T, &t0, &r.T)
-}
-
-func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
- var t0 FieldElement
-
- FeAdd(&r.X, &p.Y, &p.X)
- FeSub(&r.Y, &p.Y, &p.X)
- FeMul(&r.Z, &r.X, &q.yPlusX)
- FeMul(&r.Y, &r.Y, &q.yMinusX)
- FeMul(&r.T, &q.xy2d, &p.T)
- FeAdd(&t0, &p.Z, &p.Z)
- FeSub(&r.X, &r.Z, &r.Y)
- FeAdd(&r.Y, &r.Z, &r.Y)
- FeAdd(&r.Z, &t0, &r.T)
- FeSub(&r.T, &t0, &r.T)
-}
-
-func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
- var t0 FieldElement
-
- FeAdd(&r.X, &p.Y, &p.X)
- FeSub(&r.Y, &p.Y, &p.X)
- FeMul(&r.Z, &r.X, &q.yMinusX)
- FeMul(&r.Y, &r.Y, &q.yPlusX)
- FeMul(&r.T, &q.xy2d, &p.T)
- FeAdd(&t0, &p.Z, &p.Z)
- FeSub(&r.X, &r.Z, &r.Y)
- FeAdd(&r.Y, &r.Z, &r.Y)
- FeSub(&r.Z, &t0, &r.T)
- FeAdd(&r.T, &t0, &r.T)
-}
-
-func slide(r *[256]int8, a *[32]byte) {
- for i := range r {
- r[i] = int8(1 & (a[i>>3] >> uint(i&7)))
- }
-
- for i := range r {
- if r[i] != 0 {
- for b := 1; b <= 6 && i+b < 256; b++ {
- if r[i+b] != 0 {
- if r[i]+(r[i+b]<= -15 {
- r[i] -= r[i+b] << uint(b)
- for k := i + b; k < 256; k++ {
- if r[k] == 0 {
- r[k] = 1
- break
- }
- r[k] = 0
- }
- } else {
- break
- }
- }
- }
- }
- }
-}
-
-// GeDoubleScalarMultVartime sets r = a*A + b*B
-// where a = a[0]+256*a[1]+...+256^31 a[31].
-// and b = b[0]+256*b[1]+...+256^31 b[31].
-// B is the Ed25519 base point (x,4/5) with x positive.
-func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) {
- var aSlide, bSlide [256]int8
- var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
- var t CompletedGroupElement
- var u, A2 ExtendedGroupElement
- var i int
-
- slide(&aSlide, a)
- slide(&bSlide, b)
-
- A.ToCached(&Ai[0])
- A.Double(&t)
- t.ToExtended(&A2)
-
- for i := 0; i < 7; i++ {
- geAdd(&t, &A2, &Ai[i])
- t.ToExtended(&u)
- u.ToCached(&Ai[i+1])
- }
-
- r.Zero()
-
- for i = 255; i >= 0; i-- {
- if aSlide[i] != 0 || bSlide[i] != 0 {
- break
- }
- }
-
- for ; i >= 0; i-- {
- r.Double(&t)
-
- if aSlide[i] > 0 {
- t.ToExtended(&u)
- geAdd(&t, &u, &Ai[aSlide[i]/2])
- } else if aSlide[i] < 0 {
- t.ToExtended(&u)
- geSub(&t, &u, &Ai[(-aSlide[i])/2])
- }
-
- if bSlide[i] > 0 {
- t.ToExtended(&u)
- geMixedAdd(&t, &u, &bi[bSlide[i]/2])
- } else if bSlide[i] < 0 {
- t.ToExtended(&u)
- geMixedSub(&t, &u, &bi[(-bSlide[i])/2])
- }
-
- t.ToProjective(r)
- }
-}
-
-// equal returns 1 if b == c and 0 otherwise, assuming that b and c are
-// non-negative.
-func equal(b, c int32) int32 {
- x := uint32(b ^ c)
- x--
- return int32(x >> 31)
-}
-
-// negative returns 1 if b < 0 and 0 otherwise.
-func negative(b int32) int32 {
- return (b >> 31) & 1
-}
-
-func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) {
- FeCMove(&t.yPlusX, &u.yPlusX, b)
- FeCMove(&t.yMinusX, &u.yMinusX, b)
- FeCMove(&t.xy2d, &u.xy2d, b)
-}
-
-func selectPoint(t *PreComputedGroupElement, pos int32, b int32) {
- var minusT PreComputedGroupElement
- bNegative := negative(b)
- bAbs := b - (((-bNegative) & b) << 1)
-
- t.Zero()
- for i := int32(0); i < 8; i++ {
- PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1))
- }
- FeCopy(&minusT.yPlusX, &t.yMinusX)
- FeCopy(&minusT.yMinusX, &t.yPlusX)
- FeNeg(&minusT.xy2d, &t.xy2d)
- PreComputedGroupElementCMove(t, &minusT, bNegative)
-}
-
-// GeScalarMultBase computes h = a*B, where
-// a = a[0]+256*a[1]+...+256^31 a[31]
-// B is the Ed25519 base point (x,4/5) with x positive.
-//
-// Preconditions:
-// a[31] <= 127
-func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) {
- var e [64]int8
-
- for i, v := range a {
- e[2*i] = int8(v & 15)
- e[2*i+1] = int8((v >> 4) & 15)
- }
-
- // each e[i] is between 0 and 15 and e[63] is between 0 and 7.
-
- carry := int8(0)
- for i := 0; i < 63; i++ {
- e[i] += carry
- carry = (e[i] + 8) >> 4
- e[i] -= carry << 4
- }
- e[63] += carry
- // each e[i] is between -8 and 8.
-
- h.Zero()
- var t PreComputedGroupElement
- var r CompletedGroupElement
- for i := int32(1); i < 64; i += 2 {
- selectPoint(&t, i/2, int32(e[i]))
- geMixedAdd(&r, h, &t)
- r.ToExtended(h)
- }
-
- var s ProjectiveGroupElement
-
- h.Double(&r)
- r.ToProjective(&s)
- s.Double(&r)
- r.ToProjective(&s)
- s.Double(&r)
- r.ToProjective(&s)
- s.Double(&r)
- r.ToExtended(h)
-
- for i := int32(0); i < 64; i += 2 {
- selectPoint(&t, i/2, int32(e[i]))
- geMixedAdd(&r, h, &t)
- r.ToExtended(h)
- }
-}
-
-// The scalars are GF(2^252 + 27742317777372353535851937790883648493).
-
-// Input:
-// a[0]+256*a[1]+...+256^31*a[31] = a
-// b[0]+256*b[1]+...+256^31*b[31] = b
-// c[0]+256*c[1]+...+256^31*c[31] = c
-//
-// Output:
-// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
-// where l = 2^252 + 27742317777372353535851937790883648493.
-func ScMulAdd(s, a, b, c *[32]byte) {
- a0 := 2097151 & load3(a[:])
- a1 := 2097151 & (load4(a[2:]) >> 5)
- a2 := 2097151 & (load3(a[5:]) >> 2)
- a3 := 2097151 & (load4(a[7:]) >> 7)
- a4 := 2097151 & (load4(a[10:]) >> 4)
- a5 := 2097151 & (load3(a[13:]) >> 1)
- a6 := 2097151 & (load4(a[15:]) >> 6)
- a7 := 2097151 & (load3(a[18:]) >> 3)
- a8 := 2097151 & load3(a[21:])
- a9 := 2097151 & (load4(a[23:]) >> 5)
- a10 := 2097151 & (load3(a[26:]) >> 2)
- a11 := (load4(a[28:]) >> 7)
- b0 := 2097151 & load3(b[:])
- b1 := 2097151 & (load4(b[2:]) >> 5)
- b2 := 2097151 & (load3(b[5:]) >> 2)
- b3 := 2097151 & (load4(b[7:]) >> 7)
- b4 := 2097151 & (load4(b[10:]) >> 4)
- b5 := 2097151 & (load3(b[13:]) >> 1)
- b6 := 2097151 & (load4(b[15:]) >> 6)
- b7 := 2097151 & (load3(b[18:]) >> 3)
- b8 := 2097151 & load3(b[21:])
- b9 := 2097151 & (load4(b[23:]) >> 5)
- b10 := 2097151 & (load3(b[26:]) >> 2)
- b11 := (load4(b[28:]) >> 7)
- c0 := 2097151 & load3(c[:])
- c1 := 2097151 & (load4(c[2:]) >> 5)
- c2 := 2097151 & (load3(c[5:]) >> 2)
- c3 := 2097151 & (load4(c[7:]) >> 7)
- c4 := 2097151 & (load4(c[10:]) >> 4)
- c5 := 2097151 & (load3(c[13:]) >> 1)
- c6 := 2097151 & (load4(c[15:]) >> 6)
- c7 := 2097151 & (load3(c[18:]) >> 3)
- c8 := 2097151 & load3(c[21:])
- c9 := 2097151 & (load4(c[23:]) >> 5)
- c10 := 2097151 & (load3(c[26:]) >> 2)
- c11 := (load4(c[28:]) >> 7)
- var carry [23]int64
-
- s0 := c0 + a0*b0
- s1 := c1 + a0*b1 + a1*b0
- s2 := c2 + a0*b2 + a1*b1 + a2*b0
- s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
- s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
- s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
- s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
- s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
- s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
- s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
- s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
- s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
- s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
- s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
- s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
- s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
- s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
- s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
- s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
- s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
- s20 := a9*b11 + a10*b10 + a11*b9
- s21 := a10*b11 + a11*b10
- s22 := a11 * b11
- s23 := int64(0)
-
- carry[0] = (s0 + (1 << 20)) >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[2] = (s2 + (1 << 20)) >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[4] = (s4 + (1 << 20)) >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[6] = (s6 + (1 << 20)) >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[8] = (s8 + (1 << 20)) >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[10] = (s10 + (1 << 20)) >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
- carry[12] = (s12 + (1 << 20)) >> 21
- s13 += carry[12]
- s12 -= carry[12] << 21
- carry[14] = (s14 + (1 << 20)) >> 21
- s15 += carry[14]
- s14 -= carry[14] << 21
- carry[16] = (s16 + (1 << 20)) >> 21
- s17 += carry[16]
- s16 -= carry[16] << 21
- carry[18] = (s18 + (1 << 20)) >> 21
- s19 += carry[18]
- s18 -= carry[18] << 21
- carry[20] = (s20 + (1 << 20)) >> 21
- s21 += carry[20]
- s20 -= carry[20] << 21
- carry[22] = (s22 + (1 << 20)) >> 21
- s23 += carry[22]
- s22 -= carry[22] << 21
-
- carry[1] = (s1 + (1 << 20)) >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[3] = (s3 + (1 << 20)) >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[5] = (s5 + (1 << 20)) >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[7] = (s7 + (1 << 20)) >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[9] = (s9 + (1 << 20)) >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[11] = (s11 + (1 << 20)) >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
- carry[13] = (s13 + (1 << 20)) >> 21
- s14 += carry[13]
- s13 -= carry[13] << 21
- carry[15] = (s15 + (1 << 20)) >> 21
- s16 += carry[15]
- s15 -= carry[15] << 21
- carry[17] = (s17 + (1 << 20)) >> 21
- s18 += carry[17]
- s17 -= carry[17] << 21
- carry[19] = (s19 + (1 << 20)) >> 21
- s20 += carry[19]
- s19 -= carry[19] << 21
- carry[21] = (s21 + (1 << 20)) >> 21
- s22 += carry[21]
- s21 -= carry[21] << 21
-
- s11 += s23 * 666643
- s12 += s23 * 470296
- s13 += s23 * 654183
- s14 -= s23 * 997805
- s15 += s23 * 136657
- s16 -= s23 * 683901
- s23 = 0
-
- s10 += s22 * 666643
- s11 += s22 * 470296
- s12 += s22 * 654183
- s13 -= s22 * 997805
- s14 += s22 * 136657
- s15 -= s22 * 683901
- s22 = 0
-
- s9 += s21 * 666643
- s10 += s21 * 470296
- s11 += s21 * 654183
- s12 -= s21 * 997805
- s13 += s21 * 136657
- s14 -= s21 * 683901
- s21 = 0
-
- s8 += s20 * 666643
- s9 += s20 * 470296
- s10 += s20 * 654183
- s11 -= s20 * 997805
- s12 += s20 * 136657
- s13 -= s20 * 683901
- s20 = 0
-
- s7 += s19 * 666643
- s8 += s19 * 470296
- s9 += s19 * 654183
- s10 -= s19 * 997805
- s11 += s19 * 136657
- s12 -= s19 * 683901
- s19 = 0
-
- s6 += s18 * 666643
- s7 += s18 * 470296
- s8 += s18 * 654183
- s9 -= s18 * 997805
- s10 += s18 * 136657
- s11 -= s18 * 683901
- s18 = 0
-
- carry[6] = (s6 + (1 << 20)) >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[8] = (s8 + (1 << 20)) >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[10] = (s10 + (1 << 20)) >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
- carry[12] = (s12 + (1 << 20)) >> 21
- s13 += carry[12]
- s12 -= carry[12] << 21
- carry[14] = (s14 + (1 << 20)) >> 21
- s15 += carry[14]
- s14 -= carry[14] << 21
- carry[16] = (s16 + (1 << 20)) >> 21
- s17 += carry[16]
- s16 -= carry[16] << 21
-
- carry[7] = (s7 + (1 << 20)) >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[9] = (s9 + (1 << 20)) >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[11] = (s11 + (1 << 20)) >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
- carry[13] = (s13 + (1 << 20)) >> 21
- s14 += carry[13]
- s13 -= carry[13] << 21
- carry[15] = (s15 + (1 << 20)) >> 21
- s16 += carry[15]
- s15 -= carry[15] << 21
-
- s5 += s17 * 666643
- s6 += s17 * 470296
- s7 += s17 * 654183
- s8 -= s17 * 997805
- s9 += s17 * 136657
- s10 -= s17 * 683901
- s17 = 0
-
- s4 += s16 * 666643
- s5 += s16 * 470296
- s6 += s16 * 654183
- s7 -= s16 * 997805
- s8 += s16 * 136657
- s9 -= s16 * 683901
- s16 = 0
-
- s3 += s15 * 666643
- s4 += s15 * 470296
- s5 += s15 * 654183
- s6 -= s15 * 997805
- s7 += s15 * 136657
- s8 -= s15 * 683901
- s15 = 0
-
- s2 += s14 * 666643
- s3 += s14 * 470296
- s4 += s14 * 654183
- s5 -= s14 * 997805
- s6 += s14 * 136657
- s7 -= s14 * 683901
- s14 = 0
-
- s1 += s13 * 666643
- s2 += s13 * 470296
- s3 += s13 * 654183
- s4 -= s13 * 997805
- s5 += s13 * 136657
- s6 -= s13 * 683901
- s13 = 0
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = (s0 + (1 << 20)) >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[2] = (s2 + (1 << 20)) >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[4] = (s4 + (1 << 20)) >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[6] = (s6 + (1 << 20)) >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[8] = (s8 + (1 << 20)) >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[10] = (s10 + (1 << 20)) >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
-
- carry[1] = (s1 + (1 << 20)) >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[3] = (s3 + (1 << 20)) >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[5] = (s5 + (1 << 20)) >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[7] = (s7 + (1 << 20)) >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[9] = (s9 + (1 << 20)) >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[11] = (s11 + (1 << 20)) >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = s0 >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[1] = s1 >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[2] = s2 >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[3] = s3 >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[4] = s4 >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[5] = s5 >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[6] = s6 >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[7] = s7 >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[8] = s8 >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[9] = s9 >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[10] = s10 >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
- carry[11] = s11 >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = s0 >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[1] = s1 >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[2] = s2 >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[3] = s3 >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[4] = s4 >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[5] = s5 >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[6] = s6 >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[7] = s7 >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[8] = s8 >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[9] = s9 >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[10] = s10 >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
-
- s[0] = byte(s0 >> 0)
- s[1] = byte(s0 >> 8)
- s[2] = byte((s0 >> 16) | (s1 << 5))
- s[3] = byte(s1 >> 3)
- s[4] = byte(s1 >> 11)
- s[5] = byte((s1 >> 19) | (s2 << 2))
- s[6] = byte(s2 >> 6)
- s[7] = byte((s2 >> 14) | (s3 << 7))
- s[8] = byte(s3 >> 1)
- s[9] = byte(s3 >> 9)
- s[10] = byte((s3 >> 17) | (s4 << 4))
- s[11] = byte(s4 >> 4)
- s[12] = byte(s4 >> 12)
- s[13] = byte((s4 >> 20) | (s5 << 1))
- s[14] = byte(s5 >> 7)
- s[15] = byte((s5 >> 15) | (s6 << 6))
- s[16] = byte(s6 >> 2)
- s[17] = byte(s6 >> 10)
- s[18] = byte((s6 >> 18) | (s7 << 3))
- s[19] = byte(s7 >> 5)
- s[20] = byte(s7 >> 13)
- s[21] = byte(s8 >> 0)
- s[22] = byte(s8 >> 8)
- s[23] = byte((s8 >> 16) | (s9 << 5))
- s[24] = byte(s9 >> 3)
- s[25] = byte(s9 >> 11)
- s[26] = byte((s9 >> 19) | (s10 << 2))
- s[27] = byte(s10 >> 6)
- s[28] = byte((s10 >> 14) | (s11 << 7))
- s[29] = byte(s11 >> 1)
- s[30] = byte(s11 >> 9)
- s[31] = byte(s11 >> 17)
-}
-
-// Input:
-// s[0]+256*s[1]+...+256^63*s[63] = s
-//
-// Output:
-// s[0]+256*s[1]+...+256^31*s[31] = s mod l
-// where l = 2^252 + 27742317777372353535851937790883648493.
-func ScReduce(out *[32]byte, s *[64]byte) {
- s0 := 2097151 & load3(s[:])
- s1 := 2097151 & (load4(s[2:]) >> 5)
- s2 := 2097151 & (load3(s[5:]) >> 2)
- s3 := 2097151 & (load4(s[7:]) >> 7)
- s4 := 2097151 & (load4(s[10:]) >> 4)
- s5 := 2097151 & (load3(s[13:]) >> 1)
- s6 := 2097151 & (load4(s[15:]) >> 6)
- s7 := 2097151 & (load3(s[18:]) >> 3)
- s8 := 2097151 & load3(s[21:])
- s9 := 2097151 & (load4(s[23:]) >> 5)
- s10 := 2097151 & (load3(s[26:]) >> 2)
- s11 := 2097151 & (load4(s[28:]) >> 7)
- s12 := 2097151 & (load4(s[31:]) >> 4)
- s13 := 2097151 & (load3(s[34:]) >> 1)
- s14 := 2097151 & (load4(s[36:]) >> 6)
- s15 := 2097151 & (load3(s[39:]) >> 3)
- s16 := 2097151 & load3(s[42:])
- s17 := 2097151 & (load4(s[44:]) >> 5)
- s18 := 2097151 & (load3(s[47:]) >> 2)
- s19 := 2097151 & (load4(s[49:]) >> 7)
- s20 := 2097151 & (load4(s[52:]) >> 4)
- s21 := 2097151 & (load3(s[55:]) >> 1)
- s22 := 2097151 & (load4(s[57:]) >> 6)
- s23 := (load4(s[60:]) >> 3)
-
- s11 += s23 * 666643
- s12 += s23 * 470296
- s13 += s23 * 654183
- s14 -= s23 * 997805
- s15 += s23 * 136657
- s16 -= s23 * 683901
- s23 = 0
-
- s10 += s22 * 666643
- s11 += s22 * 470296
- s12 += s22 * 654183
- s13 -= s22 * 997805
- s14 += s22 * 136657
- s15 -= s22 * 683901
- s22 = 0
-
- s9 += s21 * 666643
- s10 += s21 * 470296
- s11 += s21 * 654183
- s12 -= s21 * 997805
- s13 += s21 * 136657
- s14 -= s21 * 683901
- s21 = 0
-
- s8 += s20 * 666643
- s9 += s20 * 470296
- s10 += s20 * 654183
- s11 -= s20 * 997805
- s12 += s20 * 136657
- s13 -= s20 * 683901
- s20 = 0
-
- s7 += s19 * 666643
- s8 += s19 * 470296
- s9 += s19 * 654183
- s10 -= s19 * 997805
- s11 += s19 * 136657
- s12 -= s19 * 683901
- s19 = 0
-
- s6 += s18 * 666643
- s7 += s18 * 470296
- s8 += s18 * 654183
- s9 -= s18 * 997805
- s10 += s18 * 136657
- s11 -= s18 * 683901
- s18 = 0
-
- var carry [17]int64
-
- carry[6] = (s6 + (1 << 20)) >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[8] = (s8 + (1 << 20)) >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[10] = (s10 + (1 << 20)) >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
- carry[12] = (s12 + (1 << 20)) >> 21
- s13 += carry[12]
- s12 -= carry[12] << 21
- carry[14] = (s14 + (1 << 20)) >> 21
- s15 += carry[14]
- s14 -= carry[14] << 21
- carry[16] = (s16 + (1 << 20)) >> 21
- s17 += carry[16]
- s16 -= carry[16] << 21
-
- carry[7] = (s7 + (1 << 20)) >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[9] = (s9 + (1 << 20)) >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[11] = (s11 + (1 << 20)) >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
- carry[13] = (s13 + (1 << 20)) >> 21
- s14 += carry[13]
- s13 -= carry[13] << 21
- carry[15] = (s15 + (1 << 20)) >> 21
- s16 += carry[15]
- s15 -= carry[15] << 21
-
- s5 += s17 * 666643
- s6 += s17 * 470296
- s7 += s17 * 654183
- s8 -= s17 * 997805
- s9 += s17 * 136657
- s10 -= s17 * 683901
- s17 = 0
-
- s4 += s16 * 666643
- s5 += s16 * 470296
- s6 += s16 * 654183
- s7 -= s16 * 997805
- s8 += s16 * 136657
- s9 -= s16 * 683901
- s16 = 0
-
- s3 += s15 * 666643
- s4 += s15 * 470296
- s5 += s15 * 654183
- s6 -= s15 * 997805
- s7 += s15 * 136657
- s8 -= s15 * 683901
- s15 = 0
-
- s2 += s14 * 666643
- s3 += s14 * 470296
- s4 += s14 * 654183
- s5 -= s14 * 997805
- s6 += s14 * 136657
- s7 -= s14 * 683901
- s14 = 0
-
- s1 += s13 * 666643
- s2 += s13 * 470296
- s3 += s13 * 654183
- s4 -= s13 * 997805
- s5 += s13 * 136657
- s6 -= s13 * 683901
- s13 = 0
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = (s0 + (1 << 20)) >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[2] = (s2 + (1 << 20)) >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[4] = (s4 + (1 << 20)) >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[6] = (s6 + (1 << 20)) >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[8] = (s8 + (1 << 20)) >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[10] = (s10 + (1 << 20)) >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
-
- carry[1] = (s1 + (1 << 20)) >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[3] = (s3 + (1 << 20)) >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[5] = (s5 + (1 << 20)) >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[7] = (s7 + (1 << 20)) >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[9] = (s9 + (1 << 20)) >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[11] = (s11 + (1 << 20)) >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = s0 >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[1] = s1 >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[2] = s2 >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[3] = s3 >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[4] = s4 >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[5] = s5 >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[6] = s6 >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[7] = s7 >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[8] = s8 >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[9] = s9 >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[10] = s10 >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
- carry[11] = s11 >> 21
- s12 += carry[11]
- s11 -= carry[11] << 21
-
- s0 += s12 * 666643
- s1 += s12 * 470296
- s2 += s12 * 654183
- s3 -= s12 * 997805
- s4 += s12 * 136657
- s5 -= s12 * 683901
- s12 = 0
-
- carry[0] = s0 >> 21
- s1 += carry[0]
- s0 -= carry[0] << 21
- carry[1] = s1 >> 21
- s2 += carry[1]
- s1 -= carry[1] << 21
- carry[2] = s2 >> 21
- s3 += carry[2]
- s2 -= carry[2] << 21
- carry[3] = s3 >> 21
- s4 += carry[3]
- s3 -= carry[3] << 21
- carry[4] = s4 >> 21
- s5 += carry[4]
- s4 -= carry[4] << 21
- carry[5] = s5 >> 21
- s6 += carry[5]
- s5 -= carry[5] << 21
- carry[6] = s6 >> 21
- s7 += carry[6]
- s6 -= carry[6] << 21
- carry[7] = s7 >> 21
- s8 += carry[7]
- s7 -= carry[7] << 21
- carry[8] = s8 >> 21
- s9 += carry[8]
- s8 -= carry[8] << 21
- carry[9] = s9 >> 21
- s10 += carry[9]
- s9 -= carry[9] << 21
- carry[10] = s10 >> 21
- s11 += carry[10]
- s10 -= carry[10] << 21
-
- out[0] = byte(s0 >> 0)
- out[1] = byte(s0 >> 8)
- out[2] = byte((s0 >> 16) | (s1 << 5))
- out[3] = byte(s1 >> 3)
- out[4] = byte(s1 >> 11)
- out[5] = byte((s1 >> 19) | (s2 << 2))
- out[6] = byte(s2 >> 6)
- out[7] = byte((s2 >> 14) | (s3 << 7))
- out[8] = byte(s3 >> 1)
- out[9] = byte(s3 >> 9)
- out[10] = byte((s3 >> 17) | (s4 << 4))
- out[11] = byte(s4 >> 4)
- out[12] = byte(s4 >> 12)
- out[13] = byte((s4 >> 20) | (s5 << 1))
- out[14] = byte(s5 >> 7)
- out[15] = byte((s5 >> 15) | (s6 << 6))
- out[16] = byte(s6 >> 2)
- out[17] = byte(s6 >> 10)
- out[18] = byte((s6 >> 18) | (s7 << 3))
- out[19] = byte(s7 >> 5)
- out[20] = byte(s7 >> 13)
- out[21] = byte(s8 >> 0)
- out[22] = byte(s8 >> 8)
- out[23] = byte((s8 >> 16) | (s9 << 5))
- out[24] = byte(s9 >> 3)
- out[25] = byte(s9 >> 11)
- out[26] = byte((s9 >> 19) | (s10 << 2))
- out[27] = byte(s10 >> 6)
- out[28] = byte((s10 >> 14) | (s11 << 7))
- out[29] = byte(s11 >> 1)
- out[30] = byte(s11 >> 9)
- out[31] = byte(s11 >> 17)
-}
-
-// order is the order of Curve25519 in little-endian form.
-var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
-
-// ScMinimal returns true if the given scalar is less than the order of the
-// curve.
-func ScMinimal(scalar *[32]byte) bool {
- for i := 3; ; i-- {
- v := binary.LittleEndian.Uint64(scalar[i*8:])
- if v > order[i] {
- return false
- } else if v < order[i] {
- break
- } else if i == 0 {
- return false
- }
- }
-
- return true
-}
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 6605bf64..a69e2249 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -14,8 +14,10 @@ import (
"time"
)
-// These constants from [PROTOCOL.certkeys] represent the key algorithm names
-// for certificate types supported by this package.
+// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear
+// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms.
+// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't
+// appear in the Signature.Format field.
const (
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
@@ -25,14 +27,21 @@ const (
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
+
+ // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
+ // Certificate.Type (or PublicKey.Type), but only in
+ // ClientConfig.HostKeyAlgorithms.
+ CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
+ CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
)
-// These constants from [PROTOCOL.certkeys] represent additional signature
-// algorithm names for certificate types supported by this package.
const (
- CertSigAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
- CertSigAlgoRSASHA2256v01 = "rsa-sha2-256-cert-v01@openssh.com"
- CertSigAlgoRSASHA2512v01 = "rsa-sha2-512-cert-v01@openssh.com"
+ // Deprecated: use CertAlgoRSAv01.
+ CertSigAlgoRSAv01 = CertAlgoRSAv01
+ // Deprecated: use CertAlgoRSASHA256v01.
+ CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
+ // Deprecated: use CertAlgoRSASHA512v01.
+ CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
)
// Certificate types distinguish between host and user
@@ -431,10 +440,14 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
}
c.SignatureKey = authority.PublicKey()
- if v, ok := authority.(AlgorithmSigner); ok {
- if v.PublicKey().Type() == KeyAlgoRSA {
- authority = &rsaSigner{v, SigAlgoRSASHA2512}
+ // Default to KeyAlgoRSASHA512 for ssh-rsa signers.
+ if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA {
+ sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512)
+ if err != nil {
+ return err
}
+ c.Signature = sig
+ return nil
}
sig, err := authority.Sign(rand, c.bytesForSigning())
@@ -445,32 +458,40 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
return nil
}
-// certAlgoNames includes a mapping from signature algorithms to the
-// corresponding certificate signature algorithm. When a key type (such
-// as ED25516) is associated with only one algorithm, the KeyAlgo
-// constant is used instead of the SigAlgo.
-var certAlgoNames = map[string]string{
- SigAlgoRSA: CertSigAlgoRSAv01,
- SigAlgoRSASHA2256: CertSigAlgoRSASHA2256v01,
- SigAlgoRSASHA2512: CertSigAlgoRSASHA2512v01,
- KeyAlgoDSA: CertAlgoDSAv01,
- KeyAlgoECDSA256: CertAlgoECDSA256v01,
- KeyAlgoECDSA384: CertAlgoECDSA384v01,
- KeyAlgoECDSA521: CertAlgoECDSA521v01,
- KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01,
- KeyAlgoED25519: CertAlgoED25519v01,
- KeyAlgoSKED25519: CertAlgoSKED25519v01,
+// certKeyAlgoNames is a mapping from known certificate algorithm names to the
+// corresponding public key signature algorithm.
+var certKeyAlgoNames = map[string]string{
+ CertAlgoRSAv01: KeyAlgoRSA,
+ CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
+ CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
+ CertAlgoDSAv01: KeyAlgoDSA,
+ CertAlgoECDSA256v01: KeyAlgoECDSA256,
+ CertAlgoECDSA384v01: KeyAlgoECDSA384,
+ CertAlgoECDSA521v01: KeyAlgoECDSA521,
+ CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
+ CertAlgoED25519v01: KeyAlgoED25519,
+ CertAlgoSKED25519v01: KeyAlgoSKED25519,
+}
+
+// underlyingAlgo returns the signature algorithm associated with algo (which is
+// an advertised or negotiated public key or host key algorithm). These are
+// usually the same, except for certificate algorithms.
+func underlyingAlgo(algo string) string {
+ if a, ok := certKeyAlgoNames[algo]; ok {
+ return a
+ }
+ return algo
}
-// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
-// Panics if a non-certificate algorithm is passed.
-func certToPrivAlgo(algo string) string {
- for privAlgo, pubAlgo := range certAlgoNames {
- if pubAlgo == algo {
- return privAlgo
+// certificateAlgo returns the certificate algorithms that uses the provided
+// underlying signature algorithm.
+func certificateAlgo(algo string) (certAlgo string, ok bool) {
+ for certName, algoName := range certKeyAlgoNames {
+ if algoName == algo {
+ return certName, true
}
}
- panic("unknown cert algorithm")
+ return "", false
}
func (cert *Certificate) bytesForSigning() []byte {
@@ -514,13 +535,13 @@ func (c *Certificate) Marshal() []byte {
return result
}
-// Type returns the key name. It is part of the PublicKey interface.
+// Type returns the certificate algorithm name. It is part of the PublicKey interface.
func (c *Certificate) Type() string {
- algo, ok := certAlgoNames[c.Key.Type()]
+ certName, ok := certificateAlgo(c.Key.Type())
if !ok {
- panic("unknown cert key type " + c.Key.Type())
+ panic("unknown certificate type for key type " + c.Key.Type())
}
- return algo
+ return certName
}
// Verify verifies a signature against the certificate's public
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
index ba8621a8..bdc356cb 100644
--- a/vendor/golang.org/x/crypto/ssh/client.go
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -113,25 +113,16 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
return c.clientAuthenticate(config)
}
-// verifyHostKeySignature verifies the host key obtained in the key
-// exchange.
+// verifyHostKeySignature verifies the host key obtained in the key exchange.
+// algo is the negotiated algorithm, and may be a certificate type.
func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error {
sig, rest, ok := parseSignatureBody(result.Signature)
if len(rest) > 0 || !ok {
return errors.New("ssh: signature parse error")
}
- // For keys, underlyingAlgo is exactly algo. For certificates,
- // we have to look up the underlying key algorithm that SSH
- // uses to evaluate signatures.
- underlyingAlgo := algo
- for sigAlgo, certAlgo := range certAlgoNames {
- if certAlgo == algo {
- underlyingAlgo = sigAlgo
- }
- }
- if sig.Format != underlyingAlgo {
- return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, underlyingAlgo)
+ if a := underlyingAlgo(algo); sig.Format != a {
+ return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a)
}
return hostKey.Verify(result.H, sig)
@@ -237,11 +228,11 @@ type ClientConfig struct {
// be used for the connection. If empty, a reasonable default is used.
ClientVersion string
- // HostKeyAlgorithms lists the key types that the client will
- // accept from the server as host key, in order of
+ // HostKeyAlgorithms lists the public key algorithms that the client will
+ // accept from the server for host key authentication, in order of
// preference. If empty, a reasonable default is used. Any
- // string returned from PublicKey.Type method may be used, or
- // any of the CertAlgoXxxx and KeyAlgoXxxx constants.
+ // string returned from a PublicKey.Type method may be used, or
+ // any of the CertAlgo and KeyAlgo constants.
HostKeyAlgorithms []string
// Timeout is the maximum amount of time for the TCP connection to establish.
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index c611aeb6..409b5ea1 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
+ "strings"
)
type authResult int
@@ -29,6 +30,33 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
if err != nil {
return err
}
+ // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we
+ // advertised willingness to receive one, which we always do) or not. See
+ // RFC 8308, Section 2.4.
+ extensions := make(map[string][]byte)
+ if len(packet) > 0 && packet[0] == msgExtInfo {
+ var extInfo extInfoMsg
+ if err := Unmarshal(packet, &extInfo); err != nil {
+ return err
+ }
+ payload := extInfo.Payload
+ for i := uint32(0); i < extInfo.NumExtensions; i++ {
+ name, rest, ok := parseString(payload)
+ if !ok {
+ return parseError(msgExtInfo)
+ }
+ value, rest, ok := parseString(rest)
+ if !ok {
+ return parseError(msgExtInfo)
+ }
+ extensions[string(name)] = value
+ payload = rest
+ }
+ packet, err = c.transport.readPacket()
+ if err != nil {
+ return err
+ }
+ }
var serviceAccept serviceAcceptMsg
if err := Unmarshal(packet, &serviceAccept); err != nil {
return err
@@ -41,7 +69,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
sessionID := c.transport.getSessionID()
for auth := AuthMethod(new(noneAuth)); auth != nil; {
- ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions)
if err != nil {
return err
}
@@ -93,7 +121,7 @@ type AuthMethod interface {
// If authentication is not successful, a []string of alternative
// method names is returned. If the slice is nil, it will be ignored
// and the previous set of possible methods will be reused.
- auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)
+ auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error)
// method returns the RFC 4252 method name.
method() string
@@ -102,7 +130,7 @@ type AuthMethod interface {
// "none" authentication, RFC 4252 section 5.2.
type noneAuth int
-func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
if err := c.writePacket(Marshal(&userAuthRequestMsg{
User: user,
Service: serviceSSH,
@@ -122,7 +150,7 @@ func (n *noneAuth) method() string {
// a function call, e.g. by prompting the user.
type passwordCallback func() (password string, err error)
-func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
type passwordAuthMsg struct {
User string `sshtype:"50"`
Service string
@@ -189,7 +217,46 @@ func (cb publicKeyCallback) method() string {
return "publickey"
}
-func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) {
+ keyFormat := signer.PublicKey().Type()
+
+ // Like in sendKexInit, if the public key implements AlgorithmSigner we
+ // assume it supports all algorithms, otherwise only the key format one.
+ as, ok := signer.(AlgorithmSigner)
+ if !ok {
+ return algorithmSignerWrapper{signer}, keyFormat
+ }
+
+ extPayload, ok := extensions["server-sig-algs"]
+ if !ok {
+ // If there is no "server-sig-algs" extension, fall back to the key
+ // format algorithm.
+ return as, keyFormat
+ }
+
+ // The server-sig-algs extension only carries underlying signature
+ // algorithm, but we are trying to select a protocol-level public key
+ // algorithm, which might be a certificate type. Extend the list of server
+ // supported algorithms to include the corresponding certificate algorithms.
+ serverAlgos := strings.Split(string(extPayload), ",")
+ for _, algo := range serverAlgos {
+ if certAlgo, ok := certificateAlgo(algo); ok {
+ serverAlgos = append(serverAlgos, certAlgo)
+ }
+ }
+
+ keyAlgos := algorithmsForKeyFormat(keyFormat)
+ algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos)
+ if err != nil {
+ // If there is no overlap, try the key anyway with the key format
+ // algorithm, to support servers that fail to list all supported
+ // algorithms.
+ return as, keyFormat
+ }
+ return as, algo
+}
+
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) {
// Authentication is performed by sending an enquiry to test if a key is
// acceptable to the remote. If the key is acceptable, the client will
// attempt to authenticate with the valid key. If not the client will repeat
@@ -201,7 +268,10 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
}
var methods []string
for _, signer := range signers {
- ok, err := validateKey(signer.PublicKey(), user, c)
+ pub := signer.PublicKey()
+ as, algo := pickSignatureAlgorithm(signer, extensions)
+
+ ok, err := validateKey(pub, algo, user, c)
if err != nil {
return authFailure, nil, err
}
@@ -209,13 +279,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
continue
}
- pub := signer.PublicKey()
pubKey := pub.Marshal()
- sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
+ data := buildDataSignedForAuth(session, userAuthRequestMsg{
User: user,
Service: serviceSSH,
Method: cb.method(),
- }, []byte(pub.Type()), pubKey))
+ }, algo, pubKey)
+ sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
if err != nil {
return authFailure, nil, err
}
@@ -229,7 +299,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
Service: serviceSSH,
Method: cb.method(),
HasSig: true,
- Algoname: pub.Type(),
+ Algoname: algo,
PubKey: pubKey,
Sig: sig,
}
@@ -266,26 +336,25 @@ func containsMethod(methods []string, method string) bool {
}
// validateKey validates the key provided is acceptable to the server.
-func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
+func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) {
pubKey := key.Marshal()
msg := publickeyAuthMsg{
User: user,
Service: serviceSSH,
Method: "publickey",
HasSig: false,
- Algoname: key.Type(),
+ Algoname: algo,
PubKey: pubKey,
}
if err := c.writePacket(Marshal(&msg)); err != nil {
return false, err
}
- return confirmKeyAck(key, c)
+ return confirmKeyAck(key, algo, c)
}
-func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
+func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) {
pubKey := key.Marshal()
- algoname := key.Type()
for {
packet, err := c.readPacket()
@@ -302,14 +371,14 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
if err := Unmarshal(packet, &msg); err != nil {
return false, err
}
- if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
+ if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) {
return false, nil
}
return true, nil
case msgUserAuthFailure:
return false, nil
default:
- return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0])
}
}
}
@@ -330,6 +399,7 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(c packetConn) (authResult, []string, error) {
+ gotMsgExtInfo := false
for {
packet, err := c.readPacket()
if err != nil {
@@ -341,6 +411,12 @@ func handleAuthResponse(c packetConn) (authResult, []string, error) {
if err := handleBannerResponse(c, packet); err != nil {
return authFailure, nil, err
}
+ case msgExtInfo:
+ // Ignore post-authentication RFC 8308 extensions, once.
+ if gotMsgExtInfo {
+ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ }
+ gotMsgExtInfo = true
case msgUserAuthFailure:
var msg userAuthFailureMsg
if err := Unmarshal(packet, &msg); err != nil {
@@ -380,10 +456,10 @@ func handleBannerResponse(c packetConn, packet []byte) error {
// disabling echoing (e.g. for passwords), and return all the answers.
// Challenge may be called multiple times in a single session. After
// successful authentication, the server may send a challenge with no
-// questions, for which the user and instruction messages should be
+// questions, for which the name and instruction messages should be
// printed. RFC 4256 section 3.3 details how the UI should behave for
// both CLI and GUI environments.
-type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
+type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error)
// KeyboardInteractive returns an AuthMethod using a prompt/response
// sequence controlled by the server.
@@ -395,7 +471,7 @@ func (cb KeyboardInteractiveChallenge) method() string {
return "keyboard-interactive"
}
-func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
type initiateMsg struct {
User string `sshtype:"50"`
Service string
@@ -412,6 +488,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
return authFailure, nil, err
}
+ gotMsgExtInfo := false
for {
packet, err := c.readPacket()
if err != nil {
@@ -425,6 +502,13 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
return authFailure, nil, err
}
continue
+ case msgExtInfo:
+ // Ignore post-authentication RFC 8308 extensions, once.
+ if gotMsgExtInfo {
+ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+ }
+ gotMsgExtInfo = true
+ continue
case msgUserAuthInfoRequest:
// OK
case msgUserAuthFailure:
@@ -465,7 +549,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
}
- answers, err := cb(msg.User, msg.Instruction, prompts, echos)
+ answers, err := cb(msg.Name, msg.Instruction, prompts, echos)
if err != nil {
return authFailure, nil, err
}
@@ -497,9 +581,9 @@ type retryableAuthMethod struct {
maxTries int
}
-func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {
+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) {
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
- ok, methods, err = r.authMethod.auth(session, user, c, rand)
+ ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions)
if ok != authFailure || err != nil { // either success, partial success or error terminate
return ok, methods, err
}
@@ -542,7 +626,7 @@ type gssAPIWithMICCallback struct {
target string
}
-func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
m := &userAuthRequestMsg{
User: user,
Service: serviceSSH,
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index 5ae22757..2a47a61d 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -44,11 +44,11 @@ var preferredCiphers = []string{
// supportedKexAlgos specifies the supported key-exchange algorithms in
// preference order.
var supportedKexAlgos = []string{
- kexAlgoCurve25519SHA256,
+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
// P384 and P521 are not constant-time yet, but since we don't
// reuse ephemeral keys, using them for ECDH should be OK.
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
- kexAlgoDH14SHA1, kexAlgoDH1SHA1,
+ kexAlgoDH14SHA256, kexAlgoDH14SHA1, kexAlgoDH1SHA1,
}
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
@@ -61,21 +61,21 @@ var serverForbiddenKexAlgos = map[string]struct{}{
// preferredKexAlgos specifies the default preference for key-exchange algorithms
// in preference order.
var preferredKexAlgos = []string{
- kexAlgoCurve25519SHA256,
+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
- kexAlgoDH14SHA1,
+ kexAlgoDH14SHA256, kexAlgoDH14SHA1,
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{
- CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01,
- CertSigAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
+ CertAlgoRSASHA512v01, CertAlgoRSASHA256v01,
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
- SigAlgoRSASHA2512, SigAlgoRSASHA2256,
- SigAlgoRSA, KeyAlgoDSA,
+ KeyAlgoRSASHA512, KeyAlgoRSASHA256,
+ KeyAlgoRSA, KeyAlgoDSA,
KeyAlgoED25519,
}
@@ -89,23 +89,33 @@ var supportedMACs = []string{
var supportedCompressions = []string{compressionNone}
-// hashFuncs keeps the mapping of supported algorithms to their respective
-// hashes needed for signature verification.
+// hashFuncs keeps the mapping of supported signature algorithms to their
+// respective hashes needed for signing and verification.
var hashFuncs = map[string]crypto.Hash{
- SigAlgoRSA: crypto.SHA1,
- SigAlgoRSASHA2256: crypto.SHA256,
- SigAlgoRSASHA2512: crypto.SHA512,
- KeyAlgoDSA: crypto.SHA1,
- KeyAlgoECDSA256: crypto.SHA256,
- KeyAlgoECDSA384: crypto.SHA384,
- KeyAlgoECDSA521: crypto.SHA512,
- CertSigAlgoRSAv01: crypto.SHA1,
- CertSigAlgoRSASHA2256v01: crypto.SHA256,
- CertSigAlgoRSASHA2512v01: crypto.SHA512,
- CertAlgoDSAv01: crypto.SHA1,
- CertAlgoECDSA256v01: crypto.SHA256,
- CertAlgoECDSA384v01: crypto.SHA384,
- CertAlgoECDSA521v01: crypto.SHA512,
+ KeyAlgoRSA: crypto.SHA1,
+ KeyAlgoRSASHA256: crypto.SHA256,
+ KeyAlgoRSASHA512: crypto.SHA512,
+ KeyAlgoDSA: crypto.SHA1,
+ KeyAlgoECDSA256: crypto.SHA256,
+ KeyAlgoECDSA384: crypto.SHA384,
+ KeyAlgoECDSA521: crypto.SHA512,
+ // KeyAlgoED25519 doesn't pre-hash.
+ KeyAlgoSKECDSA256: crypto.SHA256,
+ KeyAlgoSKED25519: crypto.SHA256,
+}
+
+// algorithmsForKeyFormat returns the supported signature algorithms for a given
+// public key format (PublicKey.Type), in order of preference. See RFC 8332,
+// Section 2. See also the note in sendKexInit on backwards compatibility.
+func algorithmsForKeyFormat(keyFormat string) []string {
+ switch keyFormat {
+ case KeyAlgoRSA:
+ return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA}
+ case CertAlgoRSAv01:
+ return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01}
+ default:
+ return []string{keyFormat}
+ }
}
// unexpectedMessageError results when the SSH message that we received didn't
@@ -152,6 +162,11 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
return 1 << 30
}
+var aeadCiphers = map[string]bool{
+ gcmCipherID: true,
+ chacha20Poly1305ID: true,
+}
+
type algorithms struct {
kex string
hostKey string
@@ -187,14 +202,18 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
return
}
- ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
- if err != nil {
- return
+ if !aeadCiphers[ctos.Cipher] {
+ ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+ if err != nil {
+ return
+ }
}
- stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
- if err != nil {
- return
+ if !aeadCiphers[stoc.Cipher] {
+ stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+ if err != nil {
+ return
+ }
}
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
@@ -278,8 +297,9 @@ func (c *Config) SetDefaults() {
}
// buildDataSignedForAuth returns the data that is signed in order to prove
-// possession of a private key. See RFC 4252, section 7.
-func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+// possession of a private key. See RFC 4252, section 7. algo is the advertised
+// algorithm, and may be a certificate type.
+func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte {
data := struct {
Session []byte
Type byte
@@ -287,7 +307,7 @@ func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubK
Service string
Method string
Sign bool
- Algo []byte
+ Algo string
PubKey []byte
}{
sessionID,
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 05ad49c3..653dc4d2 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -455,21 +455,38 @@ func (t *handshakeTransport) sendKexInit() error {
}
io.ReadFull(rand.Reader, msg.Cookie[:])
- if len(t.hostKeys) > 0 {
+ isServer := len(t.hostKeys) > 0
+ if isServer {
for _, k := range t.hostKeys {
- algo := k.PublicKey().Type()
- switch algo {
- case KeyAlgoRSA:
- msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{SigAlgoRSASHA2512, SigAlgoRSASHA2256, SigAlgoRSA}...)
- case CertAlgoRSAv01:
- msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01, CertSigAlgoRSAv01}...)
- default:
- msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo)
+ // If k is an AlgorithmSigner, presume it supports all signature algorithms
+ // associated with the key format. (Ideally AlgorithmSigner would have a
+ // method to advertise supported algorithms, but it doesn't. This means that
+ // adding support for a new algorithm is a breaking change, as we will
+ // immediately negotiate it even if existing implementations don't support
+ // it. If that ever happens, we'll have to figure something out.)
+ // If k is not an AlgorithmSigner, we can only assume it only supports the
+ // algorithms that matches the key format. (This means that Sign can't pick
+ // a different default.)
+ keyFormat := k.PublicKey().Type()
+ if _, ok := k.(AlgorithmSigner); ok {
+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...)
+ } else {
+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
}
}
} else {
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
+
+ // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
+ // algorithms the server supports for public key authentication. See RFC
+ // 8308, Section 2.1.
+ if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
+ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1)
+ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
+ msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
+ }
}
+
packet := Marshal(msg)
// writePacket destroys the contents, so save a copy.
@@ -589,9 +606,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
var result *kexResult
if len(t.hostKeys) > 0 {
- result, err = t.server(kex, t.algorithms, &magics)
+ result, err = t.server(kex, &magics)
} else {
- result, err = t.client(kex, t.algorithms, &magics)
+ result, err = t.client(kex, &magics)
}
if err != nil {
@@ -618,33 +635,52 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return nil
}
-func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
- var hostKey Signer
- for _, k := range t.hostKeys {
- kt := k.PublicKey().Type()
- if kt == algs.hostKey {
- hostKey = k
- } else if signer, ok := k.(AlgorithmSigner); ok {
- // Some signature algorithms don't show up as key types
- // so we have to manually check for a compatible host key.
- switch kt {
- case KeyAlgoRSA:
- if algs.hostKey == SigAlgoRSASHA2256 || algs.hostKey == SigAlgoRSASHA2512 {
- hostKey = &rsaSigner{signer, algs.hostKey}
- }
- case CertAlgoRSAv01:
- if algs.hostKey == CertSigAlgoRSASHA2256v01 || algs.hostKey == CertSigAlgoRSASHA2512v01 {
- hostKey = &rsaSigner{signer, certToPrivAlgo(algs.hostKey)}
- }
+// algorithmSignerWrapper is an AlgorithmSigner that only supports the default
+// key format algorithm.
+//
+// This is technically a violation of the AlgorithmSigner interface, but it
+// should be unreachable given where we use this. Anyway, at least it returns an
+// error instead of panicing or producing an incorrect signature.
+type algorithmSignerWrapper struct {
+ Signer
+}
+
+func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
+ if algorithm != underlyingAlgo(a.PublicKey().Type()) {
+ return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm")
+ }
+ return a.Sign(rand, data)
+}
+
+func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
+ for _, k := range hostKeys {
+ if algo == k.PublicKey().Type() {
+ return algorithmSignerWrapper{k}
+ }
+ k, ok := k.(AlgorithmSigner)
+ if !ok {
+ continue
+ }
+ for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) {
+ if algo == a {
+ return k
}
}
}
+ return nil
+}
+
+func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
+ hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey)
+ if hostKey == nil {
+ return nil, errors.New("ssh: internal error: negotiated unsupported signature type")
+ }
- r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
+ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey)
return r, err
}
-func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
result, err := kex.Client(t.conn, t.config.Rand, magics)
if err != nil {
return nil, err
@@ -655,7 +691,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
return nil, err
}
- if err := verifyHostKeySignature(hostKey, algs.hostKey, result); err != nil {
+ if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil {
return nil, err
}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index 766e9293..927a90cd 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -20,12 +20,14 @@ import (
)
const (
- kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
- kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
- kexAlgoECDH256 = "ecdh-sha2-nistp256"
- kexAlgoECDH384 = "ecdh-sha2-nistp384"
- kexAlgoECDH521 = "ecdh-sha2-nistp521"
- kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
+ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
+ kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
+ kexAlgoECDH256 = "ecdh-sha2-nistp256"
+ kexAlgoECDH384 = "ecdh-sha2-nistp384"
+ kexAlgoECDH521 = "ecdh-sha2-nistp521"
+ kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
+ kexAlgoCurve25519SHA256 = "curve25519-sha256"
// For the following kex only the client half contains a production
// ready implementation. The server half only consists of a minimal
@@ -75,8 +77,9 @@ func (m *handshakeMagics) write(w io.Writer) {
// kexAlgorithm abstracts different key exchange algorithms.
type kexAlgorithm interface {
// Server runs server-side key agreement, signing the result
- // with a hostkey.
- Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
+ // with a hostkey. algo is the negotiated algorithm, and may
+ // be a certificate type.
+ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error)
// Client runs the client-side key agreement. Caller is
// responsible for verifying the host key signature.
@@ -86,6 +89,7 @@ type kexAlgorithm interface {
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
type dhGroup struct {
g, p, pMinus1 *big.Int
+ hashFunc crypto.Hash
}
func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
@@ -96,8 +100,6 @@ func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int,
}
func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
- hashFunc := crypto.SHA1
-
var x *big.Int
for {
var err error
@@ -132,7 +134,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
return nil, err
}
- h := hashFunc.New()
+ h := group.hashFunc.New()
magics.write(h)
writeString(h, kexDHReply.HostKey)
writeInt(h, X)
@@ -146,12 +148,11 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
K: K,
HostKey: kexDHReply.HostKey,
Signature: kexDHReply.Signature,
- Hash: crypto.SHA1,
+ Hash: group.hashFunc,
}, nil
}
-func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
- hashFunc := crypto.SHA1
+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
packet, err := c.readPacket()
if err != nil {
return
@@ -179,7 +180,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
hostKeyBytes := priv.PublicKey().Marshal()
- h := hashFunc.New()
+ h := group.hashFunc.New()
magics.write(h)
writeString(h, hostKeyBytes)
writeInt(h, kexDHInit.X)
@@ -193,7 +194,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
// H is already a hash, but the hostkey signing will apply its
// own key-specific hash algorithm.
- sig, err := signAndMarshal(priv, randSource, H)
+ sig, err := signAndMarshal(priv, randSource, H, algo)
if err != nil {
return nil, err
}
@@ -211,7 +212,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
K: K,
HostKey: hostKeyBytes,
Signature: sig,
- Hash: crypto.SHA1,
+ Hash: group.hashFunc,
}, err
}
@@ -314,7 +315,7 @@ func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
return true
}
-func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
packet, err := c.readPacket()
if err != nil {
return nil, err
@@ -359,7 +360,7 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p
// H is already a hash, but the hostkey signing will apply its
// own key-specific hash algorithm.
- sig, err := signAndMarshal(priv, rand, H)
+ sig, err := signAndMarshal(priv, rand, H, algo)
if err != nil {
return nil, err
}
@@ -384,39 +385,62 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p
}, nil
}
+// ecHash returns the hash to match the given elliptic curve, see RFC
+// 5656, section 6.2.1
+func ecHash(curve elliptic.Curve) crypto.Hash {
+ bitSize := curve.Params().BitSize
+ switch {
+ case bitSize <= 256:
+ return crypto.SHA256
+ case bitSize <= 384:
+ return crypto.SHA384
+ }
+ return crypto.SHA512
+}
+
var kexAlgoMap = map[string]kexAlgorithm{}
func init() {
- // This is the group called diffie-hellman-group1-sha1 in RFC
- // 4253 and Oakley Group 2 in RFC 2409.
+ // This is the group called diffie-hellman-group1-sha1 in
+ // RFC 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
- pMinus1: new(big.Int).Sub(p, bigOne),
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ pMinus1: new(big.Int).Sub(p, bigOne),
+ hashFunc: crypto.SHA1,
}
- // This is the group called diffie-hellman-group14-sha1 in RFC
- // 4253 and Oakley Group 14 in RFC 3526.
+ // This are the groups called diffie-hellman-group14-sha1 and
+ // diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268,
+ // and Oakley Group 14 in RFC 3526.
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
-
- kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+ group14 := &dhGroup{
g: new(big.Int).SetInt64(2),
p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
+ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
+ hashFunc: crypto.SHA1,
+ }
+ kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{
+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
+ hashFunc: crypto.SHA256,
+ }
+
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
+ kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{}
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
}
-// curve25519sha256 implements the curve25519-sha256@libssh.org key
-// agreement protocol, as described in
-// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
+// curve25519sha256 implements the curve25519-sha256 (formerly known as
+// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731.
type curve25519sha256 struct{}
type curve25519KeyPair struct {
@@ -486,7 +510,7 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh
}, nil
}
-func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
packet, err := c.readPacket()
if err != nil {
return
@@ -527,7 +551,7 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
H := h.Sum(nil)
- sig, err := signAndMarshal(priv, rand, H)
+ sig, err := signAndMarshal(priv, rand, H, algo)
if err != nil {
return nil, err
}
@@ -553,7 +577,6 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
// diffie-hellman-group-exchange-sha256 key agreement protocols,
// as described in RFC 4419
type dhGEXSHA struct {
- g, p *big.Int
hashFunc crypto.Hash
}
@@ -563,14 +586,7 @@ const (
dhGroupExchangeMaximumBits = 8192
)
-func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
- if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
- return nil, fmt.Errorf("ssh: DH parameter out of bounds")
- }
- return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
-}
-
-func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
// Send GexRequest
kexDHGexRequest := kexDHGexRequestMsg{
MinBits: dhGroupExchangeMinimumBits,
@@ -587,35 +603,29 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
return nil, err
}
- var kexDHGexGroup kexDHGexGroupMsg
- if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
+ var msg kexDHGexGroupMsg
+ if err = Unmarshal(packet, &msg); err != nil {
return nil, err
}
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
- if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
- return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
+ if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits {
+ return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen())
}
- gex.p = kexDHGexGroup.P
- gex.g = kexDHGexGroup.G
-
- // Check if g is safe by verifing that g > 1 and g < p - 1
- one := big.NewInt(1)
- var pMinusOne = &big.Int{}
- pMinusOne.Sub(gex.p, one)
- if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
+ // Check if g is safe by verifying that 1 < g < p-1
+ pMinusOne := new(big.Int).Sub(msg.P, bigOne)
+ if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 {
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
}
// Send GexInit
- var pHalf = &big.Int{}
- pHalf.Rsh(gex.p, 1)
+ pHalf := new(big.Int).Rsh(msg.P, 1)
x, err := rand.Int(randSource, pHalf)
if err != nil {
return nil, err
}
- X := new(big.Int).Exp(gex.g, x, gex.p)
+ X := new(big.Int).Exp(msg.G, x, msg.P)
kexDHGexInit := kexDHGexInitMsg{
X: X,
}
@@ -634,13 +644,13 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
return nil, err
}
- kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
- if err != nil {
- return nil, err
+ if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 {
+ return nil, errors.New("ssh: DH parameter out of bounds")
}
+ kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P)
- // Check if k is safe by verifing that k > 1 and k < p - 1
- if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
+ // Check if k is safe by verifying that k > 1 and k < p - 1
+ if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 {
return nil, fmt.Errorf("ssh: derived k is not safe")
}
@@ -650,8 +660,8 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
- writeInt(h, gex.p)
- writeInt(h, gex.g)
+ writeInt(h, msg.P)
+ writeInt(h, msg.G)
writeInt(h, X)
writeInt(h, kexDHGexReply.Y)
K := make([]byte, intLength(kInt))
@@ -670,7 +680,7 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
//
// This is a minimal implementation to satisfy the automated tests.
-func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
// Receive GexRequest
packet, err := c.readPacket()
if err != nil {
@@ -681,35 +691,17 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
return
}
- // smoosh the user's preferred size into our own limits
- if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
- kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
- }
- if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
- kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
- }
- // fix min/max if they're inconsistent. technically, we could just pout
- // and hang up, but there's no harm in giving them the benefit of the
- // doubt and just picking a bitsize for them.
- if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
- kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
- }
- if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
- kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
- }
-
// Send GexGroup
// This is the group called diffie-hellman-group14-sha1 in RFC
// 4253 and Oakley Group 14 in RFC 3526.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
- gex.p = p
- gex.g = big.NewInt(2)
+ g := big.NewInt(2)
- kexDHGexGroup := kexDHGexGroupMsg{
- P: gex.p,
- G: gex.g,
+ msg := &kexDHGexGroupMsg{
+ P: p,
+ G: g,
}
- if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
+ if err := c.writePacket(Marshal(msg)); err != nil {
return nil, err
}
@@ -723,19 +715,19 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
return
}
- var pHalf = &big.Int{}
- pHalf.Rsh(gex.p, 1)
+ pHalf := new(big.Int).Rsh(p, 1)
y, err := rand.Int(randSource, pHalf)
if err != nil {
return
}
+ Y := new(big.Int).Exp(g, y, p)
- Y := new(big.Int).Exp(gex.g, y, gex.p)
- kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
- if err != nil {
- return nil, err
+ pMinusOne := new(big.Int).Sub(p, bigOne)
+ if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 {
+ return nil, errors.New("ssh: DH parameter out of bounds")
}
+ kInt := new(big.Int).Exp(kexDHGexInit.X, y, p)
hostKeyBytes := priv.PublicKey().Marshal()
@@ -745,8 +737,8 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
- writeInt(h, gex.p)
- writeInt(h, gex.g)
+ writeInt(h, p)
+ writeInt(h, g)
writeInt(h, kexDHGexInit.X)
writeInt(h, Y)
@@ -758,7 +750,7 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
// H is already a hash, but the hostkey signing will apply its
// own key-specific hash algorithm.
- sig, err := signAndMarshal(priv, randSource, H)
+ sig, err := signAndMarshal(priv, randSource, H, algo)
if err != nil {
return nil, err
}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index c67d3a31..1c7de1a6 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -30,8 +30,9 @@ import (
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
)
-// These constants represent the algorithm names for key types supported by this
-// package.
+// Public key algorithms names. These values can appear in PublicKey.Type,
+// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
+// arguments.
const (
KeyAlgoRSA = "ssh-rsa"
KeyAlgoDSA = "ssh-dss"
@@ -41,16 +42,21 @@ const (
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
KeyAlgoED25519 = "ssh-ed25519"
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
+
+ // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
+ // public key formats, so they can't appear as a PublicKey.Type. The
+ // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
+ KeyAlgoRSASHA256 = "rsa-sha2-256"
+ KeyAlgoRSASHA512 = "rsa-sha2-512"
)
-// These constants represent non-default signature algorithms that are supported
-// as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See
-// [PROTOCOL.agent] section 4.5.1 and
-// https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10
const (
- SigAlgoRSA = "ssh-rsa"
- SigAlgoRSASHA2256 = "rsa-sha2-256"
- SigAlgoRSASHA2512 = "rsa-sha2-512"
+ // Deprecated: use KeyAlgoRSA.
+ SigAlgoRSA = KeyAlgoRSA
+ // Deprecated: use KeyAlgoRSASHA256.
+ SigAlgoRSASHA2256 = KeyAlgoRSASHA256
+ // Deprecated: use KeyAlgoRSASHA512.
+ SigAlgoRSASHA2512 = KeyAlgoRSASHA512
)
// parsePubKey parses a public key of the given algorithm.
@@ -70,7 +76,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
case KeyAlgoSKED25519:
return parseSKEd25519(in)
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
- cert, err := parseCert(in, certToPrivAlgo(algo))
+ cert, err := parseCert(in, certKeyAlgoNames[algo])
if err != nil {
return nil, nil, err
}
@@ -289,18 +295,21 @@ func MarshalAuthorizedKey(key PublicKey) []byte {
return b.Bytes()
}
-// PublicKey is an abstraction of different types of public keys.
+// PublicKey represents a public key using an unspecified algorithm.
+//
+// Some PublicKeys provided by this package also implement CryptoPublicKey.
type PublicKey interface {
- // Type returns the key's type, e.g. "ssh-rsa".
+ // Type returns the key format name, e.g. "ssh-rsa".
Type() string
- // Marshal returns the serialized key data in SSH wire format,
- // with the name prefix. To unmarshal the returned data, use
- // the ParsePublicKey function.
+ // Marshal returns the serialized key data in SSH wire format, with the name
+ // prefix. To unmarshal the returned data, use the ParsePublicKey function.
Marshal() []byte
- // Verify that sig is a signature on the given data using this
- // key. This function will hash the data appropriately first.
+ // Verify that sig is a signature on the given data using this key. This
+ // method will hash the data appropriately first. sig.Format is allowed to
+ // be any signature algorithm compatible with the key type, the caller
+ // should check if it has more stringent requirements.
Verify(data []byte, sig *Signature) error
}
@@ -311,25 +320,32 @@ type CryptoPublicKey interface {
}
// A Signer can create signatures that verify against a public key.
+//
+// Some Signers provided by this package also implement AlgorithmSigner.
type Signer interface {
- // PublicKey returns an associated PublicKey instance.
+ // PublicKey returns the associated PublicKey.
PublicKey() PublicKey
- // Sign returns raw signature for the given data. This method
- // will apply the hash specified for the keytype to the data.
+ // Sign returns a signature for the given data. This method will hash the
+ // data appropriately first. The signature algorithm is expected to match
+ // the key format returned by the PublicKey.Type method (and not to be any
+ // alternative algorithm supported by the key format).
Sign(rand io.Reader, data []byte) (*Signature, error)
}
-// A AlgorithmSigner is a Signer that also supports specifying a specific
-// algorithm to use for signing.
+// An AlgorithmSigner is a Signer that also supports specifying an algorithm to
+// use for signing.
+//
+// An AlgorithmSigner can't advertise the algorithms it supports, so it should
+// be prepared to be invoked with every algorithm supported by the public key
+// format.
type AlgorithmSigner interface {
Signer
- // SignWithAlgorithm is like Signer.Sign, but allows specification of a
- // non-default signing algorithm. See the SigAlgo* constants in this
- // package for signature algorithms supported by this package. Callers may
- // pass an empty string for the algorithm in which case the AlgorithmSigner
- // will use its default algorithm.
+ // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired
+ // signing algorithm. Callers may pass an empty string for the algorithm in
+ // which case the AlgorithmSigner will use a default algorithm. This default
+ // doesn't currently control any behavior in this package.
SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
}
@@ -381,17 +397,11 @@ func (r *rsaPublicKey) Marshal() []byte {
}
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
- var hash crypto.Hash
- switch sig.Format {
- case SigAlgoRSA:
- hash = crypto.SHA1
- case SigAlgoRSASHA2256:
- hash = crypto.SHA256
- case SigAlgoRSASHA2512:
- hash = crypto.SHA512
- default:
+ supportedAlgos := algorithmsForKeyFormat(r.Type())
+ if !contains(supportedAlgos, sig.Format) {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
}
+ hash := hashFuncs[sig.Format]
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -466,7 +476,7 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- h := crypto.SHA1.New()
+ h := hashFuncs[sig.Format].New()
h.Write(data)
digest := h.Sum(nil)
@@ -499,7 +509,7 @@ func (k *dsaPrivateKey) PublicKey() PublicKey {
}
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
- return k.SignWithAlgorithm(rand, data, "")
+ return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())
}
func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
@@ -507,7 +517,7 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
}
- h := crypto.SHA1.New()
+ h := hashFuncs[k.PublicKey().Type()].New()
h.Write(data)
digest := h.Sum(nil)
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
@@ -603,19 +613,6 @@ func supportedEllipticCurve(curve elliptic.Curve) bool {
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
}
-// ecHash returns the hash to match the given elliptic curve, see RFC
-// 5656, section 6.2.1
-func ecHash(curve elliptic.Curve) crypto.Hash {
- bitSize := curve.Params().BitSize
- switch {
- case bitSize <= 256:
- return crypto.SHA256
- case bitSize <= 384:
- return crypto.SHA384
- }
- return crypto.SHA512
-}
-
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
var w struct {
@@ -671,7 +668,7 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- h := ecHash(k.Curve).New()
+ h := hashFuncs[sig.Format].New()
h.Write(data)
digest := h.Sum(nil)
@@ -775,7 +772,7 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- h := ecHash(k.Curve).New()
+ h := hashFuncs[sig.Format].New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -874,7 +871,7 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
- h := sha256.New()
+ h := hashFuncs[sig.Format].New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -939,15 +936,6 @@ func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
return &dsaPrivateKey{key}, nil
}
-type rsaSigner struct {
- AlgorithmSigner
- defaultAlgorithm string
-}
-
-func (s *rsaSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
- return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.defaultAlgorithm)
-}
-
type wrappedSigner struct {
signer crypto.Signer
pubKey PublicKey
@@ -970,44 +958,20 @@ func (s *wrappedSigner) PublicKey() PublicKey {
}
func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
- return s.SignWithAlgorithm(rand, data, "")
+ return s.SignWithAlgorithm(rand, data, s.pubKey.Type())
}
func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
- var hashFunc crypto.Hash
-
- if _, ok := s.pubKey.(*rsaPublicKey); ok {
- // RSA keys support a few hash functions determined by the requested signature algorithm
- switch algorithm {
- case "", SigAlgoRSA:
- algorithm = SigAlgoRSA
- hashFunc = crypto.SHA1
- case SigAlgoRSASHA2256:
- hashFunc = crypto.SHA256
- case SigAlgoRSASHA2512:
- hashFunc = crypto.SHA512
- default:
- return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
- }
- } else {
- // The only supported algorithm for all other key types is the same as the type of the key
- if algorithm == "" {
- algorithm = s.pubKey.Type()
- } else if algorithm != s.pubKey.Type() {
- return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
- }
+ if algorithm == "" {
+ algorithm = s.pubKey.Type()
+ }
- switch key := s.pubKey.(type) {
- case *dsaPublicKey:
- hashFunc = crypto.SHA1
- case *ecdsaPublicKey:
- hashFunc = ecHash(key.Curve)
- case ed25519PublicKey:
- default:
- return nil, fmt.Errorf("ssh: unsupported key type %T", key)
- }
+ supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type())
+ if !contains(supportedAlgos, algorithm) {
+ return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
}
+ hashFunc := hashFuncs[algorithm]
var digest []byte
if hashFunc != 0 {
h := hashFunc.New()
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
index ac41a416..19bc67c4 100644
--- a/vendor/golang.org/x/crypto/ssh/messages.go
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -141,6 +141,14 @@ type serviceAcceptMsg struct {
Service string `sshtype:"6"`
}
+// See RFC 8308, section 2.3
+const msgExtInfo = 7
+
+type extInfoMsg struct {
+ NumExtensions uint32 `sshtype:"7"`
+ Payload []byte `ssh:"rest"`
+}
+
// See RFC 4252, section 5.
const msgUserAuthRequest = 50
@@ -180,11 +188,11 @@ const msgUserAuthInfoRequest = 60
const msgUserAuthInfoResponse = 61
type userAuthInfoRequestMsg struct {
- User string `sshtype:"60"`
- Instruction string
- DeprecatedLanguage string
- NumPrompts uint32
- Prompts []byte `ssh:"rest"`
+ Name string `sshtype:"60"`
+ Instruction string
+ Language string
+ NumPrompts uint32
+ Prompts []byte `ssh:"rest"`
}
// See RFC 4254, section 5.1.
@@ -782,6 +790,8 @@ func decode(packet []byte) (interface{}, error) {
msg = new(serviceRequestMsg)
case msgServiceAccept:
msg = new(serviceAcceptMsg)
+ case msgExtInfo:
+ msg = new(extInfoMsg)
case msgKexInit:
msg = new(kexInitMsg)
case msgKexDHInit:
@@ -843,6 +853,7 @@ var packetTypeNames = map[byte]string{
msgDisconnect: "disconnectMsg",
msgServiceRequest: "serviceRequestMsg",
msgServiceAccept: "serviceAcceptMsg",
+ msgExtInfo: "extInfoMsg",
msgKexInit: "kexInitMsg",
msgKexDHInit: "kexDHInitMsg",
msgKexDHReply: "kexDHReplyMsg",
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 6a58e120..70045bdf 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -120,7 +120,7 @@ type ServerConfig struct {
}
// AddHostKey adds a private key as a host key. If an existing host
-// key exists with the same algorithm, it is overwritten. Each server
+// key exists with the same public key format, it is replaced. Each server
// config must have at least one host key.
func (s *ServerConfig) AddHostKey(key Signer) {
for i, k := range s.hostKeys {
@@ -212,9 +212,10 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
}
// signAndMarshal signs the data with the appropriate algorithm,
-// and serializes the result in SSH wire format.
-func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
- sig, err := k.Sign(rand, data)
+// and serializes the result in SSH wire format. algo is the negotiate
+// algorithm and may be a certificate type.
+func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) {
+ sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
if err != nil {
return nil, err
}
@@ -284,7 +285,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
func isAcceptableAlgo(algo string) bool {
switch algo {
- case SigAlgoRSA, SigAlgoRSASHA2256, SigAlgoRSASHA2512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
+ case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
return true
}
@@ -553,6 +554,7 @@ userAuthLoop:
if !ok || len(payload) > 0 {
return nil, parseError(msgUserAuthRequest)
}
+
// Ensure the public key algo and signature algo
// are supported. Compare the private key
// algorithm name that corresponds to algo with
@@ -562,7 +564,12 @@ userAuthLoop:
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
- signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
+ if underlyingAlgo(algo) != sig.Format {
+ authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo)
+ break
+ }
+
+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData)
if err := pubKey.Verify(signedData, sig); err != nil {
return nil, err
@@ -633,6 +640,30 @@ userAuthLoop:
}
authFailures++
+ if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries {
+ // If we have hit the max attempts, don't bother sending the
+ // final SSH_MSG_USERAUTH_FAILURE message, since there are
+ // no more authentication methods which can be attempted,
+ // and this message may cause the client to re-attempt
+ // authentication while we send the disconnect message.
+ // Continue, and trigger the disconnect at the start of
+ // the loop.
+ //
+ // The SSH specification is somewhat confusing about this,
+ // RFC 4252 Section 5.1 requires each authentication failure
+ // be responded to with a respective SSH_MSG_USERAUTH_FAILURE
+ // message, but Section 4 says the server should disconnect
+ // after some number of attempts, but it isn't explicit which
+ // message should take precedence (i.e. should there be a failure
+ // message than a disconnect message, or if we are going to
+ // disconnect, should we only send that message.)
+ //
+ // Either way, OpenSSH disconnects immediately after the last
+ // failed authnetication attempt, and given they are typically
+ // considered the golden implementation it seems reasonable
+ // to match that behavior.
+ continue
+ }
var failureMsg userAuthFailureMsg
if config.PasswordCallback != nil {
@@ -670,7 +701,7 @@ type sshClientKeyboardInteractive struct {
*connection
}
-func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) {
if len(questions) != len(echos) {
return nil, errors.New("ssh: echos and questions must have equal length")
}
@@ -682,6 +713,7 @@ func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, quest
}
if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
+ Name: name,
Instruction: instruction,
NumPrompts: uint32(len(questions)),
Prompts: prompts,
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
index d3321f6b..eca31a22 100644
--- a/vendor/golang.org/x/crypto/ssh/session.go
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -85,6 +85,7 @@ const (
IXANY = 39
IXOFF = 40
IMAXBEL = 41
+ IUTF8 = 42 // RFC 8160
ISIG = 50
ICANON = 51
XCASE = 52
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index 49ddc2e7..acf5a21b 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -238,15 +238,19 @@ var (
// (to setup server->client keys) or clientKeys (for client->server keys).
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher]
- macMode := macModes[algs.MAC]
iv := make([]byte, cipherMode.ivSize)
key := make([]byte, cipherMode.keySize)
- macKey := make([]byte, macMode.keySize)
generateKeyMaterial(iv, d.ivTag, kex)
generateKeyMaterial(key, d.keyTag, kex)
- generateKeyMaterial(macKey, d.macKeyTag, kex)
+
+ var macKey []byte
+ if !aeadCiphers[algs.Cipher] {
+ macMode := macModes[algs.MAC]
+ macKey = make([]byte, macMode.keySize)
+ generateKeyMaterial(macKey, d.macKeyTag, kex)
+ }
return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
}
diff --git a/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go b/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
index 1ba43101..f6877f98 100644
--- a/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
+++ b/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
-// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
+//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
+// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux
package socket
diff --git a/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go b/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
index aa1b0620..19d46789 100644
--- a/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
+++ b/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package socket
diff --git a/vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go b/vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
index 98be146b..68dc8ad6 100644
--- a/vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
+++ b/vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
@@ -4,22 +4,8 @@
package socket
-import "syscall"
-
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = int32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
-
-func controlHeaderLen() int {
- return syscall.CmsgLen(0)
-}
-
-func controlMessageLen(dataLen int) int {
- return syscall.CmsgLen(dataLen)
-}
-
-func controlMessageSpace(dataLen int) int {
- return syscall.CmsgSpace(dataLen)
-}
diff --git a/vendor/golang.org/x/net/internal/socket/iovec_64bit.go b/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
index 3dc5def2..2e94e96f 100644
--- a/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
+++ b/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos)
-// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
+//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos)
+// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build aix darwin dragonfly freebsd linux netbsd openbsd zos
package socket
diff --git a/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go b/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
index 40ebedab..0bfcf7af 100644
--- a/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
+++ b/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
@@ -9,7 +9,9 @@ package socket
import (
"net"
+ "os"
"sync"
+ "syscall"
)
type mmsghdrs []mmsghdr
@@ -93,22 +95,86 @@ func (p *mmsghdrsPacker) pack(ms []Message, parseFn func([]byte, string) (net.Ad
return hs
}
-var defaultMmsghdrsPool = mmsghdrsPool{
+// syscaller is a helper to invoke recvmmsg and sendmmsg via the RawConn.Read/Write interface.
+// It is reusable, to amortize the overhead of allocating a closure for the function passed to
+// RawConn.Read/Write.
+type syscaller struct {
+ n int
+ operr error
+ hs mmsghdrs
+ flags int
+
+ boundRecvmmsgF func(uintptr) bool
+ boundSendmmsgF func(uintptr) bool
+}
+
+func (r *syscaller) init() {
+ r.boundRecvmmsgF = r.recvmmsgF
+ r.boundSendmmsgF = r.sendmmsgF
+}
+
+func (r *syscaller) recvmmsg(c syscall.RawConn, hs mmsghdrs, flags int) (int, error) {
+ r.n = 0
+ r.operr = nil
+ r.hs = hs
+ r.flags = flags
+ if err := c.Read(r.boundRecvmmsgF); err != nil {
+ return r.n, err
+ }
+ if r.operr != nil {
+ return r.n, os.NewSyscallError("recvmmsg", r.operr)
+ }
+ return r.n, nil
+}
+
+func (r *syscaller) recvmmsgF(s uintptr) bool {
+ r.n, r.operr = recvmmsg(s, r.hs, r.flags)
+ return ioComplete(r.flags, r.operr)
+}
+
+func (r *syscaller) sendmmsg(c syscall.RawConn, hs mmsghdrs, flags int) (int, error) {
+ r.n = 0
+ r.operr = nil
+ r.hs = hs
+ r.flags = flags
+ if err := c.Write(r.boundSendmmsgF); err != nil {
+ return r.n, err
+ }
+ if r.operr != nil {
+ return r.n, os.NewSyscallError("sendmmsg", r.operr)
+ }
+ return r.n, nil
+}
+
+func (r *syscaller) sendmmsgF(s uintptr) bool {
+ r.n, r.operr = sendmmsg(s, r.hs, r.flags)
+ return ioComplete(r.flags, r.operr)
+}
+
+// mmsgTmps holds reusable temporary helpers for recvmmsg and sendmmsg.
+type mmsgTmps struct {
+ packer mmsghdrsPacker
+ syscaller syscaller
+}
+
+var defaultMmsgTmpsPool = mmsgTmpsPool{
p: sync.Pool{
New: func() interface{} {
- return new(mmsghdrsPacker)
+ tmps := new(mmsgTmps)
+ tmps.syscaller.init()
+ return tmps
},
},
}
-type mmsghdrsPool struct {
+type mmsgTmpsPool struct {
p sync.Pool
}
-func (p *mmsghdrsPool) Get() *mmsghdrsPacker {
- return p.p.Get().(*mmsghdrsPacker)
+func (p *mmsgTmpsPool) Get() *mmsgTmps {
+ return p.p.Get().(*mmsgTmps)
}
-func (p *mmsghdrsPool) Put(packer *mmsghdrsPacker) {
- p.p.Put(packer)
+func (p *mmsgTmpsPool) Put(tmps *mmsgTmps) {
+ p.p.Put(tmps)
}
diff --git a/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go b/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
index c9c592dd..42411aff 100644
--- a/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
+++ b/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (arm64 || amd64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
-// +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
+//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
+// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux
package socket
diff --git a/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go b/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
index 3fcb51b3..8f79b38f 100644
--- a/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
+++ b/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
@@ -9,32 +9,23 @@ package socket
import (
"net"
- "os"
)
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceWrite()
}
- packer := defaultMmsghdrsPool.Get()
- defer defaultMmsghdrsPool.Put(packer)
+ tmps := defaultMmsgTmpsPool.Get()
+ defer defaultMmsgTmpsPool.Put(tmps)
var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" {
parseFn = parseInetAddr
}
- hs := packer.pack(ms, parseFn, nil)
- var operr error
- var n int
- fn := func(s uintptr) bool {
- n, operr = recvmmsg(s, hs, flags)
- return ioComplete(flags, operr)
- }
- if err := c.c.Read(fn); err != nil {
+ hs := tmps.packer.pack(ms, parseFn, nil)
+ n, err := tmps.syscaller.recvmmsg(c.c, hs, flags)
+ if err != nil {
return n, err
}
- if operr != nil {
- return n, os.NewSyscallError("recvmmsg", operr)
- }
if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil {
return n, err
}
@@ -45,25 +36,17 @@ func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceRead()
}
- packer := defaultMmsghdrsPool.Get()
- defer defaultMmsghdrsPool.Put(packer)
+ tmps := defaultMmsgTmpsPool.Get()
+ defer defaultMmsgTmpsPool.Put(tmps)
var marshalFn func(net.Addr, []byte) int
if c.network != "tcp" {
marshalFn = marshalInetAddr
}
- hs := packer.pack(ms, nil, marshalFn)
- var operr error
- var n int
- fn := func(s uintptr) bool {
- n, operr = sendmmsg(s, hs, flags)
- return ioComplete(flags, operr)
- }
- if err := c.c.Write(fn); err != nil {
+ hs := tmps.packer.pack(ms, nil, marshalFn)
+ n, err := tmps.syscaller.sendmmsg(c.c, hs, flags)
+ if err != nil {
return n, err
}
- if operr != nil {
- return n, os.NewSyscallError("sendmmsg", operr)
- }
if err := hs[:n].unpack(ms[:n], nil, ""); err != nil {
return n, err
}
diff --git a/vendor/golang.org/x/net/internal/socket/sys_bsd.go b/vendor/golang.org/x/net/internal/socket/sys_bsd.go
index b6cd7708..b258879d 100644
--- a/vendor/golang.org/x/net/internal/socket/sys_bsd.go
+++ b/vendor/golang.org/x/net/internal/socket/sys_bsd.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || dragonfly || freebsd || openbsd
-// +build aix darwin dragonfly freebsd openbsd
+//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd openbsd solaris
package socket
diff --git a/vendor/golang.org/x/net/internal/socket/sys_linkname.go b/vendor/golang.org/x/net/internal/socket/sys_linkname.go
deleted file mode 100644
index 21734af4..00000000
--- a/vendor/golang.org/x/net/internal/socket/sys_linkname.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build aix || (go1.12 && darwin)
-// +build aix go1.12,darwin
-
-package socket
-
-import (
- "syscall"
- "unsafe"
-)
-
-//go:linkname syscall_getsockopt syscall.getsockopt
-func syscall_getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *uint32) error
-
-func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
- l := uint32(len(b))
- err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l)
- return int(l), err
-}
-
-//go:linkname syscall_setsockopt syscall.setsockopt
-func syscall_setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error
-
-func setsockopt(s uintptr, level, name int, b []byte) error {
- return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b)))
-}
-
-//go:linkname syscall_recvmsg syscall.recvmsg
-func syscall_recvmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error)
-
-func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
- return syscall_recvmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
-}
-
-//go:linkname syscall_sendmsg syscall.sendmsg
-func syscall_sendmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error)
-
-func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
- return syscall_sendmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
-}
diff --git a/vendor/golang.org/x/net/internal/socket/sys_linux_386.go b/vendor/golang.org/x/net/internal/socket/sys_linux_386.go
index 65121532..c877ef23 100644
--- a/vendor/golang.org/x/net/internal/socket/sys_linux_386.go
+++ b/vendor/golang.org/x/net/internal/socket/sys_linux_386.go
@@ -10,38 +10,13 @@ import (
)
const (
- sysSETSOCKOPT = 0xe
- sysGETSOCKOPT = 0xf
- sysSENDMSG = 0x10
- sysRECVMSG = 0x11
- sysRECVMMSG = 0x13
- sysSENDMMSG = 0x14
+ sysRECVMMSG = 0x13
+ sysSENDMMSG = 0x14
)
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
-func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
- l := uint32(len(b))
- _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
- return int(l), errnoErr(errno)
-}
-
-func setsockopt(s uintptr, level, name int, b []byte) error {
- _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
- return errnoErr(errno)
-}
-
-func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
-func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
return int(n), errnoErr(errno)
diff --git a/vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go b/vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go
new file mode 100644
index 00000000..af964e61
--- /dev/null
+++ b/vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build loong64
+// +build loong64
+
+package socket
+
+const (
+ sysRECVMMSG = 0xf3
+ sysSENDMMSG = 0x10d
+)
diff --git a/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go b/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
index 65121532..c877ef23 100644
--- a/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
+++ b/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
@@ -10,38 +10,13 @@ import (
)
const (
- sysSETSOCKOPT = 0xe
- sysGETSOCKOPT = 0xf
- sysSENDMSG = 0x10
- sysRECVMSG = 0x11
- sysRECVMMSG = 0x13
- sysSENDMMSG = 0x14
+ sysRECVMMSG = 0x13
+ sysSENDMMSG = 0x14
)
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
-func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
- l := uint32(len(b))
- _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
- return int(l), errnoErr(errno)
-}
-
-func setsockopt(s uintptr, level, name int, b []byte) error {
- _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
- return errnoErr(errno)
-}
-
-func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
-func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
return int(n), errnoErr(errno)
diff --git a/vendor/golang.org/x/net/internal/socket/sys_solaris.go b/vendor/golang.org/x/net/internal/socket/sys_solaris.go
deleted file mode 100644
index e79ca951..00000000
--- a/vendor/golang.org/x/net/internal/socket/sys_solaris.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package socket
-
-import (
- "syscall"
- "unsafe"
-)
-
-//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
-//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
-//go:cgo_import_dynamic libc___xnet_recvmsg __xnet_recvmsg "libsocket.so"
-//go:cgo_import_dynamic libc___xnet_sendmsg __xnet_sendmsg "libsocket.so"
-
-//go:linkname procGetsockopt libc___xnet_getsockopt
-//go:linkname procSetsockopt libc_setsockopt
-//go:linkname procRecvmsg libc___xnet_recvmsg
-//go:linkname procSendmsg libc___xnet_sendmsg
-
-var (
- procGetsockopt uintptr
- procSetsockopt uintptr
- procRecvmsg uintptr
- procSendmsg uintptr
-)
-
-func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
-func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
-
-func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
- l := uint32(len(b))
- _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procGetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
- return int(l), errnoErr(errno)
-}
-
-func setsockopt(s uintptr, level, name int, b []byte) error {
- _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
- return errnoErr(errno)
-}
-
-func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procRecvmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
-func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSendmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
- return int(n), errnoErr(errno)
-}
-
-func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
- return 0, errNotImplemented
-}
-
-func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
- return 0, errNotImplemented
-}
diff --git a/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s b/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s
deleted file mode 100644
index a18ac5ed..00000000
--- a/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-TEXT ·sysvicall6(SB),NOSPLIT,$0-88
- JMP syscall·sysvicall6(SB)
-
-TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
- JMP syscall·rawSysvicall6(SB)
diff --git a/vendor/golang.org/x/net/internal/socket/sys_unix.go b/vendor/golang.org/x/net/internal/socket/sys_unix.go
index c98ebae5..d203e298 100644
--- a/vendor/golang.org/x/net/internal/socket/sys_unix.go
+++ b/vendor/golang.org/x/net/internal/socket/sys_unix.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build dragonfly || freebsd || (linux && !s390x && !386) || netbsd || openbsd
-// +build dragonfly freebsd linux,!s390x,!386 netbsd openbsd
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
@@ -12,23 +12,32 @@ import (
"unsafe"
)
+//go:linkname syscall_getsockopt syscall.getsockopt
+func syscall_getsockopt(s, level, name int, val unsafe.Pointer, vallen *uint32) error
+
+//go:linkname syscall_setsockopt syscall.setsockopt
+func syscall_setsockopt(s, level, name int, val unsafe.Pointer, vallen uintptr) error
+
+//go:linkname syscall_recvmsg syscall.recvmsg
+func syscall_recvmsg(s int, msg *syscall.Msghdr, flags int) (int, error)
+
+//go:linkname syscall_sendmsg syscall.sendmsg
+func syscall_sendmsg(s int, msg *syscall.Msghdr, flags int) (int, error)
+
func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
l := uint32(len(b))
- _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
- return int(l), errnoErr(errno)
+ err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l)
+ return int(l), err
}
func setsockopt(s uintptr, level, name int, b []byte) error {
- _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
- return errnoErr(errno)
+ return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b)))
}
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
- return int(n), errnoErr(errno)
+ return syscall_recvmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
}
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
- n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
- return int(n), errnoErr(errno)
+ return syscall_sendmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
}
diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go
new file mode 100644
index 00000000..6a94fec2
--- /dev/null
+++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go
@@ -0,0 +1,40 @@
+// Code generated by cmd/cgo -godefs; DO NOT EDIT.
+// cgo -godefs defs_linux.go
+
+//go:build loong64
+// +build loong64
+
+package socket
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_0 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+)
diff --git a/vendor/golang.org/x/net/ipv4/zsys_linux_loong64.go b/vendor/golang.org/x/net/ipv4/zsys_linux_loong64.go
new file mode 100644
index 00000000..e15c22c7
--- /dev/null
+++ b/vendor/golang.org/x/net/ipv4/zsys_linux_loong64.go
@@ -0,0 +1,77 @@
+// Code generated by cmd/cgo -godefs; DO NOT EDIT.
+// cgo -godefs defs_linux.go
+
+//go:build loong64
+// +build loong64
+
+package ipv4
+
+const (
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
diff --git a/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go b/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go
new file mode 100644
index 00000000..598fbfa0
--- /dev/null
+++ b/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go
@@ -0,0 +1,77 @@
+// Code generated by cmd/cgo -godefs; DO NOT EDIT.
+// cgo -godefs defs_linux.go
+
+//go:build loong64
+// +build loong64
+
+package ipv6
+
+const (
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 08f8ca83..18f1083b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -133,7 +133,7 @@ github.com/pkg/sftp/internal/encoding/ssh/filexfer
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
-# github.com/richardlehane/mscfb v1.0.3
+# github.com/richardlehane/mscfb v1.0.4
## explicit
github.com/richardlehane/mscfb
# github.com/richardlehane/msoleps v1.0.1
@@ -165,20 +165,22 @@ github.com/vbauerster/mpb/v7
github.com/vbauerster/mpb/v7/cwriter
github.com/vbauerster/mpb/v7/decor
github.com/vbauerster/mpb/v7/internal
-# github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3
+# github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8
## explicit; go 1.11
github.com/xuri/efp
-# github.com/xuri/excelize/v2 v2.5.0
+# github.com/xuri/excelize/v2 v2.6.0
## explicit; go 1.15
github.com/xuri/excelize/v2
-# golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
+# github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22
+## explicit; go 1.15
+github.com/xuri/nfp
+# golang.org/x/crypto v0.0.0-20220408190544-5352b0902921
## explicit; go 1.17
golang.org/x/crypto/blowfish
golang.org/x/crypto/chacha20
golang.org/x/crypto/curve25519
golang.org/x/crypto/curve25519/internal/field
golang.org/x/crypto/ed25519
-golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/internal/poly1305
golang.org/x/crypto/internal/subtle
golang.org/x/crypto/md4
@@ -186,7 +188,7 @@ golang.org/x/crypto/ripemd160
golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/terminal
-# golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
+# golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3
## explicit; go 1.17
golang.org/x/net/bpf
golang.org/x/net/html